Files
foxhunt/adaptive-strategy/tests/tlob_integration.rs
jgrusewski d7697823cb Wave 139: Regime detection fixes - 13/19 tests passing (68.4%)
**Agent Execution Summary (10+ parallel agents):**
- Agent 180: Fixed trend detection feature indexing for 6-feature simplified mode
- Agent 182: Fixed volume test to read correct feature index (5 instead of 0)
- Agent 183: Fixed crisis confidence calculation (added to agreement check, increased bonus 0.25→0.30)
- Agent 187: Eliminated all 55 compilation warnings → 0 warnings
- Agent 188: Implemented mode-aware feature extraction (simplified vs full)
- Agent 190: Fixed 4 blocking compilation errors (Cargo.toml + type errors in examples)

**Key Production Fixes:**
1. Crisis detection confidence boost (lines 4541, 4573 in mod.rs)
2. Mode-aware feature extraction (lines 776-857 in mod.rs)
3. Trend detection indexing for 6-feature mode (lines 4476-4501 in mod.rs)
4. Volume test index correction (line 566 in regime_transition_tests.rs)

**Test Results:**
- Workspace: 198/206 tests (96.1%)
- Regime tests: 13/19 tests (68.4%)
- Compilation: Clean (0 errors, 0 warnings)

**Files Modified:**
- adaptive-strategy/src/regime/mod.rs (crisis confidence, mode-aware extraction, trend indexing)
- adaptive-strategy/tests/regime_transition_tests.rs (volume test fix, warning suppressions)
- adaptive-strategy/Cargo.toml (lint configuration fix)
- data/examples/*.rs (type error fixes)

**Remaining Work:**
6 test failures to fix for 100% target:
- test_regime_detection_volatile_to_stable
- test_regime_detection_trending_to_ranging
- test_volume_regime_thin_to_thick_liquidity
- test_volatility_regime_low_to_high_to_low
- test_extreme_market_conditions
- test_feature_extraction_with_regime_change
2025-10-11 22:11:21 +02:00

286 lines
8.2 KiB
Rust

#![allow(unused_crate_dependencies)]
//! Integration tests for TLOB model integration
//! Tests the complete TLOB functionality within adaptive-strategy
use adaptive_strategy::models::{ModelConfig, ModelFactory};
use std::time::Instant;
/// Create test order book features matching TLOB requirements
fn create_test_tlob_features() -> Vec<f64> {
let mut features = Vec::with_capacity(51);
// Bid prices (10 levels, decreasing)
for i in 0..10 {
features.push(100.0 - (i as f64 * 0.01));
}
// Ask prices (10 levels, increasing)
for i in 0..10 {
features.push(100.01 + (i as f64 * 0.01));
}
// Bid volumes (10 levels)
for i in 0..10 {
features.push(1000.0 + (i as f64 * 100.0));
}
// Ask volumes (10 levels)
for i in 0..10 {
features.push(1100.0 + (i as f64 * 100.0));
}
// Market data: last_price, volume, volatility, momentum
features.extend_from_slice(&[100.005, 5000.0, 0.02, 0.001]);
// Microstructure features (7 values)
features.extend_from_slice(&[0.1, 0.2, 0.15, 0.3, 0.25, 0.05, 0.08]);
assert_eq!(features.len(), 51);
features
}
#[tokio::test]
async fn test_tlob_model_creation() {
let config = ModelConfig::default();
let result =
ModelFactory::create_model("tlob", "test_tlob_integration".to_string(), config).await;
assert!(result.is_ok(), "Should be able to create TLOB model");
let model = result.unwrap();
assert_eq!(model.name(), "test_tlob_integration");
assert_eq!(model.model_type(), "tlob");
assert!(model.is_ready());
}
#[tokio::test]
async fn test_tlob_prediction_functionality() {
let config = ModelConfig::default();
let model = ModelFactory::create_model("tlob", "test_prediction".to_string(), config)
.await
.unwrap();
let features = create_test_tlob_features();
let result = model.predict(&features).await;
assert!(result.is_ok(), "TLOB prediction should succeed");
let prediction = result.unwrap();
// Validate prediction structure
assert!(prediction.confidence >= 0.0 && prediction.confidence <= 1.0);
assert!(!prediction.features_used.is_empty());
// Check metadata
if let Some(metadata) = prediction.metadata {
assert!(metadata.contains_key("model_type"));
assert_eq!(metadata["model_type"], "tlob");
assert!(metadata.contains_key("extraction_time_ns"));
}
}
#[tokio::test]
async fn test_tlob_performance_target() {
let config = ModelConfig::default();
let model = ModelFactory::create_model("tlob", "test_performance".to_string(), config)
.await
.unwrap();
let features = create_test_tlob_features();
// Warm up the model
for _ in 0..5 {
let _ = model.predict(&features).await.unwrap();
}
// Measure performance over multiple predictions
let mut total_time_ns = 0u64;
let iterations = 100;
for _ in 0..iterations {
let start = Instant::now();
let _result = model.predict(&features).await.unwrap();
total_time_ns += start.elapsed().as_nanos() as u64;
}
let avg_time_ns = total_time_ns / iterations;
let avg_time_us = avg_time_ns as f64 / 1000.0;
println!("Average prediction time: {:.2}μs", avg_time_us);
// Verify sub-50μs target (with some tolerance for test environment)
assert!(
avg_time_us < 100.0,
"Average prediction time {:.2}μs should be reasonable (target <50μs)",
avg_time_us
);
}
#[tokio::test]
async fn test_tlob_model_metadata() {
let config = ModelConfig::default();
let model = ModelFactory::create_model("tlob", "test_metadata".to_string(), config)
.await
.unwrap();
let metadata = model.get_metadata();
assert_eq!(metadata.model_type, "tlob");
assert_eq!(metadata.input_dimensions, 51);
assert!(metadata.description.is_some());
assert!(metadata.description.unwrap().contains("TLOB"));
// Check parameters
assert!(metadata.parameters.contains_key("feature_dim"));
assert!(metadata.parameters.contains_key("prediction_horizon"));
}
#[tokio::test]
async fn test_tlob_model_performance_metrics() {
let config = ModelConfig::default();
let model = ModelFactory::create_model("tlob", "test_metrics".to_string(), config)
.await
.unwrap();
let features = create_test_tlob_features();
// Make some predictions
for _ in 0..10 {
let _ = model.predict(&features).await.unwrap();
}
let performance = model.get_performance().await.unwrap();
assert!(performance.accuracy >= 0.0 && performance.accuracy <= 1.0);
assert!(performance.prediction_count >= 10);
}
#[tokio::test]
async fn test_tlob_invalid_features() {
let config = ModelConfig::default();
let model = ModelFactory::create_model("tlob", "test_invalid".to_string(), config)
.await
.unwrap();
// Test with insufficient features
let invalid_features = vec![1.0; 30]; // Only 30 features instead of 51
let result = model.predict(&invalid_features).await;
assert!(result.is_err(), "Should fail with insufficient features");
}
#[tokio::test]
async fn test_tlob_model_memory_usage() {
let config = ModelConfig::default();
let model = ModelFactory::create_model("tlob", "test_memory".to_string(), config)
.await
.unwrap();
let memory_usage = model.memory_usage();
assert!(
memory_usage > 0,
"Model should report non-zero memory usage"
);
assert!(
memory_usage < 100 * 1024 * 1024,
"Memory usage should be reasonable (<100MB)"
);
}
#[tokio::test]
async fn test_tlob_model_configuration() {
let mut config = ModelConfig::default();
config.batch_size = 16;
config.custom_parameters.insert(
"prediction_horizon".to_string(),
serde_json::Value::Number(serde_json::Number::from(5)),
);
let model = ModelFactory::create_model("tlob", "test_config".to_string(), config)
.await
.unwrap();
let metadata = model.get_metadata();
assert_eq!(
metadata.parameters["prediction_horizon"].as_u64().unwrap(),
5
);
}
#[tokio::test]
async fn test_tlob_concurrent_predictions() {
let config = ModelConfig::default();
let model = std::sync::Arc::new(
ModelFactory::create_model("tlob", "test_concurrent".to_string(), config)
.await
.unwrap(),
);
let features = create_test_tlob_features();
let mut tasks = Vec::new();
// Launch concurrent prediction tasks
for _i in 0..4 {
let model_clone = model.clone();
let features_clone = features.clone();
let task = tokio::spawn(async move { model_clone.predict(&features_clone).await.unwrap() });
tasks.push(task);
}
// Wait for all predictions to complete
let results = futures::future::join_all(tasks).await;
assert_eq!(results.len(), 4);
for result in results {
assert!(result.is_ok(), "Concurrent prediction should succeed");
}
}
#[tokio::test]
async fn test_model_factory_available_models() {
let available = ModelFactory::available_models();
assert!(
available.contains(&"tlob"),
"TLOB should be in available models"
);
}
// Performance stress test
#[tokio::test]
async fn test_tlob_sustained_load() {
let config = ModelConfig::default();
let model = ModelFactory::create_model("tlob", "test_sustained".to_string(), config)
.await
.unwrap();
let features = create_test_tlob_features();
// Sustained prediction load
let start_time = Instant::now();
let prediction_count = 1000;
for _ in 0..prediction_count {
let result = model.predict(&features).await;
assert!(result.is_ok(), "Sustained predictions should not fail");
}
let elapsed = start_time.elapsed();
let avg_per_prediction = elapsed.as_nanos() as f64 / prediction_count as f64 / 1000.0;
println!(
"Sustained load: {} predictions in {:.2}ms (avg {:.2}μs per prediction)",
prediction_count,
elapsed.as_millis(),
avg_per_prediction
);
// Verify reasonable performance under sustained load
assert!(
avg_per_prediction < 200.0,
"Average prediction time under sustained load should be reasonable"
);
}