rustrade_data/exchange/binance/futures/
liquidation.rs1use super::super::BinanceChannel;
2use crate::{
3 Identifier,
4 event::{MarketEvent, MarketIter},
5 subscription::liquidation::Liquidation,
6};
7use chrono::{DateTime, Utc};
8use rustrade_instrument::{Side, exchange::ExchangeId};
9use rustrade_integration::subscription::SubscriptionId;
10use serde::{Deserialize, Serialize};
11
12#[derive(Clone, PartialEq, PartialOrd, Debug, Deserialize, Serialize)]
36pub struct BinanceLiquidation {
37 #[serde(alias = "o")]
38 pub order: BinanceLiquidationOrder,
39}
40
41#[derive(Clone, PartialEq, PartialOrd, Debug, Deserialize, Serialize)]
62pub struct BinanceLiquidationOrder {
63 #[serde(alias = "s", deserialize_with = "de_liquidation_subscription_id")]
64 pub subscription_id: SubscriptionId,
65 #[serde(alias = "S")]
66 pub side: Side,
67 #[serde(
68 alias = "p",
69 deserialize_with = "rustrade_integration::serde::de::de_str"
70 )]
71 pub price: f64,
72 #[serde(
73 alias = "q",
74 deserialize_with = "rustrade_integration::serde::de::de_str"
75 )]
76 pub quantity: f64,
77 #[serde(
78 alias = "T",
79 deserialize_with = "rustrade_integration::serde::de::de_u64_epoch_ms_as_datetime_utc"
80 )]
81 pub time: DateTime<Utc>,
82}
83
84impl Identifier<Option<SubscriptionId>> for BinanceLiquidation {
85 fn id(&self) -> Option<SubscriptionId> {
86 Some(self.order.subscription_id.clone())
87 }
88}
89
90impl<InstrumentKey> From<(ExchangeId, InstrumentKey, BinanceLiquidation)>
91 for MarketIter<InstrumentKey, Liquidation>
92{
93 fn from(
94 (exchange_id, instrument, liquidation): (ExchangeId, InstrumentKey, BinanceLiquidation),
95 ) -> Self {
96 Self(vec![Ok(MarketEvent {
97 time_exchange: liquidation.order.time,
98 time_received: Utc::now(),
99 exchange: exchange_id,
100 instrument,
101 kind: Liquidation {
102 side: liquidation.order.side,
103 price: liquidation.order.price,
104 quantity: liquidation.order.quantity,
105 time: liquidation.order.time,
106 },
107 })])
108 }
109}
110
111pub fn de_liquidation_subscription_id<'de, D>(deserializer: D) -> Result<SubscriptionId, D::Error>
116where
117 D: serde::de::Deserializer<'de>,
118{
119 Deserialize::deserialize(deserializer).map(|market: String| {
120 SubscriptionId::from(format!("{}|{}", BinanceChannel::LIQUIDATIONS.0, market))
121 })
122}
123
124#[cfg(test)]
125#[allow(clippy::unwrap_used)] mod tests {
127 use super::*;
128
129 mod de {
130 use super::*;
131 use rustrade_integration::serde::de::datetime_utc_from_epoch_duration;
132 use std::time::Duration;
133
134 #[test]
135 fn test_binance_liquidation() {
136 let input = r#"
137 {
138 "e": "forceOrder",
139 "E": 1665523974222,
140 "o": {
141 "s": "BTCUSDT",
142 "S": "SELL",
143 "o": "LIMIT",
144 "f": "IOC",
145 "q": "0.009",
146 "p": "18917.15",
147 "ap": "18990.00",
148 "X": "FILLED",
149 "l": "0.009",
150 "z": "0.009",
151 "T": 1665523974217
152 }
153 }
154 "#;
155
156 assert_eq!(
157 serde_json::from_str::<BinanceLiquidation>(input).unwrap(),
158 BinanceLiquidation {
159 order: BinanceLiquidationOrder {
160 subscription_id: SubscriptionId::from("@forceOrder|BTCUSDT"),
161 side: Side::Sell,
162 price: 18917.15,
163 quantity: 0.009,
164 time: datetime_utc_from_epoch_duration(Duration::from_millis(
165 1665523974217,
166 )),
167 },
168 }
169 );
170 }
171 }
172}