Feat: Enhance integration tests

This commit is contained in:
floor-licker
2025-09-04 23:25:49 -04:00
parent ab2a4f62af
commit 0b9fa95cfc
5 changed files with 653 additions and 19 deletions
+12 -7
View File
@@ -567,21 +567,26 @@ impl OrderBook {
/// Get the total liquidity at a given price level
/// Tells you how much you can buy/sell at exactly this price
pub fn liquidity_at_price(&self, price: Decimal, side: Side) -> Decimal {
let price_u32 = decimal_to_price(price).unwrap_or(0);
match side {
Side::BUY => self.asks.get(&price).copied().unwrap_or_default(), // How much we can buy at this price
Side::SELL => self.bids.get(&price).copied().unwrap_or_default(), // How much we can sell at this price
Side::BUY => Decimal::from(self.asks.get(&price_u32).copied().unwrap_or_default()), // How much we can buy at this price
Side::SELL => Decimal::from(self.bids.get(&price_u32).copied().unwrap_or_default()), // How much we can sell at this price
}
}
/// Get the total liquidity within a price range
/// Useful for understanding how much depth exists in a certain price band
pub fn liquidity_in_range(&self, min_price: Decimal, max_price: Decimal, side: Side) -> Decimal {
let min_price_u32 = decimal_to_price(min_price).unwrap_or(0);
let max_price_u32 = decimal_to_price(max_price).unwrap_or(0);
let levels: Vec<_> = match side {
Side::BUY => self.asks.range(min_price..=max_price).collect(),
Side::SELL => self.bids.range(min_price..=max_price).rev().collect(),
Side::BUY => self.asks.range(min_price_u32..=max_price_u32).collect(),
Side::SELL => self.bids.range(min_price_u32..=max_price_u32).rev().collect(),
};
levels.into_iter().map(|(_, &size)| size).sum()
let total: i64 = levels.into_iter().map(|(_, &size)| size).sum();
Decimal::from(total)
}
/// Validate that prices are properly ordered
@@ -738,8 +743,8 @@ impl OrderBook {
pub fn analytics(&self) -> BookAnalytics {
let bid_count = self.bids.len();
let ask_count = self.asks.len();
let total_bid_size: Decimal = self.bids.values().sum(); // Add up all bid sizes
let total_ask_size: Decimal = self.asks.values().sum(); // Add up all ask sizes
let total_bid_size: Decimal = Decimal::from(self.bids.values().sum::<i64>()); // Add up all bid sizes
let total_ask_size: Decimal = Decimal::from(self.asks.values().sum::<i64>()); // Add up all ask sizes
BookAnalytics {
token_id: self.token_id.clone(),
+5 -4
View File
@@ -6,6 +6,7 @@
use alloy_primitives::{Address, U256};
use chrono::{DateTime, Utc};
use rust_decimal::Decimal;
use rust_decimal::prelude::ToPrimitive;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use uuid::Uuid;
@@ -90,7 +91,7 @@ pub const MAX_QTY: Qty = Qty::MAX / 2; // Leave room for intermediate calculatio
/// - decimal_to_price(Decimal::from_str("0.6543")) = Ok(6543)
/// - decimal_to_price(Decimal::from_str("1.0000")) = Ok(10000)
/// - decimal_to_price(Decimal::from_str("0.00005")) = Ok(1) // Rounds up to min tick
pub fn decimal_to_price(decimal: Decimal) -> Result<Price, &'static str> {
pub fn decimal_to_price(decimal: Decimal) -> std::result::Result<Price, &'static str> {
// Convert to fixed-point by multiplying by scale factor
let scaled = decimal * Decimal::from(SCALE_FACTOR);
@@ -131,7 +132,7 @@ pub fn price_to_decimal(ticks: Price) -> Decimal {
/// Examples:
/// - decimal_to_qty(Decimal::from_str("100.0")) = Ok(1000000)
/// - decimal_to_qty(Decimal::from_str("-50.5")) = Ok(-505000)
pub fn decimal_to_qty(decimal: Decimal) -> Result<Qty, &'static str> {
pub fn decimal_to_qty(decimal: Decimal) -> std::result::Result<Qty, &'static str> {
let scaled = decimal * Decimal::from(SCALE_FACTOR);
let rounded = scaled.round();
@@ -299,7 +300,7 @@ impl FastBookLevel {
/// Create from external BookLevel (with validation)
/// This is called when we receive data from the API
pub fn from_book_level(level: &BookLevel) -> Result<Self, &'static str> {
pub fn from_book_level(level: &BookLevel) -> std::result::Result<Self, &'static str> {
let price = decimal_to_price(level.price)?;
let size = decimal_to_qty(level.size)?;
Ok(Self::new(price, size))
@@ -374,7 +375,7 @@ impl FastOrderDelta {
/// This is where we enforce tick alignment - if the incoming price
/// doesn't align to valid ticks, we either reject it or round it.
/// This prevents bad data from corrupting our order book.
pub fn from_order_delta(delta: &OrderDelta, tick_size: Option<Decimal>) -> Result<Self, &'static str> {
pub fn from_order_delta(delta: &OrderDelta, tick_size: Option<Decimal>) -> std::result::Result<Self, &'static str> {
// Validate tick alignment if we have a tick size
if let Some(tick_size) = tick_size {
if !is_price_tick_aligned(delta.price, tick_size) {