[object Object]

← back to Bertha

Ken: market data refinements and portfolio query fixes

df73f40b2ae8b77ec97d74bfaeb8a29054adeb55 · 2026-02-16 07:22:44 +0000 · DW Commit Agent

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Files touched

Diff

commit df73f40b2ae8b77ec97d74bfaeb8a29054adeb55
Author: DW Commit Agent <claude@dw-agents.com>
Date:   Mon Feb 16 07:22:44 2026 +0000

    Ken: market data refinements and portfolio query fixes
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---
 kalshi-dash/server.js | 44 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 41 insertions(+), 3 deletions(-)

diff --git a/kalshi-dash/server.js b/kalshi-dash/server.js
index bf22f5b..bb8baa3 100644
--- a/kalshi-dash/server.js
+++ b/kalshi-dash/server.js
@@ -1916,10 +1916,13 @@ const routes = {
 
     // 5. Portfolio P&L (current state)
     try {
-      const { rows } = await kenQ(`SELECT p.name, p.strategy, p.balance_cents, p.trades_won, p.trades_lost, p.win_rate,
-        p.total_invested_cents, p.daily_budget_cents, p.budget_remaining, p.trades_today, p.streak
+      const { rows } = await kenQ(`SELECT p.name, p.strategy, p.balance_cents, p.trades_won, p.trades_lost,
+        p.total_invested_cents, p.daily_budget_cents, p.streak,
+        CASE WHEN (p.trades_won + p.trades_lost) > 0
+          THEN ROUND(p.trades_won * 100.0 / (p.trades_won + p.trades_lost))
+          ELSE 0 END AS win_rate
         FROM ken_portfolios p ORDER BY p.balance_cents DESC`);
-      out.portfolios = rows;
+      out.portfolios = rows.map(r => ({ ...r, balance_cents: parseInt(r.balance_cents), win_rate: parseInt(r.win_rate) }));
     } catch { out.portfolios = []; }
 
     // 6. Active markets count and top movers
@@ -2533,6 +2536,41 @@ function MarketDataTab() {
           })}
         </div>
       </div>
+
+      {/* Portfolio Leaderboard */}
+      {(mkt.portfolios || []).length > 0 && <div className="mkt-card" style={{gridColumn:'span 2'}}>
+        <div className="mkt-card-header">
+          <span className="mkt-card-title" style={{color:'var(--pink)'}}>Portfolio Leaderboard</span>
+          <span className="mkt-card-badge" style={{background:'rgba(255,105,180,.15)',color:'var(--pink)'}}>{(mkt.portfolios||[]).length} portfolios</span>
+        </div>
+        <div style={{display:'grid',gridTemplateColumns:'repeat(auto-fill,minmax(200px,1fr))',gap:8}}>
+          {(mkt.portfolios || []).map((p, i) => {
+            const stratColors = {aggressive:'#ef4444',conservative:'#3b82f6',weather:'#06b6d4',momentum:'#f59e0b',contrarian:'#8b5cf6',ai_enhanced:'#ec4899',mc_validated:'#a855f7',scalper:'#eab308',patient:'#22c55e',random:'#64748b'};
+            const stratEmojis = {aggressive:'🔥',conservative:'🏛️',weather:'⛈️',momentum:'🚀',contrarian:'🔄',ai_enhanced:'🧠',mc_validated:'🎲',scalper:'⚡',patient:'🐢',random:'🎰'};
+            const c = stratColors[p.strategy] || 'var(--muted)';
+            const pnl = parseInt(p.balance_cents) || 0;
+            return (<div key={i} style={{padding:'10px 14px',background:'rgba(255,255,255,.02)',border:'1px solid var(--border)',borderRadius:10,transition:'all .2s',borderLeftColor:c,borderLeftWidth:3}}>
+              <div style={{display:'flex',alignItems:'center',gap:8,marginBottom:4}}>
+                <span style={{fontSize:18}}>{stratEmojis[p.strategy]||'📊'}</span>
+                <div>
+                  <div style={{fontSize:12,fontWeight:700,color:c}}>{p.name}</div>
+                  <div style={{fontSize:9,color:'var(--muted)',textTransform:'uppercase'}}>{p.strategy}</div>
+                </div>
+                <div style={{marginLeft:'auto',textAlign:'right'}}>
+                  <div style={{fontSize:16,fontWeight:800,color:pnl>=0?'var(--green)':'var(--red)',fontVariantNumeric:'tabular-nums'}}>
+                    {pnl>=0?'+':''}{(pnl/100).toFixed(2)}
+                  </div>
+                </div>
+              </div>
+              <div style={{display:'flex',gap:4,fontSize:9}}>
+                <span style={{padding:'1px 6px',borderRadius:3,background:'rgba(34,197,94,.1)',color:'var(--green)'}}>W:{p.trades_won}</span>
+                <span style={{padding:'1px 6px',borderRadius:3,background:'rgba(239,68,68,.1)',color:'var(--red)'}}>L:{p.trades_lost}</span>
+                <span style={{padding:'1px 6px',borderRadius:3,background:'rgba(255,255,255,.04)',color:'var(--muted)'}}>WR:{p.win_rate}%</span>
+              </div>
+            </div>);
+          })}
+        </div>
+      </div>}
     </div>
   </div>);
 }

← 1d9f769 chore(alshi-dash): update 1 file (.js) [+361/-4]  ·  back to Bertha  ·  chore(alshi-dash): update 1 file (.js) [+82/-47] e39a225 →