#![allow(clippy::unwrap_used, clippy::expect_used)]
use rust_decimal::Decimal;
use rustrade_execution::client::{
BorrowCapacityClient, ExecutionClient, ShortabilityClient,
binance::{BinanceMargin, BinanceMarginConfig},
};
use rustrade_instrument::{Side, instrument::name::InstrumentNameExchange};
fn env(name: &str) -> String {
std::env::var(name).unwrap_or_else(|_| panic!("{name} env var required"))
}
#[tokio::test]
#[ignore]
async fn margin_borrow_terms_and_capacity_read_back() {
let _ = tracing_subscriber::fmt()
.with_env_filter("rustrade_execution=info")
.try_init();
let instrument = InstrumentNameExchange::new(env("BINANCE_MARGIN_SYMBOL"));
let is_isolated = std::env::var("BINANCE_MARGIN_ISOLATED").is_ok_and(|value| value == "true");
let (api_key, secret_key) = (
env("BINANCE_MARGIN_API_KEY"),
env("BINANCE_MARGIN_SECRET_KEY"),
);
let config = if is_isolated {
BinanceMarginConfig::isolated(api_key, secret_key, vec![instrument.clone()])
} else {
BinanceMarginConfig::cross_margin(api_key, secret_key)
};
let client = BinanceMargin::new(config);
println!("{instrument}, isolated: {is_isolated}");
let shortability = client
.fetch_shortability(&instrument)
.await
.expect("fetch_shortability");
println!("shortability: {shortability:?}");
assert!(
shortability.shortable.is_some(),
"a listed pair's flags are known"
);
let fee_rate = shortability
.fee_rate
.expect("Binance reports a rate for the base asset");
assert!(
fee_rate > Decimal::ZERO && fee_rate < Decimal::ONE,
"an annual rate as a fraction, not a percentage: {fee_rate}"
);
for side in [Side::Sell, Side::Buy] {
let capacity = client
.fetch_borrow_capacity(&instrument, side)
.await
.expect("fetch_borrow_capacity");
println!(
"{side:?} borrows {}: borrowable now is_some={} account limit is_some={}, now <= limit: {:?}",
capacity.asset,
capacity.borrowable_now.is_some(),
capacity.account_limit.is_some(),
capacity
.borrowable_now
.zip(capacity.account_limit)
.map(|(now, limit)| now <= limit),
);
}
}