fix: resolve all remaining TODOs, add dev mode auth bypass
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
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:
parent
4094e4b10f
commit
a3cdd0f1a5
16 changed files with 511 additions and 45 deletions
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue