import json import shutil import subprocess from dataclasses import asdict from typing import Callable from okx_codex_trader.models import Candle, TradeSignal from okx_codex_trader.strategy import validate_signal def analyze_with_codex( candles: list[Candle], symbol: str, bar: str, runner: Callable[..., subprocess.CompletedProcess[str]] = subprocess.run, which: Callable[[str], str | None] = shutil.which, ) -> TradeSignal: if which("codex") is None: raise FileNotFoundError("codex executable was not found on PATH") prompt = ( "Analyze these market candles and return exactly one JSON object.\n" 'Do not output markdown, prose, or code fences.\n' 'The JSON keys must be exactly: "action", "confidence", "leverage", ' '"entry_price", "take_profit_price", "stop_loss_price", "reason".\n' 'Valid actions are "long", "short", and "flat".\n' "Confidence must be a number from 0 to 1.\n" "Leverage must be an integer from 1 to 3.\n" "Price fields must be numbers or null.\n" f"symbol: {symbol}\n" f"bar: {bar}\n" f"candles: {json.dumps([asdict(candle) for candle in candles], separators=(',', ':'))}" ) completed = runner(["codex", "exec", prompt], capture_output=True, text=True, check=False) if completed.returncode != 0: raise ValueError("codex execution failed") try: payload = json.loads(completed.stdout) except json.JSONDecodeError as exc: raise ValueError("codex output is not valid JSON") from exc if not isinstance(payload, dict): raise ValueError("codex output is not valid JSON") return validate_signal(payload)