#!/usr/bin/env python3 """ Backtesting & Bulk Training Main entry point for: - Historical data backtesting - Fast sliding-window training - Model performance evaluation - Checkpoint management Usage: python main_backtest.py --start YYYY-MM-DD --end YYYY-MM-DD [--symbol SYMBOL] [--window HOURS] Examples: # Run 30-day backtest with default settings python main_backtest.py --start 2024-01-01 --end 2024-01-31 # Custom symbol and window size python main_backtest.py --start 2024-01-01 --end 2024-12-31 --symbol BTC/USDT --window 48 # Resume from checkpoint python main_backtest.py --start 2024-01-01 --end 2024-12-31 --resume """ import os import sys import logging import argparse from datetime import datetime from pathlib import Path # Add project root to path sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) # Import training runner try: from training_runner import UnifiedTrainingRunner from core.config import setup_logging except ImportError as e: print(f"Error importing modules: {e}") sys.exit(1) logger = logging.getLogger(__name__) def validate_date(date_str: str) -> datetime: """Validate and parse date string""" try: return datetime.strptime(date_str, '%Y-%m-%d') except ValueError: raise argparse.ArgumentTypeError(f"Invalid date format: {date_str}. Use YYYY-MM-DD") def main(): """Main entry point for backtesting""" parser = argparse.ArgumentParser( description='Backtesting & Bulk Training System', formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Examples: # 30-day backtest python main_backtest.py --start 2024-01-01 --end 2024-01-31 # Year-long training with custom parameters python main_backtest.py --start 2024-01-01 --end 2024-12-31 --symbol BTC/USDT --window 48 # Fast backtest with smaller window python main_backtest.py --start 2024-12-01 --end 2024-12-31 --window 12 --step 6 """ ) # Required arguments parser.add_argument( '--start', type=str, required=True, help='Start date for backtesting (YYYY-MM-DD)' ) parser.add_argument( '--end', type=str, required=True, help='End date for backtesting (YYYY-MM-DD)' ) # Optional arguments parser.add_argument( '--symbol', type=str, default='ETH/USDT', help='Trading symbol (default: ETH/USDT)' ) parser.add_argument( '--window', type=int, default=24, help='Sliding window size in hours (default: 24)' ) parser.add_argument( '--step', type=int, default=1, help='Window step size in hours (default: 1)' ) parser.add_argument( '--resume', action='store_true', help='Resume from last checkpoint' ) parser.add_argument( '--save-interval', type=int, default=2, help='Checkpoint save interval in hours (default: 2)' ) args = parser.parse_args() # Validate dates try: start_date = validate_date(args.start) end_date = validate_date(args.end) except argparse.ArgumentTypeError as e: parser.error(str(e)) if start_date >= end_date: parser.error("Start date must be before end date") # Calculate duration duration_days = (end_date - start_date).days # Setup logging try: setup_logging() logger.info("=" * 80) logger.info("BACKTESTING & BULK TRAINING SYSTEM") logger.info("=" * 80) logger.info(f"Symbol: {args.symbol}") logger.info(f"Period: {args.start} to {args.end} ({duration_days} days)") logger.info(f"Window: {args.window}h, Step: {args.step}h") logger.info(f"Checkpoint Interval: {args.save_interval}h") logger.info(f"Resume from checkpoint: {'YES' if args.resume else 'NO'}") logger.info("=" * 80) except Exception as e: print(f"Error setting up logging: {e}") # Ensure logs directory exists Path('logs').mkdir(exist_ok=True) try: # Create training runner in backtest mode logger.info("Initializing backtest training runner...") runner = UnifiedTrainingRunner( mode='backtest', symbol=args.symbol ) # Update configuration runner.config['backtest']['window_size_hours'] = args.window runner.config['backtest']['step_size_hours'] = args.step runner.config['backtest']['save_interval_hours'] = args.save_interval # Run backtest training logger.info("Starting backtest training...") runner.run_backtest_training( start_date=start_date, end_date=end_date ) logger.info("=" * 80) logger.info("BACKTEST TRAINING COMPLETE") logger.info("=" * 80) except KeyboardInterrupt: logger.info("Backtest interrupted by user") sys.exit(0) except Exception as e: logger.error(f"Error during backtest: {e}") import traceback logger.error(traceback.format_exc()) sys.exit(1) finally: logger.info("Backtest runner shutdown complete") if __name__ == '__main__': main()