fix: resolve all remaining TODOs, add dev mode auth bypass
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed

- 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
This commit is contained in:
Viktor Barzin 2026-02-25 22:02:25 +00:00
parent 4094e4b10f
commit a3cdd0f1a5
No known key found for this signature in database
GPG key ID: 0EB088298288D958
16 changed files with 511 additions and 45 deletions

View file

@ -15,10 +15,13 @@ from datetime import datetime, timezone
from uuid import UUID
from redis.asyncio import Redis
from sqlalchemy import select
from services.learning_engine.config import LearningEngineConfig
from services.learning_engine.evaluator import TradeEvaluator
from services.learning_engine.weight_adjuster import WeightAdjuster
from shared.db import create_db
from shared.models.trading import Strategy
from shared.redis_streams import StreamConsumer
from shared.schemas.learning import TradeOutcomeSchema, WeightAdjustment
from shared.schemas.trading import OrderSide, TradeExecution
@ -39,11 +42,17 @@ async def _load_strategy_weights(redis: Redis) -> dict[str, float]:
raw = await redis.get(_STRATEGY_WEIGHTS_KEY)
if raw:
return json.loads(raw)
# Default equal weights
# Default equal weights for all 9 strategies (matches seed_strategies.py)
return {
"momentum": 0.333,
"mean_reversion": 0.333,
"news_driven": 0.334,
"momentum": 0.111,
"mean_reversion": 0.111,
"news_driven": 0.111,
"value": 0.111,
"macd_crossover": 0.111,
"bollinger_breakout": 0.111,
"vwap": 0.111,
"liquidity": 0.112,
"ma_stack": 0.111,
}
@ -104,6 +113,7 @@ async def process_trade(
evaluator: TradeEvaluator,
adjuster: WeightAdjuster,
counters: dict,
strategy_id_lookup: dict[str, UUID] | None = None,
) -> list[WeightAdjustment]:
"""Process a single trade execution.
@ -132,7 +142,7 @@ async def process_trade(
"price": trade.price,
"qty": trade.qty,
"timestamp": trade.timestamp.isoformat(),
"strategy_sources": [], # would come from signal
"strategy_sources": trade.strategy_sources,
},
)
return adjustments
@ -203,8 +213,9 @@ async def process_trade(
weights[strategy_name] = new_weight
any_adjusted = True
sid = (strategy_id_lookup or {}).get(strategy_name, UUID(int=0))
adjustment = WeightAdjustment(
strategy_id=UUID(int=0), # placeholder -- DB would assign real ID
strategy_id=sid,
strategy_name=strategy_name,
old_weight=old_weight,
new_weight=new_weight,
@ -274,6 +285,19 @@ async def run(config: LearningEngineConfig | None = None) -> None:
evaluator = TradeEvaluator()
adjuster = WeightAdjuster(config)
# --- Load strategy name -> UUID lookup from DB ---
strategy_id_lookup: dict[str, UUID] = {}
try:
_engine, session_factory = create_db(config)
async with session_factory() as session:
result = await session.execute(select(Strategy))
for s in result.scalars().all():
strategy_id_lookup[s.name] = s.id
await _engine.dispose()
logger.info("Loaded %d strategy IDs from DB", len(strategy_id_lookup))
except Exception:
logger.exception("Failed to load strategy IDs — using fallback UUID(int=0)")
logger.info("Consuming from trades:executed")
# Graceful shutdown on SIGTERM/SIGINT
@ -294,7 +318,9 @@ async def run(config: LearningEngineConfig | None = None) -> None:
logger.debug("Skipping non-filled trade: %s", trade.status.value)
continue
adjustments = await process_trade(trade, redis, evaluator, adjuster, counters)
adjustments = await process_trade(
trade, redis, evaluator, adjuster, counters, strategy_id_lookup
)
if adjustments:
logger.info(
"Made %d weight adjustment(s) for %s",