Files
foxhunt/download_sequential_validation.py
jgrusewski 8ce7c52586 fix(dqn): Update evaluation script feature dimension from 125 to 128
- Fixed feature dimension mismatch in evaluate_dqn_main_orchestrator.rs
- Updated all 5 occurrences: state_dim, input comments, feature vector type
- Aligned with Wave 16D training (128 features: 125 market + 3 portfolio)

Issue: Validation backtest reveals 100% HOLD action collapse - requires reward
system investigation and redesign per latest RL research.
2025-11-08 18:28:56 +01:00

186 lines
6.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
Download sequential validation data for DQN evaluation.
Training data ends: 2025-10-19 23:59:00+00:00
Unseen data should start: 2025-10-20 00:00:00+00:00
Today: 2025-11-08
We can download ~19 days of sequential data (Oct 20 - Nov 8).
"""
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"
SYMBOL = "ESZ5" # December 2025 contract (frontmonth for Oct-Nov 2025)
SCHEMA = "ohlcv-1m"
DATASET = "GLBX.MDP3"
# Date range: Sequential after training (Oct 20 - Nov 7, 2025)
# Training ends: 2025-10-19 23:59:00
# Unseen starts: 2025-10-20 00:00:00
# End: 2025-11-07 23:59:59 (leave 1 day buffer)
START_DATE = "2025-10-20"
END_DATE = "2025-11-07"
OUTPUT_FILE_DBN = "ES_FUT_unseen_sequential.dbn"
def main():
"""Download sequential validation data."""
print("=" * 80)
print("ES.FUT Sequential Validation Data Download")
print("=" * 80)
print()
# Check API key
if not API_KEY or API_KEY == "your-key-here":
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"🎯 Symbol: {SYMBOL}")
print(f"📊 Schema: {SCHEMA}")
print(f"📦 Dataset: {DATASET}")
print(f"📅 Date range: {START_DATE} to {END_DATE}")
print()
print("📌 Context:")
print(" Training data ends: 2025-10-19 23:59:00+00:00")
print(" Unseen data starts: 2025-10-20 00:00:00+00:00")
print(" Duration: ~19 days (sequential continuation)")
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)
print()
print("-" * 80)
print(f"📥 Downloading sequential validation data: {START_DATE} to {END_DATE}")
print("-" * 80)
try:
# Parse dates
start_dt = datetime.strptime(START_DATE, "%Y-%m-%d").replace(
hour=0, minute=0, second=0, tzinfo=timezone.utc
)
end_dt = datetime.strptime(END_DATE, "%Y-%m-%d").replace(
hour=23, minute=59, second=59, tzinfo=timezone.utc
)
# Build output path
output_path = os.path.join(OUTPUT_DIR, OUTPUT_FILE_DBN)
print(f" Start: {start_dt.isoformat()}")
print(f" End: {end_dt.isoformat()}")
print(f" Output: {output_path}")
print()
# Download data
days_count = (end_dt - start_dt).days + 1
print(f"⏳ Downloading... (this may take 1-3 minutes for {days_count} days)")
data = client.timeseries.get_range(
dataset=DATASET,
symbols=[SYMBOL],
schema=SCHEMA,
start=start_dt.isoformat(),
end=end_dt.isoformat(),
)
# Write to file
print("💾 Writing to DBN file...")
data.to_file(output_path)
# Get file size
file_size = os.path.getsize(output_path)
file_size_mb = file_size / (1024 * 1024)
print()
print("✅ Download complete!")
print(f" File: {output_path}")
print(f" Size: {file_size:,} bytes ({file_size_mb:.2f} MB)")
print()
# Verify data with databento
try:
store = db.DBNStore.from_file(output_path)
df = store.to_df()
record_count = len(df)
print("📊 Data Summary:")
print(f" Total bars: {record_count:,}")
print(f" Expected bars ({days_count} days × ~150 bars/day): ~{days_count * 150:,}")
if record_count > 0:
print(f" Date range: {df.index[0]} to {df.index[-1]}")
print(f" Price range: ${df['close'].min():.2f} - ${df['close'].max():.2f}")
print(f" Total volume: {df['volume'].sum():,.0f}")
# Market balance check
bullish_bars = (df['close'] > df['open']).sum()
bullish_pct = 100 * bullish_bars / record_count
trend_pct = 100 * (df['close'].iloc[-1] - df['close'].iloc[0]) / df['close'].iloc[0]
print(f" Bullish bars: {bullish_pct:.1f}%")
print(f" Overall trend: {trend_pct:+.2f}%")
# Assess balance
if 40 <= bullish_pct <= 60:
print(f" ✅ Market balance: GOOD (40-60% range)")
elif 30 <= bullish_pct <= 70:
print(f" ⚠️ Market balance: ACCEPTABLE (30-70% range)")
else:
print(f" ❌ Market balance: BIASED (outside 30-70% range)")
else:
print(" ⚠️ WARNING: No records in file!")
except Exception as e:
print(f"⚠️ Could not verify data with databento: {e}")
print(" (File downloaded but verification failed)")
# Estimate cost
estimated_cost = 0.10 * days_count # ~$0.10 per day
print()
print(f"💰 Estimated cost: ${estimated_cost:.2f}")
print()
print("=" * 80)
print("📋 NEXT STEPS")
print("=" * 80)
print()
print("The DBN file has been downloaded. It will be automatically")
print("converted to parquet format and renamed.")
print()
print("To manually convert (if needed):")
print(f" cargo run -p data --example convert_dbn_to_parquet --release -- \\")
print(f" --input {output_path} \\")
print(f" --output test_data")
print()
print("✅ SUCCESS: Sequential validation data downloaded!")
except Exception as e:
print()
print(f"❌ Download failed: {e}")
print()
print("Possible issues:")
print(" • API key invalid or expired")
print(" • Databento API rate limit exceeded")
print(" • Network connectivity issues")
print(" • Data not available for requested date range (future dates?)")
sys.exit(1)
if __name__ == "__main__":
main()