- 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.
160 lines
5.1 KiB
Python
160 lines
5.1 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Verify chronological sequence of training and unseen validation data.
|
|
Uses databento to read parquet files.
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
|
|
def main():
|
|
try:
|
|
import databento as db
|
|
from datetime import datetime
|
|
|
|
print("=" * 60)
|
|
print("TRAINING DATA (ES_FUT_180d.parquet)")
|
|
print("=" * 60)
|
|
|
|
# Read training data
|
|
train_store = db.DBNStore.from_file('test_data/ES_FUT_180d.parquet')
|
|
train_df = train_store.to_df()
|
|
train_rows = len(train_df)
|
|
|
|
print(f"Rows: {train_rows:,}")
|
|
print(f"File size: 2.9M")
|
|
print(f"Columns: {list(train_df.columns)}")
|
|
|
|
train_start = train_df.index[0]
|
|
train_end = train_df.index[-1]
|
|
|
|
print(f"\nDate range:")
|
|
print(f" Start: {train_start}")
|
|
print(f" End: {train_end}")
|
|
|
|
# Read unseen data
|
|
print("\n" + "=" * 60)
|
|
print("UNSEEN VALIDATION DATA (ES_FUT_unseen.parquet)")
|
|
print("=" * 60)
|
|
|
|
unseen_store = db.DBNStore.from_file('test_data/ES_FUT_unseen.parquet')
|
|
unseen_df = unseen_store.to_df()
|
|
unseen_rows = len(unseen_df)
|
|
|
|
print(f"Rows: {unseen_rows:,}")
|
|
print(f"File size: 224K")
|
|
print(f"Columns: {list(unseen_df.columns)}")
|
|
|
|
unseen_start = unseen_df.index[0]
|
|
unseen_end = unseen_df.index[-1]
|
|
|
|
print(f"\nDate range:")
|
|
print(f" Start: {unseen_start}")
|
|
print(f" End: {unseen_end}")
|
|
|
|
# Check chronological sequence
|
|
print("\n" + "=" * 60)
|
|
print("CHRONOLOGICAL SEQUENCE CHECK")
|
|
print("=" * 60)
|
|
|
|
gap = unseen_start - train_end
|
|
gap_seconds = gap.total_seconds()
|
|
gap_days = gap_seconds / 86400
|
|
|
|
print(f"Training ends: {train_end}")
|
|
print(f"Unseen starts: {unseen_start}")
|
|
print(f"Gap: {gap} ({gap_seconds:,.0f} seconds = {gap_days:.1f} days)")
|
|
|
|
if gap_seconds < 0:
|
|
print(f"⚠️ OVERLAP: Unseen data starts BEFORE training ends!")
|
|
status = "FAILED"
|
|
elif gap_seconds == 0:
|
|
print(f"✅ PERFECT: No gap, immediate continuation")
|
|
status = "EXISTS"
|
|
elif gap_seconds <= 86400:
|
|
print(f"✅ ACCEPTABLE: Gap is less than 1 day")
|
|
status = "EXISTS"
|
|
else:
|
|
print(f"⚠️ GAP: {gap_days:.1f} days between training and unseen data")
|
|
status = "FAILED"
|
|
|
|
# Calculate unseen duration
|
|
unseen_duration = unseen_end - unseen_start
|
|
days = unseen_duration.total_seconds() / 86400
|
|
print(f"\nUnseen data duration: {days:.1f} days")
|
|
|
|
short_data = False
|
|
if days < 30:
|
|
print(f"⚠️ WARNING: Only {days:.1f} days (recommended: 30-90 days)")
|
|
short_data = True
|
|
else:
|
|
print(f"✅ GOOD: {days:.1f} days of validation data")
|
|
|
|
# Data quality check
|
|
print("\n" + "=" * 60)
|
|
print("DATA QUALITY CHECK")
|
|
print("=" * 60)
|
|
|
|
null_counts = unseen_df.isnull().sum()
|
|
total_nulls = null_counts.sum()
|
|
print(f"Null values: {dict(null_counts[null_counts > 0])}")
|
|
print(f"Total nulls: {total_nulls}")
|
|
|
|
has_nulls = total_nulls > 0
|
|
if has_nulls:
|
|
print(f"⚠️ WARNING: {total_nulls} null values detected")
|
|
else:
|
|
print("✅ No null values")
|
|
|
|
print(f"\nPrice stats (close):")
|
|
print(f" Min: ${unseen_df['close'].min():.2f}")
|
|
print(f" Max: ${unseen_df['close'].max():.2f}")
|
|
print(f" Mean: ${unseen_df['close'].mean():.2f}")
|
|
|
|
print(f"\nVolume stats:")
|
|
print(f" Total: {unseen_df['volume'].sum():,.0f}")
|
|
print(f" Mean: {unseen_df['volume'].mean():,.0f}")
|
|
|
|
# Final verdict
|
|
print("\n" + "=" * 60)
|
|
print("FINAL VERDICT")
|
|
print("=" * 60)
|
|
|
|
if status == "FAILED":
|
|
print(f"❌ FAILED: Need to re-download - chronological gap/overlap issue")
|
|
ready = "NO"
|
|
elif has_nulls:
|
|
print(f"❌ FAILED: Null values detected - need to re-download")
|
|
ready = "NO"
|
|
elif short_data:
|
|
print(f"⚠️ WARNING: Data exists but only {days:.1f} days (recommend 30-90)")
|
|
ready = "PARTIAL"
|
|
else:
|
|
print(f"✅ PASSED: Data is valid and ready for backtest")
|
|
ready = "YES"
|
|
|
|
print(f"\nStatus: {status}")
|
|
print(f"Ready for backtest: {ready}")
|
|
|
|
return 0 if ready in ["YES", "PARTIAL"] else 1
|
|
|
|
except ImportError as e:
|
|
print(f"ERROR: {e}")
|
|
print("\nDatabento is not installed. Installing...")
|
|
os.system("pip3 install --user databento --break-system-packages")
|
|
print("\nPlease run this script again after installation.")
|
|
return 2
|
|
except FileNotFoundError as e:
|
|
print(f"ERROR: File not found: {e}")
|
|
print("\nThe unseen validation data doesn't exist.")
|
|
print("Will need to download it from Databento.")
|
|
return 3
|
|
except Exception as e:
|
|
print(f"ERROR: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return 4
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|