fix: booked PnL from closed legs, login mutex, market cache-on-error
This commit is contained in:
parent
6f06755e11
commit
4d1c956963
2 changed files with 36 additions and 9 deletions
|
|
@ -164,8 +164,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="g3" style="margin-bottom:16px">
|
<div class="g3" style="margin-bottom:16px">
|
||||||
<div class="card scard"><div class="slbl">Open Positions</div><div class="sval" id="s-pos">—</div></div>
|
<div class="card scard"><div class="slbl">Open Positions</div><div class="sval" id="s-pos">—</div></div>
|
||||||
|
<div class="card scard"><div class="slbl">Booked P&L Today</div><div class="sval" id="s-booked">—</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">—</div></div>
|
<div class="card scard"><div class="slbl">Alerts Today</div><div class="sval amber" id="s-alrt">—</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>
|
||||||
<div class="card collapsible" id="sec-chart" style="margin-bottom:16px">
|
<div class="card collapsible" id="sec-chart" style="margin-bottom:16px">
|
||||||
<div class="card-head" onclick="toggleCard('sec-chart')">
|
<div class="card-head" onclick="toggleCard('sec-chart')">
|
||||||
|
|
|
||||||
|
|
@ -96,16 +96,38 @@ export function createServer(): express.Application {
|
||||||
WHERE recorded_at >= datetime('now', '-' || ? || ' hours')
|
WHERE recorded_at >= datetime('now', '-' || ? || ' hours')
|
||||||
ORDER BY recorded_at ASC
|
ORDER BY recorded_at ASC
|
||||||
`).all(hours);
|
`).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;
|
const latest = rows[rows.length - 1] as any;
|
||||||
res.json({
|
res.json({
|
||||||
ok: true,
|
ok: true,
|
||||||
summary: latest ? {
|
summary: {
|
||||||
totalUnrealised: latest.total_unrealised,
|
totalUnrealised,
|
||||||
totalRealised: latest.total_realised,
|
totalRealised,
|
||||||
totalPnl: latest.total_pnl,
|
totalPnl,
|
||||||
openPositions: latest.open_positions,
|
openPositions: liveOpen.cnt,
|
||||||
asOf: latest.recorded_at,
|
bookedPnl: closedRealised.r,
|
||||||
} : null,
|
asOf: latest?.recorded_at ?? new Date().toISOString(),
|
||||||
|
},
|
||||||
history: rows,
|
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`
|
`SELECT error, occurred_at FROM poll_errors ORDER BY occurred_at DESC LIMIT 1`
|
||||||
).get() as { error: string; occurred_at: string } | undefined;
|
).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({
|
res.json({
|
||||||
ok: true,
|
ok: true,
|
||||||
marketOpen: isMarketOpen(),
|
marketOpen: isMarketOpen(),
|
||||||
openPositions: posCount,
|
openPositions: posCount,
|
||||||
|
bookedPnl: bookedRealised,
|
||||||
lastError: lastError ?? null,
|
lastError: lastError ?? null,
|
||||||
uptime: Math.floor(process.uptime()),
|
uptime: Math.floor(process.uptime()),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue