use crate::{
Timed,
engine::{Processor, state::order::in_flight_recorder::InFlightRequestRecorder},
};
use barter_data::{
event::{DataKind, MarketEvent},
subscription::book::OrderBookL1,
};
use barter_execution::{
AccountEvent,
order::request::{OrderRequestCancel, OrderRequestOpen},
};
use barter_instrument::{asset::AssetIndex, exchange::ExchangeIndex, instrument::InstrumentIndex};
use derive_more::Constructor;
use rust_decimal::{Decimal, prelude::FromPrimitive};
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
pub trait InstrumentDataState<
ExchangeKey = ExchangeIndex,
AssetKey = AssetIndex,
InstrumentKey = InstrumentIndex,
> where
Self: Debug
+ Clone
+ for<'a> Processor<&'a MarketEvent<InstrumentKey, Self::MarketEventKind>>
+ for<'a> Processor<&'a AccountEvent<ExchangeKey, AssetKey, InstrumentKey>>
+ InFlightRequestRecorder<ExchangeKey, InstrumentKey>,
{
type MarketEventKind: Debug + Clone + Send;
fn price(&self) -> Option<Decimal>;
}
#[derive(
Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default, Deserialize, Serialize, Constructor,
)]
pub struct DefaultInstrumentMarketData {
pub l1: OrderBookL1,
pub last_traded_price: Option<Timed<Decimal>>,
}
impl InstrumentDataState for DefaultInstrumentMarketData {
type MarketEventKind = DataKind;
fn price(&self) -> Option<Decimal> {
self.l1
.volume_weighed_mid_price()
.or(self.last_traded_price.as_ref().map(|timed| timed.value))
}
}
impl<InstrumentKey> Processor<&MarketEvent<InstrumentKey, DataKind>>
for DefaultInstrumentMarketData
{
type Audit = ();
fn process(&mut self, event: &MarketEvent<InstrumentKey, DataKind>) -> Self::Audit {
match &event.kind {
DataKind::Trade(trade) => {
if self
.last_traded_price
.as_ref()
.is_none_or(|price| price.time < event.time_exchange)
&& let Some(price) = Decimal::from_f64(trade.price)
{
self.last_traded_price
.replace(Timed::new(price, event.time_exchange));
}
}
DataKind::OrderBookL1(l1) => {
if self.l1.last_update_time < event.time_exchange {
self.l1 = l1.clone()
}
}
_ => {}
}
}
}
impl<ExchangeKey, AssetKey, InstrumentKey>
Processor<&AccountEvent<ExchangeKey, AssetKey, InstrumentKey>> for DefaultInstrumentMarketData
{
type Audit = ();
fn process(&mut self, _: &AccountEvent<ExchangeKey, AssetKey, InstrumentKey>) -> Self::Audit {}
}
impl<ExchangeKey, InstrumentKey> InFlightRequestRecorder<ExchangeKey, InstrumentKey>
for DefaultInstrumentMarketData
{
fn record_in_flight_cancel(&mut self, _: &OrderRequestCancel<ExchangeKey, InstrumentKey>) {}
fn record_in_flight_open(&mut self, _: &OrderRequestOpen<ExchangeKey, InstrumentKey>) {}
}