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