Files
Apex_AI_MT5_EA_Optimizer/ui/templates/reports_index.html
T
LEGSTECH Optimizer 47f6012eb2 feat: Smart Autonomous 3-Phase Optimizer — complete redesign
PROBLEM: Old system repeated identical params, all scores flat at 0.2500,
user had zero control over symbol/TF/dates. Not smart, not dynamic.

NEW ARCHITECTURE:
  optimizer/                        (NEW package)
  ├── __init__.py
  ├── session_config.py             User choices (EA, symbol, TF, dates, budget, objective)
  ├── lhs_sampler.py                Latin Hypercube Sampling — diverse exploration
  ├── result_ranker.py              Relative scoring (best in session=1.0, worst=0.0)
  ├── budget.py                     Time budget tracker
  └── pipeline.py                   3-phase orchestrator

  Phase 1 — Broad Discovery (LHS, 20-26 runs):
    Samples FULL parameter space, not just defaults±tiny step
    LHS guarantees coverage: all 17 optimizable LEGSTECH params explored
    Relative ranking: profitable configs float top, losers score 0

  Phase 2 — Refinement (9 runs):
    Neighbor search around top 3 configs at ±20% range (not ±0.5 step)
    Keeps best of Phase1 vs Phase2 — never regresses

  Phase 3 — Validation (5 runs):
    OOS backtest on unseen data period
    Sensitivity test: nudge params ±20%, detect fragility
    Verdict: RECOMMENDED / RISKY / NOT_RELIABLE

  Output: Clean downloadable .set file via /download_set/<run_id>

UI REDESIGN:
  ui/templates/landing.html         New / homepage (was old dashboard)
  ui/templates/setup.html           New /setup — EA, symbol, TF, dates, budget, objective
  ui/templates/dashboard.html       Updated /dashboard with:
    - 5-step phase indicator
    - Real progress bar per run
    - Phase 1 results table (top 5 after phase1)
    - Verdict banner with download button
    - No-profitable-config warning
  ui/static/js/dashboard.js         Handles 8 new pipeline SocketIO events

  app.py                            New routes: /, /setup, /dashboard
                                    /api/start accepts full SessionConfig JSON
                                    /download_set/<id> serves optimized .set

  ea/registry.py                    +list_all() for setup page dropdown
  ui/templates/reports_index.html   Back to Dashboard → /dashboard (was /)
  ui/static/css/style.css           +dot-warn, dot-done, profit-pos/neg, aliases

FIXES:
  Score no longer flat 0.2500 (was: absolute thresholds on losing EA)
  User now controls: symbol, timeframe, dates, budget, objective
  Parameters now span full range (was: tiny step from defaults)
  Verdict is actionable: RECOMMENDED / RISKY / NOT_RELIABLE with reason

TESTED:
  8/8 pre-flight checks pass
  Browser test: landing ✓, setup form ✓, /dashboard ✓,
                phase indicator active ✓, /reports ✓, back link ✓
2026-04-13 21:14:47 +00:00

94 lines
4.3 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Reports — MT5 Optimizer</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body { background: #0a0d14; color: #e2e8f8; font-family: 'Inter', sans-serif; font-size: 13px; padding: 32px; }
header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 32px; }
h1 { font-size: 22px; font-weight: 800; }
.sub { color: #6b7fa3; font-size: 12px; margin-top: 4px; }
.back-link { color: #4f8ef7; text-decoration: none; font-size: 12px; }
.back-link:hover { text-decoration: underline; }
.empty { color: #3d4f70; text-align: center; padding: 80px 0; font-size: 16px; }
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 16px; }
.run-card {
background: #111621; border: 1px solid #1e2740; border-radius: 12px; padding: 18px 20px;
transition: border-color 0.2s, transform 0.2s;
text-decoration: none; color: inherit; display: block;
}
.run-card:hover { border-color: #4f8ef7; transform: translateY(-2px); }
.run-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 12px; }
.run-id { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: #6b7fa3; }
.run-score { font-size: 28px; font-weight: 800; font-family: 'JetBrains Mono', monospace; color: #22d3a5; }
.run-phase { font-size: 10px; padding: 2px 8px; border-radius: 4px; background: rgba(79,142,247,0.15); color: #4f8ef7; font-weight: 700; text-transform: uppercase; }
.metrics-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 10px; }
.m { text-align: center; background: #161c2a; border-radius: 6px; padding: 6px 8px; }
.m-label { font-size: 9px; color: #6b7fa3; text-transform: uppercase; letter-spacing: 0.5px; }
.m-val { font-size: 14px; font-weight: 700; font-family: 'JetBrains Mono', monospace; margin-top: 2px; }
.delta-up { color: #22d3a5; } .delta-dn { color: #f44; }
.run-ts { font-size: 10px; color: #3d4f70; margin-top: 10px; font-family: 'JetBrains Mono', monospace; }
</style>
</head>
<body>
<header>
<div>
<h1>📁 Optimization Reports</h1>
<div class="sub">{{ runs|length }} run(s) recorded · Click any card to open the full report</div>
</div>
<a class="back-link" href="/dashboard">&#8592; Back to Dashboard</a>
</header>
{% if not runs %}
<div class="empty">No reports yet.<br>Start the optimizer to generate your first run report.</div>
{% else %}
<div class="cards">
{% for r in runs %}
<a class="run-card" href="/reports/{{ r.run_id }}/summary.html" target="_blank">
<div class="run-header">
<div>
<div class="run-id">{{ r.run_id }}</div>
<div class="run-score">{{ "%.4f"|format(r.score) }}</div>
</div>
<span class="run-phase">{{ r.phase }}</span>
</div>
<div class="metrics-row">
<div class="m">
<div class="m-label">Net Profit</div>
<div class="m-val {% if r.net_profit >= 0 %}delta-up{% else %}delta-dn{% endif %}">
${{ "%.0f"|format(r.net_profit) }}
</div>
</div>
<div class="m">
<div class="m-label">Calmar</div>
<div class="m-val">{{ "%.2f"|format(r.calmar) }}</div>
</div>
<div class="m">
<div class="m-label">Drawdown</div>
<div class="m-val delta-dn">{{ "%.1f"|format(r.drawdown_pct) }}%</div>
</div>
<div class="m">
<div class="m-label">PF</div>
<div class="m-val">{{ "%.2f"|format(r.profit_factor) }}</div>
</div>
<div class="m">
<div class="m-label">Trades</div>
<div class="m-val">{{ r.total_trades }}</div>
</div>
<div class="m">
<div class="m-label">Score Δ</div>
<div class="m-val {% if r.score_delta >= 0 %}delta-up{% else %}delta-dn{% endif %}">
{{ "%+.4f"|format(r.score_delta) }}
</div>
</div>
</div>
<div class="run-ts">{{ r.ts[:19].replace("T"," ") }} UTC</div>
</a>
{% endfor %}
</div>
{% endif %}
</body>
</html>