Removed across 66 files:
- 49 instances of "// use crate::safe_operations; // DISABLED"
- 11 instances of "// use error_handling::{...}; // crate doesn't exist"
- 2 instances of "// use crate::Optimizer; // not available"
- 5 disabled test placeholder blocks (/* ... */) in ensemble/
- 1 disabled From impl in lib.rs (38 lines)
- 1 disabled test module in model.rs (113 lines)
- 1 disabled code block in integration/distillation.rs (41 lines)
- Various other disabled imports with explanation comments
All of this code references modules/crates that were removed during
prior refactoring waves and is preserved in git history. Removing it
reduces noise and makes the codebase easier to navigate.
1922 lib tests passing, compilation clean.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
127 lines
4.1 KiB
Rust
127 lines
4.1 KiB
Rust
//! # Kyle's Lambda Estimator
|
||
//!
|
||
//! Implementation of Kyle's Lambda for measuring price impact and
|
||
//! information asymmetry in financial markets.
|
||
//!
|
||
//! ## Algorithm
|
||
//!
|
||
//! Kyle's Lambda (λ) measures the price impact per unit of signed order flow:
|
||
//! - Returns = λ × SignedOrderFlow + ε
|
||
//! - λ is estimated via regression of returns on signed square-root dollar volume
|
||
//! - Higher λ indicates greater price impact (lower liquidity)
|
||
//!
|
||
//! ## Performance
|
||
//!
|
||
//! - Target latency: <25μs per calculation
|
||
//! - Rolling regression with fixed-point arithmetic
|
||
//! - Efficient covariance calculation updates
|
||
|
||
use std::collections::VecDeque;
|
||
use std::sync::atomic::{AtomicI64, AtomicU64, Ordering};
|
||
|
||
use serde::{Deserialize, Serialize};
|
||
|
||
use super::*;
|
||
use super::{
|
||
|
||
|
||
#[test]
|
||
fn test_kyle_lambda_estimator_creation() {
|
||
let estimator = KyleLambdaEstimator::default();
|
||
assert_eq!(estimator.get_lambda(), 0.0);
|
||
assert_eq!(estimator.get_interval_count(), 0);
|
||
assert_eq!(estimator.get_r_squared(), 0.0);
|
||
}
|
||
|
||
#[test]
|
||
fn test_trading_interval() {
|
||
let mut interval = TradingInterval::new(0, 1000000, 2000000);
|
||
|
||
let update = MarketDataUpdate {
|
||
timestamp: 1500000,
|
||
symbol: "AAPL".to_string(),
|
||
price: 150000,
|
||
volume: 1000,
|
||
bid: 149000,
|
||
ask: 151000,
|
||
bid_size: 100,
|
||
ask_size: 100,
|
||
direction: Some(TradeDirection::Buy),
|
||
};
|
||
|
||
interval.add_trade(&update);
|
||
|
||
assert_eq!(interval.trade_count, 1);
|
||
assert_eq!(interval.open_price, 150000);
|
||
assert_eq!(interval.close_price, 150000);
|
||
assert!(interval.signed_sqrt_dollar_volume > 0); // Buy trade
|
||
|
||
interval.finalize();
|
||
assert!(interval.is_valid());
|
||
}
|
||
|
||
#[test]
|
||
fn test_lambda_calculation() {
|
||
let config = KyleLambdaConfig {
|
||
interval_duration_ns: 1000000, // 1ms for testing
|
||
min_trades_per_interval: 1,
|
||
regression_window: 5,
|
||
..Default::default()
|
||
};
|
||
|
||
let mut estimator = KyleLambdaEstimator::new(config);
|
||
|
||
// Add trades with price impact pattern
|
||
for i in 0..20 {
|
||
let price_impact = if i % 2 == 0 { 100 } else { -100 };
|
||
let direction = if i % 2 == 0 { TradeDirection::Buy } else { TradeDirection::Sell };
|
||
|
||
let update = MarketDataUpdate {
|
||
timestamp: (i * 2000000) as u64, // 2ms intervals
|
||
symbol: "AAPL".to_string(),
|
||
price: 150000 + price_impact,
|
||
volume: 1000,
|
||
bid: 149000,
|
||
ask: 151000,
|
||
bid_size: 100,
|
||
ask_size: 100,
|
||
direction: Some(direction),
|
||
};
|
||
|
||
estimator.update(&update)?;
|
||
}
|
||
|
||
// Should have calculated lambda
|
||
let result = estimator.get_result();
|
||
assert!(result.interval_count > 0);
|
||
|
||
// Lambda should be non-zero if there's a price impact pattern
|
||
// (exact value depends on the specific pattern)
|
||
println!("Lambda: {}, R²: {}", result.lambda, result.r_squared);
|
||
}
|
||
|
||
#[test]
|
||
fn test_information_asymmetry() {
|
||
let mut estimator = KyleLambdaEstimator::default();
|
||
|
||
// Add persistent positive returns (trend)
|
||
for i in 0..10 {
|
||
let update = MarketDataUpdate {
|
||
timestamp: (i * 300_000_000_000) as u64, // 5 min intervals
|
||
symbol: "AAPL".to_string(),
|
||
price: 150000 + (i * 100), // Trending up
|
||
volume: 1000,
|
||
bid: 149000,
|
||
ask: 151000,
|
||
bid_size: 100,
|
||
ask_size: 100,
|
||
direction: Some(TradeDirection::Buy),
|
||
};
|
||
|
||
estimator.update(&update)?;
|
||
}
|
||
|
||
let info_asymmetry = estimator.get_information_asymmetry();
|
||
assert!(info_asymmetry >= 0.0); // Should detect some persistence
|
||
}
|
||
} |