use std::collections::BTreeMap;
use crate::{Level, OrderId, Price, Quantity, Side};
#[derive(Clone, Debug)]
pub struct PriceLevels {
levels: BTreeMap<Price, Level>,
best_price: Option<Price>,
side: Side,
}
impl PriceLevels {
pub fn new(side: Side) -> Self {
Self {
levels: BTreeMap::new(),
best_price: None,
side,
}
}
#[inline]
pub fn side(&self) -> Side {
self.side
}
#[inline]
pub fn is_empty(&self) -> bool {
self.levels.is_empty()
}
#[inline]
pub fn level_count(&self) -> usize {
self.levels.len()
}
#[inline]
pub fn best_price(&self) -> Option<Price> {
self.best_price
}
pub fn best_level(&self) -> Option<&Level> {
self.best_price.and_then(|p| self.levels.get(&p))
}
pub fn best_level_mut(&mut self) -> Option<&mut Level> {
self.best_price.and_then(|p| self.levels.get_mut(&p))
}
pub fn get_level(&self, price: Price) -> Option<&Level> {
self.levels.get(&price)
}
pub fn get_level_mut(&mut self, price: Price) -> Option<&mut Level> {
self.levels.get_mut(&price)
}
pub fn get_or_create_level(&mut self, price: Price) -> &mut Level {
let is_new = !self.levels.contains_key(&price);
if is_new {
self.update_best_price_after_insert(price);
self.levels.insert(price, Level::new(price));
}
self.levels.get_mut(&price).unwrap()
}
pub fn insert_order(&mut self, price: Price, order_id: OrderId, quantity: Quantity) -> usize {
let level = self.get_or_create_level(price);
let actual_index = level.orders.len();
level.push_back(order_id, quantity);
actual_index
}
pub fn mark_tombstone(&mut self, price: Price, index: usize, quantity: Quantity) {
if let Some(level) = self.levels.get_mut(&price) {
level.mark_tombstone(index, quantity);
if level.is_empty() {
self.remove_level(price);
}
}
}
pub fn compact(&mut self) {
for level in self.levels.values_mut() {
level.compact();
}
}
pub fn remove_order(&mut self, price: Price, order_id: OrderId, quantity: Quantity) -> bool {
if let Some(level) = self.levels.get_mut(&price) {
if level.remove(order_id, quantity) {
if level.is_empty() {
self.remove_level(price);
}
return true;
}
}
false
}
pub fn remove_level(&mut self, price: Price) {
if self.levels.remove(&price).is_some() {
if self.best_price == Some(price) {
self.recompute_best_price();
}
}
}
pub fn pop_best_level(&mut self) -> Option<Level> {
let price = self.best_price?;
let level = self.levels.remove(&price);
self.recompute_best_price();
level
}
pub fn iter_best_to_worst(&self) -> impl Iterator<Item = (&Price, &Level)> {
BestToWorstIter {
inner: if self.side == Side::Buy {
IterDirection::Reverse(self.levels.iter().rev())
} else {
IterDirection::Forward(self.levels.iter())
},
}
}
pub fn total_quantity(&self) -> Quantity {
self.levels.values().map(|l| l.total_quantity()).sum()
}
pub fn quantity_at_or_better(&self, price: Price) -> Quantity {
match self.side {
Side::Buy => {
self.levels
.range(price..)
.map(|(_, l)| l.total_quantity())
.sum()
}
Side::Sell => {
self.levels
.range(..=price)
.map(|(_, l)| l.total_quantity())
.sum()
}
}
}
fn recompute_best_price(&mut self) {
self.best_price = match self.side {
Side::Buy => self.levels.keys().next_back().copied(), Side::Sell => self.levels.keys().next().copied(), };
}
fn update_best_price_after_insert(&mut self, new_price: Price) {
match self.best_price {
None => {
self.best_price = Some(new_price);
}
Some(current_best) => {
let is_better = match self.side {
Side::Buy => new_price > current_best, Side::Sell => new_price < current_best, };
if is_better {
self.best_price = Some(new_price);
}
}
}
}
}
enum IterDirection<F, R> {
Forward(F),
Reverse(R),
}
type BTreeIter<'a> = std::collections::btree_map::Iter<'a, Price, Level>;
struct BestToWorstIter<'a> {
inner: IterDirection<BTreeIter<'a>, std::iter::Rev<BTreeIter<'a>>>,
}
impl<'a> Iterator for BestToWorstIter<'a> {
type Item = (&'a Price, &'a Level);
fn next(&mut self) -> Option<Self::Item> {
match &mut self.inner {
IterDirection::Forward(iter) => iter.next(),
IterDirection::Reverse(iter) => iter.next(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_bids_is_empty() {
let bids = PriceLevels::new(Side::Buy);
assert!(bids.is_empty());
assert_eq!(bids.level_count(), 0);
assert_eq!(bids.best_price(), None);
assert!(bids.best_level().is_none());
}
#[test]
fn bids_best_is_highest() {
let mut bids = PriceLevels::new(Side::Buy);
bids.insert_order(Price(100_00), OrderId(1), 100);
assert_eq!(bids.best_price(), Some(Price(100_00)));
bids.insert_order(Price(99_00), OrderId(2), 100);
assert_eq!(bids.best_price(), Some(Price(100_00)));
bids.insert_order(Price(101_00), OrderId(3), 100);
assert_eq!(bids.best_price(), Some(Price(101_00))); }
#[test]
fn bids_remove_best_updates_cache() {
let mut bids = PriceLevels::new(Side::Buy);
bids.insert_order(Price(100_00), OrderId(1), 100);
bids.insert_order(Price(99_00), OrderId(2), 100);
bids.insert_order(Price(101_00), OrderId(3), 100);
assert_eq!(bids.best_price(), Some(Price(101_00)));
bids.remove_level(Price(101_00));
assert_eq!(bids.best_price(), Some(Price(100_00)));
bids.remove_level(Price(100_00));
assert_eq!(bids.best_price(), Some(Price(99_00)));
bids.remove_level(Price(99_00));
assert_eq!(bids.best_price(), None);
}
#[test]
fn new_asks_is_empty() {
let asks = PriceLevels::new(Side::Sell);
assert!(asks.is_empty());
assert_eq!(asks.best_price(), None);
}
#[test]
fn asks_best_is_lowest() {
let mut asks = PriceLevels::new(Side::Sell);
asks.insert_order(Price(100_00), OrderId(1), 100);
assert_eq!(asks.best_price(), Some(Price(100_00)));
asks.insert_order(Price(101_00), OrderId(2), 100);
assert_eq!(asks.best_price(), Some(Price(100_00)));
asks.insert_order(Price(99_00), OrderId(3), 100);
assert_eq!(asks.best_price(), Some(Price(99_00))); }
#[test]
fn asks_remove_best_updates_cache() {
let mut asks = PriceLevels::new(Side::Sell);
asks.insert_order(Price(100_00), OrderId(1), 100);
asks.insert_order(Price(101_00), OrderId(2), 100);
asks.insert_order(Price(99_00), OrderId(3), 100);
assert_eq!(asks.best_price(), Some(Price(99_00)));
asks.remove_level(Price(99_00));
assert_eq!(asks.best_price(), Some(Price(100_00)));
}
#[test]
fn insert_multiple_orders_same_price() {
let mut bids = PriceLevels::new(Side::Buy);
bids.insert_order(Price(100_00), OrderId(1), 100);
bids.insert_order(Price(100_00), OrderId(2), 200);
bids.insert_order(Price(100_00), OrderId(3), 150);
assert_eq!(bids.level_count(), 1);
let level = bids.best_level().unwrap();
assert_eq!(level.order_count(), 3);
assert_eq!(level.total_quantity(), 450);
}
#[test]
fn remove_order_removes_empty_level() {
let mut bids = PriceLevels::new(Side::Buy);
bids.insert_order(Price(100_00), OrderId(1), 100);
bids.insert_order(Price(99_00), OrderId(2), 200);
assert_eq!(bids.level_count(), 2);
assert!(bids.remove_order(Price(100_00), OrderId(1), 100));
assert_eq!(bids.level_count(), 1);
assert_eq!(bids.best_price(), Some(Price(99_00)));
}
#[test]
fn remove_order_keeps_nonempty_level() {
let mut bids = PriceLevels::new(Side::Buy);
bids.insert_order(Price(100_00), OrderId(1), 100);
bids.insert_order(Price(100_00), OrderId(2), 200);
assert!(bids.remove_order(Price(100_00), OrderId(1), 100));
assert_eq!(bids.level_count(), 1);
let level = bids.best_level().unwrap();
assert_eq!(level.order_count(), 1);
assert_eq!(level.total_quantity(), 200);
}
#[test]
fn remove_nonexistent_order() {
let mut bids = PriceLevels::new(Side::Buy);
bids.insert_order(Price(100_00), OrderId(1), 100);
assert!(!bids.remove_order(Price(100_00), OrderId(999), 100));
assert!(!bids.remove_order(Price(999_00), OrderId(1), 100));
}
#[test]
fn iter_bids_best_to_worst() {
let mut bids = PriceLevels::new(Side::Buy);
bids.insert_order(Price(99_00), OrderId(1), 100);
bids.insert_order(Price(101_00), OrderId(2), 100);
bids.insert_order(Price(100_00), OrderId(3), 100);
let prices: Vec<_> = bids.iter_best_to_worst().map(|(p, _)| *p).collect();
assert_eq!(prices, vec![Price(101_00), Price(100_00), Price(99_00)]);
}
#[test]
fn iter_asks_best_to_worst() {
let mut asks = PriceLevels::new(Side::Sell);
asks.insert_order(Price(99_00), OrderId(1), 100);
asks.insert_order(Price(101_00), OrderId(2), 100);
asks.insert_order(Price(100_00), OrderId(3), 100);
let prices: Vec<_> = asks.iter_best_to_worst().map(|(p, _)| *p).collect();
assert_eq!(prices, vec![Price(99_00), Price(100_00), Price(101_00)]);
}
#[test]
fn total_quantity() {
let mut bids = PriceLevels::new(Side::Buy);
bids.insert_order(Price(100_00), OrderId(1), 100);
bids.insert_order(Price(100_00), OrderId(2), 200);
bids.insert_order(Price(99_00), OrderId(3), 150);
assert_eq!(bids.total_quantity(), 450);
}
#[test]
fn quantity_at_or_better_bids() {
let mut bids = PriceLevels::new(Side::Buy);
bids.insert_order(Price(100_00), OrderId(1), 100);
bids.insert_order(Price(99_00), OrderId(2), 200);
bids.insert_order(Price(98_00), OrderId(3), 150);
assert_eq!(bids.quantity_at_or_better(Price(99_00)), 300);
assert_eq!(bids.quantity_at_or_better(Price(100_00)), 100);
assert_eq!(bids.quantity_at_or_better(Price(98_00)), 450);
}
#[test]
fn quantity_at_or_better_asks() {
let mut asks = PriceLevels::new(Side::Sell);
asks.insert_order(Price(100_00), OrderId(1), 100);
asks.insert_order(Price(101_00), OrderId(2), 200);
asks.insert_order(Price(102_00), OrderId(3), 150);
assert_eq!(asks.quantity_at_or_better(Price(101_00)), 300);
assert_eq!(asks.quantity_at_or_better(Price(100_00)), 100);
assert_eq!(asks.quantity_at_or_better(Price(102_00)), 450);
}
#[test]
fn best_level_mut_allows_modification() {
let mut bids = PriceLevels::new(Side::Buy);
bids.insert_order(Price(100_00), OrderId(1), 100);
if let Some(level) = bids.best_level_mut() {
level.decrease_quantity(30);
}
assert_eq!(bids.best_level().unwrap().total_quantity(), 70);
}
#[test]
fn pop_best_level() {
let mut asks = PriceLevels::new(Side::Sell);
asks.insert_order(Price(100_00), OrderId(1), 100);
asks.insert_order(Price(101_00), OrderId(2), 200);
let popped = asks.pop_best_level().unwrap();
assert_eq!(popped.price(), Price(100_00));
assert_eq!(asks.best_price(), Some(Price(101_00)));
}
}