| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546 |
- 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)
|