#![warn(missing_docs)] #![deny(clippy::unwrap_used)] #![deny(clippy::expect_used)] //! # Foxhunt Backtesting Service //! //! Standalone backtesting service for the Foxhunt HFT trading system. //! This service provides comprehensive strategy testing and performance analysis capabilities. use anyhow::{Context, Result}; use std::net::SocketAddr; use tonic::transport::Server; use tracing::{info, warn}; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; mod model_loader_stub; mod performance; mod repositories; mod repository_impl; mod service; mod storage; mod strategy_engine; // Import the generated gRPC code mod foxhunt { pub mod tli { tonic::include_proto!("foxhunt.tli"); } } use config::structures::BacktestingDatabaseConfig; use model_loader_stub::backtesting_cache::{BacktestCacheConfig, BacktestingModelCache}; use repository_impl::create_repositories; use service::BacktestingServiceImpl; use std::sync::Arc; use storage::StorageManager; /// Main entry point for the backtesting service #[tokio::main] async fn main() -> Result<()> { // Initialize logging init_logging()?; info!("Starting Foxhunt Backtesting Service"); // Get database configuration from environment let database_url = std::env::var("DATABASE_URL").context("DATABASE_URL environment variable is required")?; // Wave 67 Agent 2: Optimized database configuration for backtesting workloads // Based on Wave 66 Agent 8 analysis - increased statement cache for better performance let database_config = BacktestingDatabaseConfig { database_url, max_connections: Some(10), min_connections: Some(2), acquire_timeout_ms: Some(5000), statement_cache_capacity: Some(500), // Increased from 100 to 500 for better cache hit rate enable_logging: Some(false), }; // Configuration loaded from environment info!("Configuration loaded from environment variables"); info!("Backtesting configuration loaded successfully"); // Initialize storage manager let storage_manager = Arc::new( StorageManager::new(&database_config) .await .context("Failed to initialize storage manager")?, ); // Initialize model cache for backtesting with shared directory let cache_config = BacktestCacheConfig { cache_dir: std::env::var("MODEL_CACHE_DIR") .unwrap_or_else(|_| "/tmp/foxhunt/model_cache".to_string()) .into(), ..Default::default() }; let mut model_cache = BacktestingModelCache::new(cache_config) .await .context("Failed to create BacktestingModelCache for backtesting")?; // Initialize model cache - this will scan for existing models model_cache .initialize() .await .context("Failed to initialize ModelCache")?; let model_cache = Arc::new(model_cache); info!("Backtesting model cache initialized with historical version support"); // Create repositories with dependency injection let repositories = Arc::new( create_repositories(storage_manager) .await .context("Failed to create repositories")?, ); // Initialize the service with repository injection and model cache let service = BacktestingServiceImpl::new(repositories, Some(Arc::clone(&model_cache))) .await .context("Failed to initialize backtesting service")?; // Setup gRPC server let grpc_port = std::env::var("GRPC_PORT") .ok() .and_then(|s| s.parse().ok()) .unwrap_or(50052); let addr: SocketAddr = format!("0.0.0.0:{}", grpc_port) .parse() .context("Invalid server address in configuration")?; info!("Starting gRPC server on {}", addr); // Wave 67 Agent 3: HTTP/2 streaming performance optimizations // Apply same optimizations as other services for consistency let enable_http2_opts = std::env::var("ENABLE_HTTP2_OPTIMIZATIONS") .ok() .and_then(|v| v.parse().ok()) .unwrap_or(true); if enable_http2_opts { info!("✅ HTTP/2 optimizations enabled:"); info!(" - tcp_nodelay: true (-40ms Nagle delay)"); info!(" - Stream window: 1MB"); info!(" - Connection window: 10MB"); info!(" - Adaptive window: true"); info!(" - Max streams: 1000"); } else { info!("⚠️ HTTP/2 optimizations disabled via feature flag"); } // Start the server with HTTP/2 optimizations let mut server_builder = Server::builder(); if enable_http2_opts { server_builder = server_builder .tcp_nodelay(true) // Critical: eliminates 40ms Nagle delay .http2_keepalive_interval(Some(std::time::Duration::from_secs(30))) .http2_keepalive_timeout(Some(std::time::Duration::from_secs(10))) .initial_stream_window_size(Some(1024 * 1024)) // 1MB .initial_connection_window_size(Some(10 * 1024 * 1024)) // 10MB .http2_adaptive_window(Some(true)) .max_concurrent_streams(Some(1000)); } server_builder .add_service( foxhunt::tli::backtesting_service_server::BacktestingServiceServer::new(service), ) .serve(addr) .await .context("gRPC server failed")?; Ok(()) } /// Initialize logging with structured output fn init_logging() -> Result<()> { tracing_subscriber::registry() .with( tracing_subscriber::EnvFilter::try_from_default_env() .unwrap_or_else(|_| "backtesting_service=info,tower=warn".into()), ) .with(tracing_subscriber::fmt::layer()) .try_init() .context("Failed to initialize logging")?; Ok(()) }