**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
286 lines
8.2 KiB
Rust
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"
|
|
);
|
|
}
|