""" Main entry point for the backtesting application. This module provides a clean command-line interface for running backtests using the modular backtesting framework. """ import argparse from pathlib import Path from cycles.application import BacktestApplication, setup_logging def parse_arguments(): """Parse command line arguments.""" parser = argparse.ArgumentParser( description="Run cryptocurrency backtests with configurable strategies.", formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Examples: python main.py # Use default config python main.py config_bbrs.json # Use specific config python main.py --debug config_combined.json # Debug mode with plotting Available configs: - config_default.json: Default meta-trend strategy - config_bbrs.json: BBRS strategy - config_combined.json: Multi-strategy combination """ ) parser.add_argument( "config", type=str, nargs="?", help="Path to config JSON file (default: configs/config_default.json)" ) parser.add_argument( "--debug", action="store_true", help="Enable debug mode (sequential execution with plotting)" ) return parser.parse_args() def validate_config_path(config_path: str) -> str: """Validate and resolve configuration path.""" if config_path is None: return "configs/config_default.json" # If just filename provided, look in configs directory if not "/" in config_path and not "\\" in config_path: config_path = f"configs/{config_path}" # Validate file exists if not Path(config_path).exists(): available_configs = list(Path("configs").glob("*.json")) available_names = [c.name for c in available_configs] raise FileNotFoundError( f"Config file '{config_path}' not found.\n" f"Available configs: {', '.join(available_names)}" ) return config_path def main(): """Main application entry point.""" # Setup logging setup_logging() # Parse arguments args = parse_arguments() try: # Validate configuration path config_path = validate_config_path(args.config) # Create and run application app = BacktestApplication(config_path) app.run(debug=args.debug) except FileNotFoundError as e: print(f"Error: {e}") return 1 except Exception as e: print(f"Application failed: {e}") return 1 return 0 if __name__ == "__main__": exit(main())