rustrade_data/exchange/bitfinex/
trade.rs1use crate::{
2 event::{MarketEvent, MarketIter},
3 subscription::trade::PublicTrade,
4};
5use chrono::{DateTime, Utc};
6use rustrade_instrument::{Side, exchange::ExchangeId};
7use rustrade_integration::serde::de::{datetime_utc_from_epoch_duration, extract_next};
8use serde::Serialize;
9use smol_str::format_smolstr;
10
11#[derive(Clone, Copy, PartialEq, PartialOrd, Debug, Serialize)]
38pub struct BitfinexTrade {
39 pub id: u64,
40 pub time: DateTime<Utc>,
41 pub side: Side,
42 pub price: f64,
43 pub amount: f64,
44}
45
46impl<InstrumentKey> From<(ExchangeId, InstrumentKey, BitfinexTrade)>
47 for MarketIter<InstrumentKey, PublicTrade>
48{
49 fn from((exchange_id, instrument, trade): (ExchangeId, InstrumentKey, BitfinexTrade)) -> Self {
50 Self(vec![Ok(MarketEvent {
51 time_exchange: trade.time,
52 time_received: Utc::now(),
53 exchange: exchange_id,
54 instrument,
55 kind: PublicTrade {
56 id: format_smolstr!("{}", trade.id),
57 price: trade.price,
58 amount: trade.amount,
59 side: trade.side,
60 },
61 })])
62 }
63}
64
65impl<'de> serde::Deserialize<'de> for BitfinexTrade {
66 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
67 where
68 D: serde::de::Deserializer<'de>,
69 {
70 struct SeqVisitor;
71
72 impl<'de> serde::de::Visitor<'de> for SeqVisitor {
73 type Value = BitfinexTrade;
74
75 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76 formatter.write_str("BitfinexTrade struct from the Bitfinex WebSocket API")
77 }
78
79 fn visit_seq<SeqAccessor>(
80 self,
81 mut seq: SeqAccessor,
82 ) -> Result<Self::Value, SeqAccessor::Error>
83 where
84 SeqAccessor: serde::de::SeqAccess<'de>,
85 {
86 let id = extract_next(&mut seq, "id")?;
88 let time_millis = extract_next(&mut seq, "time")?;
89 let amount: f64 = extract_next(&mut seq, "amount")?;
90 let price = extract_next(&mut seq, "price")?;
91 let side = match amount.is_sign_positive() {
92 true => Side::Buy,
93 false => Side::Sell,
94 };
95
96 while seq.next_element::<serde::de::IgnoredAny>()?.is_some() {}
99
100 Ok(BitfinexTrade {
101 id,
102 time: datetime_utc_from_epoch_duration(std::time::Duration::from_millis(
103 time_millis,
104 )),
105 price,
106 amount: amount.abs(),
107 side,
108 })
109 }
110 }
111
112 deserializer.deserialize_seq(SeqVisitor)
114 }
115}