binance/futures/
rest_model.rs

1use crate::rest_model::{string_or_bool, string_or_float_opt};
2pub use crate::rest_model::{string_or_float, string_or_u64, Asks, Bids, BookTickers, KlineSummaries, KlineSummary,
3                            OrderSide, OrderStatus, RateLimit, ServerTime, SymbolPrice, SymbolStatus, Tickers,
4                            TimeInForce};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Serialize, Deserialize, Clone)]
8#[serde(rename_all = "camelCase")]
9pub struct ExchangeInformation {
10    pub timezone: String,
11    pub server_time: u64,
12    pub futures_type: String,
13    pub rate_limits: Vec<RateLimit>,
14    pub exchange_filters: Vec<Filters>,
15    pub assets: Vec<AssetDetail>,
16    pub symbols: Vec<Symbol>,
17}
18
19#[derive(Debug, Serialize, Deserialize, Clone)]
20#[serde(rename_all = "camelCase")]
21pub struct AssetDetail {
22    pub asset: String,
23    pub margin_available: bool,
24    #[serde(with = "string_or_float")]
25    pub auto_asset_exchange: f64,
26}
27
28#[derive(Debug, Serialize, Deserialize, Clone)]
29#[serde(rename_all = "camelCase")]
30pub struct Symbol {
31    pub symbol: String,
32    pub pair: String,
33    pub contract_type: ContractType,
34    pub delivery_date: u64,
35    pub onboard_date: u64,
36    pub status: SymbolStatus,
37    #[serde(with = "string_or_float")]
38    pub maint_margin_percent: f64,
39    #[serde(with = "string_or_float")]
40    pub required_margin_percent: f64,
41    pub base_asset: String,
42    pub quote_asset: String,
43    pub price_precision: u16,
44    pub quantity_precision: u16,
45    pub base_asset_precision: u64,
46    pub quote_precision: u64,
47    pub underlying_type: String,
48    pub underlying_sub_type: Vec<String>,
49    pub settle_plan: u64,
50    #[serde(with = "string_or_float")]
51    pub trigger_protect: f64,
52    pub filters: Vec<Filters>,
53    pub order_types: Vec<OrderType>,
54    pub time_in_force: Vec<TimeInForce>,
55}
56
57#[derive(Debug, Deserialize, Serialize, Clone)]
58#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
59pub enum ContractType {
60    Perpetual,
61    CurrentMonth,
62    NextMonth,
63    CurrentQuarter,
64    NextQuarter,
65    #[serde(rename = "CURRENT_QUARTER DELIVERING")]
66    CurrentQuarterDelivery,
67    PerpetualDelivering,
68    #[serde(rename = "")]
69    Empty,
70}
71
72#[derive(Debug, Deserialize, Serialize, Clone)]
73#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
74pub enum OrderType {
75    Limit,
76    Market,
77    Stop,
78    StopMarket,
79    TakeProfit,
80    TakeProfitMarket,
81    TrailingStopMarket,
82}
83
84/// By default, use market orders
85impl Default for OrderType {
86    fn default() -> Self { Self::Market }
87}
88
89#[derive(Debug, Deserialize, Serialize, Clone)]
90#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
91pub enum PositionSide {
92    Both,
93    Long,
94    Short,
95}
96
97#[derive(Debug, Deserialize, Serialize, Clone)]
98#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
99pub enum WorkingType {
100    MarkPrice,
101    ContractPrice,
102}
103
104#[derive(Debug, Deserialize, Serialize, Clone)]
105#[serde(rename_all = "lowercase")]
106pub enum MarginType {
107    Isolated,
108    Cross,
109}
110
111#[derive(Debug, Serialize, Deserialize, Clone)]
112#[serde(tag = "filterType")]
113pub enum Filters {
114    #[serde(rename = "PRICE_FILTER")]
115    #[serde(rename_all = "camelCase")]
116    PriceFilter {
117        #[serde(with = "string_or_float")]
118        min_price: f64,
119        #[serde(with = "string_or_float")]
120        max_price: f64,
121        #[serde(with = "string_or_float")]
122        tick_size: f64,
123    },
124    #[serde(rename = "LOT_SIZE")]
125    #[serde(rename_all = "camelCase")]
126    LotSize {
127        #[serde(with = "string_or_float")]
128        min_qty: f64,
129        #[serde(with = "string_or_float")]
130        max_qty: f64,
131        #[serde(with = "string_or_float")]
132        step_size: f64,
133    },
134    #[serde(rename = "MARKET_LOT_SIZE")]
135    #[serde(rename_all = "camelCase")]
136    MarketLotSize {
137        min_qty: String,
138        max_qty: String,
139        step_size: String,
140    },
141    #[serde(rename = "MAX_NUM_ORDERS")]
142    #[serde(rename_all = "camelCase")]
143    MaxNumOrders { limit: u16 },
144    #[serde(rename = "MAX_NUM_ALGO_ORDERS")]
145    #[serde(rename_all = "camelCase")]
146    MaxNumAlgoOrders { limit: u16 },
147    #[serde(rename = "MIN_NOTIONAL")]
148    #[serde(rename_all = "camelCase")]
149    MinNotional {
150        #[serde(with = "string_or_float")]
151        notional: f64,
152    },
153    #[serde(rename = "PERCENT_PRICE")]
154    #[serde(rename_all = "camelCase")]
155    PercentPrice {
156        #[serde(with = "string_or_float")]
157        multiplier_up: f64,
158        #[serde(with = "string_or_float")]
159        multiplier_down: f64,
160        #[serde(with = "string_or_float")]
161        multiplier_decimal: f64,
162    },
163    #[serde(other)]
164    Others,
165}
166
167#[derive(Debug, Serialize, Deserialize, Clone)]
168#[serde(rename_all = "camelCase")]
169pub struct OrderBook {
170    pub last_update_id: u64,
171    // Undocumented
172    #[serde(rename = "E")]
173    pub event_time: u64,
174    // Undocumented
175    #[serde(rename = "T")]
176    pub trade_order_time: u64,
177    pub bids: Vec<Bids>,
178    pub asks: Vec<Asks>,
179}
180
181#[derive(Debug, Serialize, Deserialize, Clone)]
182#[serde(rename_all = "camelCase")]
183pub struct PriceStats {
184    pub symbol: String,
185    pub price_change: String,
186    pub price_change_percent: String,
187    pub weighted_avg_price: String,
188    #[serde(with = "string_or_float")]
189    pub last_price: f64,
190    #[serde(with = "string_or_float")]
191    pub open_price: f64,
192    #[serde(with = "string_or_float")]
193    pub high_price: f64,
194    #[serde(with = "string_or_float")]
195    pub low_price: f64,
196    #[serde(with = "string_or_float")]
197    pub volume: f64,
198    #[serde(with = "string_or_float")]
199    pub quote_volume: f64,
200    #[serde(with = "string_or_float")]
201    pub last_qty: f64,
202    pub open_time: u64,
203    pub close_time: u64,
204    pub first_id: u64,
205    pub last_id: u64,
206    pub count: u64,
207}
208
209#[derive(Debug, Serialize, Deserialize, Clone)]
210#[serde(untagged)]
211pub enum Trades {
212    AllTrades(Vec<Trade>),
213}
214
215#[derive(Debug, Serialize, Deserialize, Clone)]
216#[serde(rename_all = "camelCase")]
217pub struct Trade {
218    pub id: u64,
219    pub is_buyer_maker: bool,
220    #[serde(with = "string_or_float")]
221    pub price: f64,
222    #[serde(with = "string_or_float")]
223    pub qty: f64,
224    #[serde(with = "string_or_float")]
225    pub quote_qty: f64,
226    pub time: u64,
227}
228
229#[derive(Debug, Serialize, Deserialize, Clone)]
230#[serde(untagged)]
231pub enum AggTrades {
232    AllAggTrades(Vec<AggTrade>),
233}
234
235#[derive(Debug, Serialize, Deserialize, Clone)]
236#[serde(rename_all = "camelCase")]
237pub struct AggTrade {
238    #[serde(rename = "T")]
239    pub time: u64,
240    #[serde(rename = "a")]
241    pub agg_id: u64,
242    #[serde(rename = "f")]
243    pub first_id: u64,
244    #[serde(rename = "l")]
245    pub last_id: u64,
246    #[serde(rename = "m")]
247    pub maker: bool,
248    #[serde(rename = "p", with = "string_or_float")]
249    pub price: f64,
250    #[serde(rename = "q", with = "string_or_float")]
251    pub qty: f64,
252}
253
254// #[derive(Debug, Serialize, Deserialize, Clone)]
255// #[serde(untagged)]
256// pub enum MarkPrices {
257//     AllMarkPrices(Vec<MarkPrice>),
258// }
259
260#[derive(Debug, Serialize, Deserialize, Clone)]
261#[serde(rename_all = "camelCase")]
262pub struct MarkPrice {
263    pub symbol: String,
264    #[serde(with = "string_or_float")]
265    pub mark_price: f64,
266    #[serde(with = "string_or_float")]
267    pub index_price: f64,
268    #[serde(with = "string_or_float")]
269    pub estimated_settle_price: f64,
270    #[serde(with = "string_or_float")]
271    pub last_funding_rate: f64,
272    pub next_funding_time: u64,
273    #[serde(with = "string_or_float")]
274    pub interest_rate: f64,
275    pub time: u64,
276}
277
278#[derive(Debug, Serialize, Deserialize, Clone)]
279#[serde(untagged)]
280pub enum LiquidationOrders {
281    AllLiquidationOrders(Vec<LiquidationOrder>),
282}
283
284#[derive(Debug, Serialize, Deserialize, Clone)]
285#[serde(rename_all = "camelCase")]
286pub struct LiquidationOrder {
287    #[serde(with = "string_or_float")]
288    pub average_price: f64,
289    #[serde(with = "string_or_float")]
290    pub executed_qty: f64,
291    #[serde(with = "string_or_float")]
292    pub orig_qty: f64,
293    #[serde(with = "string_or_float")]
294    pub price: f64,
295    pub side: String,
296    pub status: String,
297    pub symbol: String,
298    pub time: u64,
299    pub time_in_force: String,
300    pub r#type: String,
301}
302
303#[derive(Debug, Serialize, Deserialize, Clone)]
304#[serde(rename_all = "camelCase")]
305pub struct OpenInterest {
306    #[serde(with = "string_or_float")]
307    pub open_interest: f64,
308    pub symbol: String,
309}
310
311#[derive(Debug, Deserialize, Clone)]
312#[serde(rename_all = "camelCase")]
313pub struct Order {
314    pub client_order_id: String,
315    #[serde(with = "string_or_float")]
316    pub cum_quote: f64,
317    #[serde(with = "string_or_float")]
318    pub executed_qty: f64,
319    pub order_id: u64,
320    #[serde(with = "string_or_float")]
321    pub avg_price: f64,
322    #[serde(with = "string_or_float")]
323    pub orig_qty: f64,
324    #[serde(with = "string_or_float")]
325    pub price: f64,
326    pub side: OrderSide,
327    pub reduce_only: bool,
328    pub position_side: PositionSide,
329    pub status: OrderStatus,
330    #[serde(with = "string_or_float", default = "default_stop_price")]
331    pub stop_price: f64,
332    pub close_position: bool,
333    pub symbol: String,
334    pub time_in_force: TimeInForce,
335    #[serde(rename = "type")]
336    pub order_type: OrderType,
337    pub orig_type: OrderType,
338    #[serde(with = "string_or_float", default = "default_activation_price")]
339    pub activate_price: f64,
340    #[serde(with = "string_or_float", default = "default_price_rate")]
341    pub price_rate: f64,
342    pub update_time: u64,
343    pub working_type: WorkingType,
344    pub price_protect: bool,
345}
346
347#[derive(Debug, Serialize, Deserialize, Clone)]
348#[serde(rename_all = "camelCase")]
349pub struct Transaction {
350    pub client_order_id: String,
351    #[serde(with = "string_or_float")]
352    pub cum_qty: f64,
353    #[serde(with = "string_or_float")]
354    pub cum_quote: f64,
355    #[serde(with = "string_or_float")]
356    pub executed_qty: f64,
357    pub order_id: u64,
358    #[serde(with = "string_or_float")]
359    pub avg_price: f64,
360    #[serde(with = "string_or_float")]
361    pub orig_qty: f64,
362    pub reduce_only: bool,
363    pub side: OrderSide,
364    pub position_side: PositionSide,
365    pub status: OrderStatus,
366    #[serde(with = "string_or_float")]
367    pub stop_price: f64,
368    pub close_position: bool,
369    pub symbol: String,
370    pub time_in_force: TimeInForce,
371    #[serde(rename = "type")]
372    pub type_name: OrderType,
373    pub orig_type: OrderType,
374    #[serde(default)]
375    #[serde(with = "string_or_float_opt")]
376    pub activate_price: Option<f64>,
377    #[serde(default)]
378    #[serde(with = "string_or_float_opt")]
379    pub price_rate: Option<f64>,
380    pub update_time: u64,
381    pub working_type: WorkingType,
382    price_protect: bool,
383}
384
385#[derive(Debug, Serialize, Deserialize, Clone)]
386#[serde(rename_all = "camelCase")]
387pub struct CanceledOrder {
388    pub client_order_id: String,
389    #[serde(with = "string_or_float")]
390    pub cum_qty: f64,
391    #[serde(with = "string_or_float")]
392    pub cum_quote: f64,
393    #[serde(with = "string_or_float")]
394    pub executed_qty: f64,
395    pub order_id: u64,
396    #[serde(with = "string_or_float")]
397    pub orig_qty: f64,
398    pub orig_type: String,
399    #[serde(with = "string_or_float")]
400    pub price: f64,
401    pub reduce_only: bool,
402    pub side: String,
403    pub position_side: String,
404    pub status: String,
405    #[serde(with = "string_or_float")]
406    pub stop_price: f64,
407    pub close_position: bool,
408    pub symbol: String,
409    pub time_in_force: String,
410    #[serde(rename = "type")]
411    pub type_name: String,
412    #[serde(default)]
413    #[serde(with = "string_or_float_opt")]
414    pub activate_price: Option<f64>,
415    #[serde(default)]
416    #[serde(with = "string_or_float_opt")]
417    pub price_rate: Option<f64>,
418    pub update_time: u64,
419    pub working_type: String,
420    price_protect: bool,
421}
422
423#[derive(Debug, Serialize, Deserialize, Clone)]
424#[serde(rename_all = "camelCase")]
425pub struct Position {
426    #[serde(with = "string_or_float")]
427    pub entry_price: f64,
428    pub margin_type: MarginType,
429    #[serde(with = "string_or_bool")]
430    pub is_auto_add_margin: bool,
431    #[serde(with = "string_or_float")]
432    pub isolated_margin: f64,
433    #[serde(with = "string_or_u64")]
434    pub leverage: u64,
435    #[serde(with = "string_or_float")]
436    pub liquidation_price: f64,
437    #[serde(with = "string_or_float")]
438    pub mark_price: f64,
439    #[serde(with = "string_or_float")]
440    pub max_notional_value: f64,
441    #[serde(with = "string_or_float", rename = "positionAmt")]
442    pub position_amount: f64,
443    pub symbol: String,
444    #[serde(with = "string_or_float", rename = "unRealizedProfit")]
445    pub unrealized_profit: f64,
446    pub position_side: PositionSide,
447    pub update_time: u64,
448    #[serde(with = "string_or_float")]
449    pub notional: f64,
450    #[serde(with = "string_or_float")]
451    pub isolated_wallet: f64,
452}
453
454// https://binance-docs.github.io/apidocs/futures/en/#account-information-v2-user_data
455// it has differences from Position returned by positionRisk endpoint
456#[derive(Debug, Serialize, Deserialize, Clone)]
457#[serde(rename_all = "camelCase")]
458pub struct AccountPosition {
459    pub symbol: String,
460    #[serde(with = "string_or_float")]
461    pub initial_margin: f64,
462    #[serde(with = "string_or_float", rename = "maintMargin")]
463    pub maintenance_margin: f64,
464    #[serde(with = "string_or_float")]
465    pub unrealized_profit: f64,
466    #[serde(with = "string_or_float")]
467    pub position_initial_margin: f64,
468    #[serde(with = "string_or_float")]
469    pub open_order_initial_margin: f64,
470    #[serde(with = "string_or_u64")]
471    pub leverage: u64,
472    pub isolated: bool,
473    #[serde(with = "string_or_float")]
474    pub entry_price: f64,
475    #[serde(with = "string_or_float")]
476    pub max_notional: f64,
477    #[serde(with = "string_or_float")]
478    pub bid_notional: f64,
479    #[serde(with = "string_or_float")]
480    pub ask_notional: f64,
481    pub position_side: PositionSide,
482    #[serde(with = "string_or_float", rename = "positionAmt")]
483    pub position_amount: f64,
484    pub update_time: u64,
485}
486
487#[derive(Debug, Serialize, Deserialize, Clone)]
488#[serde(rename_all = "camelCase")]
489pub struct AccountAsset {
490    pub asset: String,
491    #[serde(with = "string_or_float")]
492    pub wallet_balance: f64,
493    #[serde(with = "string_or_float")]
494    pub unrealized_profit: f64,
495    #[serde(with = "string_or_float")]
496    pub margin_balance: f64,
497    #[serde(with = "string_or_float")]
498    pub maint_margin: f64,
499    #[serde(with = "string_or_float")]
500    pub initial_margin: f64,
501    #[serde(with = "string_or_float")]
502    pub position_initial_margin: f64,
503    #[serde(with = "string_or_float")]
504    pub open_order_initial_margin: f64,
505    #[serde(with = "string_or_float")]
506    pub cross_wallet_balance: f64,
507    #[serde(with = "string_or_float", rename = "crossUnPnl")]
508    pub cross_unrealized_pnl: f64,
509    #[serde(with = "string_or_float")]
510    pub available_balance: f64,
511    #[serde(with = "string_or_float")]
512    pub max_withdraw_amount: f64,
513    pub margin_available: bool,
514    pub update_time: u64,
515}
516
517#[derive(Debug, Serialize, Deserialize, Clone)]
518#[serde(rename_all = "camelCase")]
519pub struct AccountInformation {
520    pub fee_tier: u64,
521    pub can_trade: bool,
522    pub can_deposit: bool,
523    pub can_withdraw: bool,
524    pub update_time: u64,
525    pub multi_assets_margin: bool,
526    #[serde(with = "string_or_float")]
527    pub total_initial_margin: f64,
528    #[serde(with = "string_or_float", rename = "totalMaintMargin")]
529    pub total_maintenance_margin: f64,
530    #[serde(with = "string_or_float")]
531    pub total_wallet_balance: f64,
532    #[serde(with = "string_or_float")]
533    pub total_unrealized_profit: f64,
534    #[serde(with = "string_or_float")]
535    pub total_margin_balance: f64,
536    #[serde(with = "string_or_float")]
537    pub total_position_initial_margin: f64,
538    #[serde(with = "string_or_float")]
539    pub total_open_order_initial_margin: f64,
540    #[serde(with = "string_or_float")]
541    pub total_cross_wallet_balance: f64,
542    #[serde(with = "string_or_float", rename = "totalCrossUnPnl")]
543    pub total_cross_unrealized_pnl: f64,
544    #[serde(with = "string_or_float")]
545    pub available_balance: f64,
546    #[serde(with = "string_or_float")]
547    pub max_withdraw_amount: f64,
548    pub assets: Vec<AccountAsset>,
549    pub positions: Vec<AccountPosition>,
550}
551
552#[derive(Debug, Serialize, Deserialize, Clone)]
553#[serde(rename_all = "camelCase")]
554pub struct AccountBalance {
555    pub account_alias: String,
556    pub asset: String,
557    #[serde(with = "string_or_float")]
558    pub balance: f64,
559    #[serde(with = "string_or_float")]
560    pub cross_wallet_balance: f64,
561    #[serde(with = "string_or_float", rename = "crossUnPnl")]
562    pub cross_unrealized_pnl: f64,
563    #[serde(with = "string_or_float")]
564    pub available_balance: f64,
565    #[serde(with = "string_or_float")]
566    pub max_withdraw_amount: f64,
567    pub margin_available: bool,
568    pub update_time: u64,
569}
570
571#[derive(Debug, Serialize, Deserialize, Clone)]
572#[serde(rename_all = "camelCase")]
573pub struct ChangeLeverageResponse {
574    pub leverage: u8,
575    #[serde(with = "string_or_float")]
576    pub max_notional_value: f64,
577    pub symbol: String,
578}
579
580fn default_stop_price() -> f64 { 0.0 }
581fn default_activation_price() -> f64 { 0.0 }
582fn default_price_rate() -> f64 { 0.0 }
583
584#[derive(Serialize)]
585#[serde(rename_all = "camelCase")]
586pub(crate) struct HistoryQuery {
587    pub start_time: Option<u64>,
588    pub end_time: Option<u64>,
589    pub from_id: Option<u64>,
590    pub limit: u16,
591    pub symbol: String,
592    pub interval: Option<String>,
593    pub period: Option<String>,
594}
595
596impl HistoryQuery {
597    pub fn validate(&self) -> crate::errors::Result<()> {
598        if let Some(period) = &self.period {
599            if !PERIODS.contains(&period.as_str()) {
600                return Err(crate::errors::Error::InvalidPeriod(period.clone()));
601            }
602        }
603        Ok(())
604    }
605}
606
607#[derive(Serialize)]
608#[serde(rename_all = "camelCase")]
609pub(crate) struct IndexQuery {
610    pub start_time: Option<u64>,
611    pub end_time: Option<u64>,
612    pub limit: u16,
613    pub pair: String,
614    pub interval: Option<String>,
615}
616
617#[derive(Deserialize, Debug, Clone)]
618#[serde(rename_all = "camelCase")]
619pub struct FundingRate {
620    pub symbol: String,
621    pub funding_time: u64,
622    #[serde(with = "string_or_float")]
623    pub funding_rate: f64,
624}
625
626pub static PERIODS: &[&str] = &["5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d"];
627
628#[derive(Deserialize)]
629#[serde(rename_all = "camelCase")]
630pub struct OpenInterestHistory {
631    pub symbol: String,
632    #[serde(with = "string_or_float")]
633    pub sum_open_interest: f64,
634    #[serde(with = "string_or_float")]
635    pub sum_open_interest_value: f64,
636    pub timestamp: u64,
637}
638
639#[derive(Deserialize)]
640#[serde(rename_all = "camelCase")]
641pub struct LongShortRatio {
642    pub symbol: String,
643    #[serde(with = "string_or_float")]
644    pub long_account: f64,
645    #[serde(with = "string_or_float")]
646    pub long_short_ratio: f64,
647    #[serde(with = "string_or_float")]
648    pub short_account: f64,
649    pub timestamp: u64,
650}
651
652#[derive(Deserialize)]
653#[serde(rename_all = "camelCase")]
654pub struct LeverageBracket {
655    pub bracket: u8,
656    pub initial_leverage: u8,
657    pub notional_cap: u64,
658    pub notional_floor: u64,
659    pub maint_margin_ratio: f64,
660    pub cum: f64,
661}
662
663#[derive(Deserialize)]
664#[serde(rename_all = "camelCase")]
665pub struct SymbolBrackets {
666    pub symbol: String,
667    pub notional_coef: Option<f64>,
668    pub brackets: Vec<LeverageBracket>,
669}