# Spot Trading Loss Controls 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:** Reduce spot trading churn by narrowing new buy candidates and blocking cost-negative strategy sells during the first hold window.

**Architecture:** Add a small cost-basis helper that reconstructs FIFO open lots from synced spot fills and returns a sell guard decision. Wire that decision into automatic sell and AI sell risk flow before sell reservation, while leaving existing exchange order execution unchanged.

**Tech Stack:** Python 3.11, Pydantic settings, SQLite-backed `Storage`, pytest.

---

### Task 1: Cost-Basis Guard

**Files:**
- Create: `src/binance_quant/spot_cost_basis.py`
- Test: `tests/test_spot_cost_basis.py`

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

Create tests that record BUY fills, evaluate a below-cost sell inside the hold window, evaluate the same sell after the hold window, and evaluate a symbol with no fills.

- [ ] **Step 2: Run tests to verify failure**

Run: `python -m pytest tests/test_spot_cost_basis.py -q`

Expected: import failure for `binance_quant.spot_cost_basis`.

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

Implement FIFO lot reconstruction from `Storage.list_spot_trade_fills(symbol, limit=0)` or direct SQLite access via `Storage._connect()`, returning a decision object with `approved`, `reason`, `matched_cost`, `estimated_proceeds`, and `oldest_opened_at_ms`.

- [ ] **Step 4: Run focused tests**

Run: `python -m pytest tests/test_spot_cost_basis.py -q`

Expected: all tests pass.

### Task 2: Configuration

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

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

Assert defaults:

```python
assert settings.auto_sell_require_profit is True
assert settings.auto_sell_min_hold_seconds == 21600
```

Assert negative `auto_sell_min_hold_seconds` is rejected.

- [ ] **Step 2: Run config tests to verify failure**

Run: `python -m pytest tests/test_config.py -q`

Expected: missing settings attributes.

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

Add:

```python
auto_sell_require_profit: bool = True
auto_sell_min_hold_seconds: int = Field(default=21600, ge=0)
```

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

Run: `python -m pytest tests/test_config.py -q`

Expected: all tests pass.

### Task 3: Automatic Sell Wiring

**Files:**
- Modify: `src/binance_quant/auto_sell.py`
- Test: `tests/test_auto_sell_runner.py`

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

Record a recent buy fill with cost above current bid and assert `run_live_auto_sell_once` returns `rejected` with reason `sell below cost before minimum hold`. Record an older buy fill and assert the same sell proceeds.

- [ ] **Step 2: Run focused tests to verify failure**

Run: `python -m pytest tests/test_auto_sell_runner.py -q`

Expected: below-cost recent sell still sells before implementation.

- [ ] **Step 3: Wire guard after existing risk approval**

After `AutoSellRiskEngine.evaluate()` approves a candidate, call the cost-basis helper with current `now_ms`, selected symbol, rounded quantity, and bid. If rejected, treat it like a skippable candidate rejection so a later symbol may still be sold.

- [ ] **Step 4: Run focused tests**

Run: `python -m pytest tests/test_auto_sell_runner.py -q`

Expected: all auto-sell runner tests pass.

### Task 4: AI Sell Wiring

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

- [ ] **Step 1: Write failing AI sell test**

Record a recent buy fill with cost above current bid, return a high-confidence SELL prediction, and assert the AI run is rejected with `sell below cost before minimum hold` and no market sell call is made.

- [ ] **Step 2: Run focused test to verify failure**

Run: `python -m pytest tests/test_ai_trader.py::<test_name> -q`

Expected: AI sell proceeds before implementation.

- [ ] **Step 3: Wire guard in `_execute_ai_sell`**

After existing risk approval and any protective-stop cancellation recheck, call the same helper before reservation and execution. Record rejection through the existing `reject()` path.

- [ ] **Step 4: Run focused AI tests**

Run: `python -m pytest tests/test_ai_trader.py -q`

Expected: all AI trader tests pass.

### Task 5: Local Runtime Configuration

**Files:**
- Modify: `.env`

- [ ] **Step 1: Restrict buy and AI symbols**

Set:

```text
BINANCE_AUTO_BUY_SYMBOLS=BTCUSDT,ETHUSDT,BNBUSDT,SOLUSDT
BINANCE_AI_TRADER_SYMBOLS=BTCUSDT,ETHUSDT,BNBUSDT,SOLUSDT
BINANCE_AUTO_SELL_REQUIRE_PROFIT=true
BINANCE_AUTO_SELL_MIN_HOLD_SECONDS=21600
```

Leave `BINANCE_AUTO_SELL_SYMBOLS` unchanged.

- [ ] **Step 2: Verify settings load**

Run: `python -c "from binance_quant.config import load_settings; s=load_settings(); print(s.auto_buy_symbols, s.ai_trader_symbols, s.auto_sell_require_profit, s.auto_sell_min_hold_seconds)"`

Expected: tuple of four symbols, `True`, and `21600`.

### Task 6: Final Verification

**Files:**
- No additional files.

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

Run:

```powershell
$env:PYTHONPATH='src'; .\.venv\Scripts\python.exe -m pytest tests/test_spot_cost_basis.py tests/test_config.py tests/test_auto_sell_runner.py tests/test_ai_trader.py -q
```

- [ ] **Step 2: Run full suite**

Run:

```powershell
$env:PYTHONPATH='src'; .\.venv\Scripts\python.exe -m pytest -q
```

