2026-10-28 00:30:38 -04:00 | | | """Compatibility CLI for the supported real-history universal model pipeline.
|
| | |
|
| | | Gate acceptance is not a financial outcome. The retired snapshot trainer used
|
| | | fabricated single-class labels and preprocessing fitted before splitting.
|
| | | This module delegates to the shared MQL5 pipeline, without Python ML packages.
|
| | | """
|
| | | from __future__ import annotations
|
| | | import argparse
|
| | | import json
|
| | | from pathlib import Path
|
| | | import subprocess
|
| | | import sys
|
| | |
|
| | | TRAIN_SCRIPT = Path(__file__).resolve().with_name("Build-MarketModel.ps1")
|
| | | DEFAULT_OUTPUT = Path(__file__).resolve().parent / "artifacts" / "universal"
|
| | |
|
| | |
|
| | | def build_command(symbols: str | None, output_directory: str | Path) -> list[str]:
|
| | | command = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass",
|
| | | "-File", str(TRAIN_SCRIPT), "-OutputDirectory",
|
| | | str(Path(output_directory).expanduser().resolve())]
|
| | | if symbols is not None:
|
| | | if any(ord(c) < 32 for c in symbols):
|
| | | raise ValueError("--symbols cannot contain control characters")
|
| | | names = [name.strip() for name in symbols.split(",")]
|
| | | if not names or any(not name for name in names):
|
| | | raise ValueError("--symbols must contain nonempty comma-separated broker symbols")
|
| | | if len({name.casefold() for name in names}) != len(names):
|
| | | raise ValueError("--symbols contains duplicate broker symbols")
|
| | | command.extend(["-Symbols", ",".join(names)])
|
| | | return command
|
| | |
|
| | |
|
| | | def main(argv: list[str] | None = None) -> int:
|
| | | parser = argparse.ArgumentParser(description=__doc__)
|
| | | parser.add_argument("--symbols", help="Exact comma-separated broker symbols; omitted uses the supported default universe")
|
| | | parser.add_argument("--output-directory", "--out-dir", "--out_dir", default=str(DEFAULT_OUTPUT))
|
| | | parser.add_argument("--dry-run", action="store_true", help="Print exact argv as JSON without training")
|
| | | args = parser.parse_args(argv)
|
| | | try:
|
| | | command = build_command(args.symbols, args.output_directory)
|
| | | except ValueError as error:
|
| | | parser.error(str(error))
|
| | | if args.dry_run:
|
| | | print(json.dumps(command, indent=2))
|
| | | return 0
|
| | | if not TRAIN_SCRIPT.is_file():
|
| | | parser.error(f"Training orchestrator is missing: {TRAIN_SCRIPT}")
|
| | | if sys.platform != "win32":
|
| | | parser.error("This pipeline requires Windows MetaTrader 5 and real broker history")
|
| | | try:
|
| | | return subprocess.run(command, check=False).returncode
|
| | | except OSError as error:
|
| | | parser.exit(1, f"Could not launch the real-history training pipeline: {error}\n")
|
| | |
|
| | |
|
| | | if __name__ == "__main__":
|
| | | raise SystemExit(main())
|