//! Multi-Day DBN Loading Example //! //! This example shows how to load data from multiple DBN files (multi-day backtests). //! //! ## Usage //! //! ```bash //! cargo run --example dbn_multi_day_loading //! ``` use backtesting_service::dbn_data_source::DbnDataSource; use std::collections::HashMap; #[tokio::main] async fn main() -> anyhow::Result<()> { println!("=== DBN Multi-Day Loading Example ===\n"); // 1. Create file mapping with multiple files per symbol let mut file_mapping = HashMap::new(); file_mapping.insert( "ESH4".to_string(), vec![ "test_data/real/databento/ESH4_ohlcv-1m_2024-01-03.dbn".to_string(), "test_data/real/databento/ESH4_ohlcv-1m_2024-01-04.dbn".to_string(), "test_data/real/databento/ESH4_ohlcv-1m_2024-01-05.dbn".to_string(), ], ); println!("Creating data source with 3 files for ESH4..."); // 2. Create data source (multi-file mode) let data_source = DbnDataSource::new_multi_file(file_mapping).await?; println!("Files configured: {}", data_source.get_file_count("ESH4")); // 3. Load all files (merged and sorted) println!("\nLoading all days for ESH4..."); let start = std::time::Instant::now(); let bars = data_source.load_ohlcv_bars_all("ESH4").await?; let duration = start.elapsed(); println!( "āœ… Loaded {} bars from {} files in {:?} ({:.2}ms)", bars.len(), 3, duration, duration.as_secs_f64() * 1000.0 ); // 4. Analyze data by day println!("\n=== Data by Day ==="); let mut day_stats: HashMap> = HashMap::new(); for bar in &bars { let day = bar.timestamp.format("%Y-%m-%d").to_string(); day_stats.entry(day).or_default().push(bar); } for (day, bars_for_day) in day_stats.iter() { let first = bars_for_day.first().unwrap(); let last = bars_for_day.last().unwrap(); println!( "{}: {} bars | {} to {} | Range: {} to {}", day, bars_for_day.len(), first.timestamp.format("%H:%M"), last.timestamp.format("%H:%M"), first.close, last.close ); } // 5. Verify chronological ordering across all days println!("\n=== Cross-Day Validation ==="); let mut ordered = true; for i in 1..bars.len() { if bars[i].timestamp < bars[i - 1].timestamp { println!( "āŒ Ordering issue at index {}: {} < {}", i, bars[i].timestamp, bars[i - 1].timestamp ); ordered = false; break; } } if ordered { println!("āœ… All bars properly ordered across {} days", day_stats.len()); } // 6. Calculate daily returns println!("\n=== Daily Returns ==="); for (day, bars_for_day) in day_stats.iter() { if bars_for_day.len() > 1 { let first_close = bars_for_day.first().unwrap().close; let last_close = bars_for_day.last().unwrap().close; let return_pct = ((last_close - first_close) / first_close * rust_decimal::Decimal::from(100)) .to_string() .parse::() .unwrap(); println!("{}: {:.2}% return", day, return_pct); } } println!("\nāœ… Example completed successfully!"); Ok(()) }