149 lines
4.8 KiB
Python
149 lines
4.8 KiB
Python
#!/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()
|