use crate::api::account::BalanceRequest;
use crate::model::InstType;
use crate::test_util::MockTransport;
use super::super::{
AccountPositionTiersRequest, PositionBuilderRequest, SetRiskOffsetAmountRequest,
SimulatedAsset, SimulatedMarginRequest, SimulatedPosition,
};
use super::signed_client;
#[tokio::test]
async fn get_greeks_queries_currency() {
let body = r#"{"code":"0","msg":"","data":[{
"ccy":"BTC","deltaBS":"1","deltaPA":"0.91","gammaBS":"0.00111","gammaPA":"0.00121",
"thetaBS":"-24.46655352","thetaPA":"-23.25","ts":"1630982931600","vegaBS":"4601.26","vegaPA":"4626.55"}]}"#;
let mock = MockTransport::new(body);
let client = signed_client(mock.clone());
let result = client
.account()
.get_greeks(BalanceRequest::new().currency("BTC"))
.await
.unwrap();
assert_eq!(result[0].delta_pa.as_str(), "0.91");
let req = mock.captured();
assert_eq!(req.query(), Some("ccy=BTC"));
assert!(req.is_signed());
}
#[tokio::test]
async fn get_account_position_tiers_uses_builder_query() {
let body = r#"{"code":"0","msg":"","data":[{
"instType":"OPTION","uly":"BTC-USD","instFamily":"BTC-USD","posType":"1",
"minSz":"0","maxSz":"100","mmrFactor":"0.1","imrFactor":"0.3","netDeltaAmount":"0.02"}]}"#;
let mock = MockTransport::new(body);
let client = signed_client(mock.clone());
let request = AccountPositionTiersRequest::new(InstType::Option).underlying("BTC-USD");
let result = client
.account()
.get_account_position_tiers(&request)
.await
.unwrap();
assert_eq!(result[0].max_sz.as_str(), "100");
let req = mock.captured();
assert_eq!(req.query(), Some("instType=OPTION&uly=BTC-USD"));
assert!(req.is_signed());
}
#[test]
fn account_position_tiers_request_serializes_inst_family_filter() {
let request = AccountPositionTiersRequest::new(InstType::Swap).inst_family("BTC-USDT");
let query = serde_urlencoded::to_string(&request).unwrap();
assert_eq!(query, "instType=SWAP&instFamily=BTC-USDT");
}
#[tokio::test]
async fn get_simulated_margin_posts_body_and_omits_unset_fields() {
let body = r#"{"code":"0","msg":"","data":[{
"imr":"3174.99999","mmr":"126.39999","mr":"54085.3541","notionalUsd":"","ts":"1629453864251",
"details":[{
"instId":"BTC-USDT-SWAP","pos":"1","imr":"3174.99999","mmr":"126.39999",
"upl":"12.20","optVal":"","delta":"","gamma":"","vega":"","theta":""}]}]}"#;
let mock = MockTransport::new(body);
let client = signed_client(mock.clone());
let request = SimulatedMarginRequest::new()
.inst_type(InstType::Swap)
.simulated_positions(vec![
SimulatedPosition::new("BTC-USDT-SWAP")
.position("1")
.leverage("10"),
]);
let result = client
.account()
.get_simulated_margin(&request)
.await
.unwrap();
assert_eq!(result[0].details[0].upl.as_str(), "12.20");
let req = mock.captured();
assert_eq!(req.method, http::Method::POST);
assert!(req.uri.ends_with("/api/v5/account/simulated_margin"));
let sent: serde_json::Value = serde_json::from_str(req.body_str()).unwrap();
assert_eq!(sent["instType"], "SWAP");
assert_eq!(sent["simPos"][0]["instId"], "BTC-USDT-SWAP");
assert_eq!(sent["simPos"][0]["pos"], "1");
assert_eq!(sent["simPos"][0]["lever"], "10");
assert!(sent.get("inclRealPos").is_none());
assert!(sent["simPos"][0].get("avgPx").is_none());
assert!(req.is_signed());
}
#[tokio::test]
async fn set_risk_offset_amount_posts_body() {
let body = r#"{"code":"0","msg":"","data":[{"ccy":"BTC","clSpotInUseAmt":"0.5"}]}"#;
let mock = MockTransport::new(body);
let client = signed_client(mock.clone());
let result = client
.account()
.set_risk_offset_amount(&SetRiskOffsetAmountRequest::new("BTC", "0.5"))
.await
.unwrap();
assert_eq!(result[0].ccy, "BTC");
assert_eq!(result[0].cl_spot_in_use_amt.as_str(), "0.5");
let req = mock.captured();
assert_eq!(req.method, http::Method::POST);
assert!(req.uri.ends_with("/api/v5/account/set-riskOffset-amt"));
let sent: serde_json::Value = serde_json::from_str(req.body_str()).unwrap();
assert_eq!(sent["ccy"], "BTC");
assert_eq!(sent["clSpotInUseAmt"], "0.5");
assert!(req.is_signed());
}
#[tokio::test]
async fn position_builder_posts_body_and_omits_unset_fields() {
let body = r#"{"code":"0","msg":"","data":[{
"eq":"10000","totalMmr":"126.39","totalImr":"3174.99","borrowMmr":"0","derivMmr":"126.39",
"marginRatio":"79.12","upl":"2","acctLever":"1.5","ts":"1629453864251",
"assets":[{"ccy":"USDT","availEq":"10000","spotInUse":"0","borrowMmr":"","borrowImr":""}],
"riskUnitData":[{
"riskUnit":"BTC","mmrBf":"","mmr":"126.39","imrBf":"","imr":"3174.99","upl":"2",
"mr1":"100","mr2":"0","mr3":"0","mr4":"0","mr5":"0","mr6":"126.39","mr7":"0","mr8":"0","mr9":"0",
"mr1Scenarios":{"volSame":{"0":"0","0.08":"-776.27"},"volShockUp":{},"volShockDown":{}}}]}]}"#;
let mock = MockTransport::new(body);
let client = signed_client(mock.clone());
let request = PositionBuilderRequest::new()
.account_level("2")
.include_real_positions_and_equity(false)
.simulated_positions(vec![SimulatedPosition::new("BTC-USDT-SWAP").position("1")])
.simulated_assets(vec![SimulatedAsset::new("USDT").equity("10000")]);
let result = client.account().position_builder(&request).await.unwrap();
assert_eq!(result[0].eq.as_str(), "10000");
assert_eq!(result[0].assets[0].ccy, "USDT");
assert_eq!(result[0].risk_unit_data[0].risk_unit, "BTC");
assert_eq!(result[0].risk_unit_data[0].mmr.as_str(), "126.39");
assert_eq!(
result[0].risk_unit_data[0]
.mr1_scenarios
.as_ref()
.unwrap()
.vol_same["0.08"]
.as_str(),
"-776.27"
);
let req = mock.captured();
assert_eq!(req.method, http::Method::POST);
assert!(req.uri.ends_with("/api/v5/account/position-builder"));
let sent: serde_json::Value = serde_json::from_str(req.body_str()).unwrap();
assert_eq!(sent["acctLv"], "2");
assert_eq!(sent["inclRealPosAndEq"], false);
assert_eq!(sent["simPos"][0]["instId"], "BTC-USDT-SWAP");
assert_eq!(sent["simAsset"][0]["ccy"], "USDT");
assert!(sent.get("lever").is_none());
assert!(sent["simPos"][0].get("avgPx").is_none());
assert!(req.is_signed());
}