from __future__ import annotations import argparse import json from pathlib import Path ROOT = Path(__file__).resolve().parents[1] REPORT_DIR = ROOT / "reports" / "eth-exploration" MARKDOWN_REPORT = REPORT_DIR / "eth-robust-twap-live-plan.md" JSON_REPORT = REPORT_DIR / "eth-robust-twap-live-plan.json" REQUIRED_SOURCE_FILES = ( ROOT / "okx_codex_trader" / "okx_client.py", ROOT / "okx_codex_trader" / "cli.py", ROOT / "okx_codex_trader" / "paper_engine.py", ROOT / "freqtrade" / "README.md", ROOT / "freqtrade" / "user_data" / "strategies" / "BtcRsi2Guarded.py", ROOT / "scripts" / "search_eth_twap_robustness_10y.py", ROOT / "scripts" / "explore_ultrashort.py", REPORT_DIR / "eth-twap-robustness-10y-summary.md", REPORT_DIR / "eth-twap-robustness-10y-ranked.csv", ) REQUIRED_MARKDOWN_HEADINGS = ( "# ETH Robust Price TWAP 15m live execution plan", "## Signal clock", "## Entry orders", "## Partial fills", "## Exit and stop", "## State file", "## Minimum real-funds test", "## Commands and files", ) REQUIRED_JSON_KEYS = ( "strategy", "source_read", "signal_clock", "entry_orders", "partial_fills", "exit_and_stop", "state_file", "minimum_real_funds_test", "minimal_implementation_path", ) def validate() -> list[str]: errors: list[str] = [] for path in REQUIRED_SOURCE_FILES: if not path.exists(): errors.append(f"missing source file: {path.relative_to(ROOT)}") if not MARKDOWN_REPORT.exists(): errors.append(f"missing markdown report: {MARKDOWN_REPORT.relative_to(ROOT)}") else: text = MARKDOWN_REPORT.read_text(encoding="utf-8") for heading in REQUIRED_MARKDOWN_HEADINGS: if heading not in text: errors.append(f"missing markdown heading: {heading}") forbidden_phrases = ("place_order(", "/api/v5/trade/order", "confirm-live") for phrase in forbidden_phrases: if phrase in text: errors.append(f"report must not describe an executable order call: {phrase}") if not JSON_REPORT.exists(): errors.append(f"missing json report: {JSON_REPORT.relative_to(ROOT)}") else: try: payload = json.loads(JSON_REPORT.read_text(encoding="utf-8")) except json.JSONDecodeError as exc: errors.append(f"json report is invalid: {exc}") else: if not isinstance(payload, dict): errors.append("json report root must be an object") else: for key in REQUIRED_JSON_KEYS: if key not in payload: errors.append(f"missing json key: {key}") return errors def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("--json", action="store_true", help="print validation result as JSON") args = parser.parse_args() errors = validate() result = { "ok": not errors, "checked_reports": [ str(MARKDOWN_REPORT.relative_to(ROOT)), str(JSON_REPORT.relative_to(ROOT)), ], "errors": errors, } if args.json: print(json.dumps(result, indent=2)) elif errors: print("\n".join(errors)) else: print("eth robust twap live plan static check passed") return 1 if errors else 0 if __name__ == "__main__": raise SystemExit(main())