"""Developer helper: drive Tick_Forge headless on a TESTING terminal install and report. usage: tf_run.py SRC NAME FROM TO MODE OFFSET_HOURS FUNCTION [SCREENSHOT.png] Set TF_DATA / TF_EXE for your own install. Defaults point at the OANDA testing install used in development. Never point this at a live-money terminal. """ import os, subprocess, sys, time from pathlib import Path D = Path(os.environ.get("TF_DATA", r"C:\Users\gebruiker\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075")) EXE = os.environ.get("TF_EXE", r"C:\Program Files\MetaTrader 5\terminal64.exe") def w16(p, s): Path(p).write_bytes(b"\xff\xfe" + s.replace("\n", "\r\n").encode("utf-16-le")) def kill(): subprocess.run(["powershell", "-NoProfile", "-Command", "Get-Process terminal64 -EA SilentlyContinue | Where-Object {$_.Path -eq '%s'} | Stop-Process -Force" % EXE]) sym, name, fr, to, mode, off, fn = sys.argv[1:8] shot = sys.argv[8] if len(sys.argv) > 8 else "" guirun = os.environ.get("TF_GUIRUN") == "1" # drive the real window: fill the form and press GENERATE guiaudit = os.environ.get("TF_GUIAUDIT") == "1" # same, but press "Audit set" (7 symbols) auto = "false" if (shot or guirun or guiaudit) else "true" w16(D / "MQL5/Presets/tf_auto.set", "InpAuto=%s\nInpScreenshot=%s\nInpSource=%s\nInpTarget=%s\nInpFromDate=%s\nInpToDate=%s\nInpDataMode=%s\n" "InpOffsetHours=%s\nInpFunction=%s\nInpScaleSpread=true\nInpOverwrite=true\nInpCloseTerminal=true\nInpGuiRun=%s\nInpGuiAudit=%s\n" % (auto, shot, sym, name, fr, to, mode, off, fn, "true" if guirun else "false", "true" if guiaudit else "false")) import shutil (D / "MQL5/Profiles/Tester").mkdir(parents=True, exist_ok=True) shutil.copy2(D / "MQL5/Presets/tf_auto.set", D / "MQL5/Profiles/Tester/tf_auto.set") ini = Path(os.environ["TEMP"]) / "tf_auto.ini" w16(ini, "[StartUp]\nExpert=Tick_Forge\\TF_Dev\nExpertParameters=tf_auto.set\nSymbol=%s\nPeriod=M1\n" % sym) kill() time.sleep(2) for l in (D / "MQL5/Logs").glob("*.log"): try: l.rename(l.with_suffix(".bak%d" % int(time.time()))) except OSError: pass subprocess.Popen([EXE, "/config:%s" % ini]) key = "TICKFORGE_SHOT" if shot else "TICKFORGE_RESULT" t0 = time.time() lines = [] while time.time() - t0 < 900: time.sleep(4) logs = sorted((D / "MQL5/Logs").glob("*.log")) if logs: lines = logs[-1].read_bytes().decode("utf-16-le", "ignore").splitlines() if any(key in x for x in lines): break time.sleep(8) for x in lines: if "TICKFORGE" in x or "TickForge" in x: print(x.encode("ascii", "ignore").decode()[:300]) kill() if shot else None # headless generation closes the terminal itself (graceful, flushes the symbol list)