feat: page Historique Positions + diff entre 2 snapshots PnL
Backend:
- get_pnl_snapshot(id) : détail complet d'un snapshot avec trades parsés
- diff_pnl_snapshots(a, b) : diff positions entre deux snapshots (nouvelles /
fermées / évolution PnL par position + delta portfolio)
- GET /api/var/pnl/snapshots/{id} : détail snapshot
- GET /api/var/pnl/diff?a=&b= : calcul du diff
Frontend PositionHistory.tsx :
- Timeline scrollable des snapshots avec sparkline PnL
- Clic snapshot → détail des positions à ce moment (prix entrée, prix actuel,
PnL %, PnL €, régime macro)
- Boutons A/B par snapshot → sélection de deux points à comparer
- Vue diff A→B : nouvelles positions, fermées, évolution PnL par trade,
delta portfolio (capital, PnL %, PnL €)
- Route /position-history + nav sidebar
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,8 @@ from pydantic import BaseModel
|
||||
from services.var_service import (
|
||||
compute_var, save_var_snapshot,
|
||||
get_var_snapshots, get_var_snapshot, get_latest_var_snapshot,
|
||||
get_pnl_snapshots, get_latest_pnl_snapshot, save_pnl_snapshot,
|
||||
get_pnl_snapshots, get_pnl_snapshot, get_latest_pnl_snapshot, save_pnl_snapshot,
|
||||
diff_pnl_snapshots,
|
||||
)
|
||||
from services.var_scheduler import (
|
||||
get_scheduler_status, restart_var_scheduler, restart_pnl_scheduler,
|
||||
@@ -64,10 +65,27 @@ def pnl_latest():
|
||||
|
||||
|
||||
@router.get("/pnl/snapshots")
|
||||
def pnl_snapshots(limit: int = Query(default=48, ge=1, le=200)):
|
||||
def pnl_snapshots(limit: int = Query(default=100, ge=1, le=500)):
|
||||
return {"snapshots": get_pnl_snapshots(limit)}
|
||||
|
||||
|
||||
@router.get("/pnl/snapshots/{snapshot_id}")
|
||||
def pnl_snapshot_detail(snapshot_id: int):
|
||||
snap = get_pnl_snapshot(snapshot_id)
|
||||
if not snap:
|
||||
raise HTTPException(404, "Snapshot not found")
|
||||
return snap
|
||||
|
||||
|
||||
@router.get("/pnl/diff")
|
||||
def pnl_diff(a: int = Query(..., description="ID snapshot A (earlier)"),
|
||||
b: int = Query(..., description="ID snapshot B (later)")):
|
||||
try:
|
||||
return diff_pnl_snapshots(a, b)
|
||||
except ValueError as e:
|
||||
raise HTTPException(404, str(e))
|
||||
|
||||
|
||||
@router.post("/pnl/run-now")
|
||||
def pnl_run_now():
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user