# AI Trader Official Realtime Data Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Add Binance Spot REST aggregate trades and short-lived WebSocket sampling features to the AI trader market context.

**Architecture:** Extend the existing exchange client with a small REST aggregate-trade method. Add deterministic feature builders and a one-shot WebSocket sampler, then thread compact feature objects into the existing AI context. Live commands remain synchronous and best-effort.

**Tech Stack:** Python 3.12, httpx, websockets, pydantic-settings, pytest, pytest-asyncio.

---

### Task 1: Config And REST Aggregate Trades

**Files:**
- Modify: `src/binance_quant/config.py`
- Modify: `src/binance_quant/exchange.py`
- Test: `tests/test_config.py`
- Test: `tests/test_exchange.py`

- [ ] **Step 1: Write failing config tests**

Add assertions for defaults:

```python
assert settings.ai_trader_agg_trades_limit == 500
assert settings.ai_trader_ws_enabled is True
assert settings.ai_trader_ws_sample_seconds == 15
```

Add env parsing:

```python
monkeypatch.setenv("BINANCE_AI_TRADER_AGG_TRADES_LIMIT", "250")
monkeypatch.setenv("BINANCE_AI_TRADER_WS_ENABLED", "false")
monkeypatch.setenv("BINANCE_AI_TRADER_WS_SAMPLE_SECONDS", "3")
```

- [ ] **Step 2: Run config tests**

Run: `uv run --extra dev pytest tests/test_config.py::test_ai_trader_defaults_are_disabled_and_conservative tests/test_config.py::test_ai_trader_settings_parse_environment -q`

Expected: FAIL because settings do not exist.

- [ ] **Step 3: Implement settings**

Add:

```python
ai_trader_agg_trades_limit: int = Field(default=500, ge=1, le=1000)
ai_trader_ws_enabled: bool = True
ai_trader_ws_sample_seconds: int = Field(default=15, ge=1, le=60)
```

- [ ] **Step 4: Write failing exchange test**

Add:

```python
def test_aggregate_trades_returns_json_with_symbol_and_limit_params():
    ...
    result = client.aggregate_trades("btcusdt", limit=123)
    assert requests[0].url.path.endswith("/v3/aggTrades")
    assert requests[0].url.params["symbol"] == "BTCUSDT"
    assert requests[0].url.params["limit"] == "123"
```

- [ ] **Step 5: Implement exchange method**

Add:

```python
def aggregate_trades(self, symbol: str, limit: int = 500) -> list:
    response = self._client.get(f"{self.base_url}/v3/aggTrades", params={"symbol": symbol.upper(), "limit": limit})
    response.raise_for_status()
    return response.json()
```

- [ ] **Step 6: Verify task**

Run: `uv run --extra dev pytest tests/test_config.py tests/test_exchange.py -q`

Expected: PASS.

### Task 2: Aggregate Trade Features In AI Context

**Files:**
- Modify: `src/binance_quant/ai_trader.py`
- Test: `tests/test_ai_trader.py`

- [ ] **Step 1: Write failing feature test**

Use fake aggregate trades:

```python
[
    {"a": 1, "p": "100", "q": "2", "T": 1000, "m": False},
    {"a": 2, "p": "110", "q": "1", "T": 2000, "m": True},
]
```

Assert `market["aggregate_trades"]` includes buy quote `200`, sell quote `110`, ratio, VWAP, and IDs.

- [ ] **Step 2: Run the failing test**

Run: `uv run --extra dev pytest tests/test_ai_trader.py::test_run_live_ai_trade_once_passes_aggregate_trade_features_to_ai_context -q`

Expected: FAIL because aggregate trade features are missing.

- [ ] **Step 3: Implement feature builder**

Add `_aggregate_trade_features(trades, now_ms=None)` that handles empty input and Binance `m` buy/sell split. Serialize Decimal values through existing JSON default behavior.

- [ ] **Step 4: Thread REST data into context**

In `_build_ai_market_context`, call `exchange_client.aggregate_trades(symbol, limit=settings.ai_trader_agg_trades_limit)` per symbol. On exception or missing method, use `_aggregate_trade_features(())`.

- [ ] **Step 5: Verify task**

Run: `uv run --extra dev pytest tests/test_ai_trader.py::test_run_live_ai_trade_once_passes_aggregate_trade_features_to_ai_context tests/test_ai_trader.py::test_run_live_ai_trade_once_passes_enriched_market_features_to_ai_context -q`

Expected: PASS.

### Task 3: One-Shot WebSocket Sampling

**Files:**
- Modify: `src/binance_quant/market_data.py`
- Test: `tests/test_market_data.py`

- [ ] **Step 1: Write failing sampler test**

Mock `websockets.connect` to yield combined-stream messages for `bookTicker`, `depth20@100ms`, and `aggTrade`. Assert `sample_realtime_market(["BTCUSDT"], ..., sample_seconds=1)` returns an object with `status == "ok"`, update counts, spread averages, depth notional averages, and buy/sell aggTrade ratio.

- [ ] **Step 2: Run failing test**

Run: `uv run --extra dev pytest tests/test_market_data.py::test_sample_realtime_market_aggregates_book_depth_and_trades -q`

Expected: FAIL because sampler does not exist.

- [ ] **Step 3: Implement sampler**

Create dataclass or dict-based accumulators in `market_data.py`. Build combined stream URL from configured symbols and base URL. Use `asyncio.timeout(sample_seconds)` and parse messages without raising on malformed payloads.

- [ ] **Step 4: Add unavailable test**

Mock connect to raise and assert status is `unavailable`.

- [ ] **Step 5: Verify task**

Run: `uv run --extra dev pytest tests/test_market_data.py -q`

Expected: PASS.

### Task 4: Realtime Features In AI Context

**Files:**
- Modify: `src/binance_quant/ai_trader.py`
- Test: `tests/test_ai_trader.py`
- Update: `README.md`

- [ ] **Step 1: Write failing AI context tests**

Patch `binance_quant.ai_trader.sample_realtime_market` to return a per-symbol dict and assert `market["realtime"]` is included.

Add disabled case with `ai_trader_ws_enabled=False` and assert `realtime.status == "disabled"`.

- [ ] **Step 2: Run failing tests**

Run: `uv run --extra dev pytest tests/test_ai_trader.py::test_run_live_ai_trade_once_passes_realtime_features_to_ai_context tests/test_ai_trader.py::test_run_live_ai_trade_once_marks_realtime_disabled_when_configured -q`

Expected: FAIL because realtime features are missing.

- [ ] **Step 3: Implement context threading**

Call `asyncio.run(sample_realtime_market(...))` when enabled. If it raises, use unavailable status for each symbol. Add result under `market[].realtime`.

- [ ] **Step 4: Update README**

Document new environment variables and new context fields.

- [ ] **Step 5: Verify task**

Run: `uv run --extra dev pytest tests/test_ai_trader.py tests/test_run_script.py -q`

Expected: PASS.

### Task 5: Full Verification

**Files:**
- Review all modified files.

- [ ] **Step 1: Run full tests**

Run: `uv run --extra dev pytest -q`

Expected: PASS.

- [ ] **Step 2: Clean generated lockfile**

If `uv.lock` is untracked, remove it after verifying the path is inside the workspace.

- [ ] **Step 3: Commit**

Run:

```bash
git add src/binance_quant/config.py src/binance_quant/exchange.py src/binance_quant/ai_trader.py src/binance_quant/market_data.py tests/test_config.py tests/test_exchange.py tests/test_ai_trader.py tests/test_market_data.py README.md docs/superpowers/plans/2026-06-21-ai-trader-official-realtime-data.md
git commit -m "feat: add official realtime ai trader data"
```
