← back to Bertha
Fix all double-escaped unicode sequences + update footer to 50 portfolios
059d3e154ba38ded0255b0e3ddc2300418f3e39c · 2026-02-16 17:58:48 +0000 · DW Commit Agent
Replaced ~60 instances of \\uXXXX with actual Unicode characters throughout
server.js. These were showing as literal text (\u25BC, \u00A2, etc.) in the
browser because Node.js template literals send \\uXXXX as raw text. Fixes
sort arrows, cent signs, em dashes, emojis, medals, checkmarks, bullets,
and expand arrows across portFAUXlio, SWOT, trade history, and strategy
guide sections. Also updated footer from "10 paper portfolios" to 50.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Files touched
Diff
commit 059d3e154ba38ded0255b0e3ddc2300418f3e39c
Author: DW Commit Agent <claude@dw-agents.com>
Date: Mon Feb 16 17:58:48 2026 +0000
Fix all double-escaped unicode sequences + update footer to 50 portfolios
Replaced ~60 instances of \\uXXXX with actual Unicode characters throughout
server.js. These were showing as literal text (\u25BC, \u00A2, etc.) in the
browser because Node.js template literals send \\uXXXX as raw text. Fixes
sort arrows, cent signs, em dashes, emojis, medals, checkmarks, bullets,
and expand arrows across portFAUXlio, SWOT, trade history, and strategy
guide sections. Also updated footer from "10 paper portfolios" to 50.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---
kalshi-dash/server.js | 66 +++++++++++++++++++++++++--------------------------
1 file changed, 33 insertions(+), 33 deletions(-)
diff --git a/kalshi-dash/server.js b/kalshi-dash/server.js
index 09cbad7..bd9d15f 100644
--- a/kalshi-dash/server.js
+++ b/kalshi-dash/server.js
@@ -2652,7 +2652,7 @@ function updateHUD(d) {
const t = d.tournament;
const wStart = new Date(t.week_start).toLocaleDateString('en-US', {month:'short',day:'numeric'});
const wEnd = new Date(t.week_end).toLocaleDateString('en-US', {month:'short',day:'numeric'});
- document.getElementById('week-info').textContent = 'Week ' + t.id + ' \\u2022 ' + wStart + ' - ' + wEnd + ' \\u2022 $' + (t.budget_per_portfolio_cents/100).toFixed(0) + ' per portfolio';
+ document.getElementById('week-info').textContent = 'Week ' + t.id + ' • ' + wStart + ' - ' + wEnd + ' • $' + (t.budget_per_portfolio_cents/100).toFixed(0) + ' per portfolio';
let html = '';
let alphaTotal = 0, betaTotal = 0;
sorted.forEach((e, i) => {
@@ -2667,7 +2667,7 @@ function updateHUD(d) {
html += '<div class="name">' + e.name + '</div>';
html += '<div class="strat">' + e.strategy + '</div>';
html += '<div class="pnl ' + pnlClass + '">' + pnlStr + '</div>';
- html += '<div class="trades">' + (e.live_trades||0) + ' trades \\u2022 $' + ((e.live_invested||0)/100).toFixed(2) + ' deployed</div>';
+ html += '<div class="trades">' + (e.live_trades||0) + ' trades • $' + ((e.live_invested||0)/100).toFixed(2) + ' deployed</div>';
html += '<div class="bar"><div class="bar-fill" style="width:' + budgetUsed + '%;background:' + barColor + '"></div></div>';
html += '</div>';
if (i === 2) {
@@ -2969,7 +2969,7 @@ body::after{content:'';position:fixed;top:0;left:0;right:0;bottom:0;background-i
.swot-quadrant-t{background:rgba(245,158,11,.06);border:1px solid rgba(245,158,11,.15)}
.swot-q-title{font-weight:800;font-size:9px;text-transform:uppercase;letter-spacing:.5px;margin-bottom:6px}
.swot-q-item{padding:2px 0;color:var(--muted);line-height:1.4}
-.swot-q-item::before{content:'\\u2022 '}
+.swot-q-item::before{content:'• '}
.swot-models{display:flex;flex-wrap:wrap;gap:4px;padding:8px 16px 14px}
.swot-model-tag{padding:2px 8px;border-radius:4px;font-size:9px;font-weight:600;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.06)}
.pf-lb-row:hover{background:rgba(255,255,255,.03)}
@@ -3099,7 +3099,7 @@ function SignalFeed({ signals }) {
</div>
<div className="signal-conf">{(s.confidence * 100).toFixed(0)}%</div>
<div className="signal-approved" style={{ background: s.approved ? 'rgba(34,197,94,0.15)' : 'rgba(239,68,68,0.1)', color: s.approved ? 'var(--green)' : 'var(--red)' }}>
- {s.approved ? '\\u2713' : '\\u2717'}
+ {s.approved ? '✓' : '✗'}
</div>
<div className="signal-time">{timeAgo(s.time)}</div>
</div>
@@ -3144,7 +3144,7 @@ function PortfoliosTab() {
}, []);
const stratColors = {aggressive:'#ef4444',conservative:'#3b82f6',weather:'#06b6d4',momentum:'#f59e0b',contrarian:'#8b5cf6',ai_enhanced:'#ec4899',mc_validated:'#a855f7',scalper:'#eab308',patient:'#22c55e',random:'#64748b',penny_pincher:'#94a3b8',spray_pray:'#fb923c',nickel_slots:'#a78bfa',degen_lite:'#f43f5e',politics_junkie:'#0ea5e9',double_down:'#dc2626',volatility_rider:'#14b8a6',whale:'#1d4ed8',yolo:'#e11d48',full_send:'#b91c1c',kelly_criterion:'#059669',sharpe_sniper:'#7c3aed',bayesian_blend:'#0891b2',ensemble_lock:'#c026d3',mean_revert:'#d97706',info_ratio:'#2563eb',anti_fomo:'#16a34a',nightcrawler:'#4c1d95',heatseeker:'#ea580c',quant_core:'#0d9488',etf_presidential:'#dc143c',etf_cabinet:'#ff6347',etf_congress:'#4169e1',etf_scotus:'#2f4f4f',etf_fed:'#228b22',etf_economy:'#daa520',etf_geopolitics:'#8b0000',etf_territory:'#006400',etf_climate:'#00bfff',etf_energy:'#ff8c00',etf_tech:'#7b68ee',etf_space:'#191970',etf_crypto:'#ffd700',etf_sports:'#32cd32',etf_entertainment:'#ff1493',etf_legal:'#708090',etf_financials:'#4682b4',etf_govreform:'#b22222',etf_global_social:'#9370db',etf_broad_market:'#c0a050'};
- 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',penny_pincher:'\\uD83E\\uDE99',spray_pray:'\\uD83D\\uDCA6',nickel_slots:'\\uD83C\\uDFB0',degen_lite:'\\uD83D\\uDE08',politics_junkie:'\\uD83C\\uDFDB\\uFE0F',double_down:'\\u2B06\\uFE0F',volatility_rider:'\\uD83C\\uDFC4',whale:'\\uD83D\\uDC33',yolo:'\\uD83E\\uDDE8',full_send:'\\uD83D\\uDCA3',kelly_criterion:'\\uD83C\\uDFB0',sharpe_sniper:'\\uD83C\\uDFAF',bayesian_blend:'\\uD83E\\uDDEE',ensemble_lock:'\\uD83D\\uDD10',mean_revert:'\\u21A9\\uFE0F',info_ratio:'\\uD83D\\uDCCA',anti_fomo:'\\uD83E\\uDDD8',nightcrawler:'\\uD83E\\uDD87',heatseeker:'\\uD83D\\uDD2C',quant_core:'\\u2211',etf_presidential:'\\uD83C\\uDFDB\\uFE0F',etf_cabinet:'\\uD83D\\uDCBC',etf_congress:'\\uD83D\\uDDF3\\uFE0F',etf_scotus:'\\u2696\\uFE0F',etf_fed:'\\uD83C\\uDFE6',etf_economy:'\\uD83D\\uDCC8',etf_geopolitics:'\\uD83C\\uDF0D',etf_territory:'\\uD83D\\uDDFA\\uFE0F',etf_climate:'\\uD83C\\uDF21\\uFE0F',etf_energy:'\\u26FD',etf_tech:'\\uD83E\\uDD16',etf_space:'\\uD83D\\uDE80',etf_crypto:'\\u20BF',etf_sports:'\\u26BD',etf_entertainment:'\\uD83C\\uDFAC',etf_legal:'\\uD83D\\uDD28',etf_financials:'\\uD83D\\uDCB9',etf_govreform:'\\u2702\\uFE0F',etf_global_social:'\\u26EA',etf_broad_market:'\\uD83C\\uDF10'};
+ const stratEmojis = {aggressive:'🔥',conservative:'🏛️',weather:'⛈️',momentum:'🚀',contrarian:'🔄',ai_enhanced:'🧠',mc_validated:'🎲',scalper:'⚡',patient:'🐢',random:'🎰',penny_pincher:'🪙',spray_pray:'💦',nickel_slots:'🎰',degen_lite:'😈',politics_junkie:'🏛️',double_down:'⬆️',volatility_rider:'🏄',whale:'🐳',yolo:'🧨',full_send:'💣',kelly_criterion:'🎰',sharpe_sniper:'🎯',bayesian_blend:'🧮',ensemble_lock:'🔐',mean_revert:'↩️',info_ratio:'📊',anti_fomo:'🧘',nightcrawler:'🦇',heatseeker:'🔬',quant_core:'∑',etf_presidential:'🏛️',etf_cabinet:'💼',etf_congress:'🗳️',etf_scotus:'⚖️',etf_fed:'🏦',etf_economy:'📈',etf_geopolitics:'🌍',etf_territory:'🗺️',etf_climate:'🌡️',etf_energy:'⛽',etf_tech:'🤖',etf_space:'🚀',etf_crypto:'₿',etf_sports:'⚽',etf_entertainment:'🎬',etf_legal:'🔨',etf_financials:'💹',etf_govreform:'✂️',etf_global_social:'⛪',etf_broad_market:'🌐'};
const stratNames = {aggressive:'Alpha',conservative:'Beta',weather:'Storm',momentum:'Momentum',contrarian:'Contrarian',ai_enhanced:'Nova',mc_validated:'Oracle',scalper:'Shark',patient:'Turtle',random:'Wildcard',penny_pincher:'Penny',spray_pray:'Spray',nickel_slots:'Nickel',degen_lite:'Degen',politics_junkie:'Capitol',double_down:'Doubler',volatility_rider:'Rider',whale:'Moby',yolo:'YOLO',full_send:'Cannon',kelly_criterion:'Kelly',sharpe_sniper:'Sniper',bayesian_blend:'Bayes',ensemble_lock:'Voltron',mean_revert:'Revert',info_ratio:'Signal',anti_fomo:'Zen',nightcrawler:'Shadow',heatseeker:'Heatseek',quant_core:'Quant',etf_presidential:'PRES',etf_cabinet:'Cabinet',etf_congress:'Congress',etf_scotus:'SCOTUS',etf_fed:'Fed',etf_economy:'Economy',etf_geopolitics:'Geo',etf_territory:'Territory',etf_climate:'Climate',etf_energy:'Energy',etf_tech:'Tech',etf_space:'Space',etf_crypto:'Crypto',etf_sports:'Sports',etf_entertainment:'Showbiz',etf_legal:'Legal',etf_financials:'Finance',etf_govreform:'GovReform',etf_global_social:'Global',etf_broad_market:'Broad Mkt'};
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',penny_pincher:'Any edge >=1% — micro bets, max volume',spray_pray:'Random 50% of all signals — luck vs skill',nickel_slots:'Edge >=2% + conf >=20% — low bar catcher',degen_lite:'Edge >=5%, ignores confidence — pure edge',politics_junkie:'Political markets only — elections/congress',double_down:'Edge >=20% — goes big on massive edges',volatility_rider:'High MC stddev + edge — volatile markets',whale:'Edge >=25% + conf >=60% — rare massive sniper',yolo:'Edge >=30% — max degen, no filters',full_send:'Takes EVERY signal — pipeline profitability test',kelly_criterion:'Kelly fraction: edge/(1+edge) — bankroll math',sharpe_sniper:'Signal-to-noise ratio >2.0 — edge/stddev',bayesian_blend:'Bayesian posterior: conf * evidence * edge',ensemble_lock:'ALL must align: AI + MC + conf + edge + articles',mean_revert:'High volatility + moderate edge — reversion play',info_ratio:'(articles * agreement) / noise — quality intel',anti_fomo:'Small edge + high conf — calm, certain plays',nightcrawler:'BUY_NO + AI + MC — sophisticated shorts',heatseeker:'Multi-factor composite: 40e + 30c + 20a + 10n',quant_core:'Geometric mean sqrt(edge*conf) — pure math',etf_presidential:'Presidential election & 2028 race markets',etf_cabinet:'Cabinet confirmations & departures',etf_congress:'House, Senate & legislative markets',etf_scotus:'Supreme Court rulings & retirements',etf_fed:'Federal Reserve, rates & monetary policy',etf_economy:'GDP, jobs & economic indicators',etf_geopolitics:'Wars, treaties, sanctions & foreign affairs',etf_territory:'Greenland, statehood & territorial expansion',etf_climate:'Weather, warming & climate events',etf_energy:'LNG, oil, power grid & energy commodities',etf_tech:'AI, fusion, tech companies & semiconductors',etf_space:'SpaceX, NASA, Mars & Moon missions',etf_crypto:'Bitcoin, Ethereum & digital assets',etf_sports:'NBA, NFL, MLB & sports outcomes',etf_entertainment:'Celebrity, media, awards & pop culture',etf_legal:'Pardons, impeachment & legal proceedings',etf_financials:'Bonds, yields & financial markets',etf_govreform:'DOGE, agency cuts & government reform',etf_global_social:'Pope, referendums & global social movements',etf_broad_market:'Index fund — high-quality signals all sectors'};
@@ -3230,7 +3230,7 @@ function PortfoliosTab() {
{t.market_title || t.market_id}
</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.contracts}x @ {t.entry_price_cents}¢</span>
<span>{'$'}{(t.cost_cents / 100).toFixed(2)}</span>
<span>{timeAgo(t.created_at)}</span>
</div>
@@ -3246,24 +3246,24 @@ function PortfoliosTab() {
<span style={{fontSize:9,fontWeight:400,color:'var(--muted)',textTransform:'none',letterSpacing:0}}>ranked by {sortBy}</span>
<div style={{marginLeft:'auto',display:'flex',gap:6}}>
{compareMode && compareIds.length >= 2 && <button onClick={() => setCompareMode('show')} style={{padding:'3px 10px',borderRadius:6,fontSize:9,fontWeight:700,background:'rgba(6,182,212,.15)',border:'1px solid var(--cyan)',color:'var(--cyan)',cursor:'pointer'}}>
- Compare {compareIds.length} \\u2192
+ Compare {compareIds.length} →
</button>}
<button onClick={() => { if (compareMode) { setCompareMode(false); setCompareIds([]); } else setCompareMode(true); }} style={{padding:'3px 10px',borderRadius:6,fontSize:9,fontWeight:700,background:compareMode?'rgba(168,85,247,.15)':'transparent',border:'1px solid '+(compareMode?'var(--purple)':'var(--border)'),color:compareMode?'var(--purple)':'var(--muted)',cursor:'pointer'}}>
- {compareMode ? '\\u2715 Cancel' : '\\uD83D\\uDCCA Compare'}
+ {compareMode ? '✕ Cancel' : '📊 Compare'}
</button>
</div>
</div>
<div className="pf-leaderboard">
<div className="pf-lb-header">
<span>#</span>
- <span style={{cursor:'pointer'}} onClick={() => toggleSort('name')}>Model {sortBy==='name' ? (sortDir==='asc'?'\\u25B2':'\\u25BC') : ''}</span>
- <span style={{cursor:'pointer'}} onClick={() => toggleSort('pnl')}>P&L {sortBy==='pnl' ? (sortDir==='asc'?'\\u25B2':'\\u25BC') : ''}</span>
- <span style={{cursor:'pointer'}} onClick={() => toggleSort('invested')}>Invested {sortBy==='invested' ? (sortDir==='asc'?'\\u25B2':'\\u25BC') : ''}</span>
- <span style={{cursor:'pointer'}} onClick={() => toggleSort('roi')}>ROI {sortBy==='roi' ? (sortDir==='asc'?'\\u25B2':'\\u25BC') : ''}</span>
- <span style={{cursor:'pointer'}} onClick={() => toggleSort('wins')}>W {sortBy==='wins' ? (sortDir==='asc'?'\\u25B2':'\\u25BC') : ''}</span>
+ <span style={{cursor:'pointer'}} onClick={() => toggleSort('name')}>Model {sortBy==='name' ? (sortDir==='asc'?'▲':'▼') : ''}</span>
+ <span style={{cursor:'pointer'}} onClick={() => toggleSort('pnl')}>P&L {sortBy==='pnl' ? (sortDir==='asc'?'▲':'▼') : ''}</span>
+ <span style={{cursor:'pointer'}} onClick={() => toggleSort('invested')}>Invested {sortBy==='invested' ? (sortDir==='asc'?'▲':'▼') : ''}</span>
+ <span style={{cursor:'pointer'}} onClick={() => toggleSort('roi')}>ROI {sortBy==='roi' ? (sortDir==='asc'?'▲':'▼') : ''}</span>
+ <span style={{cursor:'pointer'}} onClick={() => toggleSort('wins')}>W {sortBy==='wins' ? (sortDir==='asc'?'▲':'▼') : ''}</span>
<span>L</span>
- <span style={{cursor:'pointer'}} onClick={() => toggleSort('trades')}>Trades {sortBy==='trades' ? (sortDir==='asc'?'\\u25B2':'\\u25BC') : ''}</span>
- <span style={{cursor:'pointer'}} onClick={() => toggleSort('strategy')}>Strategy {sortBy==='strategy' ? (sortDir==='asc'?'\\u25B2':'\\u25BC') : ''}</span>
+ <span style={{cursor:'pointer'}} onClick={() => toggleSort('trades')}>Trades {sortBy==='trades' ? (sortDir==='asc'?'▲':'▼') : ''}</span>
+ <span style={{cursor:'pointer'}} onClick={() => toggleSort('strategy')}>Strategy {sortBy==='strategy' ? (sortDir==='asc'?'▲':'▼') : ''}</span>
<span>Chart</span>
</div>
{portfolios.map((p, i) => {
@@ -3274,7 +3274,7 @@ function PortfoliosTab() {
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'];
+ const medals = ['🥇','🥈','🥉'];
const cd = chartData[p.id];
const miniPts = cd ? (cd.snapshots || []).map(s => s.nav / 100) : (cd?.daily || []).map(d => d.cumulative / 100);
return (<div key={p.id} className="pf-lb-row" style={compareMode && compareIds.includes(p.id) ? {background:'rgba(168,85,247,.08)',borderLeft:'3px solid var(--purple)'} : {}} onClick={() => {
@@ -3314,7 +3314,7 @@ function PortfoliosTab() {
{/* ═══ Overlap Analysis ═══ */}
{overlaps.length > 0 && <div className="pf-overlap">
<div className="pf-overlap-title">
- \\u26A0\\uFE0F Strategy Overlap — Markets with 2+ models
+ ⚠️ Strategy Overlap — Markets with 2+ models
</div>
<div style={{display:'flex',flexDirection:'column',gap:4}}>
{overlaps.slice(0, 8).map((o, i) => (
@@ -3350,7 +3350,7 @@ function PortfoliosTab() {
<span style={{fontSize:10,fontWeight:700,color:m.edge >= 10 ? 'var(--green)' : 'var(--yellow)'}}>{m.edge.toFixed(1)}% edge</span>
<span style={{fontSize:10,fontVariantNumeric:'tabular-nums',color:'var(--muted)'}}>{'$'}{(m.total_cost / 100).toFixed(2)}</span>
<span style={{fontSize:10,fontWeight:700,color: m.open_count > 0 ? 'var(--green)' : 'var(--muted)'}}>{m.open_count > 0 ? m.open_count + ' OPEN' : 'CLOSED'}</span>
- <span style={{fontSize:14,color:'var(--muted)',transform:isOpen?'rotate(180deg)':'rotate(0)',transition:'transform .2s'}}>\\u25BC</span>
+ <span style={{fontSize:14,color:'var(--muted)',transform:isOpen?'rotate(180deg)':'rotate(0)',transition:'transform .2s'}}>▼</span>
</div>
{isOpen && <div>
<div className="swot-grid">
@@ -3376,8 +3376,8 @@ function PortfoliosTab() {
</div>
<div style={{padding:'4px 16px 6px',fontSize:10,color:'var(--muted)',display:'flex',gap:16,flexWrap:'wrap'}}>
<span>Conf: <strong style={{color:'var(--cyan)'}}>{Math.round(m.confidence * 100)}%</strong></span>
- <span>Entry: <strong>{m.entry_price}\\u00A2</strong></span>
- {m.mc_mean > 0 && <span>MC: <strong>{m.mc_mean.toFixed(1)}% \\u00B1{m.mc_std.toFixed(1)}%</strong></span>}
+ <span>Entry: <strong>{m.entry_price}¢</strong></span>
+ {m.mc_mean > 0 && <span>MC: <strong>{m.mc_mean.toFixed(1)}% ±{m.mc_std.toFixed(1)}%</strong></span>}
{m.articles > 0 && <span>News: <strong>{m.articles} articles</strong></span>}
{m.agreement > 0 && <span>Agree: <strong>{m.agreement}%</strong></span>}
</div>
@@ -3424,7 +3424,7 @@ function PortfoliosTab() {
{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
+ {t.contracts}x @ {t.entry_price_cents}¢
</span>
<span style={{fontVariantNumeric:'tabular-nums',color:'var(--muted)',fontSize:10,minWidth:45,textAlign:'right'}}>
{'$'}{(t.cost_cents / 100).toFixed(2)}
@@ -3471,7 +3471,7 @@ function PortfoliosTab() {
<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>
+ <span style={{margin:'0 4px'}}>—</span>
{desc}
</div>
</div>
@@ -3562,7 +3562,7 @@ function Sparkline({ data, width = 120, height = 30, color = '#8b5cf6', showDots
})}
</svg>
{label && <div style={{position:'absolute',top:2,right:4,fontSize:9,color:trending?'var(--green)':'var(--red)',fontWeight:700}}>
- {trending?'\\u25B2':'\\u25BC'} {lastVal.toLocaleString()}
+ {trending?'▲':'▼'} {lastVal.toLocaleString()}
</div>}
</div>
);
@@ -3668,7 +3668,7 @@ function FullChart({ chartData: initialData, portfolioId, strategy, name, color,
<button key={p} className={period === p ? 'chart-period-active' : 'chart-period'} onClick={() => setPeriod(p)}>{p}</button>
))}
</div>
- <button className="chart-close" onClick={onClose}>\\u2715</button>
+ <button className="chart-close" onClick={onClose}>✕</button>
</div>
<div style={{height:340,position:'relative'}}><canvas ref={canvasRef} /></div>
</div>
@@ -3733,14 +3733,14 @@ function ComparisonChart({ portfolioIds, allChartData, stratColors, stratNames,
<div className="chart-modal" onClick={onClose}>
<div className="chart-modal-content" onClick={e => e.stopPropagation()} style={{maxWidth:1100}}>
<div className="chart-modal-header">
- <span style={{fontSize:16}}>\\uD83D\\uDCCA</span>
+ <span style={{fontSize:16}}>📊</span>
<span style={{fontWeight:800,color:'var(--cyan)'}}>Compare {portfolioIds.length} Portfolios</span>
<div className="chart-period-btns" style={{marginLeft:'auto'}}>
{periods.map(p => (
<button key={p} className={period === p ? 'chart-period-active' : 'chart-period'} onClick={() => setPeriod(p)}>{p}</button>
))}
</div>
- <button className="chart-close" onClick={onClose}>\\u2715</button>
+ <button className="chart-close" onClick={onClose}>✕</button>
</div>
<div style={{height:400,position:'relative'}}><canvas ref={canvasRef} /></div>
</div>
@@ -3817,7 +3817,7 @@ function MarketDataTab() {
const totalSent24h = sentVals.reduce((a, b) => a + b, 0);
const totalSignals = signalVals.reduce((a, b) => a + b, 0);
const at = mkt.approvalTrend || {};
- const changeArrow = at.change > 0 ? '\\u25B2' : at.change < 0 ? '\\u25BC' : '\\u2014';
+ const changeArrow = at.change > 0 ? '▲' : at.change < 0 ? '▼' : '—';
const changeClass = at.change > 0 ? 'up' : at.change < 0 ? 'down' : 'flat';
const totalPnl = (mkt.portfolios || []).reduce((s, p) => s + (p.pnl_cents || 0), 0);
const totalTrades = (mkt.portfolios || []).reduce((s, p) => s + (p.total_trades || 0), 0);
@@ -3837,7 +3837,7 @@ function MarketDataTab() {
const doubledTicker = tickerItems.concat(tickerItems);
const stratColors = {aggressive:'#ef4444',conservative:'#3b82f6',weather:'#06b6d4',momentum:'#f59e0b',contrarian:'#8b5cf6',ai_enhanced:'#ec4899',mc_validated:'#a855f7',scalper:'#eab308',patient:'#22c55e',random:'#64748b',penny_pincher:'#94a3b8',spray_pray:'#fb923c',nickel_slots:'#a78bfa',degen_lite:'#f43f5e',politics_junkie:'#0ea5e9',double_down:'#dc2626',volatility_rider:'#14b8a6',whale:'#1d4ed8',yolo:'#e11d48',full_send:'#b91c1c',kelly_criterion:'#059669',sharpe_sniper:'#7c3aed',bayesian_blend:'#0891b2',ensemble_lock:'#c026d3',mean_revert:'#d97706',info_ratio:'#2563eb',anti_fomo:'#16a34a',nightcrawler:'#4c1d95',heatseeker:'#ea580c',quant_core:'#0d9488',etf_presidential:'#dc143c',etf_cabinet:'#ff6347',etf_congress:'#4169e1',etf_scotus:'#2f4f4f',etf_fed:'#228b22',etf_economy:'#daa520',etf_geopolitics:'#8b0000',etf_territory:'#006400',etf_climate:'#00bfff',etf_energy:'#ff8c00',etf_tech:'#7b68ee',etf_space:'#191970',etf_crypto:'#ffd700',etf_sports:'#32cd32',etf_entertainment:'#ff1493',etf_legal:'#708090',etf_financials:'#4682b4',etf_govreform:'#b22222',etf_global_social:'#9370db',etf_broad_market:'#c0a050'};
- 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',penny_pincher:'\\uD83E\\uDE99',spray_pray:'\\uD83D\\uDCA6',nickel_slots:'\\uD83C\\uDFB0',degen_lite:'\\uD83D\\uDE08',politics_junkie:'\\uD83C\\uDFDB\\uFE0F',double_down:'\\u2B06\\uFE0F',volatility_rider:'\\uD83C\\uDFC4',whale:'\\uD83D\\uDC33',yolo:'\\uD83E\\uDDE8',full_send:'\\uD83D\\uDCA3',kelly_criterion:'\\uD83C\\uDFB0',sharpe_sniper:'\\uD83C\\uDFAF',bayesian_blend:'\\uD83E\\uDDEE',ensemble_lock:'\\uD83D\\uDD10',mean_revert:'\\u21A9\\uFE0F',info_ratio:'\\uD83D\\uDCCA',anti_fomo:'\\uD83E\\uDDD8',nightcrawler:'\\uD83E\\uDD87',heatseeker:'\\uD83D\\uDD2C',quant_core:'\\u2211',etf_presidential:'\\uD83C\\uDFDB\\uFE0F',etf_cabinet:'\\uD83D\\uDCBC',etf_congress:'\\uD83D\\uDDF3\\uFE0F',etf_scotus:'\\u2696\\uFE0F',etf_fed:'\\uD83C\\uDFE6',etf_economy:'\\uD83D\\uDCC8',etf_geopolitics:'\\uD83C\\uDF0D',etf_territory:'\\uD83D\\uDDFA\\uFE0F',etf_climate:'\\uD83C\\uDF21\\uFE0F',etf_energy:'\\u26FD',etf_tech:'\\uD83E\\uDD16',etf_space:'\\uD83D\\uDE80',etf_crypto:'\\u20BF',etf_sports:'\\u26BD',etf_entertainment:'\\uD83C\\uDFAC',etf_legal:'\\uD83D\\uDD28',etf_financials:'\\uD83D\\uDCB9',etf_govreform:'\\u2702\\uFE0F',etf_global_social:'\\u26EA',etf_broad_market:'\\uD83C\\uDF10'};
+ const stratEmojis = {aggressive:'🔥',conservative:'🏛️',weather:'⛈️',momentum:'🚀',contrarian:'🔄',ai_enhanced:'🧠',mc_validated:'🎲',scalper:'⚡',patient:'🐢',random:'🎰',penny_pincher:'🪙',spray_pray:'💦',nickel_slots:'🎰',degen_lite:'😈',politics_junkie:'🏛️',double_down:'⬆️',volatility_rider:'🏄',whale:'🐳',yolo:'🧨',full_send:'💣',kelly_criterion:'🎰',sharpe_sniper:'🎯',bayesian_blend:'🧮',ensemble_lock:'🔐',mean_revert:'↩️',info_ratio:'📊',anti_fomo:'🧘',nightcrawler:'🦇',heatseeker:'🔬',quant_core:'∑',etf_presidential:'🏛️',etf_cabinet:'💼',etf_congress:'🗳️',etf_scotus:'⚖️',etf_fed:'🏦',etf_economy:'📈',etf_geopolitics:'🌍',etf_territory:'🗺️',etf_climate:'🌡️',etf_energy:'⛽',etf_tech:'🤖',etf_space:'🚀',etf_crypto:'₿',etf_sports:'⚽',etf_entertainment:'🎬',etf_legal:'🔨',etf_financials:'💹',etf_govreform:'✂️',etf_global_social:'⛪',etf_broad_market:'🌐'};
return (<div>
{/* ═══ Hero P&L Banner ═══ */}
@@ -3862,7 +3862,7 @@ function MarketDataTab() {
<span style={{color:'var(--muted)',fontSize:9,textTransform:'uppercase',letterSpacing:.5}}>{t.label}</span>
<span style={{color:t.color,fontWeight:800}}>{t.value}</span>
{t.change !== undefined && <span className={'mkt-change ' + (t.change > 0 ? 'up' : t.change < 0 ? 'down' : 'flat')}>
- {t.change > 0 ? '\\u25B2' : t.change < 0 ? '\\u25BC' : ''}{Math.abs(t.change)}%
+ {t.change > 0 ? '▲' : t.change < 0 ? '▼' : ''}{Math.abs(t.change)}%
</span>}
</div>
))}
@@ -3919,7 +3919,7 @@ function MarketDataTab() {
<Sparkline data={sentVals} width={300} height={50} color="#ec4899" label={true} />
<div style={{display:'flex',justifyContent:'space-between',marginTop:8,fontSize:10,color:'var(--muted)'}}>
<span>Avg: <strong style={{color: sentScoreVals.length > 0 && sentScoreVals.reduce((a,b)=>a+b,0)/sentScoreVals.length > 0 ? 'var(--green)' : 'var(--red)'}}>
- {sentScoreVals.length > 0 ? (sentScoreVals.reduce((a,b)=>a+b,0)/sentScoreVals.length).toFixed(3) : '\\u2014'}
+ {sentScoreVals.length > 0 ? (sentScoreVals.reduce((a,b)=>a+b,0)/sentScoreVals.length).toFixed(3) : '—'}
</strong></span>
<span>{(mkt.sourceMix||[]).length} sources</span>
</div>
@@ -4054,7 +4054,7 @@ function MarketDataTab() {
<span className="trade-portfolio" style={{color:c}}>{t.portfolio_name}</span>
<span className={'signal-dir ' + t.direction} style={{fontSize:9}}>{t.direction}</span>
<span style={{flex:1,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap',color:'var(--muted)'}}>{t.market_id}</span>
- <span style={{fontSize:10,color:'var(--muted)'}}>{t.contracts}x @ {t.entry_price_cents}\\u00A2</span>
+ <span style={{fontSize:10,color:'var(--muted)'}}>{t.contracts}x @ {t.entry_price_cents}¢</span>
<span className="trade-pnl" style={{color: t.pnl_cents >= 0 ? 'var(--green)' : 'var(--red)'}}>
{t.pnl_cents >= 0 ? '+' : ''}{(t.pnl_cents / 100).toFixed(2)}
</span>
@@ -4199,7 +4199,7 @@ function App() {
</div>}
<div className="footer">
- Ken Inc. Trading Intelligence • {d.system.cpuCores} cores • {d.system.uptime_hours}h uptime • 10 paper portfolios •
+ Ken Inc. Trading Intelligence • {d.system.cpuCores} cores • {d.system.uptime_hours}h uptime • 50 paper portfolios •
<a href="/"> Back to Dashboard</a>
</div>
</div>
@@ -6295,7 +6295,7 @@ async function signalPipeline(activeMarkets) {
console.log(`[Ken] SIGNAL: ${direction} ${ticker} — edge ${(mcEdge * 100).toFixed(1)}%, conf ${(confidence * 100).toFixed(0)}%, MC:${mcResult.edgeConsistent ? 'consistent' : 'mixed'}${signal.aiEnhanced ? ', AI-enhanced' : ''}, size ${risk.sizeRecommendation}`);
}
- // Auto-trade across all 10 paper portfolios
+ // Auto-trade across all 50 paper portfolios
if (risk.approved) {
autoPortfolioTrade({
...signal, marketId: ticker, market_title: market.title,
← d8e8eeb chore(alshi-dash,kalshi-dash): update 7 files (.js) [+415/-5
·
back to Bertha
·
chore(alshi-dash): update 1 file (.js) [+1/-1] 5036849 →