#!/usr/bin/env python3 import os import sys import argparse import logging from datetime import datetime logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) OPTIMIZER_DIR = os.path.join(os.path.dirname(__file__), 'scripts', 'optimizer') sys.path.insert(0, OPTIMIZER_DIR) from ea_config_parser import load_all_ea_configs, load_ea_config from smart_search import SmartSearch from parameter_constraint import create_constraint_engine from analyze_results import ResultAnalyzer from ea_batch_optimizer import EABatchOptimizer def setup_directories(base_dir): dirs = ['configs', 'set_files', 'reports', 'results', 'scripts', 'logs'] for d in dirs: os.makedirs(os.path.join(base_dir, d), exist_ok=True) def cmd_generate(args): optimizer = EABatchOptimizer(args.base_dir) configs = load_all_ea_configs(os.path.join(args.base_dir, 'configs')) if not configs: logger.error('No EA configs found in ' + os.path.join(args.base_dir, 'configs')) return for ea_name, config in configs.items(): if args.ea and ea_name not in args.ea: continue logger.info('Processing: ' + ea_name) optimizer.generate_set_files(config, max_samples=args.max_samples) optimizer.generate_ini_for_ea(config, []) logger.info('Generation completed!') def cmd_run(args): optimizer = EABatchOptimizer(args.base_dir) if not args.ps_script: logger.error('PowerShell script path required. Generate SET files first.') return logger.info('Running PowerShell script: ' + args.ps_script) try: result = subprocess.run(['powershell', '-ExecutionPolicy', 'Bypass', '-File', args.ps_script], capture_output=True, text=True) logger.info(result.stdout) if result.stderr: logger.error(result.stderr) except Exception as e: logger.error('Error running script: ' + str(e)) def cmd_analyze(args): optimizer = EABatchOptimizer(args.base_dir) analyzer = ResultAnalyzer(os.path.join(args.base_dir, 'reports')) results = analyzer.parse_all_reports() if not results: logger.warning('No results found') return logger.info('Total results: ' + str(len(results))) criterion = args.sort or 'profit_factor' best = analyzer.find_optimal_params(results, criterion=criterion) output_path = os.path.join(args.base_dir, 'results', 'optimization_report.txt') analyzer.generate_report(best, output_path) logger.info('Report saved: ' + output_path) if args.csv: analyzer.save_to_csv(best, args.csv) logger.info('CSV saved: ' + args.csv) def cmd_list(args): configs_dir = os.path.join(args.base_dir, 'configs') configs = load_all_ea_configs(configs_dir) print() print('=' * 60) print('EA Configurations') print('=' * 60) for ea_name, config in configs.items(): print() print('Name: ' + ea_name) print('Path: ' + config.ea_path) print('Parameters: ' + str(len(config.parameters))) print('Combinations: ' + str(config.get_total_combinations())) print('Strategy: ' + config.search_strategy) print('Estimate time: ' + config.estimate_search_time()) def main(): parser = argparse.ArgumentParser(description='MT5 EA Optimizer') parser.add_argument('--base-dir', '-d', default='optimizer', help='Base directory for optimizer') parser.add_argument('--ea', '-e', nargs='+', help='EA names to process') parser.add_argument('--max-samples', '-m', type=int, default=2000, help='Maximum samples to generate') parser.add_argument('--sort', '-s', default='profit_factor', choices=['profit_factor', 'net_profit', 'win_rate', 'sharpe_ratio'], help='Sort criterion') parser.add_argument('--csv', '-c', help='Export results to CSV') parser.add_argument('--ps-script', '-p', help='PowerShell script to run') subparsers = parser.add_subparsers(dest='command', help='Commands') subparsers.add_parser('generate', help='Generate SET files and INI') subparsers.add_parser('run', parents=[parser], help='Run MT5 tests') subparsers.add_parser('analyze', parents=[parser], help='Analyze results') subparsers.add_parser('list', help='List EA configurations') args = parser.parse_args() setup_directories(args.base_dir) if args.command == 'generate': cmd_generate(args) elif args.command == 'run': cmd_run(args) elif args.command == 'analyze': cmd_analyze(args) elif args.command == 'list': cmd_list(args) else: cmd_generate(args) if __name__ == '__main__': main()