refactor: restructure repo — crates/, bin/, testing/ layout

Move 17 library crates into crates/, CLI binary into bin/fxt,
consolidate 10 test crates into testing/, split config crate
from deployment config files.

Root directory reduced from 38+ to ~17 directories.
All Cargo.toml paths and build.rs proto refs updated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-02-25 11:18:20 +01:00
parent c821f2bec8
commit 9c3d741a08
1967 changed files with 140 additions and 139 deletions

View File

@@ -0,0 +1,127 @@
//! # 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_owned(),
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_owned(),
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_owned(),
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
}
}