Files
DOLPHIN/nautilus_dolphin/run_full_backtest.py
hjnormey 01c19662cb initial: import DOLPHIN baseline 2026-04-21 from dolphinng5_predict working tree
Includes core prod + GREEN/BLUE subsystems:
- prod/ (BLUE harness, configs, scripts, docs)
- nautilus_dolphin/ (GREEN Nautilus-native impl + dvae/ preserved)
- adaptive_exit/ (AEM engine + models/bucket_assignments.pkl)
- Observability/ (EsoF advisor, TUI, dashboards)
- external_factors/ (EsoF producer)
- mc_forewarning_qlabs_fork/ (MC regime/envelope)

Excludes runtime caches, logs, backups, and reproducible artifacts per .gitignore.
2026-04-21 16:58:38 +02:00

263 lines
9.3 KiB
Python
Executable File

"""
FULL BACKTEST EXECUTION - Nautilus-Dolphin vs itest_v7 Comparison
=================================================================
This script runs a complete Nautilus-Dolphin backtest with tight_3_3
configuration and compares results to itest_v7 reference data.
Usage:
python run_full_backtest.py [--output OUTPUT_DIR]
"""
import argparse
import asyncio
import json
import sys
from pathlib import Path
from datetime import datetime
from typing import Dict, List, Any
# Add parent to path
sys.path.insert(0, str(Path(__file__).parent))
# Check Nautilus availability
try:
from nautilus_trader.config import TradingNodeConfig
NAUTILUS_AVAILABLE = True
print("[OK] Nautilus Trader is available")
except ImportError as e:
NAUTILUS_AVAILABLE = False
print(f"[WARN] Nautilus Trader not available: {e}")
async def run_full_backtest(output_dir: str = "backtest_results"):
"""
Run full Nautilus-Dolphin backtest.
Parameters
----------
output_dir : str
Directory to save backtest results
"""
print("=" * 80)
print("NAUTILUS-DOLPHIN FULL BACKTEST")
print("=" * 80)
print(f"Start Time: {datetime.now().isoformat()}")
print(f"Nautilus Available: {NAUTILUS_AVAILABLE}")
print()
# Configuration matching itest_v7 tight_3_3
config = {
'venue': 'BINANCE_FUTURES',
'environment': 'BACKTEST',
'trader_id': 'DOLPHIN-BACKTEST-001',
'strategy': {
'venue': 'BINANCE_FUTURES',
'max_leverage': 2.5,
'min_leverage': 0.5,
'leverage_convexity': 3.0,
'capital_fraction': 0.15,
'max_hold_bars': 120,
'tp_bps': 99,
'irp_alignment_min': 0.45,
'momentum_magnitude_min': 0.000075,
'excluded_assets': ['TUSDUSDT', 'USDCUSDT'],
'acb_enabled': True,
'max_concurrent_positions': 10,
'daily_loss_limit_pct': 10.0,
},
'signal_bridge': {
'redis_url': 'redis://localhost:6379',
'stream_key': 'dolphin:signals:stream',
'max_signal_age_sec': 60,
},
'data_catalog': {
'eigenvalues_dir': '../eigenvalues',
'catalog_path': 'nautilus_dolphin/catalog',
'start_date': '2025-12-31',
'end_date': '2026-02-14',
'assets': [
'BTCUSDT', 'ETHUSDT', 'ADAUSDT', 'SOLUSDT', 'DOTUSDT',
'AVAXUSDT', 'MATICUSDT', 'LINKUSDT', 'UNIUSDT', 'ATOMUSDT'
],
},
}
print("Configuration (tight_3_3 from itest_v7):")
print(f" Max Leverage: {config['strategy']['max_leverage']}x")
print(f" Capital Fraction: {config['strategy']['capital_fraction']}")
print(f" Max Hold Bars: {config['strategy']['max_hold_bars']}")
print(f" IRP Alignment Min: {config['strategy']['irp_alignment_min']}")
print(f" Date Range: {config['data_catalog']['start_date']} to {config['data_catalog']['end_date']}")
print()
# Create output directory
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
print("Phase 1: Reference Data Loading")
print("-" * 40)
# Load reference data
reference_results_file = Path('../itest_v7_results.json')
reference_trades_file = Path('../itest_v7_trades.jsonl')
reference_data = None
if reference_results_file.exists():
with open(reference_results_file, 'r') as f:
ref_data = json.load(f)
reference_data = ref_data['strategies']['tight_3_3']
print(f"[OK] Reference results loaded: {reference_data['trades']} trades")
else:
print(f"[WARN] Reference results not found: {reference_results_file}")
if reference_trades_file.exists():
ref_trade_count = 0
with open(reference_trades_file, 'r') as f:
for line in f:
data = json.loads(line.strip())
if data.get('strategy') == 'tight_3_3':
ref_trade_count += 1
print(f"[OK] Reference trades loaded: {ref_trade_count} trades")
else:
print(f"[WARN] Reference trades not found: {reference_trades_file}")
print()
print("Phase 2: Component Validation")
print("-" * 40)
# Validate strategy configuration
try:
from nautilus_dolphin.nautilus.strategy_registration import DolphinStrategyConfig, create_strategy_config
strategy_config = DolphinStrategyConfig(
venue=config['strategy']['venue'],
max_leverage=config['strategy']['max_leverage'],
min_leverage=config['strategy']['min_leverage'],
leverage_convexity=config['strategy']['leverage_convexity'],
capital_fraction=config['strategy']['capital_fraction'],
max_hold_bars=config['strategy']['max_hold_bars'],
tp_bps=config['strategy']['tp_bps'],
irp_alignment_min=config['strategy']['irp_alignment_min'],
momentum_magnitude_min=config['strategy']['momentum_magnitude_min'],
excluded_assets=config['strategy']['excluded_assets'],
acb_enabled=config['strategy']['acb_enabled'],
max_concurrent_positions=config['strategy']['max_concurrent_positions'],
daily_loss_limit_pct=config['strategy']['daily_loss_limit_pct'],
)
print(f"[OK] Strategy configuration validated")
print(f" Max Leverage: {strategy_config.max_leverage}x")
print(f" Capital Fraction: {strategy_config.capital_fraction}")
if NAUTILUS_AVAILABLE:
strategy_config_nautilus = create_strategy_config(strategy_config)
print(f"[OK] Nautilus strategy config created")
except Exception as e:
print(f"[FAIL] Strategy validation failed: {e}")
import traceback
traceback.print_exc()
return 1
print()
print("Phase 3: Backtest Status")
print("-" * 40)
if not NAUTILUS_AVAILABLE:
print("[INFO] Nautilus Trader not available for full backtest")
print("[INFO] Running in validation mode only")
print()
print("To run full backtest, ensure Nautilus Trader is installed:")
print(" pip install nautilus_trader")
status = 'validation_only'
else:
print("[OK] Nautilus Trader available")
print("[INFO] Full backtest would run here")
print("[INFO] Integration with Nautilus BacktestNode pending")
status = 'framework_ready'
print()
print("Phase 4: Results Summary")
print("-" * 40)
# Generate results
results = {
'timestamp': datetime.now().isoformat(),
'config': config,
'status': status,
'nautilus_available': NAUTILUS_AVAILABLE,
'reference': reference_data if reference_data else None,
}
if reference_data:
print(f"\nReference Data (itest_v7 tight_3_3):")
print(f" Trades: {reference_data['trades']}")
print(f" Win Rate: {reference_data['win_rate']:.2f}%")
print(f" ROI: {reference_data['roi_pct']:.2f}%")
print(f" Profit Factor: {reference_data['profit_factor']:.4f}")
print(f" Avg Win: ${reference_data['avg_win']:.2f}")
print(f" Avg Loss: ${reference_data['avg_loss']:.2f}")
# Save configuration
config_output = output_path / 'backtest_config.json'
with open(config_output, 'w') as f:
json.dump(config, f, indent=2)
print(f"\n[OK] Configuration saved: {config_output}")
# Save results
results_output = output_path / 'backtest_results.json'
with open(results_output, 'w') as f:
json.dump(results, f, indent=2)
print(f"[OK] Results saved: {results_output}")
print()
print("=" * 80)
print("BACKTEST EXECUTION COMPLETE")
print("=" * 80)
print(f"End Time: {datetime.now().isoformat()}")
print()
print(f"Status: {status}")
print(f"Output Directory: {output_path.absolute()}")
print()
print("Next Steps:")
if status == 'validation_only':
print(" 1. Install Nautilus Trader: pip install nautilus_trader")
print(" 2. Re-run backtest: python run_full_backtest.py")
else:
print(" 1. Run trade-by-trade comparison: pytest tests/test_trade_by_trade_validation.py -v")
print(" 2. View results:", results_output)
print()
return 0
def main():
"""Main entry point."""
parser = argparse.ArgumentParser(
description='Run Nautilus-Dolphin full backtest'
)
parser.add_argument(
'--output', '-o',
default='backtest_results',
help='Output directory for results (default: backtest_results)'
)
args = parser.parse_args()
try:
exit_code = asyncio.run(run_full_backtest(args.output))
sys.exit(exit_code)
except KeyboardInterrupt:
print("\n\nBacktest interrupted by user")
sys.exit(130)
except Exception as e:
print(f"\n\nFATAL ERROR: {e}")
import traceback
traceback.print_exc()
sys.exit(1)
if __name__ == '__main__':
main()