2026-11-04 01:33:38 +01:00 | | | """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 ""
|
2026-11-04 15:03:18 +01:00 | | | guirun = os.environ.get("TF_GUIRUN") == "1" # drive the real window: fill the form and press GENERATE
|
2026-11-04 15:50:31 +01:00 | | | guiaudit = os.environ.get("TF_GUIAUDIT") == "1" # same, but press "Audit set" (7 symbols)
|
| | | auto = "false" if (shot or guirun or guiaudit) else "true"
|
2026-11-04 01:33:38 +01:00 | | | w16(D / "MQL5/Presets/tf_auto.set",
|
| | | "InpAuto=%s\nInpScreenshot=%s\nInpSource=%s\nInpTarget=%s\nInpFromDate=%s\nInpToDate=%s\nInpDataMode=%s\n"
|
2026-11-04 15:50:31 +01:00 | | | "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"))
|
2026-11-04 01:33:38 +01:00 | | | 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"
|
2026-11-04 15:03:18 +01:00 | | | w16(ini, "[StartUp]\nExpert=Tick_Forge\\TF_Dev\nExpertParameters=tf_auto.set\nSymbol=%s\nPeriod=M1\n" % sym)
|
2026-11-04 01:33:38 +01:00 | | | 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)
|