Models#
Every adapter returns these types, so code written against one exchange reads the same on another. They live in tradersdk_core::models and are re-exported by the prelude. Prices and quantities are f64 unless noted. Timestamps are Unix milliseconds.
Market type and interval#
pub enum MarketType { Spot, Swap } // default Spot
pub enum Interval { M1, M5, M15, M30, H1, H4, D1, W1 }
MarketType::from("perp") gives Swap. The strings swap, futures, perp and perpetual map to Swap; anything else is Spot. Interval::to_seconds() returns the length in seconds.
Balance#
pub struct Balance { pub asset: String, pub free: f64, pub locked: f64 }
pub struct AccountBalance {
pub total_balance: f64,
pub available_balance: f64,
pub currency: String,
pub margin_balance: Option<f64>,
pub used_margin: Option<f64>,
pub unrealized_pnl: Option<f64>,
pub realized_pnl: Option<f64>,
pub balances: Vec<Balance>,
}
Helpers: get_balance(asset) (case-insensitive), get_free_balance(asset) (0.0 when missing), margin_usage_percent() (0 to 100, None unless margin_balance is positive).
Candle#
Candle { timestamp, open, high, low, close, volume, turnover } with timestamp as the candle open time. Helpers: is_bullish, is_bearish, is_doji(threshold), body, range, upper_shadow, lower_shadow, body_percentage, change, change_percent, typical_price. vwap() is the estimate typical_price * volume, not a running VWAP.
Ticker, funding, open interest#
pub struct TickerInfo {
pub symbol: String, pub last_price: f64,
pub bid_price: Option<f64>, pub ask_price: Option<f64>,
pub high_24h: Option<f64>, pub low_24h: Option<f64>,
pub volume_24h: Option<f64>, pub turnover_24h: Option<f64>, pub change_24h: Option<f64>,
pub open_interest: Option<f64>, pub open_interest_value: Option<f64>,
pub funding_rate: Option<f64>, pub next_funding_time: Option<i64>,
pub mark_price: Option<f64>, pub index_price: Option<f64>,
pub timestamp: i64,
}
pub struct FundingRateEntry { pub symbol: String, pub funding_rate: f64, pub funding_time: i64 }
pub struct OpenInterestEntry { pub symbol: String, pub open_interest: f64, pub open_interest_value: f64, pub timestamp: i64 }
TickerInfo has mid_price(), spread() and spread_percent(). Optional fields are None when the exchange does not report them.
Order book#
Orderbook { symbol, bids, asks, timestamp } with OrderbookLevel { price, quantity }. Bids must be sorted high to low and asks low to high. The methods rely on that order: best_bid, best_ask, mid_price, spread, spread_bps, bid_depth, ask_depth, bid_depth_to_price, ask_depth_to_price, avg_buy_price(qty) and avg_sell_price(qty). The two average-price methods return None when the book is too thin to fill the quantity.
Symbol metadata#
SymbolInfo carries precisions, min_quantity, max_quantity, min_notional, tick_size, step_size and max_leverage (these use Decimal). ExchangeInfo { name, symbols } has get_symbol(name), an exact, case-sensitive lookup.
Orders#
pub enum OrderSide { Buy, Sell }
pub enum OrderType { Market, Limit, StopMarket, StopLimit, TakeProfitMarket, TakeProfitLimit, TrailingStop }
pub enum OrderStatus { Pending, New, PartiallyFilled, Filled, Cancelled, Rejected, Expired }
pub enum TimeInForce { GTC, IOC, FOK, PostOnly, GTX }
OrderSide::from("short") is Sell; every other string, including unknown ones, is Buy. OrderStatus::is_final() is true for Filled, Cancelled, Rejected and Expired. is_active() is true for Pending, New and PartiallyFilled.
pub struct OrderResult {
pub success: bool,
pub order_id: Option<String>,
pub symbol: String, pub side: OrderSide, pub order_type: OrderType,
pub quantity: Option<f64>, pub entry_price: Option<f64>,
pub position_size: Option<f64>, pub position_usdt: Option<f64>,
pub error: Option<String>,
pub raw_response: Option<HashMap<String, serde_json::Value>>,
}
Check success as well as the outer Result: some adapters report an exchange rejection as Ok with success: false and the reason in error. OrderResult::success(..) and OrderResult::failure(..) are the constructors.
OrderInfo is what get_order_status returns: order_id, client_order_id, symbol, status, side, order_type, price, quantity, filled_quantity, remaining_quantity, avg_price, timestamp, time_in_force, reduce_only. fill_percentage() gives 0 to 100.
Positions#
Position has symbol, exchange, side (PositionSide::Long/Short), entry_price, amount, mark_price, liquidation_price, leverage, margin_mode (Cross default, or Isolated), unrealized_pnl, realized_pnl, margin and is_open. Helpers: notional_value(), calculate_pnl(price), pnl_percentage(price) (multiplied by leverage).
Events and test results#
OrderUpdateEvent: exchange, order ids, status, side, type, price, quantity,filled_quantity,avg_fill_price,fee,fee_currency,exchange_timestamp,received_at,raw. Methods:latency_ms()(received minus exchange time),is_filled(),remaining_quantity(),fill_percentage().TradeEvent: symbol,trade_id, price, quantity, side string, timestamp.is_buy()matches onlybuy, case-insensitive.value()is price times quantity.WsTestResult:connected,latency_ms,messages_received,subscription_type,data_sample.OrderTestResult:valid,order_type,side,symbol,quantity,price,estimated_cost,error.
Capabilities#
CapabilityStatus is Supported, Emulated, NotSupported or Unknown (the default). ExchangeCapabilities has one such field per feature: market kinds, order kinds, order management, positions, market data, WebSocket streams and account functions. supported_count() counts Supported and Emulated; is_supported("name") looks a field up by name. See Capabilities.