{ "report": "okx-order-support-plan", "scope": "static implementation plan only; no OKX request, no order, no cancel", "readiness_gap": "ETH-focused quasi-live portfolio needs a full order lifecycle before any submit-capable runner is valid.", "source_files_checked": [ { "path": "okx_codex_trader/okx_client.py", "facts": [ "Signed _request already supports GET/POST with params/json_body.", "place_order is a single-order submitter.", "place_order emits ordType=market or ordType=limit only.", "No batch-orders, orders-pending, cancel-order, order status, or fills method exists.", "get_positions reads exchange positions but is not tied to portfolio-owned state." ] }, { "path": "tests/test_okx_client.py", "facts": [ "DummySession records request path/body and can support endpoint-level client tests.", "Existing tests cover request signing, live/demo header, contract sizing, leverage validation, single order payload, and position parsing.", "No tests cover post_only payloads, batch payloads, order list/cancel/status/fills, or state persistence." ] }, { "path": "okx_codex_trader/cli.py", "facts": [ "okx-account is read-only and returns balance plus positions.", "okx-order is submit-capable and calls place_order.", "No read-only ETH order-intent/state command exists.", "No quasi-live state path or append-only lifecycle log is wired." ] } ], "official_okx_api_surface": [ { "capability": "single post-only limit order payload", "endpoint": "POST /api/v5/trade/order", "boundary": "submit-capable only after read-only payload rendering is tested", "required_fields": [ "instId", "tdMode", "side", "posSide", "ordType", "px", "sz", "clOrdId" ], "fixed_eth_values": { "instId": "ETH-USDT-SWAP", "tdMode": "isolated", "side": "buy", "posSide": "long", "ordType": "post_only" } }, { "capability": "batch entry orders", "endpoint": "POST /api/v5/trade/batch-orders", "boundary": "submit-capable; read-only stage renders the exact array only", "required_shape": "list of three post_only entry payloads with deterministic clOrdId values" }, { "capability": "list open orders", "endpoint": "GET /api/v5/trade/orders-pending", "boundary": "read-only", "minimum_params": { "instType": "SWAP", "instId": "ETH-USDT-SWAP" } }, { "capability": "cancel open order", "endpoint": "POST /api/v5/trade/cancel-order", "boundary": "submit-capable; read-only stage renders cancel intents only", "required_fields": [ "instId", "ordId or clOrdId" ] }, { "capability": "cancel open orders in batch", "endpoint": "POST /api/v5/trade/cancel-batch-orders", "boundary": "submit-capable; read-only stage renders cancel intent array only", "required_shape": "list of tracked open order ids for ETH strategy-owned orders" }, { "capability": "order status", "endpoint": "GET /api/v5/trade/order", "boundary": "read-only", "minimum_params": { "instId": "ETH-USDT-SWAP", "ordId_or_clOrdId": "tracked order identity" } }, { "capability": "recent fills", "endpoint": "GET /api/v5/trade/fills", "boundary": "read-only", "minimum_params": { "instType": "SWAP", "instId": "ETH-USDT-SWAP" } } ], "state_persistence": { "boundary": "local read/write only; not an OKX API call", "minimum_file": "state/eth_robust_twap_15m_live.json", "fields": [ "strategy_id", "symbol", "bar", "td_mode", "pos_side", "leverage", "last_confirmed_candle_ts", "last_signal_candle_ts", "orders", "fills", "position", "planned_margin_usdt", "max_margin_usdt", "updated_at" ], "event_log": "append-only JSONL for signal, order-intent, cancel-intent, order-status, fills, and state-transition events" }, "minimum_patch_plan_by_file": [ { "file": "okx_codex_trader/okx_client.py", "patch_plan": [ "Add small dataclasses or typed dicts only if needed by return values: OkxOrder, OkxFill, OkxOrderAck.", "Add render_post_only_limit_order_payload(...) as a non-submitting function using existing _format_number and build_contract_size.", "Add render_eth_entry_batch_payloads(...) that returns exactly three post_only payloads for offsets 0.003, 0.006, 0.009.", "Add list_open_orders(symbol) calling GET /api/v5/trade/orders-pending with instType=SWAP and instId=symbol.", "Add get_order(symbol, ord_id=None, client_order_id=None) calling GET /api/v5/trade/order.", "Add list_fills(symbol) calling GET /api/v5/trade/fills with instType=SWAP and instId=symbol.", "Add cancel_order(symbol, ord_id=None, client_order_id=None) and cancel_batch_orders(symbol, order_ids) only when moving past read-only intent.", "Do not change existing place_order semantics for the first patch; it is not suitable for the ETH portfolio lifecycle." ] }, { "file": "okx_codex_trader/cli.py", "patch_plan": [ "Add read-only eth-robust-twap-order-intent command that prints signal, three entry payloads, expiry, and state transition preview.", "Add read-only eth-robust-twap-open-orders command that lists current OKX pending orders for ETH-USDT-SWAP.", "Add read-only eth-robust-twap-reconcile command that reads state, queries open orders/status/fills, and writes a new local state snapshot plus JSONL audit event.", "Keep okx-order unchanged and do not route portfolio intents through it.", "Only after read-only commands pass tests, add explicit submit commands for batch entry and cancellation." ] }, { "file": "tests/test_okx_client.py", "patch_plan": [ "Add tests for post_only payload shape: ETH-USDT-SWAP, isolated, buy, long, post_only, px, sz, deterministic clOrdId.", "Add tests for batch payload shape: exactly three orders, offsets 0.003/0.006/0.009, each level sized independently and rounded to lotSz.", "Add tests for GET /api/v5/trade/orders-pending params and normalized open-order state values.", "Add tests for POST /api/v5/trade/cancel-order and /cancel-batch-orders request bodies before enabling submit commands.", "Add tests for GET /api/v5/trade/order by ordId and by clOrdId.", "Add tests for GET /api/v5/trade/fills parsing fillSz, fillPx, tradeId, ordId, clOrdId, fee, and fillTime.", "Add tests that malformed OKX lifecycle payloads raise the existing stable invalid-payload error." ] }, { "file": "new okx_codex_trader/eth_robust_twap_state.py", "patch_plan": [ "Add only the dedicated state schema and load/save functions needed by the ETH quasi-live lifecycle.", "Persist exchange order ids, client order ids, fills, position, last confirmed candle, active state, and audit cursor.", "Reject state whose symbol/bar/strategy_id does not match the command arguments." ] }, { "file": "new tests/test_eth_robust_twap_state.py", "patch_plan": [ "Add load empty state test.", "Add save/read roundtrip for one signal with three open orders and one partial fill.", "Add state mismatch rejection tests for symbol, bar, and strategy_id." ] } ], "readonly_boundary": [ "Render post_only single and batch order payloads without calling POST /api/v5/trade/order or /batch-orders.", "Read account balance, positions, pending orders, order details, and fills.", "Write local state snapshots and append-only JSONL audit events.", "Render cancel intents without calling cancel endpoints." ], "submit_capable_boundary": [ "POST /api/v5/trade/order with ordType=post_only.", "POST /api/v5/trade/batch-orders.", "POST /api/v5/trade/cancel-order.", "POST /api/v5/trade/cancel-batch-orders.", "Any reduce-only market close path." ], "test_checklist": [ "Existing tests: rtk .venv/bin/pytest tests/test_okx_client.py", "New client tests for render-only post_only payloads make no DummySession requests.", "New client tests for list_open_orders/get_order/list_fills assert method/path/params and parsed output.", "New cancel tests assert request body shape but stay behind commands that are not wired in the read-only phase.", "New CLI tests assert read-only order-intent/reconcile commands do not call submit/cancel endpoints.", "New state tests assert deterministic state roundtrip and event append order." ], "sources": [ "https://www.okx.com/docs-v5/en/", "reports/eth-exploration/eth-focused-portfolio-live-readiness.md", "reports/eth-exploration/eth-robust-twap-live-plan.md" ] }