sandbox-quant 1.0.7

Exchange-truth trading core for Binance Spot and Futures
Documentation
use crate::domain::balance::BalanceSnapshot;
use crate::domain::instrument::Instrument;
use crate::domain::market::Market;
use crate::domain::order::{OpenOrder, OrderStatus};
use crate::domain::position::PositionSnapshot;
use crate::domain::position::Side;
use crate::exchange::symbol_rules::SymbolRules;
use crate::exchange::types::{AuthoritativeSnapshot, CloseOrderAccepted, CloseOrderRequest};

use crate::exchange::binance::account::{RawAccountState, RawBalance, RawPosition};
use crate::exchange::binance::orders::{
    RawCloseOrderAck, RawCloseOrderRequest, RawOpenOrder, RawSymbolRules,
};

#[derive(Debug, Default, Clone)]
pub struct BinanceMapper;

impl BinanceMapper {
    pub fn map_account_snapshot(
        &self,
        market: Market,
        state: RawAccountState,
    ) -> AuthoritativeSnapshot {
        AuthoritativeSnapshot {
            balances: state.balances.into_iter().map(map_balance).collect(),
            positions: state
                .positions
                .into_iter()
                .map(|position| map_position(market, position))
                .collect(),
            open_orders: state.open_orders.into_iter().map(map_open_order).collect(),
        }
    }

    pub fn map_symbol_rules(&self, rules: RawSymbolRules) -> SymbolRules {
        SymbolRules {
            min_qty: rules.min_qty,
            max_qty: rules.max_qty,
            step_size: rules.step_size,
        }
    }

    pub fn map_close_request(&self, request: CloseOrderRequest) -> RawCloseOrderRequest {
        RawCloseOrderRequest {
            symbol: request.instrument.0,
            market: request.market,
            side: match request.side {
                crate::domain::position::Side::Buy => "BUY",
                crate::domain::position::Side::Sell => "SELL",
            },
            qty: request.qty_text,
            order_type: request.order_type,
            reduce_only: request.reduce_only,
        }
    }

    pub fn map_close_ack(&self, ack: RawCloseOrderAck) -> CloseOrderAccepted {
        CloseOrderAccepted {
            remote_order_id: ack.remote_order_id,
        }
    }
}

fn map_balance(balance: RawBalance) -> BalanceSnapshot {
    BalanceSnapshot {
        asset: balance.asset,
        free: balance.free,
        locked: balance.locked,
    }
}

fn map_position(market: Market, position: RawPosition) -> PositionSnapshot {
    PositionSnapshot {
        instrument: Instrument::new(position.symbol),
        market,
        signed_qty: position.signed_qty,
        entry_price: position.entry_price,
    }
}

fn map_open_order(order: RawOpenOrder) -> OpenOrder {
    OpenOrder {
        order_id: order
            .order_id
            .and_then(|value| value.parse::<u64>().ok())
            .map(crate::domain::identifiers::OrderId),
        client_order_id: order.client_order_id,
        instrument: Instrument::new(order.symbol),
        market: order.market,
        side: match order.side {
            "SELL" => Side::Sell,
            _ => Side::Buy,
        },
        orig_qty: order.orig_qty,
        executed_qty: order.executed_qty,
        reduce_only: order.reduce_only,
        status: map_order_status(&order.status),
    }
}

fn map_order_status(status: &str) -> OrderStatus {
    match status {
        "NEW" | "ACCEPTED" => OrderStatus::Submitted,
        "FILLED" => OrderStatus::Filled,
        "CANCELED" | "CANCELLED" => OrderStatus::Cancelled,
        "REJECTED" => OrderStatus::Rejected,
        _ => OrderStatus::PendingSubmit,
    }
}