use super::TickTypes;
use crate::contracts::tick_types::TickType;
use crate::contracts::OptionComputation;
use crate::market_data::MarketDataType;
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[derive(Debug, Clone, Default, PartialEq)]
#[non_exhaustive]
pub struct Quote {
pub bid: Option<f64>,
pub ask: Option<f64>,
pub last: Option<f64>,
pub open: Option<f64>,
pub high: Option<f64>,
pub low: Option<f64>,
pub close: Option<f64>,
pub bid_size: Option<f64>,
pub ask_size: Option<f64>,
pub last_size: Option<f64>,
pub volume: Option<f64>,
pub market_data_type: Option<MarketDataType>,
pub bid_greeks: Option<OptionComputation>,
pub ask_greeks: Option<OptionComputation>,
pub last_greeks: Option<OptionComputation>,
pub model_greeks: Option<OptionComputation>,
}
impl Quote {
pub fn from_ticks<'a>(ticks: impl IntoIterator<Item = &'a TickTypes>) -> Self {
let mut quote = Self::default();
for tick in ticks {
quote.apply(tick);
}
quote
}
pub fn apply(&mut self, tick: &TickTypes) {
match tick {
TickTypes::Price(tick) => self.set_price(tick.tick_type, tick.price),
TickTypes::Size(tick) => self.set_size(tick.tick_type, tick.size),
TickTypes::PriceSize(tick) => {
self.set_price(tick.price_tick_type, tick.price);
self.set_size(tick.size_tick_type, tick.size);
}
TickTypes::OptionComputation(computation) => self.set_greeks(computation),
TickTypes::MarketDataType(market_data_type) => self.market_data_type = Some(*market_data_type),
TickTypes::String(_) | TickTypes::Generic(_) | TickTypes::SnapshotEnd | TickTypes::RequestParameters(_) => {}
}
}
fn set_price(&mut self, tick_type: TickType, price: f64) {
let slot = match tick_type {
TickType::Bid | TickType::DelayedBid => &mut self.bid,
TickType::Ask | TickType::DelayedAsk => &mut self.ask,
TickType::Last | TickType::DelayedLast => &mut self.last,
TickType::Open | TickType::DelayedOpen => &mut self.open,
TickType::High | TickType::DelayedHigh => &mut self.high,
TickType::Low | TickType::DelayedLow => &mut self.low,
TickType::Close | TickType::DelayedClose => &mut self.close,
_ => return,
};
*slot = Some(price);
}
fn set_size(&mut self, tick_type: TickType, size: f64) {
let slot = match tick_type {
TickType::BidSize | TickType::DelayedBidSize => &mut self.bid_size,
TickType::AskSize | TickType::DelayedAskSize => &mut self.ask_size,
TickType::LastSize | TickType::DelayedLastSize => &mut self.last_size,
TickType::Volume | TickType::DelayedVolume => &mut self.volume,
_ => return,
};
*slot = Some(size);
}
fn set_greeks(&mut self, computation: &OptionComputation) {
let slot = match computation.field {
TickType::BidOption | TickType::DelayedBidOption => &mut self.bid_greeks,
TickType::AskOption | TickType::DelayedAskOption => &mut self.ask_greeks,
TickType::LastOption | TickType::DelayedLastOption => &mut self.last_greeks,
TickType::ModelOption | TickType::DelayedModelOption => &mut self.model_greeks,
_ => return,
};
*slot = Some(computation.clone());
}
}
#[cfg(test)]
#[path = "quote_tests.rs"]
mod tests;