Files
foxhunt/docs/examples/dbn_multi_day_loading.rs
jgrusewski e8a68ee39f Download 360 DBN files (36.3 MB) using Rust databento client
- Created data/examples/download_ml_training_data.rs using reqwest + Databento HTTP API
- Downloaded 90 days × 4 symbols (ES.FUT, NQ.FUT, ZN.FUT, 6E.FUT)
- Files saved to test_data/real/databento/ml_training/
- Total: 360 files, 15 MB compressed DBN format
- Used existing Rust pattern from download_nq_fut.rs
- API key loaded from .env file
- 100% success rate (360/360 files)
- Ready for ML training benchmarks

Next: Create simplified training benchmark for RTX 3050 Ti GPU measurements
2025-10-13 13:30:02 +02:00

117 lines
3.4 KiB
Rust

//! 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<String, Vec<_>> = 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::<f64>()
.unwrap();
println!("{}: {:.2}% return", day, return_pct);
}
}
println!("\n✅ Example completed successfully!");
Ok(())
}