use ordered_float::OrderedFloat;
use std::collections::BTreeMap;
use std::collections::HashMap;
pub type PVMap = BTreeMap<OrderedFloat<f64>, OrderedFloat<f64>>;
struct PVMapDebug<'a>(&'a PVMap);
impl<'a> std::fmt::Debug for PVMapDebug<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut list = f.debug_list();
for (price, volume) in self.0 {
list.entry(&format_args!("{price}: {volume}"));
}
list.finish()
}
}
#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct Orderbook {
pub ask: PVMap,
pub bid: PVMap,
pub sequence: u64,
}
impl std::fmt::Debug for Orderbook {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Orderbook")
.field("sequence", &self.sequence)
.field("ask", &PVMapDebug(&self.ask))
.field("bid", &PVMapDebug(&self.bid))
.finish()
}
}
pub type FullOrderbook = HashMap<String, Orderbook>;
impl Orderbook {
pub fn new() -> Orderbook {
Orderbook {
ask: PVMap::new(),
bid: PVMap::new(),
sequence: 0,
}
}
pub fn merge(&mut self, to_merge: Orderbook) -> Result<Option<Orderbook>, String> {
let to_merge_clone = to_merge.clone();
let zero = 0.0;
let min_ask = self.ask.first_key_value().unwrap().0.to_owned();
let max_bid = self.bid.last_key_value().unwrap().0.to_owned();
if self.sequence > to_merge.sequence {
return Err(std::format!(
"[{}] -> [{}]",
to_merge.sequence,
self.sequence
));
}
self.sequence = to_merge.sequence;
for (price, volume) in to_merge.ask.into_iter() {
if volume.eq(&zero) {
if self.ask.remove(&price).is_none() {
}
continue;
}
self.ask.insert(price, volume);
}
for (price, volume) in to_merge.bid.into_iter() {
if volume.eq(&zero) {
if self.bid.remove(&price).is_none() {
}
continue;
}
self.bid.insert(price, volume);
}
if let Some((merge_min_ask, _)) = to_merge_clone.ask.first_key_value() {
if merge_min_ask.to_owned() <= min_ask {
return Ok(Some(to_merge_clone));
}
}
if let Some((merge_max_bid, _)) = to_merge_clone.bid.last_key_value() {
if merge_max_bid.to_owned() >= max_bid {
return Ok(Some(to_merge_clone));
}
}
Ok(None)
}
}