trading/docs/plans/remaining-work-plan.md
Viktor Barzin a3cdd0f1a5
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
fix: resolve all remaining TODOs, add dev mode auth bypass
- Learning engine: expand default weights from 3 to all 9 strategies
- Learning engine: resolve placeholder strategy_id with DB lookup
- Learning engine: pass strategy_sources from trade execution
- Trade executor: respect trading:paused Redis flag in RiskManager
- Portfolio sync: compute actual daily P&L from day-start snapshot
- Portfolio API: cumulative P&L from first snapshot, read pause flag
- Portfolio metrics: compute max drawdown and avg hold duration
- Add strategy_sources field to TradeExecution schema
- Add dev_mode config (TRADING_DEV_MODE) to bypass auth for local dev
- Dashboard: VITE_DEV_MODE bypasses ProtectedRoute and 401 redirects
- Vite proxy target configurable via VITE_API_TARGET
- Add top-level README.md and remaining-work-plan.md
- Update CLAUDE.md with correct counts and remove stale TODOs
- 404 tests passing

Made-with: Cursor
2026-02-25 22:02:25 +00:00

183 lines
5.9 KiB
Markdown

# Trading Bot — Remaining Work Plan
**Created**: 2026-02-25
**Status**: Complete
## Overview
This plan addresses all remaining TODOs, placeholders, and incomplete features in the
trading bot. Tasks are ordered by dependency — earlier tasks unblock later ones.
---
## Task 1: Learning engine — expand default weights to all 9 strategies
**Status**: [x] Complete
**Files**: `services/learning_engine/main.py`
**Problem**: `_load_strategy_weights()` defaults to 3 strategies (momentum, mean_reversion,
news_driven) but the signal generator uses all 9. When Redis has no cached weights, the
learning engine operates on a stale subset.
**Fix**: Change the default fallback to all 9 strategies with equal weights (~0.111 each),
matching `scripts/seed_strategies.py`.
---
## Task 2: Portfolio sync — compute actual daily P&L
**Status**: [x] Complete
**Files**: `services/api_gateway/tasks/portfolio_sync.py`
**Problem**: `daily_pnl` is hardcoded to `0.0` in `_sync_once()` (line 60).
**Fix**: Before inserting the new snapshot, query the most recent prior snapshot for
today. Compute `daily_pnl = current_total_value - day_start_total_value`. If no prior
snapshot exists for today, the first snapshot's daily_pnl is 0.0.
---
## Task 3: Portfolio API — cumulative P&L from first snapshot
**Status**: [x] Complete
**Files**: `services/api_gateway/routes/portfolio.py`
**Problem**: `total_pnl` on line 90 just returns `latest.daily_pnl` instead of the
cumulative P&L since inception.
**Fix**: Query the earliest `PortfolioSnapshot` and compute:
- `total_pnl = latest.total_value - earliest.total_value`
- `total_pnl_pct = total_pnl / earliest.total_value * 100`
---
## Task 4: Portfolio API — read trading pause flag from Redis
**Status**: [x] Complete
**Files**: `services/api_gateway/routes/portfolio.py`
**Problem**: `trading_active` is hardcoded to `True` (line 92).
**Fix**: Read the `trading:paused` key from Redis (same key used by
`services/api_gateway/routes/controls.py`). Return `trading_active = not paused`.
---
## Task 5: Portfolio metrics — compute max drawdown from snapshots
**Status**: [x] Complete
**Files**: `services/api_gateway/routes/portfolio.py`
**Problem**: `max_drawdown` is hardcoded to `0.0` (line 170).
**Fix**: Query all `PortfolioSnapshot` rows, compute the running peak and maximum
percentage drop from peak. Return as a positive decimal (e.g. 0.12 = 12% drawdown).
---
## Task 6: Portfolio metrics — compute avg hold duration from trade outcomes
**Status**: [x] Complete
**Files**: `services/api_gateway/routes/portfolio.py`
**Problem**: `avg_hold_duration` is hardcoded to `"0h"` (line 172).
**Fix**: Query `TradeOutcome` rows, average the `hold_duration_seconds` column,
and format as a human-readable string (e.g. "4h 30m", "2d 6h").
---
## Task 7: Trade executor — respect the trading pause flag
**Status**: [x] Complete
**Files**: `services/trade_executor/risk_manager.py`
**Problem**: The controls API sets/clears `trading:paused` in Redis, but the trade
executor's `RiskManager.check_risk()` never checks it. Pausing has no effect.
**Fix**: Accept a Redis client in `RiskManager.__init__()`. Add a check at the top of
`check_risk()` that reads `trading:paused` and rejects with `"trading_paused"` if set.
Wire the Redis client through from `trade_executor/main.py`.
---
## Task 8: Learning engine — resolve placeholder strategy_id
**Status**: [x] Complete
**Files**: `services/learning_engine/main.py`
**Problem**: `WeightAdjustment` on line 207 uses `strategy_id=UUID(int=0)` as a
placeholder. This means weight history records can't be linked to the correct strategy.
**Fix**: On startup, load the `strategies` table into a `name -> UUID` lookup dict.
Use this lookup when building `WeightAdjustment` records. Fall back to `UUID(int=0)`
only if the strategy name isn't in the DB.
---
## Task 9: Pass strategy_sources from signal through to learning engine
**Status**: [x] Complete
**Files**: `services/trade_executor/main.py`, `services/learning_engine/main.py`
**Problem**: `TradeExecution` doesn't carry `strategy_sources`. When the learning engine
stores the opening trade (line 136), `strategy_sources` is always `[]`. This means credit
attribution (`evaluator.attribute_credit()`) has no strategies to reward.
**Fix**:
1. Add `strategy_sources: list[str] = []` to the `TradeExecution` schema.
2. In the trade executor's `process_signal()`, copy `signal.strategy_sources` into the
execution message.
3. In the learning engine, read `trade.strategy_sources` (via the extended schema) and
store them in the opening trade record.
---
## Task 10: Update CLAUDE.md and add top-level README
**Status**: [x] Complete
**Files**: `.claude/CLAUDE.md`, `README.md`
**Fix**:
- Remove "No CI/CD pipeline yet" from Known Issues (Woodpecker exists).
- Update strategy count references (3 → 9) in Project Structure section.
- Update model count (14 → 16 tables).
- Create a concise top-level `README.md` with: project description, architecture diagram
(text), quickstart (docker compose up), dev setup, and test commands.
---
## Execution Order
Tasks are grouped by dependency:
**Group A (independent, do first)**:
- Task 1 (learning engine weights)
- Task 7 (trade executor pause flag)
- Task 9 (strategy_sources passthrough)
**Group B (depends on nothing, can parallel with A)**:
- Task 2 (portfolio sync daily P&L)
- Task 8 (learning engine strategy_id lookup)
**Group C (depends on Task 2)**:
- Task 3 (cumulative P&L API)
- Task 4 (trading_active flag API)
- Task 5 (max drawdown API)
- Task 6 (avg hold duration API)
**Group D (after all code changes)**:
- Task 10 (documentation)
---
## Test Strategy
After each task, run the relevant unit tests:
```bash
python -m pytest tests/ -v -m "not integration" --tb=short
```
Existing tests should continue to pass. New tests may be needed for:
- Task 7: risk manager pause check
- Task 9: strategy_sources in TradeExecution schema