mirror of
https://github.com/floor-licker/polyfill-rs.git
synced 2026-08-08 02:07:45 +00:00
Feat: Enhance integration tests
This commit is contained in:
+12
-7
@@ -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
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user