docs: update PROJECT_HANDOFF.md with Phase 2 complete status
- Added GitHub URL - Documented all 6 critical bugs found and fixed: * UTF-16 LE report encoding * Report location (appdata root not /reports/) * INI Period string format (H1 not 16385) * INI Report relative path * MQL5 reference syntax * Stale report detection - Added full SocketIO events table - Added baseline run results (597 trades confirmed parsed) - Updated file structure with all Phase 2 files - Updated next steps to Phase 3 (PyInstaller packaging)
This commit is contained in:
+285
-229
@@ -1,8 +1,9 @@
|
||||
# MT5 EA Optimizer — Full Project Handoff Document
|
||||
|
||||
**Last Updated:** 2026-04-13
|
||||
**Status:** Phase 1 complete (backend engine). Phase 2 (GUI app) = NEXT STEP
|
||||
**Primary EA:** LEGSTECH_EA_V2 | Symbol: XAUUSD | Timeframe: H1
|
||||
**Broker Timezone:** UTC+2
|
||||
**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
|
||||
|
||||
---
|
||||
|
||||
@@ -10,340 +11,395 @@
|
||||
|
||||
Build an automated, iterative backtesting and analysis system for MT5 Expert Advisors.
|
||||
It is NOT a trading bot. It is an **optimization engine** that:
|
||||
|
||||
- Runs MT5 strategy tester automatically with different parameter sets
|
||||
- Extracts rich trade-level data (MAE/MFE) after each run
|
||||
- Analyzes results to find failure patterns
|
||||
- Proposes and tests parameter mutations
|
||||
- Validates improvements before accepting them
|
||||
- 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)
|
||||
- Prevents overfitting via Walk-Forward + Out-of-Sample testing
|
||||
- Displays everything live in a beautiful browser dashboard
|
||||
- Writes human-readable reports to a visible `Reports\` folder
|
||||
|
||||
**End user:** Traders (non-technical). Must be a double-click app, not a terminal tool.
|
||||
**End user:** Traders (non-technical). Double-click app, no terminal needed.
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Architecture Overview
|
||||
|
||||
```
|
||||
MT5 Terminal (GUI)
|
||||
└── Strategy Tester (automated via .ini files)
|
||||
└── LEGSTECH_EA_V2.ex5 (compiled EA with TradeLogger)
|
||||
└── Writes: LEGSTECH_EA_V2_XAUUSD_TradeLog.csv
|
||||
|
||||
Python Optimizer (backend engine)
|
||||
├── MT5 Runner → launch terminal, wait for report, collect files
|
||||
├── Report Parser → parse MT5 XML/HTML report into metrics + trades
|
||||
├── Log Reader → merge TradeLogger CSV (MAE/MFE) into trade objects
|
||||
├── Analysis Engine → 4 modules detecting failure patterns
|
||||
│ ├── ReversalAnalyzer → trades that went in profit then reversed
|
||||
│ ├── TimePerformanceAnalyzer → bad sessions/hours/days
|
||||
│ ├── EntryExitQualityAnalyzer → MAE/MFE quality scores
|
||||
│ └── EquityCurveAnalyzer → flatness, loss clusters, R²
|
||||
├── Composite Scorer → Calmar-primary weighted score (0-1)
|
||||
├── Mutation Engine → findings → parameter hypotheses (13 KB rules)
|
||||
├── Validation Gate → IS check → Walk-Forward → OOS
|
||||
└── Data Store → SQLite (metadata) + Parquet (trade arrays)
|
||||
|
||||
Web App (NEXT TO BUILD — Phase 2)
|
||||
├── Flask backend → serves UI, runs optimization loop
|
||||
├── WebSocket → pushes live updates to browser
|
||||
├── HTML/JS frontend → live dashboard, charts, findings
|
||||
└── Reports folder → HTML + CSV reports per run
|
||||
[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]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📁 File Structure (Current State)
|
||||
## 📁 Complete File Structure
|
||||
|
||||
```
|
||||
C:\Users\DELL\Desktop\MT5_Optimizer\
|
||||
├── main.py ← CLI entry point (terminal-based, to be replaced by app.py)
|
||||
├── config.yaml ← ALL settings (MT5 paths, symbols, scoring weights, thresholds)
|
||||
│
|
||||
├── 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)
|
||||
├── requirements.txt ← Python dependencies
|
||||
├── PROJECT_HANDOFF.md ← THIS DOCUMENT
|
||||
├── "Launch Optimizer.bat" ← Double-click to start (opens browser automatically)
|
||||
│ Uses Python 3.11 at hardcoded path
|
||||
│
|
||||
├── mql5/
|
||||
│ └── TradeLogger.mqh ← MQL5 include file (ALREADY DEPLOYED to MT5)
|
||||
│ └── TradeLogger.mqh ← MQL5 include: per-trade MAE/MFE logger
|
||||
│ DEPLOYED to: ...Terminal\...\MQL5\Include\
|
||||
│ INTEGRATED in: LEGSTECH_EA_V2.mq5 via TL_OnTick()
|
||||
│
|
||||
├── data/
|
||||
│ ├── models.py ← Pydantic v2 models: Trade, RunMetrics, Run, Finding, Hypothesis, Candidate
|
||||
│ └── store.py ← DataStore: SQLite + Parquet storage layer
|
||||
│ ├── models.py ← Pydantic v2: Trade, RunMetrics, Run, Finding,
|
||||
│ │ Hypothesis, Candidate, RunResult
|
||||
│ └── store.py ← DataStore: SQLite metadata + Parquet trade arrays
|
||||
│
|
||||
├── mt5/
|
||||
│ ├── ini_builder.py ← Builds MT5 tester .ini files from param dicts
|
||||
│ ├── runner.py ← Launches MT5 subprocess, waits for report
|
||||
│ ├── report_parser.py ← Parses MT5 XML/HTML report → RunMetrics + list[Trade]
|
||||
│ └── log_reader.py ← Merges TradeLogger CSV, computes sessions/quality scores
|
||||
│ ├── 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
|
||||
│
|
||||
├── analysis/
|
||||
│ ├── base.py ← BaseAnalyzer ABC + statistical helpers
|
||||
│ ├── reversal.py ← ReversalAnalyzer
|
||||
│ ├── time_performance.py ← TimePerformanceAnalyzer
|
||||
│ ├── entry_exit_quality.py ← EntryExitQualityAnalyzer
|
||||
│ └── equity_curve.py ← EquityCurveAnalyzer
|
||||
│ ├── 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
|
||||
│
|
||||
├── scoring/
|
||||
│ └── composite.py ← CompositeScorer (Calmar + PF + MFE capture + stability + recovery)
|
||||
│ └── composite.py ← Weighted scorer: Calmar(35%) + PF(20%) +
|
||||
│ MFE capture(20%) + stability(15%) + recovery(10%)
|
||||
│
|
||||
├── mutation/
|
||||
│ ├── engine.py ← MutationEngine: findings → Hypothesis objects
|
||||
│ ├── knowledge_base.yaml ← 13 rules mapping findings to param changes
|
||||
│ └── param_manifest.yaml ← Full EA parameter space with types/bounds/defaults
|
||||
│ ├── 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
|
||||
│
|
||||
├── validation/
|
||||
│ └── gate.py ← IS check + Walk-Forward + OOS + sensitivity check
|
||||
│ └── gate.py ← IS check → Walk-Forward (2 folds) → OOS
|
||||
│
|
||||
└── tests/
|
||||
└── test_analyzers.py ← 10 unit tests (all passing ✅)
|
||||
├── 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
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Configuration (config.yaml) — Key Values
|
||||
## ⚙️ Configuration (config.yaml)
|
||||
|
||||
```yaml
|
||||
ea:
|
||||
name: "LEGSTECH_EA_V2"
|
||||
file: "LEGSTECH_EA_V2" # no extension — MT5 adds .ex5
|
||||
symbol: "XAUUSD"
|
||||
timeframe: "H1"
|
||||
|
||||
periods:
|
||||
train_start: "2022.01.01"
|
||||
train_end: "2023.12.31"
|
||||
train_start: "2022.01.01"
|
||||
train_end: "2023.12.31"
|
||||
validate_start: "2024.01.01"
|
||||
validate_end: "2024.06.30"
|
||||
oos_start: "2024.07.01" # LOCKED — never touch during optimization
|
||||
oos_end: "2024.12.31"
|
||||
oos_start: "2024.07.01" # SACRED — never optimize against this
|
||||
oos_end: "2024.12.31"
|
||||
|
||||
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"
|
||||
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
|
||||
|
||||
broker:
|
||||
timezone_offset_hours: 2 # UTC+2
|
||||
|
||||
scoring:
|
||||
weights:
|
||||
calmar: 0.35
|
||||
profit_factor: 0.20
|
||||
mfe_capture: 0.20
|
||||
session_stability: 0.15
|
||||
recovery_factor: 0.10
|
||||
timezone_offset_hours: 2 # UTC+2 (HFMarkets)
|
||||
deposit: 10000.0
|
||||
currency: "USD"
|
||||
leverage: 100
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ What is Done (Phase 1 — Backend Engine)
|
||||
## ✅ What Is Complete
|
||||
|
||||
### Phase 1 — Backend Engine
|
||||
|
||||
| Component | Status | Notes |
|
||||
|---|---|---|
|
||||
| TradeLogger.mqh | ✅ Complete + deployed | In MT5 Include folder, tested, CSV confirmed working |
|
||||
| data/models.py | ✅ Complete | All Pydantic v2 models |
|
||||
| data/store.py | ✅ Complete | SQLite + Parquet CRUD |
|
||||
| mt5/ini_builder.py | ✅ Complete | Generates valid MT5 tester INI files |
|
||||
| mt5/runner.py | ✅ Complete | Process launch + polling + timeout |
|
||||
| mt5/report_parser.py | ✅ Complete | XML + HTML dual-format parser |
|
||||
| mt5/log_reader.py | ✅ Complete | MAE/MFE merge + session classification |
|
||||
| analysis/reversal.py | ✅ Complete | Permutation-tested |
|
||||
| analysis/time_performance.py | ✅ Complete | Hour/Session/Day analysis |
|
||||
| analysis/entry_exit_quality.py | ✅ Complete | 4-case diagnosis matrix |
|
||||
| analysis/equity_curve.py | ✅ Complete | Flatness + R² + loss clusters |
|
||||
| scoring/composite.py | ✅ Complete | Calmar-primary weighted scorer |
|
||||
| mutation/engine.py | ✅ Complete | 13 KB rules, dedup, cascade |
|
||||
| validation/gate.py | ✅ Complete | IS + WFV + OOS + sensitivity |
|
||||
| main.py | ✅ Complete | Terminal CLI (will be replaced by app) |
|
||||
| tests/ | ✅ 10/10 passing | Pure Python, no MT5 needed |
|
||||
| Unit tests verified | ✅ Working | Python 3.11 required (see below) |
|
||||
| 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 |
|
||||
|
||||
---
|
||||
|
||||
## 🔴 What is NOT Done Yet (Phase 2 — GUI App)
|
||||
## 🐛 Critical Bugs Found & Fixed (Important for Future AI)
|
||||
|
||||
### The Big Next Step: Web App with Live Dashboard
|
||||
|
||||
**Goal:** Replace `main.py` terminal interface with a beautiful browser-based app that:
|
||||
|
||||
1. **Double-click `MT5_Optimizer.exe`** → browser opens automatically at `http://localhost:5000`
|
||||
2. **Dashboard shows live:**
|
||||
- Iteration counter + current phase badge
|
||||
- Score history line chart (Calmar + composite over time)
|
||||
- Live MT5 run status with elapsed timer
|
||||
- Current parameters being tested
|
||||
3. **Analysis panel shows** findings in plain English after each run
|
||||
4. **Parameter changes panel** shows before → after with reason
|
||||
5. **Results folder** `MT5_Optimizer\Reports\` gets:
|
||||
- `run_001\summary.html` — full backtest result in readable format
|
||||
- `run_001\trades.csv` — all trades with MAE/MFE
|
||||
- `run_001\findings.csv` — analysis findings
|
||||
- `run_001\parameters.json` — params used
|
||||
6. **Controls:** Start, Pause, Skip Hypothesis, View Report buttons
|
||||
7. **PyInstaller** bundles into single `MT5_Optimizer.exe`
|
||||
|
||||
### Tech Stack for Phase 2
|
||||
|
||||
```
|
||||
Flask + Flask-SocketIO → backend API + WebSocket push
|
||||
Chart.js or Plotly.js → charts in browser
|
||||
Bootstrap 5 (dark theme) → UI framework
|
||||
Jinja2 → HTML report templates
|
||||
PyInstaller → package to .exe
|
||||
### 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
|
||||
```
|
||||
|
||||
### Files to create in Phase 2
|
||||
|
||||
### 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.
|
||||
```
|
||||
app.py ← Flask app entry point (replaces main.py)
|
||||
ui/
|
||||
templates/
|
||||
index.html ← Main dashboard
|
||||
report.html ← Per-run report template
|
||||
findings.html ← Findings detail page
|
||||
static/
|
||||
css/style.css
|
||||
js/dashboard.js ← WebSocket + Chart.js logic
|
||||
reports/ ← All run outputs go here (user-visible)
|
||||
MT5_Optimizer.spec ← PyInstaller spec file
|
||||
build.bat ← One-click build to .exe
|
||||
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
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Environment & Dependencies
|
||||
## 🔧 Environment Details
|
||||
|
||||
**Python version:** 3.11 (NOT 3.13 — use `C:\Users\DELL\AppData\Local\Programs\Python\Python311\python.exe`)
|
||||
| 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 |
|
||||
|
||||
**Install command:**
|
||||
**Install all dependencies:**
|
||||
```powershell
|
||||
C:\Users\DELL\AppData\Local\Programs\Python\Python311\python.exe -m pip install -r requirements.txt
|
||||
```
|
||||
|
||||
**Run tests:**
|
||||
```powershell
|
||||
cd C:\Users\DELL\Desktop\MT5_Optimizer
|
||||
C:\Users\DELL\AppData\Local\Programs\Python\Python311\python.exe -m pytest tests/ -v
|
||||
**Key dependencies:**
|
||||
```
|
||||
|
||||
**Key dependency versions:**
|
||||
```
|
||||
pydantic>=2.5, pandas>=2.1, pyarrow>=14.0, lxml>=4.9
|
||||
loguru>=0.7, rich>=13.0, scipy>=1.11, pyyaml>=6.0
|
||||
```
|
||||
|
||||
**Additional needed for Phase 2:**
|
||||
```
|
||||
flask, flask-socketio, eventlet, jinja2, pyinstaller
|
||||
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
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧠 Key Design Decisions (Important Context)
|
||||
## 🧠 Key Design Decisions
|
||||
|
||||
1. **Hypothesis-driven, not brute-force** — We don't grid-search all params. We detect failure patterns, hypothesize a fix, test it, validate it.
|
||||
|
||||
2. **Calmar ratio is primary score metric** — Return / MaxDrawdown is most relevant for live trading.
|
||||
|
||||
3. **Three validation gates** — IS threshold → Walk-Forward (2 folds) → OOS (locked period). No candidate is promoted unless it passes all three.
|
||||
|
||||
4. **MFE/MAE is critical** — Without the TradeLogger, the analyzer still works but is less powerful. Always confirm CSV is being generated.
|
||||
|
||||
5. **OOS is sacred** — `2024.07.01 → 2024.12.31` is NEVER used during optimization. Only tested as final confirmation.
|
||||
|
||||
6. **Broker timezone = UTC+2** — All session analysis normalizes to UTC internally. Sessions: London=07-16 UTC, NY=13-22 UTC.
|
||||
|
||||
7. **Python 3.11 is required** — The system Python on this machine is 3.13 which doesn't have the packages. Always use the 3.11 path.
|
||||
|
||||
8. **MQL5 reference syntax fix** — MQL5 does not support C++ `&` references to array elements. `TradeLogger.mqh` was patched to use direct `TL_Positions[idx].field` access.
|
||||
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.
|
||||
|
||||
---
|
||||
|
||||
## 📍 Current Machine Paths (This User's System)
|
||||
## 📋 Live Dashboard Events (SocketIO)
|
||||
|
||||
```
|
||||
MT5 Terminal EXE: C:\Program Files\MetaTrader 5\terminal64.exe
|
||||
MT5 Terminal Data: C:\Users\DELL\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\
|
||||
MT5 Tester Files: C:\Users\DELL\AppData\Roaming\MetaQuotes\Tester\D0E8209F77C8CF37AD8BF550E51FF075\Agent-127.0.0.1-3000\MQL5\Files\
|
||||
EA Source File: C:\Users\DELL\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Experts\LEGSTECH_EA_V2.mq5
|
||||
TradeLogger (deployed): ...Terminal\...\MQL5\Include\TradeLogger.mqh
|
||||
Project Folder: C:\Users\DELL\Desktop\MT5_Optimizer\
|
||||
Python 3.11: C:\Users\DELL\AppData\Local\Programs\Python\Python311\python.exe
|
||||
```
|
||||
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 |
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Phase 2 Build Instructions (For Next AI Session)
|
||||
## 🚀 Next Steps (Phase 3 — Packaging)
|
||||
|
||||
When continuing this project, build Phase 2 in this order:
|
||||
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
|
||||
|
||||
### Step 1 — Flask app skeleton
|
||||
Create `app.py` with:
|
||||
- Flask app + SocketIO
|
||||
- Route: `GET /` → serve dashboard
|
||||
- Route: `GET /api/status` → current run status JSON
|
||||
- Route: `POST /api/start` → start optimization loop in background thread
|
||||
- Route: `POST /api/pause` → pause loop
|
||||
- SocketIO event: emit `run_update` after each test completes
|
||||
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
|
||||
|
||||
### Step 2 — Dashboard HTML
|
||||
Create `ui/templates/index.html`:
|
||||
- Dark theme (Bootstrap 5 dark)
|
||||
- Left panel: score history chart (Chart.js line chart)
|
||||
- Right panel: current run metrics card
|
||||
- Bottom panel: scrollable findings feed
|
||||
- Top bar: Start/Pause button, iteration counter, phase badge, timer
|
||||
3. **Email/Telegram notification** — Alert the trader when a candidate is promoted
|
||||
|
||||
### Step 3 — Report template
|
||||
Create `ui/templates/report.html`:
|
||||
- Full metrics table
|
||||
- Findings list in plain English
|
||||
- Parameter delta table (old → new → why)
|
||||
- Trade table with MAE/MFE columns
|
||||
4. **Multi-symbol support** — Run optimization across EURUSD, GBPUSD alongside XAUUSD
|
||||
|
||||
### Step 4 — Reports folder writer
|
||||
Create `reports/writer.py`:
|
||||
- `write_run_report(run_id, metrics, trades_df, findings)` → writes HTML + CSV
|
||||
- All outputs go to `MT5_Optimizer\Reports\run_XXX\`
|
||||
|
||||
### Step 5 — PyInstaller packaging
|
||||
Create `build.bat`:
|
||||
```bat
|
||||
pyinstaller --onefile --noconsole --name MT5_Optimizer app.py
|
||||
```
|
||||
Create `MT5_Optimizer.spec` with proper hidden imports for Flask, SocketIO, etc.
|
||||
|
||||
### Step 6 — Test end-to-end
|
||||
- Double-click `MT5_Optimizer.exe`
|
||||
- Browser opens at localhost:5000
|
||||
- Click Start
|
||||
- Watch live updates
|
||||
- Check Reports folder
|
||||
5. **Monte Carlo simulation** — Test robustness of promoted candidates
|
||||
|
||||
---
|
||||
|
||||
## 💡 Future Enhancements (v2)
|
||||
## ⚠️ Known Issues & Watch Points
|
||||
|
||||
- Multi-symbol optimization (EURUSD, GBPUSD alongside XAUUSD)
|
||||
- Full rolling window WFV (currently 2-fold MVP)
|
||||
- Portfolio-level Calmar (across symbols)
|
||||
- Monte Carlo simulation for robustness testing
|
||||
- Email/Telegram notification when a candidate is promoted
|
||||
- Parameter sensitivity heatmap visualization
|
||||
- Automatic .set file export for validated candidates
|
||||
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.
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Known Issues / Watch Points
|
||||
## 📊 Baseline Run Results (Confirmed Working)
|
||||
|
||||
1. **MT5 tester model** — Currently config uses `tester_model: 0` (Every Tick). For XAUUSD this is slow. Use model `4` (OHLC M1) for faster iteration during development.
|
||||
First successful parser test on real MT5 report (2026-04-13):
|
||||
|
||||
2. **ShutdownTerminal=1** — The INI closes MT5 after each test. If MT5 is also being used for live trading, this will interrupt it. Separate terminal instances are recommended.
|
||||
| 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 |
|
||||
|
||||
3. **Agent path** — The Tester Agent path (`Agent-127.0.0.1-3000`) may change if the MT5 tester port changes. If CSV is not found, check the Tester folder.
|
||||
|
||||
4. **WFV fold count** — Currently hardcoded to 2 folds in `validation/gate.py`. Easy to increase.
|
||||
|
||||
5. **INI Period code** — H1 = 16385 in MT5 (ENUM_TIMEFRAMES). This is hardcoded in `config.yaml` as `mt5_period_code: 16385`. Do not change unless changing timeframe.
|
||||
> This is the baseline — the optimizer's job is to improve these numbers over iterations.
|
||||
|
||||
---
|
||||
|
||||
*This document was generated by Antigravity AI on 2026-04-13.*
|
||||
*Continue building from Phase 2 — GUI App.*
|
||||
*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).*
|
||||
|
||||
Reference in New Issue
Block a user