barter_data/exchange/gateio/
market.rs

1use super::Gateio;
2use crate::{Identifier, instrument::MarketInstrumentData, subscription::Subscription};
3use barter_instrument::{
4    Keyed,
5    instrument::{
6        kind::option::OptionKind,
7        market_data::{MarketDataInstrument, kind::MarketDataInstrumentKind::*},
8    },
9};
10use chrono::{
11    DateTime, Utc,
12    format::{DelayedFormat, StrftimeItems},
13};
14use serde::{Deserialize, Serialize};
15use smol_str::{SmolStr, StrExt, format_smolstr};
16
17/// Type that defines how to translate a Barter [`Subscription`] into a
18/// [`Gateio`] market that can be subscribed to.
19///
20/// See docs: <https://www.okx.com/docs-v5/en/#websocket-api-public-channel>
21#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Deserialize, Serialize)]
22pub struct GateioMarket(pub SmolStr);
23
24impl<Server, Kind> Identifier<GateioMarket>
25    for Subscription<Gateio<Server>, MarketDataInstrument, Kind>
26{
27    fn id(&self) -> GateioMarket {
28        gateio_market(&self.instrument)
29    }
30}
31
32impl<Server, InstrumentKey, Kind> Identifier<GateioMarket>
33    for Subscription<Gateio<Server>, Keyed<InstrumentKey, MarketDataInstrument>, Kind>
34{
35    fn id(&self) -> GateioMarket {
36        gateio_market(&self.instrument.value)
37    }
38}
39
40impl<Server, InstrumentKey, Kind> Identifier<GateioMarket>
41    for Subscription<Gateio<Server>, MarketInstrumentData<InstrumentKey>, Kind>
42{
43    fn id(&self) -> GateioMarket {
44        GateioMarket(self.instrument.name_exchange.name().clone())
45    }
46}
47
48impl AsRef<str> for GateioMarket {
49    fn as_ref(&self) -> &str {
50        &self.0
51    }
52}
53
54fn gateio_market(instrument: &MarketDataInstrument) -> GateioMarket {
55    let MarketDataInstrument { base, quote, kind } = instrument;
56
57    GateioMarket(
58        match kind {
59            Spot | Perpetual => format_smolstr!("{base}_{quote}"),
60            Future(future) => {
61                format_smolstr!("{base}_{quote}_QUARTERLY_{}", format_expiry(future.expiry))
62            }
63            Option(option) => format_smolstr!(
64                "{base}_{quote}-{}-{}-{}",
65                format_expiry(option.expiry),
66                option.strike,
67                match option.kind {
68                    OptionKind::Call => "C",
69                    OptionKind::Put => "P",
70                },
71            ),
72        }
73        .to_uppercase_smolstr(),
74    )
75}
76
77/// Format the expiry DateTime<Utc> to be Gateio API compatible.
78///
79/// eg/ "20241231" (31st of December 2024)
80///
81/// See docs: <https://www.gate.io/docs/developers/options/ws/en/#public-contract-trades-channel>
82fn format_expiry<'a>(expiry: DateTime<Utc>) -> DelayedFormat<StrftimeItems<'a>> {
83    expiry.date_naive().format("%Y%m%d")
84}