codex_analyzer.py 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. import json
  2. import shutil
  3. import subprocess
  4. from dataclasses import asdict
  5. from typing import Callable
  6. from okx_codex_trader.models import Candle, TradeSignal
  7. from okx_codex_trader.strategy import validate_signal
  8. def analyze_with_codex(
  9. candles: list[Candle],
  10. symbol: str,
  11. bar: str,
  12. runner: Callable[..., subprocess.CompletedProcess[str]] = subprocess.run,
  13. which: Callable[[str], str | None] = shutil.which,
  14. ) -> TradeSignal:
  15. if which("codex") is None:
  16. raise FileNotFoundError("codex executable was not found on PATH")
  17. prompt = (
  18. "Analyze these market candles and return exactly one JSON object.\n"
  19. 'Do not output markdown, prose, or code fences.\n'
  20. 'The JSON keys must be exactly: "action", "confidence", "leverage", '
  21. '"entry_price", "take_profit_price", "stop_loss_price", "reason".\n'
  22. 'Valid actions are "long", "short", and "flat".\n'
  23. "Confidence must be a number from 0 to 1.\n"
  24. "Leverage must be an integer from 1 to 3.\n"
  25. "Price fields must be numbers or null.\n"
  26. f"symbol: {symbol}\n"
  27. f"bar: {bar}\n"
  28. f"candles: {json.dumps([asdict(candle) for candle in candles], separators=(',', ':'))}"
  29. )
  30. completed = runner(["codex", "exec", prompt], capture_output=True, text=True, check=False)
  31. if completed.returncode != 0:
  32. raise ValueError("codex execution failed")
  33. try:
  34. payload = json.loads(completed.stdout)
  35. except json.JSONDecodeError as exc:
  36. raise ValueError("codex output is not valid JSON") from exc
  37. if not isinstance(payload, dict):
  38. raise ValueError("codex output is not valid JSON")
  39. return validate_signal(payload)