2026-04-13 02:28:09 +00:00
# MT5 EA Optimizer — Full Project Handoff Document
2026-04-13 02:40:13 +00:00
2026-04-13 02:28:09 +00:00
**Last Updated:** 2026-04-13
2026-04-13 02:40:13 +00:00
**Status:** ✅ Phase 1 (Backend Engine) + ✅ Phase 2 (Live Web Dashboard) — BOTH COMPLETE
**GitHub:** https://github.com/tonnylegacy/MT5_Optimizer
**Primary EA:** LEGSTECH_EA_V2 | Symbol: XAUUSD | Timeframe: H1 | Broker TZ: UTC+2
2026-04-13 02:28:09 +00:00
---
## 🎯 Project Goal
Build an automated, iterative backtesting and analysis system for MT5 Expert Advisors.
It is NOT a trading bot. It is an **optimization engine** that:
2026-04-13 02:40:13 +00:00
2026-04-13 02:28:09 +00:00
- Runs MT5 strategy tester automatically with different parameter sets
- Extracts rich trade-level data (MAE/MFE) after each run
2026-04-13 02:40:13 +00:00
- Analyzes results to find failure patterns using statistical methods
- Proposes and tests parameter mutations based on findings
- Validates improvements before accepting them (IS → WFV → OOS)
2026-04-13 02:28:09 +00:00
- Prevents overfitting via Walk-Forward + Out-of-Sample testing
2026-04-13 02:40:13 +00:00
- Displays everything live in a beautiful browser dashboard
- Writes human-readable reports to a visible `Reports\` folder
2026-04-13 02:28:09 +00:00
2026-04-13 02:40:13 +00:00
**End user:** Traders (non-technical). Double-click app, no terminal needed.
2026-04-13 02:28:09 +00:00
---
## 🏗️ Architecture Overview
```
2026-04-13 02:40:13 +00:00
[Trader double-clicks "Launch Optimizer.bat"]
↓
[Browser auto-opens http://localhost:5000]
↓
[Flask + SocketIO Dashboard]
↓
[Trader clicks ▶ Start]
↓
┌────────────────────────────────────────────────────┐
│ OPTIMIZATION LOOP │
│ │
│ 1. Kill any running MT5 process (psutil) │
│ 2. Clear stale report files │
│ 3. Validate environment (EA exists, paths valid) │
│ 4. Build INI file (Period=H1, Report=relative) │
│ 5. Launch fresh MT5 via subprocess /config: │
│ 6. Wait 10s for data readiness │
│ 7. Poll MT5 appdata root for Optimizer_*.htm │
│ 8. Parse report (UTF-16 LE HTML → metrics+trades) │
│ 9. Run 4 analyzers on trade data │
│ 10. Score composite (Calmar-primary) │
│ 11. Mutate parameters → Hypotheses │
│ 12. Test each hypothesis (steps 1-10 repeated) │
│ 13. Validate: IS check → WFV → promote candidate │
│ 14. Write Reports\run_XXX\ (HTML + CSV + JSON) │
│ 15. Repeat until converged or max_iterations │
└────────────────────────────────────────────────────┘
↓
[Dashboard updates live via WebSocket events]
[Reports\ folder has all results]
2026-04-13 02:28:09 +00:00
```
---
2026-04-13 02:40:13 +00:00
## 📁 Complete File Structure
2026-04-13 02:28:09 +00:00
```
C:\Users\DELL\Desktop\MT5_Optimizer\
2026-04-13 02:40:13 +00:00
│
├── app.py ← Flask + SocketIO app entry point
│ Auto-opens browser at localhost:5000
│ Routes: /, /api/start, /api/pause,
│ /api/stop, /api/skip, /reports
│
├── optimizer_loop.py ← Background thread: full optimization pipeline
│ Emits SocketIO events for every phase/run/finding
│
├── config.yaml ← ALL settings (see section below)
2026-04-13 02:28:09 +00:00
├── requirements.txt ← Python dependencies
├── PROJECT_HANDOFF.md ← THIS DOCUMENT
2026-04-13 02:40:13 +00:00
├── "Launch Optimizer.bat" ← Double-click to start (opens browser automatically)
│ Uses Python 3.11 at hardcoded path
2026-04-13 02:28:09 +00:00
│
├── mql5/
2026-04-13 02:40:13 +00:00
│ └── TradeLogger.mqh ← MQL5 include: per-trade MAE/MFE logger
│ DEPLOYED to: ...Terminal\...\MQL5\Include\
│ INTEGRATED in: LEGSTECH_EA_V2.mq5 via TL_OnTick()
2026-04-13 02:28:09 +00:00
│
├── data/
2026-04-13 02:40:13 +00:00
│ ├── models.py ← Pydantic v2: Trade, RunMetrics, Run, Finding,
│ │ Hypothesis, Candidate, RunResult
│ └── store.py ← DataStore: SQLite metadata + Parquet trade arrays
2026-04-13 02:28:09 +00:00
│
├── mt5/
2026-04-13 02:40:13 +00:00
│ ├── ini_builder.py ← Builds MT5 tester .ini files
│ │ CRITICAL: Period=H1 (string), Report=relative name
│ │ Model=4 (OHLC M1), ShutdownTerminal=1
│ ├── runner.py ← Full MT5 process control:
│ │ kill_mt5() → clear_stale() → validate() →
│ │ launch() → wait_data() → poll_report() → retry
│ │ Report location: appdata_path\ root (NOT /reports/)
│ ├── report_parser.py ← Parses MT5 HTML report
│ │ CRITICAL: MT5 reports are UTF-16 LE encoded!
│ │ Uses lhtml.document_fromstring(raw_bytes)
│ │ Pairs in/out deals → complete Trade objects
│ └── log_reader.py ← Merges TradeLogger CSV (MAE/MFE) into trades
2026-04-13 02:28:09 +00:00
│
├── analysis/
│ ├── base.py ← BaseAnalyzer ABC + statistical helpers
2026-04-13 02:40:13 +00:00
│ ├── reversal.py ← Trades that went to MFE then reversed (permutation test)
│ ├── time_performance.py ← Bad sessions/hours/days (Z-score)
│ ├── entry_exit_quality.py ← MAE/MFE quality matrix (4-case diagnosis)
│ └── equity_curve.py ← Flatness, loss clusters, R² of equity curve
2026-04-13 02:28:09 +00:00
│
├── scoring/
2026-04-13 02:40:13 +00:00
│ └── composite.py ← Weighted scorer: Calmar(35%) + PF(20%) +
│ MFE capture(20%) + stability(15%) + recovery(10%)
2026-04-13 02:28:09 +00:00
│
├── mutation/
2026-04-13 02:40:13 +00:00
│ ├── engine.py ← Findings → Hypothesis objects (dedup, cascade)
│ ├── knowledge_base.yaml ← 13 rules: finding_type → param_delta
│ └── param_manifest.yaml ← Full EA parameter space: types, bounds, defaults
2026-04-13 02:28:09 +00:00
│
├── validation/
2026-04-13 02:40:13 +00:00
│ └── gate.py ← IS check → Walk-Forward (2 folds) → OOS
2026-04-13 02:28:09 +00:00
│
2026-04-13 02:40:13 +00:00
├── reports/
│ └── writer.py ← Writes per-run: summary.json, summary.html,
│ trades.csv, findings.csv, parameters.json
│
├── ui/
│ ├── templates/
│ │ ├── index.html ← Live dashboard (dark premium design)
│ │ ├── report.html ← Per-run report template
│ │ └── reports_index.html ← Reports browser page (card grid)
│ └── static/
│ ├── css/style.css ← Full dark theme CSS (glassmorphism, animations)
│ └── js/dashboard.js ← SocketIO events + Chart.js + live metrics
│
├── tests/
│ └── test_analyzers.py ← 10 unit tests (all passing ✅)
│
└── runs/ ← Generated INI + local run folders (gitignored)
└── baseline_YYYYMMDD_.../
└── run.ini
2026-04-13 02:28:09 +00:00
```
---
2026-04-13 02:40:13 +00:00
## ⚙️ Configuration (config.yaml)
2026-04-13 02:28:09 +00:00
```yaml
ea :
name : "LEGSTECH_EA_V2"
2026-04-13 02:40:13 +00:00
file : "LEGSTECH_EA_V2" # no extension — MT5 adds .ex5
2026-04-13 02:28:09 +00:00
symbol : "XAUUSD"
timeframe : "H1"
periods :
2026-04-13 02:40:13 +00:00
train_start : "2022.01.01"
train_end : "2023.12.31"
2026-04-13 02:28:09 +00:00
validate_start : "2024.01.01"
validate_end : "2024.06.30"
2026-04-13 02:40:13 +00:00
oos_start : "2024.07.01" # SACRED — never optimize against this
oos_end : "2024.12.31"
2026-04-13 02:28:09 +00:00
mt5 :
terminal_exe : "C:/Program Files/MetaTrader 5/terminal64.exe"
appdata_path : "C:/Users/DELL/AppData/Roaming/MetaQuotes/Terminal/D0E8209F77C8CF37AD8BF550E51FF075"
mql5_files_path : "C:/Users/DELL/AppData/Roaming/MetaQuotes/Tester/D0E8209F77C8CF37AD8BF550E51FF075/Agent-127.0.0.1-3000/MQL5/Files"
2026-04-13 02:40:13 +00:00
tester_model : 4 # 4=OHLC M1 (fast). 0=Every Tick (slow, needs tick data)
tester_timeout_seconds : 1800
shutdown_terminal : 1 # MT5 closes itself after each test
data_readiness_wait_seconds : 10
kill_on_start : true # Always kill existing MT5 before each run
2026-04-13 02:28:09 +00:00
broker :
2026-04-13 02:40:13 +00:00
timezone_offset_hours : 2 # UTC+2 (HFMarkets)
deposit : 10000.0
currency : "USD"
leverage : 100
2026-04-13 02:28:09 +00:00
```
---
2026-04-13 02:40:13 +00:00
## ✅ What Is Complete
### Phase 1 — Backend Engine
2026-04-13 02:28:09 +00:00
| Component | Status | Notes |
|---|---|---|
2026-04-13 02:40:13 +00:00
| TradeLogger.mqh | ✅ Deployed | In MT5 Include folder, integrated in EA |
| data/models.py | ✅ | All Pydantic v2 models |
| data/store.py | ✅ | SQLite + Parquet |
| mt5/ini_builder.py | ✅ | Period=H1 string, relative Report path |
| mt5/runner.py | ✅ | Kill→validate→launch→wait→poll→retry |
| mt5/report_parser.py | ✅ | UTF-16 LE HTML, pairs 597 trades |
| mt5/log_reader.py | ✅ | MAE/MFE merge + session labelling |
| analysis/reversal.py | ✅ | Permutation-tested |
| analysis/time_performance.py | ✅ | Z-score per hour/session/day |
| analysis/entry_exit_quality.py | ✅ | 4-case diagnosis matrix |
| analysis/equity_curve.py | ✅ | Flatness + R² + loss clusters |
| scoring/composite.py | ✅ | Calmar-primary (0-1 score) |
| mutation/engine.py | ✅ | 13 KB rules, dedup, cascade |
| validation/gate.py | ✅ | IS → WFV → OOS → sensitivity |
| tests/ | ✅ 10/10 | Pure Python, no MT5 needed |
### Phase 2 — Live Web Dashboard
| Component | Status | Notes |
|---|---|---|
| app.py | ✅ | Flask + SocketIO, all API routes |
| optimizer_loop.py | ✅ | Background thread, live event emitter |
| ui/templates/index.html | ✅ | Score chart, metrics, findings, log, candidates |
| ui/templates/report.html | ✅ | Per-run full report with trade table |
| ui/templates/reports_index.html | ✅ | Card grid browser page |
| ui/static/css/style.css | ✅ | Premium dark theme |
| ui/static/js/dashboard.js | ✅ | SocketIO + Chart.js + live updates |
| reports/writer.py | ✅ | HTML + CSV + JSON per run |
| Launch Optimizer.bat | ✅ | Double-click launcher |
| GitHub | ✅ | https://github.com/tonnylegacy/MT5_Optimizer |
2026-04-13 02:28:09 +00:00
---
2026-04-13 02:40:13 +00:00
## 🐛 Critical Bugs Found & Fixed (Important for Future AI)
2026-04-13 02:28:09 +00:00
2026-04-13 02:40:13 +00:00
### 1. MT5 Report Encoding — UTF-16 LE
**Problem:** MT5 HTML reports (`.htm` ) are UTF-16 LE encoded (BOM: `\xFF\xFE` ).
Standard `decode('utf-8')` silently failed, lxml returned a single `<p>` element.
**Fix:** Detect BOM and use `lhtml.document_fromstring(raw_bytes)` directly.
```python
if raw [: 2 ] == b ' \xff\xfe ' :
tree = lhtml . document_fromstring ( raw ) # handles UTF-16 internally
2026-04-13 02:28:09 +00:00
```
2026-04-13 02:40:13 +00:00
### 2. MT5 Report Location
**Problem:** Runner was looking in `appdata_path/reports/` — folder doesn't exist.
**Reality:** MT5 writes reports to the **root** of `appdata_path\` directly.
2026-04-13 02:28:09 +00:00
```
2026-04-13 02:40:13 +00:00
C:\Users\DELL\AppData\Roaming\MetaQuotes\Terminal\D0E8209F...\Optimizer_baseline_*.htm
```
**Fix:** `self.mt5_reports_dir = self.appdata_path` (not `/ "reports"` )
### 3. INI Period Format
**Problem:** Code used `Period=16385` (ENUM integer) — MT5 CLI ignores this.
**Fix:** `Period=H1` (string name). `TIMEFRAME_NAMES = {"H1": "H1", ...}`
### 4. INI Report Path
**Problem:** `Report=C:/absolute/path/...` — MT5 ignores absolute paths in CLI mode.
**Fix:** `Report=Optimizer_{run_id}` (relative name only — MT5 writes to appdata root).
### 5. MQL5 Reference Syntax
**Problem:** `TL_Positions[idx]&.fieldname` — C++ reference syntax, invalid in MQL5.
**Fix:** `TL_Positions[idx].fieldname` — direct array index access.
### 6. Stale Report Detection
**Problem:** Old `Optimizer_*.htm` files from previous runs triggered false-positive detection.
**Fix:** `_clear_stale_reports()` deletes old files before each new run.
---
## 🖥️ How to Run (For Any User)
### Prerequisites
1. MT5 installed at `C:\Program Files\MetaTrader 5\terminal64.exe`
2. LEGSTECH_EA_V2 compiled in MetaEditor (`.ex5` file must exist)
3. Python 3.11 installed at `C:\Users\DELL\AppData\Local\Programs\Python\Python311\`
4. Dependencies installed: `python.exe -m pip install -r requirements.txt`
### Starting the App
1. **Close MT5** if it's open (the optimizer kills and relaunches it automatically from the next run, but first run needs it clean)
2. **Double-click** `Launch Optimizer.bat` on Desktop
3. Browser opens at `http://localhost:5000`
4. Click ** ▶ Start Optimizer**
5. Watch it run live — MT5 launches automatically, results appear in real-time
6. Reports saved to `MT5_Optimizer\Reports\run_XXX\`
### Save Changes to GitHub
```powershell
cd "C:\Users\DELL\Desktop\MT5_Optimizer"
git add .
git commit -m "describe what changed"
git push
2026-04-13 02:28:09 +00:00
```
---
2026-04-13 02:40:13 +00:00
## 🔧 Environment Details
2026-04-13 02:28:09 +00:00
2026-04-13 02:40:13 +00:00
| Item | Value |
|---|---|
| Python | 3.11 — `C:\Users\DELL\AppData\Local\Programs\Python\Python311\python.exe` |
| GitHub | https://github.com/tonnylegacy/MT5_Optimizer |
| MT5 Terminal ID | `D0E8209F77C8CF37AD8BF550E51FF075` |
| MT5 Broker | HFMarketsGlobal-Live3 (Build 5660) |
| Tester Agent | `Agent-127.0.0.1-3000` |
| OS | Windows 11 |
2026-04-13 02:28:09 +00:00
2026-04-13 02:40:13 +00:00
**Install all dependencies:**
2026-04-13 02:28:09 +00:00
```powershell
C: \ Users \ DELL \ AppData \ Local \ Programs \ Python \ Python311 \ python . exe -m pip install -r requirements . txt
```
2026-04-13 02:40:13 +00:00
**Key dependencies:**
2026-04-13 02:28:09 +00:00
```
2026-04-13 02:40:13 +00:00
flask, flask-socketio, eventlet ← Web dashboard
pydantic>=2.5, pandas>=2.1, pyarrow ← Data layer
lxml>=4.9, beautifulsoup4 ← Report parsing
psutil ← MT5 process control
loguru, rich, scipy, pyyaml ← Utilities
2026-04-13 02:28:09 +00:00
```
---
2026-04-13 02:40:13 +00:00
## 🧠 Key Design Decisions
2026-04-13 02:28:09 +00:00
2026-04-13 02:40:13 +00:00
1. **Hypothesis-driven, not brute-force** — Detect failure patterns → hypothesize fix → test → validate. Not grid search.
2. **Calmar ratio = primary score** — Return/MaxDrawdown most relevant for live trading.
3. **Three validation gates** — IS → WFV (2 folds) → OOS. No candidate promoted unless all pass.
4. **OOS is sacred** — `2024.07.01 → 2024.12.31` is NEVER used during optimization. Final check only.
5. **MT5 process control** — Always kill existing instance, launch clean, retry once on failure.
6. **UTF-16 LE** — ALL MT5 HTML reports are UTF-16 LE. Always use `document_fromstring(raw_bytes)` .
7. **Report location** — Always `appdata_path\Optimizer_{run_id}.htm` (root, not subfolder).
8. **Python 3.11 required** — System Python on this machine is 3.13 which is missing packages.
9. **Broker TZ = UTC+2** — Session analysis normalizes to UTC. London=07-16, NY=13-22.
2026-04-13 02:28:09 +00:00
---
2026-04-13 02:40:13 +00:00
## 📋 Live Dashboard Events (SocketIO)
2026-04-13 02:28:09 +00:00
2026-04-13 02:40:13 +00:00
The optimizer emits these events to the browser in real-time:
| Event | Payload | When |
|---|---|---|
| `status_change` | `{state, phase}` | Phase transitions |
| `run_started` | `{run_id, phase, period, params}` | MT5 launches |
| `run_complete` | `{score, calmar, pf, dd, trades, ...}` | Report parsed |
| `run_failed` | `{run_id, error}` | MT5 failed |
| `finding` | `{analyzer, severity, description, confidence}` | Each finding |
| `hypotheses` | `{items: [{id, desc, delta}]}` | Mutations proposed |
| `score_update` | `{iteration, score, calmar, pf}` | Chart data point |
| `candidate_promoted` | `{score, delta, params}` | Validation passed |
| `optimization_complete` | `{candidates, best_score, iterations}` | Loop done |
| `log` | `{level, msg}` | Live log feed |
2026-04-13 02:28:09 +00:00
---
2026-04-13 02:40:13 +00:00
## 🚀 Next Steps (Phase 3 — Packaging)
2026-04-13 02:28:09 +00:00
2026-04-13 02:40:13 +00:00
1. **PyInstaller EXE** — Bundle everything into `MT5_Optimizer.exe`
```bat
pyinstaller --onefile --noconsole --name MT5_Optimizer app.py
` ``
Note: Need ` --add-data` flags for templates, static, config, yaml files
2026-04-13 02:28:09 +00:00
2026-04-13 02:40:13 +00:00
2. **Auto ` .set` file export** — When a candidate is promoted, export its params as a valid MT5 ` .set` file the trader can load directly into the EA
2026-04-13 02:28:09 +00:00
2026-04-13 02:40:13 +00:00
3. **Email/Telegram notification** — Alert the trader when a candidate is promoted
2026-04-13 02:28:09 +00:00
2026-04-13 02:40:13 +00:00
4. **Multi-symbol support** — Run optimization across EURUSD, GBPUSD alongside XAUUSD
2026-04-13 02:28:09 +00:00
2026-04-13 02:40:13 +00:00
5. **Monte Carlo simulation** — Test robustness of promoted candidates
2026-04-13 02:28:09 +00:00
---
2026-04-13 02:40:13 +00:00
## ⚠️ Known Issues & Watch Points
2026-04-13 02:28:09 +00:00
2026-04-13 02:40:13 +00:00
1. **First run needs MT5 closed manually** — From the second run onward, the system kills MT5 automatically via psutil.
2. **Tester Agent path** — ` Agent-127.0.0.1-3000` may change if MT5 port changes. If TradeLog CSV not found, check Tester folder for new agent subfolder.
3. **WFV fold count** — Currently 2 folds (hardcoded in ` validation/gate.py`). Easy to increase.
4. **XAUUSD data** — If the date range 2022-2023 gives errors, ensure XAUUSD H1 history is downloaded in MT5 (Tools → History Center).
5. **Model 4 vs 0** — ` tester_model: 4` (OHLC M1) is fast and reliable. ` tester_model: 0` (Every Tick) is more accurate but requires full tick data download and takes ~10x longer.
6. **ShutdownTerminal=1** — MT5 closes itself after each test. Cannot be used for live trading simultaneously.
2026-04-13 02:28:09 +00:00
---
2026-04-13 02:40:13 +00:00
## 📊 Baseline Run Results (Confirmed Working)
2026-04-13 02:28:09 +00:00
2026-04-13 02:40:13 +00:00
First successful parser test on real MT5 report (2026-04-13):
2026-04-13 02:28:09 +00:00
2026-04-13 02:40:13 +00:00
| Metric | Value |
|---|---|
| Net Profit | -$621.15 |
| Profit Factor | 0.95 |
| Max Drawdown | 19.25% |
| Calmar Ratio | -0.32 |
| Sharpe Ratio | -1.60 |
| Total Trades | 597 |
| Win Rate | 77.7% |
| Test Period | 2022.01.01 → 2023.12.31 |
| Model | OHLC M1 (Model 4) |
| Duration | ~56 seconds |
2026-04-13 02:28:09 +00:00
2026-04-13 02:40:13 +00:00
> This is the baseline — the optimizer's job is to improve these numbers over iterations.
2026-04-13 02:28:09 +00:00
---
2026-04-13 02:40:13 +00:00
*Last updated by Antigravity AI — 2026-04-13*
*GitHub: https://github.com/tonnylegacy/MT5_Optimizer*
*Both Phase 1 and Phase 2 are complete. Continue from Phase 3 (packaging).*