fix: booked PnL from closed legs, login mutex, market cache-on-error

This commit is contained in:
Manohar 2026-05-12 04:33:15 +00:00
parent 6f06755e11
commit 4d1c956963
2 changed files with 36 additions and 9 deletions

View file

@ -164,8 +164,8 @@
</div>
<div class="g3" style="margin-bottom:16px">
<div class="card scard"><div class="slbl">Open Positions</div><div class="sval" id="s-pos">&#8212;</div></div>
<div class="card scard"><div class="slbl">Booked P&amp;L Today</div><div class="sval" id="s-booked">&#8212;</div><div style="font-size:.6rem;color:var(--text3);margin-top:2px">Closed legs realised</div></div>
<div class="card scard"><div class="slbl">Alerts Today</div><div class="sval amber" id="s-alrt">&#8212;</div></div>
<div class="card scard"><div class="slbl">System</div><div class="sval" id="s-err" style="font-size:.88rem;font-family:'Geist',sans-serif;margin-top:2px;color:var(--green)">Healthy</div></div>
</div>
<div class="card collapsible" id="sec-chart" style="margin-bottom:16px">
<div class="card-head" onclick="toggleCard('sec-chart')">

View file

@ -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()),
});