mirror of
https://github.com/floor-licker/polyfill-rs.git
synced 2026-07-31 22:37:44 +00:00
tests: further tests for fill.rs and book.rs
This commit is contained in:
+20
-16
@@ -796,7 +796,9 @@ impl OrderBook {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use rust_decimal_macros::dec; // Convenient macro for creating Decimal literals
|
||||
use rust_decimal_macros::dec;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration; // Convenient macro for creating Decimal literals
|
||||
|
||||
#[test]
|
||||
fn test_order_book_creation() {
|
||||
@@ -929,26 +931,28 @@ mod tests {
|
||||
fn test_liquidity_analysis() {
|
||||
let mut book = OrderBook::new("test_token".to_string(), 10);
|
||||
|
||||
// Build order book
|
||||
book.apply_delta_fast(7500, 1000); // bid at 0.75, size 100
|
||||
book.apply_delta_fast(7400, 500); // bid at 0.74, size 50
|
||||
book.apply_delta_fast(7600, 800); // ask at 0.76, size 80
|
||||
book.apply_delta_fast(7700, 1200); // ask at 0.77, size 120
|
||||
// Build order book using legacy methods
|
||||
book.apply_bid_delta(Decimal::from_str("0.75").unwrap(), Decimal::from_str("100.0").unwrap());
|
||||
book.apply_bid_delta(Decimal::from_str("0.74").unwrap(), Decimal::from_str("50.0").unwrap());
|
||||
book.apply_ask_delta(Decimal::from_str("0.76").unwrap(), Decimal::from_str("80.0").unwrap());
|
||||
book.apply_ask_delta(Decimal::from_str("0.77").unwrap(), Decimal::from_str("120.0").unwrap());
|
||||
|
||||
// Test liquidity at specific price
|
||||
let bid_liquidity = book.liquidity_at_price(Decimal::from_str("0.75").unwrap());
|
||||
// Test liquidity at specific price (bids)
|
||||
let bid_liquidity = book.liquidity_at_price(Decimal::from_str("0.75").unwrap(), Side::BUY);
|
||||
assert_eq!(bid_liquidity, Decimal::from_str("100.0").unwrap());
|
||||
|
||||
let ask_liquidity = book.liquidity_at_price(Decimal::from_str("0.76").unwrap());
|
||||
// Test liquidity at specific price (asks)
|
||||
let ask_liquidity = book.liquidity_at_price(Decimal::from_str("0.76").unwrap(), Side::SELL);
|
||||
assert_eq!(ask_liquidity, Decimal::from_str("80.0").unwrap());
|
||||
|
||||
// Test liquidity in range
|
||||
// Test liquidity in range (both sides)
|
||||
let range_liquidity = book.liquidity_in_range(
|
||||
Decimal::from_str("0.74").unwrap(),
|
||||
Decimal::from_str("0.77").unwrap()
|
||||
Decimal::from_str("0.77").unwrap(),
|
||||
Side::BUY
|
||||
);
|
||||
// Should include: 50 (0.74 bid) + 100 (0.75 bid) + 80 (0.76 ask) + 120 (0.77 ask) = 350
|
||||
assert_eq!(range_liquidity, Decimal::from_str("350.0").unwrap());
|
||||
// Should include bid liquidity: 50 (0.74 bid) + 100 (0.75 bid) = 150
|
||||
assert_eq!(range_liquidity, Decimal::from_str("150.0").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -959,12 +963,12 @@ mod tests {
|
||||
assert!(book.is_valid());
|
||||
|
||||
// Add normal levels
|
||||
book.apply_delta_fast(7500, 1000); // bid at 0.75
|
||||
book.apply_delta_fast(7600, 800); // ask at 0.76
|
||||
book.apply_bid_delta(Decimal::from_str("0.75").unwrap(), Decimal::from_str("100.0").unwrap());
|
||||
book.apply_ask_delta(Decimal::from_str("0.76").unwrap(), Decimal::from_str("80.0").unwrap());
|
||||
assert!(book.is_valid());
|
||||
|
||||
// Create crossed book (invalid) - bid higher than ask
|
||||
book.apply_delta_fast(7700, 500); // bid at 0.77 (higher than ask at 0.76)
|
||||
book.apply_bid_delta(Decimal::from_str("0.77").unwrap(), Decimal::from_str("50.0").unwrap());
|
||||
assert!(!book.is_valid());
|
||||
}
|
||||
|
||||
|
||||
+142
@@ -564,4 +564,146 @@ mod tests {
|
||||
assert!(processor.process_fill(fill).is_ok());
|
||||
assert_eq!(processor.pending_fills.len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fill_engine_market_order_execution() {
|
||||
let mut engine = FillEngine::new();
|
||||
|
||||
// Create a market order
|
||||
let market_order = MarketOrder {
|
||||
id: "market_1".to_string(),
|
||||
side: Side::BUY,
|
||||
size: dec!(50),
|
||||
token_id: "token_1".to_string(),
|
||||
max_slippage: Some(dec!(0.05)), // 5% slippage tolerance
|
||||
};
|
||||
|
||||
// Execute the market order
|
||||
let result = engine.execute_market_order(market_order);
|
||||
assert!(result.is_ok());
|
||||
|
||||
let execution = result.unwrap();
|
||||
assert_eq!(execution.order_id, "market_1");
|
||||
assert_eq!(execution.side, Side::BUY);
|
||||
assert_eq!(execution.requested_size, dec!(50));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fill_processor_batch_processing() {
|
||||
let mut processor = FillProcessor::new();
|
||||
|
||||
// Add multiple fills
|
||||
let fill1 = Fill {
|
||||
id: "fill_1".to_string(),
|
||||
order_id: "order_1".to_string(),
|
||||
side: Side::BUY,
|
||||
size: dec!(25),
|
||||
price: dec!(0.75),
|
||||
fee: dec!(0.01),
|
||||
timestamp: 1234567890,
|
||||
token_id: "token_1".to_string(),
|
||||
};
|
||||
|
||||
let fill2 = Fill {
|
||||
id: "fill_2".to_string(),
|
||||
order_id: "order_2".to_string(),
|
||||
side: Side::SELL,
|
||||
size: dec!(30),
|
||||
price: dec!(0.76),
|
||||
fee: dec!(0.015),
|
||||
timestamp: 1234567891,
|
||||
token_id: "token_1".to_string(),
|
||||
};
|
||||
|
||||
processor.add_fill(fill1);
|
||||
processor.add_fill(fill2);
|
||||
|
||||
// Process all fills
|
||||
processor.process_pending_fills();
|
||||
|
||||
assert_eq!(processor.stats.processed_fills, 2);
|
||||
assert_eq!(processor.stats.processed_volume, dec!(55)); // 25 + 30
|
||||
assert_eq!(processor.stats.pending_fills, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_market_order_validation() {
|
||||
let valid_order = MarketOrder {
|
||||
id: "valid_1".to_string(),
|
||||
side: Side::BUY,
|
||||
size: dec!(10),
|
||||
token_id: "0x1234567890123456789012345678901234567890".to_string(),
|
||||
max_slippage: Some(dec!(0.1)),
|
||||
};
|
||||
|
||||
let result = validate_market_order(&valid_order);
|
||||
assert!(result.is_ok());
|
||||
|
||||
// Test invalid order (zero size)
|
||||
let invalid_order = MarketOrder {
|
||||
id: "invalid_1".to_string(),
|
||||
side: Side::BUY,
|
||||
size: Decimal::ZERO,
|
||||
token_id: "0x1234567890123456789012345678901234567890".to_string(),
|
||||
max_slippage: Some(dec!(0.1)),
|
||||
};
|
||||
|
||||
let result = validate_market_order(&invalid_order);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fee_calculation_edge_cases() {
|
||||
// Test very small amounts
|
||||
let small_fee = calculate_fee(dec!(0.001), dec!(0.005));
|
||||
assert!(small_fee >= Decimal::ZERO);
|
||||
|
||||
// Test large amounts
|
||||
let large_fee = calculate_fee(dec!(10000), dec!(0.005));
|
||||
assert_eq!(large_fee, dec!(50)); // 10000 * 0.005
|
||||
|
||||
// Test zero fee rate
|
||||
let zero_fee = calculate_fee(dec!(100), Decimal::ZERO);
|
||||
assert_eq!(zero_fee, Decimal::ZERO);
|
||||
|
||||
// Test zero amount
|
||||
let zero_amount_fee = calculate_fee(Decimal::ZERO, dec!(0.005));
|
||||
assert_eq!(zero_amount_fee, Decimal::ZERO);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fill_processor_statistics() {
|
||||
let mut processor = FillProcessor::new();
|
||||
|
||||
// Initial stats should be zero
|
||||
assert_eq!(processor.stats.pending_fills, 0);
|
||||
assert_eq!(processor.stats.processed_fills, 0);
|
||||
assert_eq!(processor.stats.pending_volume, Decimal::ZERO);
|
||||
assert_eq!(processor.stats.processed_volume, Decimal::ZERO);
|
||||
|
||||
// Add a fill
|
||||
let fill = Fill {
|
||||
id: "fill_stats".to_string(),
|
||||
order_id: "order_stats".to_string(),
|
||||
side: Side::BUY,
|
||||
size: dec!(75),
|
||||
price: dec!(0.80),
|
||||
fee: dec!(0.02),
|
||||
timestamp: 1234567892,
|
||||
token_id: "token_1".to_string(),
|
||||
};
|
||||
|
||||
processor.add_fill(fill);
|
||||
|
||||
// Check pending stats
|
||||
assert_eq!(processor.stats.pending_fills, 1);
|
||||
assert_eq!(processor.stats.pending_volume, dec!(75));
|
||||
|
||||
// Process and check final stats
|
||||
processor.process_pending_fills();
|
||||
assert_eq!(processor.stats.processed_fills, 1);
|
||||
assert_eq!(processor.stats.processed_volume, dec!(75));
|
||||
assert_eq!(processor.stats.pending_fills, 0);
|
||||
assert_eq!(processor.stats.pending_volume, Decimal::ZERO);
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user