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(contract) => {
61                format_smolstr!(
62                    "{base}_{quote}_QUARTERLY_{}",
63                    format_expiry(contract.expiry)
64                )
65            }
66            Option(contract) => format_smolstr!(
67                "{base}_{quote}-{}-{}-{}",
68                format_expiry(contract.expiry),
69                contract.strike,
70                match contract.kind {
71                    OptionKind::Call => "C",
72                    OptionKind::Put => "P",
73                },
74            ),
75        }
76        .to_uppercase_smolstr(),
77    )
78}
79
80/// Format the expiry DateTime<Utc> to be Gateio API compatible.
81///
82/// eg/ "20241231" (31st of December 2024)
83///
84/// See docs: <https://www.gate.io/docs/developers/options/ws/en/#public-contract-trades-channel>
85fn format_expiry<'a>(expiry: DateTime<Utc>) -> DelayedFormat<StrftimeItems<'a>> {
86    expiry.date_naive().format("%Y%m%d")
87}