[object Object]

← back to Bertha

chore(alshi-dash): update 1 file (.js) [+209/-56]

a53e7ad258fb7032db6575240921add10608c9e8 · 2026-02-16 16:47:31 +0000 · DW Commit Agent

Files touched

Diff

commit a53e7ad258fb7032db6575240921add10608c9e8
Author: DW Commit Agent <commit-agent@dw-agents.com>
Date:   Mon Feb 16 16:47:31 2026 +0000

    chore(alshi-dash): update 1 file (.js) [+209/-56]
---
 kalshi-dash/server.js | 265 +++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 209 insertions(+), 56 deletions(-)

diff --git a/kalshi-dash/server.js b/kalshi-dash/server.js
index 8562d71..1f77e88 100644
--- a/kalshi-dash/server.js
+++ b/kalshi-dash/server.js
@@ -2449,70 +2449,223 @@ function SignalFeed({ signals }) {
 
 // ── PORTFOLIOS TAB ──
 function PortfoliosTab() {
-  const [portfolios, setPortfolios] = useState([]);
-  const [trades, setTrades] = useState([]);
-  const [selectedPf, setSelectedPf] = useState(null);
+  const [data, setData] = useState(null);
+  const [histFilter, setHistFilter] = useState('all');
   useEffect(() => {
-    api('/api/portfolios').then(setPortfolios).catch(()=>{});
-    api('/api/portfolio-trades').then(setTrades).catch(()=>{});
-    const iv = setInterval(() => {
-      api('/api/portfolios').then(setPortfolios).catch(()=>{});
-      if (selectedPf) api('/api/portfolio-trades?portfolio_id='+selectedPf).then(setTrades).catch(()=>{});
-    }, 20000);
+    const load = () => api('/api/portfauxlio').then(setData).catch(e => console.error(e));
+    load();
+    const iv = setInterval(load, 15000);
     return () => clearInterval(iv);
-  }, [selectedPf]);
+  }, []);
+
+  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:'\\uD83D\\uDD25',conservative:'\\uD83C\\uDFDB\\uFE0F',weather:'\\u26C8\\uFE0F',momentum:'\\uD83D\\uDE80',contrarian:'\\uD83D\\uDD04',ai_enhanced:'\\uD83E\\uDDE0',mc_validated:'\\uD83C\\uDFB2',scalper:'\\u26A1',patient:'\\uD83D\\uDC22',random:'\\uD83C\\uDFB0'};
+  const stratNames = {aggressive:'Alpha',conservative:'Beta',weather:'Storm',momentum:'Momentum',contrarian:'Contrarian',ai_enhanced:'Nova',mc_validated:'Oracle',scalper:'Shark',patient:'Turtle',random:'Wildcard'};
+  const stratDesc = {aggressive:'High edge (>15%), low confidence — speculative swings',conservative:'High confidence (>70%) — quality over quantity',weather:'Weather/climate markets only',momentum:'High agreement + articles — follows the trend',contrarian:'BUY_NO only — bets against the crowd',ai_enhanced:'Gemini AI enhanced signals only',mc_validated:'Monte Carlo validated, tight spread',scalper:'Small edges (3-10%) — quantity plays',patient:'Needs everything: conf>80%, MC, 5+ articles',random:'20% random — control group for luck testing'};
 
-  const personalities = { aggressive:'Swings big on high-edge', conservative:'Quality over quantity', weather:'Weather markets only', momentum:'Follows the trend', contrarian:'Bets against the crowd', ai_enhanced:'Gemini AI picks only', mc_validated:'Monte Carlo confirmed', scalper:'Tiny edges, high volume', patient:'Waits for perfect setup', random:'Control group (luck test)' };
-  const emojis = { aggressive:'🔥', conservative:'🏛️', weather:'⛈️', momentum:'🚀', contrarian:'🔄', ai_enhanced:'🧠', mc_validated:'🎲', scalper:'⚡', patient:'🐢', random:'🎰' };
-  const colors = { aggressive:'#ef4444', conservative:'#3b82f6', weather:'#06b6d4', momentum:'#f59e0b', contrarian:'#8b5cf6', ai_enhanced:'#ec4899', mc_validated:'#a855f7', scalper:'#eab308', patient:'#22c55e', random:'#64748b' };
+  if (!data) return <div style={{textAlign:'center',padding:60,color:'var(--muted)'}}>Loading portFAUXlio data...</div>;
+
+  const { portfolios, activeTrades, tradeHistory, overlaps, summary } = data;
+  const maxInvested = Math.max(...portfolios.map(p => parseInt(p.total_invested_cents) || 0), 1);
+  const filteredHistory = histFilter === 'all' ? tradeHistory : tradeHistory.filter(t => t.strategy === histFilter);
 
   return (<div>
-    <div style={{display:'grid',gridTemplateColumns:'repeat(auto-fill,minmax(280px,1fr))',gap:12,marginBottom:20}}>
-      {portfolios.map(pf => {
-        const c = colors[pf.strategy]||'var(--muted)';
-        return (<div key={pf.id} onClick={()=>{setSelectedPf(pf.id);api('/api/portfolio-trades?portfolio_id='+pf.id).then(setTrades);}}
-          style={{background:'var(--card)',border:selectedPf===pf.id?'1px solid '+c:'1px solid var(--border)',borderRadius:14,padding:16,cursor:'pointer',transition:'all .2s',position:'relative',overflow:'hidden'}}>
-          <div style={{position:'absolute',top:0,left:0,right:0,height:3,background:c,opacity:.7}}/>
-          <div style={{display:'flex',alignItems:'center',gap:10,marginBottom:8}}>
-            <span style={{fontSize:24}}>{emojis[pf.strategy]||'📊'}</span>
-            <div>
-              <div style={{fontSize:15,fontWeight:700,color:c}}>{pf.name}</div>
-              <div style={{fontSize:10,color:'var(--muted)',textTransform:'uppercase',letterSpacing:.5}}>{pf.strategy}</div>
+    {/* ═══ Banner ═══ */}
+    <div className="pf-banner">
+      <div className="pf-banner-title">portFAUXlio</div>
+      <div className="pf-banner-sub">10 Strategy Models &bull; Paper Trading &bull; Real Signals &bull; Zero Real Money</div>
+    </div>
+
+    {/* ═══ Summary Stats ═══ */}
+    <div className="pf-summary-row">
+      <div className="pf-summary-card">
+        <div className="pf-summary-val" style={{color: summary.totalPnl >= 0 ? 'var(--green)' : 'var(--red)'}}>
+          {summary.totalPnl >= 0 ? '+' : ''}{'$'}{(summary.totalPnl / 100).toFixed(2)}
+        </div>
+        <div className="pf-summary-lbl">Total P&L</div>
+      </div>
+      <div className="pf-summary-card">
+        <div className="pf-summary-val" style={{color:'var(--blue)'}}>{'$'}{(summary.totalInvested / 100).toFixed(2)}</div>
+        <div className="pf-summary-lbl">Invested</div>
+      </div>
+      <div className="pf-summary-card">
+        <div className="pf-summary-val" style={{color:'var(--purple)'}}>{summary.totalTrades}</div>
+        <div className="pf-summary-lbl">Total Trades</div>
+      </div>
+      <div className="pf-summary-card">
+        <div className="pf-summary-val" style={{color:'var(--green)'}}>{summary.openTrades}</div>
+        <div className="pf-summary-lbl">Open Positions</div>
+      </div>
+      <div className="pf-summary-card">
+        <div className="pf-summary-val" style={{color:'var(--cyan)'}}>{summary.uniqueMarkets}</div>
+        <div className="pf-summary-lbl">Markets</div>
+      </div>
+      <div className="pf-summary-card">
+        <div className="pf-summary-val" style={{color:'var(--yellow)'}}>{summary.activeModels}/10</div>
+        <div className="pf-summary-lbl">Active Models</div>
+      </div>
+    </div>
+
+    {/* ═══ Active Trades Strip ═══ */}
+    {activeTrades.length > 0 && <div className="pf-active-strip">
+      <div className="pf-active-header">
+        <span className="dot" />
+        {activeTrades.length} Open Positions
+      </div>
+      <div className="pf-active-scroll">
+        {activeTrades.map((t, i) => {
+          const c = stratColors[t.strategy] || 'var(--muted)';
+          return (<div key={i} className="pf-active-card" style={{borderTopColor: c}}>
+            <div style={{display:'flex',alignItems:'center',gap:6,marginBottom:4}}>
+              <span style={{fontSize:14}}>{stratEmojis[t.strategy] || ''}</span>
+              <span style={{fontSize:11,fontWeight:700,color:c}}>{t.portfolio_name}</span>
+              <span style={{marginLeft:'auto',padding:'1px 6px',borderRadius:4,fontSize:9,fontWeight:700,
+                background: t.direction === 'BUY_YES' ? 'rgba(34,197,94,.15)' : 'rgba(239,68,68,.15)',
+                color: t.direction === 'BUY_YES' ? 'var(--green)' : 'var(--red)'
+              }}>{t.direction === 'BUY_YES' ? 'YES' : 'NO'}</span>
             </div>
-            <div style={{marginLeft:'auto',textAlign:'right'}}>
-              <div style={{fontSize:18,fontWeight:700,color:pf.balance_cents>=0?'var(--green)':'var(--red)',fontVariantNumeric:'tabular-nums'}}>
-                {pf.balance_cents>=0?'+':''}\${(pf.balance_cents/100).toFixed(2)}
-              </div>
-              <div style={{fontSize:10,color:'var(--muted)'}}>P&L</div>
+            <div style={{fontSize:10,fontWeight:600,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap',marginBottom:3}} title={t.market_title || t.market_id}>
+              {t.market_title || t.market_id}
             </div>
-          </div>
-          <div style={{fontSize:11,color:'var(--muted)',marginBottom:8,lineHeight:1.4}}>{personalities[pf.strategy]}</div>
-          <div style={{display:'flex',gap:6,flexWrap:'wrap'}}>
-            <span style={{padding:'2px 8px',borderRadius:4,fontSize:10,background:'rgba(34,197,94,.12)',color:'var(--green)'}}>W:{pf.trades_won}</span>
-            <span style={{padding:'2px 8px',borderRadius:4,fontSize:10,background:'rgba(239,68,68,.12)',color:'var(--red)'}}>L:{pf.trades_lost}</span>
-            <span style={{padding:'2px 8px',borderRadius:4,fontSize:10,background:'rgba(255,255,255,.05)',color:'var(--muted)'}}>WR:{pf.win_rate}%</span>
-            <span style={{padding:'2px 8px',borderRadius:4,fontSize:10,background:'rgba(255,255,255,.05)',color:'var(--muted)'}}>Today:{pf.trades_today}</span>
-            <span style={{padding:'2px 8px',borderRadius:4,fontSize:10,background:pf.budget_remaining>0?'rgba(34,197,94,.08)':'rgba(239,68,68,.08)',color:pf.budget_remaining>0?'var(--green)':'var(--red)'}}>{'$'}{(pf.budget_remaining/100).toFixed(2)} left</span>
-            {pf.streak!==0&&<span style={{padding:'2px 8px',borderRadius:4,fontSize:10,background:pf.streak>0?'rgba(34,197,94,.15)':'rgba(239,68,68,.15)',color:pf.streak>0?'var(--green)':'var(--red)'}}>{pf.streak>0?'🔥':'❄️'}{Math.abs(pf.streak)} streak</span>}
-          </div>
-        </div>);
-      })}
+            <div style={{display:'flex',justifyContent:'space-between',fontSize:10,color:'var(--muted)'}}>
+              <span>{t.contracts}x @ {t.entry_price_cents}\\u00A2</span>
+              <span>{'$'}{(t.cost_cents / 100).toFixed(2)}</span>
+              <span>{timeAgo(t.created_at)}</span>
+            </div>
+          </div>);
+        })}
+      </div>
+    </div>}
+
+    {/* ═══ Model Leaderboard ═══ */}
+    <div style={{marginBottom:18}}>
+      <div style={{fontSize:13,fontWeight:700,textTransform:'uppercase',letterSpacing:.5,marginBottom:10,color:'var(--pink)',display:'flex',alignItems:'center',gap:8}}>
+        Model Leaderboard
+        <span style={{fontSize:9,fontWeight:400,color:'var(--muted)',textTransform:'none',letterSpacing:0}}>ranked by P&L</span>
+      </div>
+      <div className="pf-leaderboard">
+        <div className="pf-lb-header">
+          <span>#</span><span>Model</span><span>P&L</span><span>Invested</span><span>ROI</span><span>W</span><span>L</span><span>Trades</span><span>Strategy</span>
+        </div>
+        {portfolios.map((p, i) => {
+          const c = stratColors[p.strategy] || 'var(--muted)';
+          const pnl = parseInt(p.pnl_cents) || 0;
+          const invested = parseInt(p.total_invested_cents) || 0;
+          const resolved = parseInt(p.resolved_trades) || 0;
+          const roi = parseFloat(p.roi_pct) || 0;
+          const totalT = (parseInt(p.trades_won) || 0) + (parseInt(p.trades_lost) || 0) + (parseInt(p.trades_expired) || 0);
+          const openCount = activeTrades.filter(t => t.portfolio_id === p.id).length;
+          const medals = ['\\uD83E\\uDD47','\\uD83E\\uDD48','\\uD83E\\uDD49'];
+          return (<div key={p.id} className="pf-lb-row">
+            <span className="pf-lb-rank">{i < 3 ? medals[i] : (i+1)}</span>
+            <span className="pf-lb-name" style={{color:c}}>
+              <span style={{fontSize:16}}>{stratEmojis[p.strategy]||''}</span>
+              {p.name}
+            </span>
+            <span className="pf-lb-pnl" style={{color: pnl >= 0 ? 'var(--green)' : 'var(--red)'}}>
+              {pnl >= 0 ? '+' : ''}{'$'}{(pnl / 100).toFixed(2)}
+            </span>
+            <span className="pf-lb-invested">{'$'}{(invested / 100).toFixed(2)}</span>
+            <span className="pf-lb-roi" style={{
+              background: roi > 0 ? 'rgba(34,197,94,.12)' : roi < 0 ? 'rgba(239,68,68,.12)' : 'rgba(255,255,255,.04)',
+              color: roi > 0 ? 'var(--green)' : roi < 0 ? 'var(--red)' : 'var(--muted)'
+            }}>{roi > 0 ? '+' : ''}{roi}%</span>
+            <span className="pf-lb-wl" style={{color:'var(--green)'}}>{p.trades_won}</span>
+            <span className="pf-lb-wl" style={{color:'var(--red)'}}>{p.trades_lost}</span>
+            <span style={{fontVariantNumeric:'tabular-nums',color:'var(--muted)'}}>
+              {openCount > 0 ? <span>{openCount} <span style={{fontSize:8,color:'var(--green)'}}>OPEN</span></span> : <span style={{color:'var(--muted)'}}>0</span>}
+              {resolved > 0 && <span style={{marginLeft:4,fontSize:9}}>+{resolved}</span>}
+            </span>
+            <span style={{fontSize:9,color:'var(--muted)',overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}} title={stratDesc[p.strategy]}>
+              {p.strategy}
+            </span>
+          </div>);
+        })}
+      </div>
     </div>
-    {selectedPf && trades.length > 0 && (<div>
-      <h3 style={{fontSize:14,fontWeight:600,marginBottom:10,color:'var(--muted)'}}>Recent Trades — {portfolios.find(p=>p.id===selectedPf)?.name}</h3>
+
+    {/* ═══ Overlap Analysis ═══ */}
+    {overlaps.length > 0 && <div className="pf-overlap">
+      <div className="pf-overlap-title">
+        \\u26A0\\uFE0F Strategy Overlap — Markets with 2+ models
+      </div>
       <div style={{display:'flex',flexDirection:'column',gap:4}}>
-        {trades.slice(0,20).map((t,i) => (<div key={i} style={{display:'flex',alignItems:'center',gap:10,padding:'8px 14px',background:'var(--card)',border:'1px solid var(--border)',borderRadius:8,fontSize:12}}>
-          <span style={{padding:'2px 8px',borderRadius:4,fontWeight:700,fontSize:11,background:t.direction==='BUY_YES'?'rgba(34,197,94,.15)':'rgba(239,68,68,.15)',color:t.direction==='BUY_YES'?'var(--green)':'var(--red)',minWidth:55,textAlign:'center'}}>{t.direction==='BUY_YES'?'YES':'NO'}</span>
-          <span style={{flex:1,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{t.market_title||t.market_id}</span>
-          <span style={{fontVariantNumeric:'tabular-nums',color:'var(--muted)'}}>{t.entry_price_cents}¢ x{t.contracts}</span>
-          <span style={{fontWeight:700,fontVariantNumeric:'tabular-nums',color:t.status==='won'?'var(--green)':t.status==='lost'?'var(--red)':'var(--muted)',minWidth:50,textAlign:'right'}}>
-            {t.status==='open'?'OPEN':t.pnl_cents>0?'+'+t.pnl_cents+'¢':t.pnl_cents+'¢'}
-          </span>
-          <span style={{fontSize:10,color:'var(--muted)',minWidth:60,textAlign:'right'}}>{new Date(t.created_at).toLocaleTimeString('en-US',{hour:'numeric',minute:'2-digit',hour12:true})}</span>
-        </div>))}
+        {overlaps.slice(0, 8).map((o, i) => (
+          <div key={i} style={{display:'flex',alignItems:'center',gap:8,fontSize:10,padding:'4px 0'}}>
+            <span style={{fontWeight:700,color:'var(--yellow)',minWidth:20}}>{o.num_strategies}x</span>
+            <span style={{fontWeight:600,minWidth:180,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{o.market_id}</span>
+            <span style={{color:'var(--muted)',flex:1,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>
+              {(o.portfolios || []).join(', ')}
+            </span>
+            <span style={{fontVariantNumeric:'tabular-nums',color:'var(--muted)'}}>{'$'}{((o.total_exposure || 0) / 100).toFixed(2)}</span>
+          </div>
+        ))}
       </div>
-    </div>)}
-    {(!selectedPf || trades.length === 0) && <div style={{textAlign:'center',padding:30,color:'var(--muted)',fontSize:13}}>Click a portfolio to see its trades. Portfolios auto-trade every 2 minutes from approved signals.</div>}
+    </div>}
+
+    {/* ═══ Trade History ═══ */}
+    <div className="pf-history">
+      <div className="pf-history-header">
+        <span style={{fontSize:13,fontWeight:700,textTransform:'uppercase',letterSpacing:.5,color:'var(--cyan)'}}>Trade History</span>
+        <div style={{display:'flex',gap:4}}>
+          <button onClick={() => setHistFilter('all')} style={{padding:'3px 10px',borderRadius:6,border:'1px solid '+(histFilter==='all'?'var(--cyan)':'var(--border)'),background:histFilter==='all'?'rgba(6,182,212,.1)':'transparent',color:histFilter==='all'?'var(--cyan)':'var(--muted)',fontSize:10,fontWeight:600,cursor:'pointer'}}>All</button>
+          {portfolios.filter(p => parseInt(p.total_invested_cents) > 0).map(p => (
+            <button key={p.strategy} onClick={() => setHistFilter(p.strategy)} style={{padding:'3px 10px',borderRadius:6,border:'1px solid '+(histFilter===p.strategy?stratColors[p.strategy]:'var(--border)'),background:histFilter===p.strategy?stratColors[p.strategy]+'18':'transparent',color:histFilter===p.strategy?stratColors[p.strategy]:'var(--muted)',fontSize:10,fontWeight:600,cursor:'pointer'}}>
+              {stratEmojis[p.strategy] || ''} {p.name}
+            </button>
+          ))}
+        </div>
+      </div>
+      <div className="pf-history-list">
+        {filteredHistory.length === 0 && <div style={{textAlign:'center',padding:30,color:'var(--muted)',fontSize:12}}>No trades for this filter</div>}
+        {filteredHistory.slice(0, 100).map((t, i) => {
+          const c = stratColors[t.strategy] || 'var(--muted)';
+          const pnl = parseInt(t.pnl_cents) || 0;
+          return (<div key={i} className="pf-history-row">
+            <span style={{width:6,height:6,borderRadius:'50%',flexShrink:0,background:
+              t.status === 'open' ? 'var(--green)' : t.status === 'won' ? 'var(--blue)' : t.status === 'lost' ? 'var(--red)' : 'var(--muted)'
+            }} />
+            <span style={{minWidth:60,fontWeight:700,color:c,fontSize:10}}>{t.portfolio_name}</span>
+            <span style={{padding:'1px 6px',borderRadius:3,fontSize:9,fontWeight:700,
+              background: t.direction === 'BUY_YES' ? 'rgba(34,197,94,.12)' : 'rgba(239,68,68,.12)',
+              color: t.direction === 'BUY_YES' ? 'var(--green)' : 'var(--red)'
+            }}>{t.direction === 'BUY_YES' ? 'YES' : 'NO'}</span>
+            <span style={{flex:1,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap',color:'var(--text)'}} title={t.market_title || t.market_id}>
+              {t.market_title || t.market_id}
+            </span>
+            <span style={{fontVariantNumeric:'tabular-nums',color:'var(--muted)',fontSize:10}}>
+              {t.contracts}x @ {t.entry_price_cents}\\u00A2
+            </span>
+            <span style={{fontVariantNumeric:'tabular-nums',color:'var(--muted)',fontSize:10,minWidth:45,textAlign:'right'}}>
+              {'$'}{(t.cost_cents / 100).toFixed(2)}
+            </span>
+            <span style={{fontWeight:800,fontVariantNumeric:'tabular-nums',minWidth:55,textAlign:'right',fontSize:10,
+              color: t.status === 'open' ? 'var(--yellow)' : pnl >= 0 ? 'var(--green)' : 'var(--red)'
+            }}>
+              {t.status === 'open' ? 'OPEN' : (pnl >= 0 ? '+' : '') + (pnl / 100).toFixed(2)}
+            </span>
+            <span style={{fontSize:9,color:'var(--muted)',minWidth:55,textAlign:'right'}}>{timeAgo(t.created_at)}</span>
+          </div>);
+        })}
+      </div>
+    </div>
+
+    {/* ═══ Strategy Guide ═══ */}
+    <div style={{marginTop:18,padding:16,background:'var(--card)',border:'1px solid var(--border)',borderRadius:14}}>
+      <div style={{fontSize:11,fontWeight:700,color:'var(--muted)',textTransform:'uppercase',letterSpacing:.5,marginBottom:10}}>Strategy Guide</div>
+      <div style={{display:'grid',gridTemplateColumns:'repeat(auto-fill,minmax(280px,1fr))',gap:6}}>
+        {Object.entries(stratDesc).map(([strat, desc]) => (
+          <div key={strat} style={{display:'flex',alignItems:'flex-start',gap:8,fontSize:10,padding:'4px 0',color:'var(--muted)'}}>
+            <span style={{fontSize:14,flexShrink:0}}>{stratEmojis[strat]||''}</span>
+            <div>
+              <span style={{fontWeight:700,color:stratColors[strat]}}>{stratNames[strat]}</span>
+              <span style={{margin:'0 4px'}}>\\u2014</span>
+              {desc}
+            </div>
+          </div>
+        ))}
+      </div>
+    </div>
   </div>);
 }
 
@@ -2987,7 +3140,7 @@ function App() {
     return () => clearInterval(iv);
   }, []);
 
-  if (loading) return (
+  if (loading || !data) return (
     <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100vh', flexDirection: 'column', gap: 16 }}>
       <div style={{ width: 60, height: 60, borderRadius: '50%', background: 'linear-gradient(135deg,#ff69b4,#8b5cf6)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 28, animation: 'avatarFloat 2s ease-in-out infinite' }}>K</div>
       <div style={{ color: 'var(--muted)', fontSize: 14, letterSpacing: 2 }}>INITIALIZING KEN INC...</div>
@@ -3020,7 +3173,7 @@ function App() {
       <div style={{display:'flex',justifyContent:'center',gap:8,marginBottom:24,flexWrap:'wrap'}}>
         <button style={tabStyle('command')} onClick={()=>setTab('command')}>Command Center</button>
         <button style={tabStyle('market')} onClick={()=>setTab('market')}>Market Data</button>
-        <button style={tabStyle('portfolios')} onClick={()=>setTab('portfolios')}>Portfolios (10)</button>
+        <button style={tabStyle('portfolios')} onClick={()=>setTab('portfolios')}>portFAUXlio</button>
         <button style={tabStyle('predictions')} onClick={()=>setTab('predictions')}>Predictions</button>
         <button style={tabStyle('signals')} onClick={()=>setTab('signals')}>Live Signals</button>
       </div>

← eb35535 chore(alshi-dash): update 1 file (.js) [+209/-20]  ·  back to Bertha  ·  chore(alshi-dash): update 1 file (.js) [+118/-6] 2875eb9 →