Files
foxhunt/docs/examples/dbn_backtesting_integration.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

155 lines
4.8 KiB
Rust

//! DBN Backtesting Integration Example
//!
//! This example demonstrates using DBN data with the backtesting service's
//! MarketDataRepository interface.
//!
//! ## Usage
//!
//! ```bash
//! cargo run --example dbn_backtesting_integration
//! ```
use backtesting_service::{
dbn_repository::DbnMarketDataRepository,
repositories::MarketDataRepository,
};
use chrono::{TimeZone, Utc};
use std::collections::HashMap;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
println!("=== DBN Backtesting Integration Example ===\n");
// 1. Setup repository with DBN data
let mut file_mapping = HashMap::new();
file_mapping.insert(
"ES.FUT".to_string(),
"test_data/real/databento/ES.FUT_ohlcv-1m_2024-01-02.dbn".to_string(),
);
println!("Creating MarketDataRepository with DBN backend...");
let repo = DbnMarketDataRepository::new(file_mapping).await?;
println!("Available symbols: {:?}", repo.available_symbols());
// 2. Define backtest time range
let start_time = Utc
.with_ymd_and_hms(2024, 1, 2, 14, 30, 0)
.unwrap()
.timestamp_nanos_opt()
.unwrap();
let end_time = Utc
.with_ymd_and_hms(2024, 1, 2, 16, 0, 0)
.unwrap()
.timestamp_nanos_opt()
.unwrap();
println!(
"\nBacktest window: {} to {}",
Utc.timestamp_nanos(start_time).format("%Y-%m-%d %H:%M:%S"),
Utc.timestamp_nanos(end_time).format("%Y-%m-%d %H:%M:%S")
);
// 3. Load historical data via repository interface
let symbols = vec!["ES.FUT".to_string()];
println!("\nLoading historical data for {:?}...", symbols);
let data = repo.load_historical_data(&symbols, start_time, end_time).await?;
println!("✅ Loaded {} bars via repository interface\n", data.len());
// 4. Check data availability
println!("=== Data Availability Check ===");
let availability = repo
.check_data_availability(&symbols, start_time, end_time)
.await?;
for (symbol, available) in availability.iter() {
println!(
"{}: {}",
symbol,
if *available { "✅ Available" } else { "❌ Not available" }
);
}
// 5. Simulate simple backtest logic
println!("\n=== Simulating Simple Backtest ===");
let mut position = 0i32;
let mut pnl = 0.0;
let mut trades = 0;
for (i, bar) in data.iter().enumerate() {
let close_f64 = bar.close.to_string().parse::<f64>().unwrap();
// Simple strategy: Buy when price drops, sell when price rises
if i > 0 {
let prev_close = data[i - 1].close.to_string().parse::<f64>().unwrap();
let price_change = close_f64 - prev_close;
if position == 0 && price_change < -1.0 {
// Buy signal
position = 1;
pnl -= close_f64; // Entry cost
trades += 1;
println!(" [{}] BUY @ {:.2}", bar.timestamp.format("%H:%M"), close_f64);
} else if position == 1 && price_change > 1.0 {
// Sell signal
position = 0;
pnl += close_f64; // Exit proceeds
trades += 1;
println!(" [{}] SELL @ {:.2}", bar.timestamp.format("%H:%M"), close_f64);
}
}
}
// Close any open position
if position != 0 {
let last_close = data.last().unwrap().close.to_string().parse::<f64>().unwrap();
pnl += last_close * position as f64;
trades += 1;
println!(
" [{}] CLOSE @ {:.2}",
data.last().unwrap().timestamp.format("%H:%M"),
last_close
);
}
println!("\n=== Backtest Results ===");
println!("Total trades: {}", trades);
println!("Final PnL: ${:.2}", pnl);
// 6. Advanced repository features
println!("\n=== Advanced Repository Features ===");
// Load with volume filter
let min_volume = rust_decimal::Decimal::from(50);
let high_volume_bars = repo
.load_with_volume_filter(&symbols, min_volume, start_time, end_time)
.await?;
println!(
"High-volume bars (volume >= {}): {}",
min_volume,
high_volume_bars.len()
);
// Get date range
let (first_ts, last_ts) = repo.get_date_range("ES.FUT").await?;
println!("Data range: {} to {}", first_ts, last_ts);
// Generate summary statistics
let stats = repo.generate_summary_stats(&data);
println!("\nSummary Statistics:");
println!(" Count: {}", stats.get("count").unwrap());
println!(" Mean close: ${:.2}", stats.get("mean_close").unwrap());
println!(" Std close: ${:.2}", stats.get("std_close").unwrap());
println!(" Min close: ${:.2}", stats.get("min_close").unwrap());
println!(" Max close: ${:.2}", stats.get("max_close").unwrap());
println!("\n✅ Example completed successfully!");
Ok(())
}