Files
foxhunt/download_es_databento_v2.py
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

217 lines
6.9 KiB
Python

#!/usr/bin/env python3
"""
Download ES.FUT data from Databento for different market regimes (V2).
This script downloads multiple days of E-mini S&P 500 futures data
using specific contract codes (ESH4, ESM4, etc.) to ensure data availability.
Usage:
python3 download_es_databento_v2.py
"""
import os
import sys
from datetime import datetime, timezone
import databento as db
# Configuration
API_KEY = os.getenv("DATABENTO_API_KEY", "db-95LEt9gtDRPJfc55NVUB5KL3A3uf6")
OUTPUT_DIR = "test_data/real/databento"
SCHEMA = "ohlcv-1m"
DATASET = "GLBX.MDP3"
# Target dates with specific contracts
# ESH4 = March 2024 contract (expires mid-March)
# ESM4 = June 2024 contract (expires mid-June)
DOWNLOAD_CONFIGS = [
{
"date": "2024-01-03",
"symbol": "ESH4",
"regime": "Trending",
"description": "Strong uptrend continuation from Jan 2"
},
{
"date": "2024-01-04",
"symbol": "ESH4",
"regime": "Ranging",
"description": "Consolidation, sideways movement"
},
{
"date": "2024-01-05",
"symbol": "ESH4",
"regime": "Volatile",
"description": "High volatility, whipsaws"
},
]
def main():
"""Download ES futures data for multiple days."""
print("=" * 80)
print("ES Futures Multi-Day Databento Download (V2)")
print("=" * 80)
print()
# Check API key
if not API_KEY:
print("❌ ERROR: DATABENTO_API_KEY not found in environment!")
print("Set it with: export DATABENTO_API_KEY='your-key-here'")
sys.exit(1)
# Create output directory
os.makedirs(OUTPUT_DIR, exist_ok=True)
print(f"📁 Output directory: {OUTPUT_DIR}")
print(f"📊 Schema: {SCHEMA}")
print(f"📦 Dataset: {DATASET}")
print()
# Initialize Databento client
try:
client = db.Historical(API_KEY)
print("✅ Databento client initialized")
except Exception as e:
print(f"❌ Failed to initialize Databento client: {e}")
sys.exit(1)
# Track results
total_cost = 0.0
successful_downloads = []
failed_downloads = []
# Download each date
for config in DOWNLOAD_CONFIGS:
date_str = config["date"]
symbol = config["symbol"]
regime = config["regime"]
description = config["description"]
print()
print("-" * 80)
print(f"📥 Downloading: {date_str} ({regime})")
print(f" Symbol: {symbol}")
print(f" {description}")
print("-" * 80)
try:
# Parse date (start at midnight UTC, end at 23:59:59 UTC)
start_date = datetime.strptime(date_str, "%Y-%m-%d").replace(tzinfo=timezone.utc)
end_date = start_date.replace(hour=23, minute=59, second=59)
# Build output filename
output_file = os.path.join(OUTPUT_DIR, f"{symbol}_{SCHEMA}_{date_str}.dbn")
# Download data
print(f" Start: {start_date.isoformat()}")
print(f" End: {end_date.isoformat()}")
print(f" Output: {output_file}")
print()
# Request data
data = client.timeseries.get_range(
dataset=DATASET,
symbols=[symbol],
schema=SCHEMA,
start=start_date.isoformat(),
end=end_date.isoformat(),
)
# Write to file
data.to_file(output_file)
# Get file size
file_size = os.path.getsize(output_file)
file_size_kb = file_size / 1024
# Read back to verify data count
try:
store = db.DBNStore.from_file(output_file)
df = store.to_df()
record_count = len(df)
print(f"✅ Download complete!")
print(f" File size: {file_size:,} bytes ({file_size_kb:.2f} KB)")
print(f" Records: {record_count}")
# Show sample data
if record_count > 0:
print(f" Price range: ${df['close'].min():.2f} - ${df['close'].max():.2f}")
print(f" Volume: {df['volume'].sum():,.0f}")
else:
print(" ⚠️ WARNING: No records in file!")
except Exception as e:
print(f"✅ Download complete!")
print(f" File size: {file_size:,} bytes ({file_size_kb:.2f} KB)")
print(f" ⚠️ Could not verify record count: {e}")
# Estimate cost (rough: ~$0.10 per day of 1-minute OHLCV data)
estimated_cost = 0.10
total_cost += estimated_cost
print(f" Estimated cost: ${estimated_cost:.2f}")
successful_downloads.append({
"date": date_str,
"symbol": symbol,
"regime": regime,
"path": output_file,
"size_kb": file_size_kb
})
except Exception as e:
print(f"❌ Download failed for {date_str}: {e}")
failed_downloads.append((date_str, symbol, str(e)))
# Summary
print()
print("=" * 80)
print("📊 DOWNLOAD SUMMARY")
print("=" * 80)
print()
print(f"✅ Successful: {len(successful_downloads)}/{len(DOWNLOAD_CONFIGS)}")
print(f"❌ Failed: {len(failed_downloads)}/{len(DOWNLOAD_CONFIGS)}")
print(f"💰 Total estimated cost: ${total_cost:.2f}")
print()
if successful_downloads:
print("✅ Successfully downloaded files:")
for download in successful_downloads:
print(f"{download['date']} ({download['regime']}): {download['symbol']} - {download['size_kb']:.2f} KB")
print()
if failed_downloads:
print("❌ Failed downloads:")
for date, symbol, error in failed_downloads:
print(f"{date} ({symbol}): {error}")
print()
# Regime classification summary
print("📋 REGIME CLASSIFICATION:")
for config in DOWNLOAD_CONFIGS:
status = "" if any(d["date"] == config["date"] for d in successful_downloads) else ""
print(f" {status} {config['date']} - {config['regime']}: {config['description']}")
print()
print("📋 NEXT STEPS:")
print("1. Validate each file:")
print(" cd /home/jgrusewski/Work/foxhunt")
print(" cargo run -p backtesting_service --example validate_dbn_data")
print("2. Use data for regime detection testing in adaptive strategy")
print("3. Analyze market characteristics:")
print(" • Price movements, volatility patterns")
print(" • Volume distribution")
print(" • Regime transition detection")
print()
if len(successful_downloads) >= 2:
print("✅ SUCCESS: Downloaded sufficient data for regime testing!")
elif len(successful_downloads) >= 1:
print("⚠️ WARNING: Only 1 day downloaded. Consider downloading more.")
else:
print("❌ ERROR: No data downloaded successfully!")
sys.exit(1)
if __name__ == "__main__":
main()