mod limit;
mod order;
mod test;
use limit::Limit;
use order::Order;
use std::{
collections::{btree_map::BTreeMap, HashMap},
fmt,
};
pub struct Book {
buy_limits: BTreeMap<u64, Limit>,
sell_limits: BTreeMap<u64, Limit>,
order_map: HashMap<u64, Order>,
}
#[derive(Debug)]
pub struct ExistingIdError {
id: u64,
}
impl ExistingIdError {
fn new(id: u64) -> Self {
Self { id }
}
}
impl fmt::Display for ExistingIdError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Book already contains id {}", self.id)
}
}
#[derive(Debug)]
pub struct NonExistingIdError {
id: u64,
}
impl NonExistingIdError {
fn new(id: u64) -> Self {
Self { id }
}
}
impl fmt::Display for NonExistingIdError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Book does not contain id {}", self.id)
}
}
impl Book {
#[must_use]
pub fn new() -> Self {
Self {
buy_limits: BTreeMap::new(),
sell_limits: BTreeMap::new(),
order_map: HashMap::new(),
}
}
pub fn add_order(
&mut self,
order_id: u64,
is_buy: bool,
shares: u64,
limit_value: u64,
timestamp: u64,
) -> Result<(), ExistingIdError> {
if self.order_map.contains_key(&order_id) {
return Err(ExistingIdError::new(order_id));
}
let order = Order::new(order_id, is_buy, shares, limit_value, timestamp);
self.order_map.insert(order_id, order);
let limit_tree = if is_buy {
&mut self.buy_limits
} else {
&mut self.sell_limits
};
if let Some(l) = limit_tree.get_mut(&limit_value) {
l.add(order_id);
} else {
let mut limit = Limit::new(limit_value);
limit.add(order_id);
let _ = limit_tree.insert(limit_value, limit);
};
Ok(())
}
pub fn cancel_order(&mut self, order_id: u64) -> Result<(), NonExistingIdError> {
match self.order_map.remove(&order_id) {
Some(o) => {
let limit_tree = if o.is_buy {
&mut self.buy_limits
} else {
&mut self.sell_limits
};
let is_empty = match limit_tree.get_mut(&o.limit) {
Some(l) => l.cancel(o.order_id),
None => panic!(""),
};
if is_empty {
limit_tree.remove(&o.limit);
}
Ok(())
}
None => Err(NonExistingIdError::new(order_id)),
}
}
pub fn execute_market_order(&mut self, shares: u64, is_buy: bool) -> (bool, Vec<(u64, u64)>) {
let mut shares_left = shares;
let mut result: Vec<(u64, u64)> = vec![];
let limit_tree = if is_buy {
&mut self.sell_limits
} else {
&mut self.buy_limits
};
while shares_left > 0 {
let limit_key_value = if is_buy {
limit_tree.values_mut().next()
} else {
limit_tree.values_mut().last()
};
let Some(limit) = limit_key_value else {
return (false, result);
};
let (shares_executed, is_empty) = limit.execute(shares_left, &mut self.order_map);
shares_left -= shares_executed;
result.push((limit.limit_price, shares_executed));
if is_empty {
if is_buy {
limit_tree.pop_first();
} else {
limit_tree.pop_last();
}
}
}
(true, result)
}
}
impl Default for Book {
fn default() -> Self {
Self::new()
}
}