use digdigdig3::core::types::{AccountType, ExchangeId};
use digdigdig3::core::websocket::KlineInterval;
use crate::data::{
AggTradePoint, AuctionEventPoint, BarPoint, BasisPoint, BlockTradePoint, CompositeIndexPoint,
FundingRatePoint, FundingSettlementPoint, HistoricalVolatilityPoint, IndexPriceKlinePoint,
IndexPricePoint, InsuranceFundPoint, LiquidationPoint, MarkPriceKlinePoint, MarkPricePoint,
MarketWarningPoint, ObSnapshotPoint, OpenInterestPoint, OptionGreeksPoint, OrderbookL3Point,
PredictedFundingPoint, PremiumIndexKlinePoint, RiskLimitPoint, SettlementEventPoint,
TickerPoint, TradePoint, VolatilityIndexPoint,
};
use crate::series::{Kind, SeriesKey};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Stream {
Ticker,
Trade,
Orderbook,
Kline(KlineInterval),
MarkPrice,
FundingRate,
OpenInterest,
Liquidation,
AggTrade,
BlockTrade,
IndexPrice,
CompositeIndex,
OptionGreeks,
VolatilityIndex,
HistoricalVolatility,
Basis,
InsuranceFund,
OrderbookL3,
SettlementEvent,
AuctionEvent,
MarketWarning,
RiskLimit,
PredictedFunding,
FundingSettlement,
MarkPriceKline(KlineInterval),
IndexPriceKline(KlineInterval),
PremiumIndexKline(KlineInterval),
}
impl Stream {
pub(crate) fn to_kind(&self) -> Kind {
match self {
Stream::Trade => Kind::Trade,
Stream::AggTrade => Kind::AggTrade,
Stream::Kline(iv) => Kind::Kline(iv.clone()),
Stream::Ticker => Kind::Ticker,
Stream::Orderbook => Kind::Orderbook,
Stream::MarkPrice => Kind::MarkPrice,
Stream::FundingRate => Kind::FundingRate,
Stream::OpenInterest => Kind::OpenInterest,
Stream::Liquidation => Kind::Liquidation,
Stream::BlockTrade => Kind::BlockTrade,
Stream::IndexPrice => Kind::IndexPrice,
Stream::CompositeIndex => Kind::CompositeIndex,
Stream::OptionGreeks => Kind::OptionGreeks,
Stream::VolatilityIndex => Kind::VolatilityIndex,
Stream::HistoricalVolatility => Kind::HistoricalVolatility,
Stream::Basis => Kind::Basis,
Stream::InsuranceFund => Kind::InsuranceFund,
Stream::OrderbookL3 => Kind::OrderbookL3,
Stream::SettlementEvent => Kind::SettlementEvent,
Stream::AuctionEvent => Kind::AuctionEvent,
Stream::MarketWarning => Kind::MarketWarning,
Stream::RiskLimit => Kind::RiskLimit,
Stream::PredictedFunding => Kind::PredictedFunding,
Stream::FundingSettlement => Kind::FundingSettlement,
Stream::MarkPriceKline(iv) => Kind::MarkPriceKline(iv.clone()),
Stream::IndexPriceKline(iv) => Kind::IndexPriceKline(iv.clone()),
Stream::PremiumIndexKline(iv) => Kind::PremiumIndexKline(iv.clone()),
}
}
}
#[derive(Debug, Clone)]
pub(crate) struct Entry {
pub(crate) exchange: ExchangeId,
pub(crate) symbol: String,
pub(crate) account_type: AccountType,
pub(crate) streams: Vec<Stream>,
pub(crate) is_raw: bool,
}
#[derive(Debug, Default, Clone)]
pub struct SubscriptionSet {
pub(crate) entries: Vec<Entry>,
}
impl SubscriptionSet {
pub fn new() -> Self { Self::default() }
pub fn add(
mut self,
exchange: ExchangeId,
symbol: impl Into<String>,
account_type: AccountType,
streams: impl IntoIterator<Item = Stream>,
) -> Self {
self.entries.push(Entry {
exchange,
symbol: symbol.into(),
account_type,
streams: streams.into_iter().collect(),
is_raw: false,
});
self
}
pub fn add_raw(
mut self,
exchange: ExchangeId,
symbol: impl Into<String>,
account_type: AccountType,
streams: impl IntoIterator<Item = Stream>,
) -> Self {
self.entries.push(Entry {
exchange,
symbol: symbol.into(),
account_type,
streams: streams.into_iter().collect(),
is_raw: true,
});
self
}
pub fn len(&self) -> usize { self.entries.len() }
pub fn is_empty(&self) -> bool { self.entries.is_empty() }
}
#[derive(Debug, Clone)]
pub enum Event {
Trade {
exchange: ExchangeId,
symbol: String,
point: TradePoint,
},
AggTrade {
exchange: ExchangeId,
symbol: String,
point: AggTradePoint,
},
Bar {
exchange: ExchangeId,
symbol: String,
timeframe: KlineInterval,
point: BarPoint,
},
Ticker {
exchange: ExchangeId,
symbol: String,
point: TickerPoint,
},
OrderbookSnapshot {
exchange: ExchangeId,
symbol: String,
point: ObSnapshotPoint,
},
MarkPrice {
exchange: ExchangeId,
symbol: String,
point: MarkPricePoint,
},
FundingRate {
exchange: ExchangeId,
symbol: String,
point: FundingRatePoint,
},
OpenInterest {
exchange: ExchangeId,
symbol: String,
point: OpenInterestPoint,
},
Liquidation {
exchange: ExchangeId,
symbol: String,
point: LiquidationPoint,
},
BlockTrade {
exchange: ExchangeId,
symbol: String,
point: BlockTradePoint,
},
IndexPrice {
exchange: ExchangeId,
symbol: String,
point: IndexPricePoint,
},
CompositeIndex {
exchange: ExchangeId,
symbol: String,
point: CompositeIndexPoint,
},
OptionGreeks {
exchange: ExchangeId,
symbol: String,
point: OptionGreeksPoint,
},
VolatilityIndex {
exchange: ExchangeId,
symbol: String,
point: VolatilityIndexPoint,
},
HistoricalVolatility {
exchange: ExchangeId,
symbol: String,
point: HistoricalVolatilityPoint,
},
Basis {
exchange: ExchangeId,
symbol: String,
point: BasisPoint,
},
InsuranceFund {
exchange: ExchangeId,
symbol: String,
point: InsuranceFundPoint,
},
OrderbookL3 {
exchange: ExchangeId,
symbol: String,
point: OrderbookL3Point,
},
SettlementEvent {
exchange: ExchangeId,
symbol: String,
point: SettlementEventPoint,
},
AuctionEvent {
exchange: ExchangeId,
symbol: String,
point: AuctionEventPoint,
},
MarketWarning {
exchange: ExchangeId,
symbol: String,
point: MarketWarningPoint,
},
RiskLimit {
exchange: ExchangeId,
symbol: String,
point: RiskLimitPoint,
},
PredictedFunding {
exchange: ExchangeId,
symbol: String,
point: PredictedFundingPoint,
},
FundingSettlement {
exchange: ExchangeId,
symbol: String,
point: FundingSettlementPoint,
},
MarkPriceKline {
exchange: ExchangeId,
symbol: String,
timeframe: KlineInterval,
point: MarkPriceKlinePoint,
},
IndexPriceKline {
exchange: ExchangeId,
symbol: String,
timeframe: KlineInterval,
point: IndexPriceKlinePoint,
},
PremiumIndexKline {
exchange: ExchangeId,
symbol: String,
timeframe: KlineInterval,
point: PremiumIndexKlinePoint,
},
}
impl Event {
pub fn exchange(&self) -> ExchangeId {
match self {
Event::Trade { exchange, .. } | Event::AggTrade { exchange, .. } |
Event::Bar { exchange, .. } | Event::Ticker { exchange, .. } |
Event::OrderbookSnapshot { exchange, .. } | Event::MarkPrice { exchange, .. } |
Event::FundingRate { exchange, .. } | Event::OpenInterest { exchange, .. } |
Event::Liquidation { exchange, .. } |
Event::BlockTrade { exchange, .. } | Event::IndexPrice { exchange, .. } |
Event::CompositeIndex { exchange, .. } | Event::OptionGreeks { exchange, .. } |
Event::VolatilityIndex { exchange, .. } | Event::HistoricalVolatility { exchange, .. } |
Event::Basis { exchange, .. } | Event::InsuranceFund { exchange, .. } |
Event::OrderbookL3 { exchange, .. } | Event::SettlementEvent { exchange, .. } |
Event::AuctionEvent { exchange, .. } | Event::MarketWarning { exchange, .. } |
Event::RiskLimit { exchange, .. } | Event::PredictedFunding { exchange, .. } |
Event::FundingSettlement { exchange, .. } |
Event::MarkPriceKline { exchange, .. } | Event::IndexPriceKline { exchange, .. } |
Event::PremiumIndexKline { exchange, .. } => *exchange,
}
}
pub fn symbol(&self) -> &str {
match self {
Event::Trade { symbol, .. } | Event::AggTrade { symbol, .. } |
Event::Bar { symbol, .. } | Event::Ticker { symbol, .. } |
Event::OrderbookSnapshot { symbol, .. } | Event::MarkPrice { symbol, .. } |
Event::FundingRate { symbol, .. } | Event::OpenInterest { symbol, .. } |
Event::Liquidation { symbol, .. } |
Event::BlockTrade { symbol, .. } | Event::IndexPrice { symbol, .. } |
Event::CompositeIndex { symbol, .. } | Event::OptionGreeks { symbol, .. } |
Event::VolatilityIndex { symbol, .. } | Event::HistoricalVolatility { symbol, .. } |
Event::Basis { symbol, .. } | Event::InsuranceFund { symbol, .. } |
Event::OrderbookL3 { symbol, .. } | Event::SettlementEvent { symbol, .. } |
Event::AuctionEvent { symbol, .. } | Event::MarketWarning { symbol, .. } |
Event::RiskLimit { symbol, .. } | Event::PredictedFunding { symbol, .. } |
Event::FundingSettlement { symbol, .. } |
Event::MarkPriceKline { symbol, .. } | Event::IndexPriceKline { symbol, .. } |
Event::PremiumIndexKline { symbol, .. } => symbol,
}
}
pub(crate) fn set_symbol(&mut self, new_symbol: String) {
match self {
Event::Trade { symbol, .. }
| Event::AggTrade { symbol, .. }
| Event::Bar { symbol, .. }
| Event::Ticker { symbol, .. }
| Event::OrderbookSnapshot { symbol, .. }
| Event::MarkPrice { symbol, .. }
| Event::FundingRate { symbol, .. }
| Event::OpenInterest { symbol, .. }
| Event::Liquidation { symbol, .. }
| Event::BlockTrade { symbol, .. }
| Event::IndexPrice { symbol, .. }
| Event::CompositeIndex { symbol, .. }
| Event::OptionGreeks { symbol, .. }
| Event::VolatilityIndex { symbol, .. }
| Event::HistoricalVolatility { symbol, .. }
| Event::Basis { symbol, .. }
| Event::InsuranceFund { symbol, .. }
| Event::OrderbookL3 { symbol, .. }
| Event::SettlementEvent { symbol, .. }
| Event::AuctionEvent { symbol, .. }
| Event::MarketWarning { symbol, .. }
| Event::RiskLimit { symbol, .. }
| Event::PredictedFunding { symbol, .. }
| Event::FundingSettlement { symbol, .. }
| Event::MarkPriceKline { symbol, .. }
| Event::IndexPriceKline { symbol, .. }
| Event::PremiumIndexKline { symbol, .. } => *symbol = new_symbol,
}
}
pub fn timestamp_ms(&self) -> i64 {
use crate::series::DataPoint;
match self {
Event::Trade { point, .. } => point.timestamp_ms(),
Event::AggTrade { point, .. } => point.timestamp_ms(),
Event::Bar { point, .. } => point.timestamp_ms(),
Event::Ticker { point, .. } => point.timestamp_ms(),
Event::OrderbookSnapshot { point, .. } => point.timestamp_ms(),
Event::MarkPrice { point, .. } => point.timestamp_ms(),
Event::FundingRate { point, .. } => point.timestamp_ms(),
Event::OpenInterest { point, .. } => point.timestamp_ms(),
Event::Liquidation { point, .. } => point.timestamp_ms(),
Event::BlockTrade { point, .. } => point.timestamp_ms(),
Event::IndexPrice { point, .. } => point.timestamp_ms(),
Event::CompositeIndex { point, .. } => point.timestamp_ms(),
Event::OptionGreeks { point, .. } => point.timestamp_ms(),
Event::VolatilityIndex { point, .. } => point.timestamp_ms(),
Event::HistoricalVolatility { point, .. } => point.timestamp_ms(),
Event::Basis { point, .. } => point.timestamp_ms(),
Event::InsuranceFund { point, .. } => point.timestamp_ms(),
Event::OrderbookL3 { point, .. } => point.timestamp_ms(),
Event::SettlementEvent { point, .. } => point.timestamp_ms(),
Event::AuctionEvent { point, .. } => point.timestamp_ms(),
Event::MarketWarning { point, .. } => point.timestamp_ms(),
Event::RiskLimit { point, .. } => point.timestamp_ms(),
Event::PredictedFunding { point, .. } => point.timestamp_ms(),
Event::FundingSettlement { point, .. } => point.timestamp_ms(),
Event::MarkPriceKline { point, .. } => point.timestamp_ms(),
Event::IndexPriceKline { point, .. } => point.timestamp_ms(),
Event::PremiumIndexKline { point, .. } => point.timestamp_ms(),
}
}
}
pub struct SubscriptionHandle {
pub(crate) rx: tokio::sync::mpsc::UnboundedReceiver<Event>,
pub(crate) _refs: Vec<MultiplexRef>,
}
impl std::fmt::Debug for SubscriptionHandle {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SubscriptionHandle").finish()
}
}
impl SubscriptionHandle {
pub async fn recv(&mut self) -> Option<Event> {
self.rx.recv().await
}
}
#[derive(Debug)]
pub struct FailedStream {
pub exchange: ExchangeId,
pub account_type: AccountType,
pub symbol: String,
pub stream: Stream,
pub error: crate::StationError,
}
pub struct SubscribeReport {
pub handle: SubscriptionHandle,
pub ok: Vec<SeriesKey>,
pub failed: Vec<FailedStream>,
}
impl SubscribeReport {
pub fn is_fully_ok(&self) -> bool { self.failed.is_empty() }
pub fn total(&self) -> usize { self.ok.len() + self.failed.len() }
}
impl std::fmt::Debug for SubscribeReport {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SubscribeReport")
.field("ok", &self.ok.len())
.field("failed", &self.failed.len())
.finish()
}
}
pub(crate) struct MultiplexRef {
pub(crate) station: std::sync::Weak<crate::station::StationInner>,
pub(crate) key: SeriesKey,
}
impl Drop for MultiplexRef {
fn drop(&mut self) {
if let Some(inner) = self.station.upgrade() {
inner.release_consumer(&self.key);
}
}
}