use crate::{
protocol::ws::Timestamp,
types::trading::{Candle, CandleWidth},
InstrumentState,
};
use enumflags2::bitflags;
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "lowercase")]
pub enum MarketdataRequest<'a> {
Subscribe {
symbol: &'a str,
level: SubscriptionLevel,
},
Unsubscribe { symbol: &'a str },
#[serde(rename = "subscribe_candles")]
SubscribeCandles { symbol: &'a str, width: CandleWidth },
#[serde(rename = "unsubscribe_candles")]
UnsubscribeCandles { symbol: &'a str, width: CandleWidth },
}
#[bitflags]
#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum SubscriptionLevel {
#[serde(rename = "LEVEL_1")]
Level1 = 0b001,
#[serde(rename = "LEVEL_2")]
Level2 = 0b010,
#[serde(rename = "LEVEL_3")]
Level3 = 0b100,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "t")]
pub enum MarketdataEvent {
#[serde(rename = "h")]
Heartbeat(Timestamp),
#[serde(rename = "s")]
Ticker(Ticker),
#[serde(rename = "1")]
L1BookUpdate(L1BookUpdate),
#[serde(rename = "2")]
L2BookUpdate(L2BookUpdate),
#[serde(rename = "3")]
L3BookUpdate(L3BookUpdate),
#[serde(rename = "t")]
Trade(Trade),
#[serde(rename = "c")]
Candle(Candle),
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub struct Ticker {
#[serde(flatten)]
pub timestamp: Timestamp,
#[serde(rename = "s")]
pub symbol: String,
#[serde(rename = "p")]
pub last_trade_price: Option<Decimal>,
#[serde(rename = "q")]
pub last_trade_quantity: i32,
#[serde(rename = "o")]
pub session_open_price: Option<Decimal>,
#[serde(rename = "l")]
pub session_low_price: Option<Decimal>,
#[serde(rename = "h")]
pub session_high_price: Option<Decimal>,
#[serde(rename = "v")]
pub total_volume: i32,
#[serde(rename = "oi")]
pub open_interest: u32,
#[serde(rename = "i")]
#[serde(default)]
pub instrument_state: InstrumentState,
}
pub type L1BookUpdate = L2BookUpdate;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct L2BookUpdate {
#[serde(flatten)]
pub timestamp: Timestamp,
#[serde(rename = "s")]
pub symbol: String,
#[serde(rename = "b")]
pub bids: Vec<L2BookLevel>,
#[serde(rename = "a")]
pub asks: Vec<L2BookLevel>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct L2BookLevel {
#[serde(rename = "p")]
pub price: Decimal,
#[serde(rename = "q")]
pub quantity: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct L3BookUpdate {
#[serde(flatten)]
pub timestamp: Timestamp,
#[serde(rename = "s")]
pub symbol: String,
#[serde(rename = "b")]
pub bids: Vec<L3BookLevel>,
#[serde(rename = "a")]
pub asks: Vec<L3BookLevel>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct L3BookLevel {
#[serde(rename = "p")]
pub price: Decimal,
#[serde(rename = "q")]
pub quantity: i32,
#[serde(rename = "o")]
pub order_quantities: Vec<i32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Trade {
#[serde(rename = "p")]
pub price: Decimal,
#[serde(rename = "q")]
pub quantity: i32,
#[serde(rename = "s")]
pub symbol: String,
#[serde(rename = "d")]
pub taker_side: crate::types::trading::Side,
#[serde(flatten)]
pub timestamp: Timestamp,
}