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

@ -52,15 +52,30 @@ async def _sync_once(
# 1. Snapshot account state
account = await broker.get_account()
# 2. Compute daily P&L: difference from the first snapshot today
today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
daily_pnl = 0.0
async with session_factory() as read_session:
day_start_snapshot = (
await read_session.execute(
select(PortfolioSnapshot)
.where(PortfolioSnapshot.timestamp >= today_start)
.order_by(PortfolioSnapshot.timestamp)
.limit(1)
)
).scalar_one_or_none()
if day_start_snapshot is not None:
daily_pnl = account.portfolio_value - day_start_snapshot.total_value
snapshot = PortfolioSnapshot(
timestamp=now,
total_value=account.portfolio_value,
cash=account.cash,
positions_value=account.portfolio_value - account.cash,
daily_pnl=0.0,
daily_pnl=daily_pnl,
)
# 2. Fetch broker positions
# 3. Fetch broker positions
broker_positions = await broker.get_positions()
broker_tickers = {p.ticker for p in broker_positions}
@ -91,7 +106,7 @@ async def _sync_once(
)
session.add(new_pos)
# 3. Remove positions that are no longer held at the broker
# 4. Remove positions that are no longer held at the broker
if broker_tickers:
await session.execute(
delete(Position).where(Position.ticker.notin_(broker_tickers))