From 4d1c9569639c5ed8ab51b829cf41bb5b416fefa1 Mon Sep 17 00:00:00 2001 From: Manohar Date: Tue, 12 May 2026 04:33:15 +0000 Subject: [PATCH] fix: booked PnL from closed legs, login mutex, market cache-on-error --- public/index.html | 2 +- src/api/server.ts | 43 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/public/index.html b/public/index.html index 759c5b4..5c06ec1 100644 --- a/public/index.html +++ b/public/index.html @@ -164,8 +164,8 @@
Open Positions
+
Booked P&L Today
Closed legs realised
Alerts Today
-
System
Healthy
diff --git a/src/api/server.ts b/src/api/server.ts index 36b5050..e6c632e 100644 --- a/src/api/server.ts +++ b/src/api/server.ts @@ -96,16 +96,38 @@ export function createServer(): express.Application { WHERE recorded_at >= datetime('now', '-' || ? || ' hours') ORDER BY recorded_at ASC `).all(hours); + + // Real-time summary: sum from DB positions directly (includes closed legs) + const liveOpen = db.prepare(` + SELECT COALESCE(SUM(unrealised_pnl),0) as u, + COALESCE(SUM(realised_pnl),0) as r, + COUNT(*) as cnt + FROM positions WHERE is_closed = 0 AND netqty != 0 + `).get() as any; + + // Realised from fully-closed positions (netqty=0, is_closed=1) — booked today + const closedRealised = db.prepare(` + SELECT COALESCE(SUM(realised_pnl),0) as r + FROM positions + WHERE (is_closed = 1 OR netqty = 0) AND realised_pnl != 0 + AND updated_at >= date('now') + `).get() as any; + + const totalUnrealised = liveOpen.u; + const totalRealised = liveOpen.r + closedRealised.r; + const totalPnl = totalUnrealised + totalRealised; + const latest = rows[rows.length - 1] as any; res.json({ ok: true, - summary: latest ? { - totalUnrealised: latest.total_unrealised, - totalRealised: latest.total_realised, - totalPnl: latest.total_pnl, - openPositions: latest.open_positions, - asOf: latest.recorded_at, - } : null, + summary: { + totalUnrealised, + totalRealised, + totalPnl, + openPositions: liveOpen.cnt, + bookedPnl: closedRealised.r, + asOf: latest?.recorded_at ?? new Date().toISOString(), + }, history: rows, }); }); @@ -115,12 +137,17 @@ export function createServer(): express.Application { `SELECT error, occurred_at FROM poll_errors ORDER BY occurred_at DESC LIMIT 1` ).get() as { error: string; occurred_at: string } | undefined; - const posCount = (db.prepare(`SELECT COUNT(*) as n FROM positions WHERE is_closed = 0`).get() as { n: number }).n; + const posCount = (db.prepare(`SELECT COUNT(*) as n FROM positions WHERE is_closed = 0 AND netqty != 0`).get() as { n: number }).n; + const bookedRealised = (db.prepare(` + SELECT COALESCE(SUM(realised_pnl),0) as r FROM positions + WHERE (is_closed=1 OR netqty=0) AND realised_pnl!=0 AND updated_at>=date('now') + `).get() as { r: number }).r; res.json({ ok: true, marketOpen: isMarketOpen(), openPositions: posCount, + bookedPnl: bookedRealised, lastError: lastError ?? null, uptime: Math.floor(process.uptime()), });