sandbox-quant 1.0.8

Exchange-truth trading core for Binance Spot and Futures
Documentation
use sandbox_quant::app::bootstrap::AppBootstrap;
use sandbox_quant::app::commands::AppCommand;
use sandbox_quant::app::runtime::AppRuntime;
use sandbox_quant::domain::instrument::Instrument;
use sandbox_quant::domain::market::Market;
use sandbox_quant::error::exchange_error::ExchangeError;
use sandbox_quant::exchange::facade::ExchangeFacade;
use sandbox_quant::exchange::symbol_rules::SymbolRules;
use sandbox_quant::exchange::types::{
    AuthoritativeSnapshot, CloseOrderAccepted, CloseOrderRequest, SubmitOrderAccepted,
};
use sandbox_quant::portfolio::store::PortfolioStateStore;

#[derive(Debug, Default)]
struct AuthFailExchange;

impl ExchangeFacade for AuthFailExchange {
    type Error = ExchangeError;

    fn load_authoritative_snapshot(&self) -> Result<AuthoritativeSnapshot, Self::Error> {
        Err(ExchangeError::AuthenticationFailed {
            status: 401,
            code: Some(-2015),
            endpoint: "/api/v3/account".to_string(),
            message: "Invalid API-key, IP, or permissions for action".to_string(),
        })
    }

    fn load_today_realized_pnl_usdt(&self) -> Result<f64, Self::Error> {
        Err(ExchangeError::UnsupportedMarketOperation)
    }

    fn load_today_funding_pnl_usdt(&self) -> Result<f64, Self::Error> {
        Err(ExchangeError::UnsupportedMarketOperation)
    }

    fn load_margin_ratio(&self) -> Result<Option<f64>, Self::Error> {
        Err(ExchangeError::UnsupportedMarketOperation)
    }

    fn load_last_price(
        &self,
        _instrument: &Instrument,
        _market: Market,
    ) -> Result<f64, Self::Error> {
        Err(ExchangeError::UnsupportedMarketOperation)
    }

    fn load_symbol_rules(
        &self,
        _instrument: &Instrument,
        _market: Market,
    ) -> Result<SymbolRules, Self::Error> {
        Err(ExchangeError::UnsupportedMarketOperation)
    }

    fn submit_close_order(
        &self,
        _request: CloseOrderRequest,
    ) -> Result<CloseOrderAccepted, Self::Error> {
        Err(ExchangeError::UnsupportedMarketOperation)
    }

    fn submit_order(
        &self,
        _request: CloseOrderRequest,
    ) -> Result<SubmitOrderAccepted, Self::Error> {
        Err(ExchangeError::UnsupportedMarketOperation)
    }
}

#[test]
fn refresh_surfaces_detailed_authentication_failure_from_exchange() {
    let exchange = AuthFailExchange;
    let mut app = AppBootstrap::new(exchange, PortfolioStateStore::default());
    let mut runtime = AppRuntime::default();

    let error = runtime
        .run(&mut app, AppCommand::RefreshAuthoritativeState)
        .expect_err("refresh should surface exchange auth error");

    assert_eq!(
        error.to_string(),
        "exchange error: authentication failed: status=401 code=Some(-2015) endpoint=/api/v3/account message=Invalid API-key, IP, or permissions for action"
    );
}