Spaces:
No application file
No application file
File size: 4,722 Bytes
669d6a1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | from __future__ import annotations
import argparse
import re
import shutil
import subprocess
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
DEFAULT_TERMINAL_DATA = Path(
r"C:\Users\aksha\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075"
)
DEFAULT_METAEDITOR = Path(r"C:\Program Files\MetaTrader 5\MetaEditor64.exe")
EA_SOURCE = ROOT / "mql5" / "Experts" / "AFML" / "AFMLLiveONNXEA.mq5"
PRODUCTION_ROOT = ROOT / "production_models" / "live_mt5"
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(
description="Deploy AFML ONNX models and live EA into the local MT5 terminal."
)
parser.add_argument("--terminal-data", default=str(DEFAULT_TERMINAL_DATA))
parser.add_argument("--metaeditor", default=str(DEFAULT_METAEDITOR))
parser.add_argument("--timeframe", default="M15")
return parser.parse_args()
def latest_model(symbol: str, timeframe: str) -> Path:
model_dir = PRODUCTION_ROOT / symbol / timeframe
candidates = sorted(model_dir.glob("*.onnx"))
if not candidates:
raise FileNotFoundError(f"No ONNX models found in {model_dir}")
return candidates[-1]
def compile_ea(metaeditor: Path, ea_path: Path, log_path: Path) -> tuple[bool, int, str]:
proc = subprocess.run(
[str(metaeditor), f"/compile:{ea_path}", f"/log:{log_path}"],
capture_output=True,
text=True,
timeout=120,
)
log_text = log_path.read_text(encoding="utf-16", errors="replace") if log_path.exists() else ""
# MetaEditor may return non-zero even when compile finishes with warnings only.
# Prefer the compiler summary line when available.
match = re.search(r"Result:\s*(\d+)\s+errors", log_text)
if match:
return int(match.group(1)) == 0, proc.returncode, log_text
return proc.returncode == 0, proc.returncode, log_text
def write_set_file(path: Path, model_rel_path: str, timeframe: str, magic_number: int) -> None:
path.write_text(
"\n".join(
[
f"InpOnnxModelFile={model_rel_path}",
f"InpSignalTimeframe={timeframe}",
"InpEnableTrading=false",
"InpCloseOpposite=true",
"InpFixedLot=0.01",
"InpBuyThreshold=0.55",
"InpSellThreshold=0.45",
"InpStopAtrMultiplier=1.5",
"InpTakeAtrMultiplier=2.0",
"InpMaxSpreadPoints=500",
"InpSlippagePoints=30",
f"InpMagicNumber={magic_number}",
]
),
encoding="utf-8",
)
def main() -> int:
args = parse_args()
terminal_data = Path(args.terminal_data)
metaeditor = Path(args.metaeditor)
experts_dir = terminal_data / "MQL5" / "Experts" / "AFML"
files_dir = terminal_data / "MQL5" / "Files" / "AFML" / "Models"
presets_dir = terminal_data / "MQL5" / "Profiles" / "Tester"
experts_dir.mkdir(parents=True, exist_ok=True)
files_dir.mkdir(parents=True, exist_ok=True)
presets_dir.mkdir(parents=True, exist_ok=True)
deployed = []
for symbol, stable_name in [("BTCUSD", "btcusd_m15_live.onnx"), ("XAUUSD", "xauusd_m15_live.onnx")]:
source = latest_model(symbol, args.timeframe)
target = files_dir / stable_name
shutil.copy2(source, target)
deployed.append((symbol, source, target))
ea_target = experts_dir / EA_SOURCE.name
shutil.copy2(EA_SOURCE, ea_target)
write_set_file(
presets_dir / "AFML_BTCUSD_M15.set",
"AFML\\Models\\btcusd_m15_live.onnx",
args.timeframe,
202605031,
)
write_set_file(
presets_dir / "AFML_XAUUSD_M15.set",
"AFML\\Models\\xauusd_m15_live.onnx",
args.timeframe,
202605032,
)
log_path = ROOT / "diagnostics" / "metaeditor_compile.log"
log_path.parent.mkdir(parents=True, exist_ok=True)
compile_ok = None
compile_code = None
compile_log = ""
if metaeditor.exists():
compile_ok, compile_code, compile_log = compile_ea(metaeditor, ea_target, log_path)
print(f"EA deployed to: {ea_target}")
for symbol, source, target in deployed:
print(f"{symbol}: {source.name} -> {target}")
print(f"Preset files: {presets_dir / 'AFML_BTCUSD_M15.set'}")
print(f"Preset files: {presets_dir / 'AFML_XAUUSD_M15.set'}")
if compile_code is not None:
print(f"MetaEditor exit code: {compile_code}")
if compile_log:
print("\nCompile log tail:\n")
print(compile_log[-4000:])
if compile_ok is None:
return 0
return 0 if compile_ok else 1
if __name__ == "__main__":
raise SystemExit(main())
|