"""Parse MT5 optimization XML and export best / high-trade sets."""
from __future__ import annotations
import re
import sys
from pathlib import Path
LAB = Path(__file__).resolve().parent
SET_DEFAULTS = {
"UseDailyBias": "false",
"DailyEmaPeriod": "50",
"HtfZoneBars": "12",
"MinBreakBodyRatio": "0.40",
"UseDoubleTrap": "false",
"NyChaosStartHour": "12",
"NyChaosEndHour": "14",
"MomentumStartHour": "8",
"MomentumEndHour": "23",
"UseMomentumWindow": "false",
"LtfFastEma": "6",
"LtfSlowEma": "18",
"EntryMode": "3",
"AllowLtfPullback": "true",
"AllowEmaCross": "true",
"MinEmaGapPips": "0.0",
"AtrSlMult": "1.3",
"AtrTpMult": "1.8",
"UseTrailing": "true",
"TrailAtrMult": "0.8",
"MaxBarsInTrade": "20",
"CooldownBars": "0",
"MaxSpreadPips": "8",
"UseCompressionFilter": "false",
"CompressAtrRatio": "0.70",
}
def parse_xml(path: Path) -> tuple[list[str], list[dict[str, str]]]:
text = path.read_text(encoding="utf-8", errors="ignore")
header = re.search(r".*?Pass.*?
", text, re.S)
if not header:
raise SystemExit("header not found")
cols = re.findall(r'([^<]+)', header.group(0))
out: list[dict[str, str]] = []
for row in re.findall(r"(.*?)
", text, re.S)[1:]:
cells = re.findall(r'([^<]+)', row)
if len(cells) >= len(cols):
out.append(dict(zip(cols, cells)))
return cols, out
def row_to_set_params(row: dict[str, str]) -> dict[str, str]:
merged = dict(SET_DEFAULTS)
for k, v in row.items():
if k in merged:
merged[k] = v
if "EntryMode" not in row:
merged["EntryMode"] = "3"
return merged
def write_set(path: Path, params: dict[str, str]) -> None:
merged = {**SET_DEFAULTS, **params}
lines = [
"; USDCHF Playbook — MT5 genetic optimization export",
"Timeframe=16388",
"HtfTimeframe=16396",
"DailyTimeframe=16408",
"MagicNumber=20260625",
"LotSize=0.10",
"AtrPeriod=14",
"ExtendHoldMomentum=false",
"CompressLookback=48",
]
for k in SET_DEFAULTS:
lines.append(f"{k}={merged[k]}")
path.write_text("\n".join(lines) + "\n", encoding="utf-8")
def main() -> None:
xml = Path(sys.argv[1]) if len(sys.argv) > 1 else None
if xml is None:
xml = LAB.parent.parent.parent / ".." / "USDCHF_USDCHF_optimize.xml"
if not xml.exists():
import MetaTrader5 as mt5
if not mt5.initialize():
raise SystemExit("MT5 init failed")
data = Path(mt5.terminal_info().data_path)
mt5.shutdown()
xml = data / "USDCHF_USDCHF_optimize.xml"
if not xml.exists():
raise SystemExit(f"missing {xml}")
_, rows = parse_xml(xml)
best_profit = max(rows, key=lambda r: float(r["Profit"]))
best_balanced = None
for r in rows:
profit = float(r["Profit"])
trades = int(float(r["Trades"]))
pf = float(r["Profit Factor"])
if profit > 0 and pf >= 1.05 and trades >= 80:
sc = profit + trades * 15.0
if best_balanced is None or sc > float(best_balanced["score"]):
best_balanced = {**r, "score": str(sc)}
out_profit = LAB / "USDCHF_optimized.set"
write_set(out_profit, row_to_set_params(best_profit))
print(f"Best profit: ${float(best_profit['Profit']):,.2f} trades={best_profit['Trades']} PF={best_profit['Profit Factor']}")
print(f"Wrote {out_profit}")
if best_balanced:
out_bal = LAB / "USDCHF_optimized_balanced.set"
write_set(out_bal, row_to_set_params(best_balanced))
print(
f"Best balanced: ${float(best_balanced['Profit']):,.2f} "
f"trades={best_balanced['Trades']} PF={best_balanced['Profit Factor']}"
)
print(f"Wrote {out_bal}")
if __name__ == "__main__":
main()