import os import json from datetime import datetime from typing import List, Dict, Optional import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) class ReportGenerator: def __init__(self, results: List[Dict] = None): self.results = results or [] def generate_excel(self, output_path: str = "reports/batch_report.xlsx") -> str: try: import openpyxl from openpyxl.styles import Font, Alignment, PatternFill, Border, Side wb = openpyxl.Workbook() ws = wb.active ws.title = "Backtest Results" headers = [ "EA Name", "Symbol", "Period", "Model", "Total Trades", "Winning Trades", "Losing Trades", "Win Rate %", "Gross Profit", "Gross Loss", "Profit Factor", "Expected Payoff", "Initial Deposit", "Final Balance" ] header_fill = PatternFill(start_color="366092", end_color="366092", fill_type="solid") header_font = Font(bold=True, color="FFFFFF") thin_border = Border( left=Side(style='thin'), right=Side(style='thin'), top=Side(style='thin'), bottom=Side(style='thin') ) for col, header in enumerate(headers, 1): cell = ws.cell(row=1, column=col, value=header) cell.fill = header_fill cell.font = header_font cell.alignment = Alignment(horizontal='center', vertical='center') cell.border = thin_border for row_idx, result in enumerate(self.results, 2): metrics = result.get("metrics", {}) test_info = result.get("test_info", {}) row_data = [ test_info.get("expert", ""), test_info.get("symbol", ""), test_info.get("period", ""), test_info.get("model", ""), metrics.get("total_trades", 0), metrics.get("winning_trades", 0), metrics.get("losing_trades", 0), metrics.get("win_rate", 0), metrics.get("gross_profit", 0), metrics.get("gross_loss", 0), metrics.get("profit_factor", 0), metrics.get("expected_payoff", 0), metrics.get("initial_deposit", 0), metrics.get("final_balance", 0) ] for col, value in enumerate(row_data, 1): cell = ws.cell(row=row_idx, column=col, value=value) cell.border = thin_border if col >= 5: cell.number_format = '0.00' for col in range(1, len(headers) + 1): ws.column_dimensions[openpyxl.utils.get_column_letter(col)].width = 15 ws.auto_filter.ref = f"A1:N{len(self.results) + 1}" os.makedirs(os.path.dirname(output_path), exist_ok=True) wb.save(output_path) logger.info(f"Excel report saved: {output_path}") return output_path except Exception as e: logger.error(f"Error generating Excel report: {e}") raise def generate_csv(self, output_path: str = "reports/batch_report.csv") -> str: try: import csv os.makedirs(os.path.dirname(output_path) or '.', exist_ok=True) headers = [ "EA Name", "Symbol", "Period", "Model", "Total Trades", "Winning Trades", "Losing Trades", "Win Rate %", "Gross Profit", "Gross Loss", "Profit Factor", "Expected Payoff", "Initial Deposit", "Final Balance" ] with open(output_path, 'w', newline='', encoding='utf-8-sig') as f: writer = csv.writer(f) writer.writerow(headers) for result in self.results: metrics = result.get("metrics", {}) test_info = result.get("test_info", {}) row_data = [ test_info.get("expert", ""), test_info.get("symbol", ""), test_info.get("period", ""), test_info.get("model", ""), metrics.get("total_trades", 0), metrics.get("winning_trades", 0), metrics.get("losing_trades", 0), metrics.get("win_rate", 0), metrics.get("gross_profit", 0), metrics.get("gross_loss", 0), metrics.get("profit_factor", 0), metrics.get("expected_payoff", 0), metrics.get("initial_deposit", 0), metrics.get("final_balance", 0) ] writer.writerow(row_data) logger.info(f"CSV report saved: {output_path}") return output_path except Exception as e: logger.error(f"Error generating CSV report: {e}") raise def generate_html(self, output_path: str = "reports/batch_report.html") -> str: try: os.makedirs(os.path.dirname(output_path) or '.', exist_ok=True) html_content = f"""
Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
Total Tests: {len(self.results)}
| EA Name | Symbol | Period | Total Trades | Win Rate % | Profit Factor | Gross Profit | Gross Loss | Final Balance |
|---|---|---|---|---|---|---|---|---|
| {test_info.get("expert", "")} | {test_info.get("symbol", "")} | {test_info.get("period", "")} | {metrics.get("total_trades", 0)} | {metrics.get("win_rate", 0):.2f}% | {pf:.2f} | {metrics.get("gross_profit", 0):.2f} | {metrics.get("gross_loss", 0):.2f} | {metrics.get("final_balance", 0):.2f} |