refactor(ui): tokenize trade profile metrics

This commit is contained in:
root 2026-05-07 05:20:49 +00:00
parent c935f15943
commit 931a3cde1d

View File

@ -80,13 +80,13 @@ export interface ProfileTradeStats {
// --- CONSTANTS ---
const AVAILABLE_RULES = [
{ id: 'TrendBiasRule', name: 'Trend Bias', desc: 'EMA50/200 direction check on 4H timeframe', icon: TrendingUp, color: '#3b82f6', defaultParams: { fastPeriod: 50, slowPeriod: 200 } },
{ id: 'MomentumRule', name: 'Momentum', desc: 'RSI overbought/oversold confirmation', icon: Activity, color: '#06b6d4', defaultParams: { rsiPeriod: 14, overbought: 70, oversold: 30 } },
{ id: 'ZoneRule', name: 'Zone Proximity', desc: 'Price relative to EMA value zones', icon: Target, color: '#a855f7', defaultParams: { zonePercent: 1.5 } },
{ id: 'SessionRule', name: 'Session Filter', desc: 'Trade only during major sessions', icon: Clock, color: '#f59e0b', defaultParams: { sessions: 'LDN,NY' } },
{ id: 'EntryTriggerRule', name: 'Entry Trigger', desc: 'Pattern-based precise entry logic', icon: Play, color: '#10b981', defaultParams: { showPatterns: true } },
{ id: 'RiskManagementRule', name: 'Risk Guard', desc: 'ATR-based stop loss & position sizing', icon: Shield, color: '#ef4444', defaultParams: { maxRisk: 2.0 } },
{ id: 'AIAnalysisRule', name: 'AI Sentiment', desc: 'LLM-powered market analysis', icon: Cpu, color: '#8b5cf6', defaultParams: { minConfidence: 70 } }
{ id: 'TrendBiasRule', name: 'Trend Bias', desc: 'EMA50/200 direction check on 4H timeframe', icon: TrendingUp, color: 'var(--bl-info-strong)', defaultParams: { fastPeriod: 50, slowPeriod: 200 } },
{ id: 'MomentumRule', name: 'Momentum', desc: 'RSI overbought/oversold confirmation', icon: Activity, color: 'var(--bl-attention)', defaultParams: { rsiPeriod: 14, overbought: 70, oversold: 30 } },
{ id: 'ZoneRule', name: 'Zone Proximity', desc: 'Price relative to EMA value zones', icon: Target, color: 'var(--bl-emphasis)', defaultParams: { zonePercent: 1.5 } },
{ id: 'SessionRule', name: 'Session Filter', desc: 'Trade only during major sessions', icon: Clock, color: 'var(--bl-warning)', defaultParams: { sessions: 'LDN,NY' } },
{ id: 'EntryTriggerRule', name: 'Entry Trigger', desc: 'Pattern-based precise entry logic', icon: Play, color: 'var(--bl-success)', defaultParams: { showPatterns: true } },
{ id: 'RiskManagementRule', name: 'Risk Guard', desc: 'ATR-based stop loss & position sizing', icon: Shield, color: 'var(--bl-danger)', defaultParams: { maxRisk: 2.0 } },
{ id: 'AIAnalysisRule', name: 'AI Sentiment', desc: 'LLM-powered market analysis', icon: Cpu, color: 'var(--bl-emphasis)', defaultParams: { minConfidence: 70 } }
];
const SESSION_PRESET_OPTIONS = [
@ -137,6 +137,8 @@ const panelClass = 'rounded-xl border border-[var(--border)] bg-[var(--card-elev
const subtlePanelClass = 'rounded-xl border border-[var(--border)] bg-[var(--muted)]/35';
const iconButtonClass = 'h-8 w-8 rounded-xl';
const accentTextClass = 'text-[var(--accent)]';
const statSuccessClass = 'text-emerald-600 dark:text-emerald-400';
const statDangerClass = 'text-red-600 dark:text-red-400';
export const normalizeSessionPresetValue = (raw: unknown): string => {
if (raw === undefined || raw === null) return 'LDN,NY';
@ -580,10 +582,10 @@ export const TradeProfileManager = ({ botState = DEFAULT_BOT_STATE }: TradeProfi
{/* Aggregate stats */}
<div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
<StatPill icon={Layers} label="Total Profiles" value={`${activeCount} / ${profiles.length}`} color="#00ff88" />
<StatPill icon={DollarSign} label="Total Capital" value={`$${totalCapital.toLocaleString()}`} color="#3b82f6" />
<StatPill icon={BarChart3} label="Realized P&L" value={`${totalPnl >= 0 ? '+' : ''}$${totalPnl.toFixed(2)}`} color={totalPnl >= 0 ? '#00ff88' : '#ef4444'} />
<StatPill icon={Activity} label="Total Trades" value={`${totalTrades}`} color="#a855f7" />
<StatPill icon={Layers} label="Total Profiles" value={`${activeCount} / ${profiles.length}`} color="var(--bl-success)" />
<StatPill icon={DollarSign} label="Total Capital" value={`$${totalCapital.toLocaleString()}`} color="var(--bl-info-strong)" />
<StatPill icon={BarChart3} label="Realized P&L" value={`${totalPnl >= 0 ? '+' : ''}$${totalPnl.toFixed(2)}`} color={totalPnl >= 0 ? 'var(--bl-success)' : 'var(--bl-danger)'} />
<StatPill icon={Activity} label="Total Trades" value={`${totalTrades}`} color="var(--bl-emphasis)" />
</div>
</div>
@ -724,15 +726,15 @@ export const TradeProfileManager = ({ botState = DEFAULT_BOT_STATE }: TradeProfi
{/* Stats header row */}
<div className="grid grid-cols-3">
{[
{ icon: DollarSign, label: 'Capital', val: `$${p.allocated_capital.toLocaleString()}`, color: '#3b82f6', valClass: 'text-[var(--foreground)]' },
{ icon: BarChart3, label: 'Realized', val: `${stats.totalPnl >= 0 ? '+' : ''}${stats.totalPnl.toFixed(2)}`, color: stats.totalPnl >= 0 ? '#16a34a' : '#dc2626', valClass: stats.totalPnl >= 0 ? 'text-emerald-600 dark:text-emerald-400' : 'text-red-600 dark:text-red-400' },
{ icon: AlertTriangle, label: 'Risk', val: `${p.risk_per_trade_percent}%`, color: '#f59e0b', valClass: 'text-[var(--foreground)]' },
{ icon: DollarSign, label: 'Capital', val: `$${p.allocated_capital.toLocaleString()}`, color: 'var(--bl-info-strong)', valClass: 'text-[var(--foreground)]' },
{ icon: BarChart3, label: 'Realized', val: `${stats.totalPnl >= 0 ? '+' : ''}${stats.totalPnl.toFixed(2)}`, color: stats.totalPnl >= 0 ? 'var(--bl-success)' : 'var(--bl-danger)', valClass: stats.totalPnl >= 0 ? statSuccessClass : statDangerClass },
{ icon: AlertTriangle, label: 'Risk', val: `${p.risk_per_trade_percent}%`, color: 'var(--bl-warning)', valClass: 'text-[var(--foreground)]' },
].map((item, i) => (
<div key={item.label} className={cn('relative px-4 py-4 text-center', i < 2 && 'border-r border-[var(--border)]')}>
<div className="relative">
<div className="flex items-center justify-center gap-1.5 mb-1.5">
<div className="flex h-4 w-4 items-center justify-center rounded" style={{
background: `${item.color}15`,
background: `color-mix(in oklab, ${item.color} 15%, transparent)`,
}}>
<item.icon size={9} style={{ color: item.color }} />
</div>
@ -768,10 +770,10 @@ export const TradeProfileManager = ({ botState = DEFAULT_BOT_STATE }: TradeProfi
style={{
width: `${Math.max(stats.winRate, 2)}%`,
background: stats.winRate >= 50
? '#16a34a'
? 'var(--bl-success)'
: stats.winRate >= 30
? '#f59e0b'
: '#dc2626',
? 'var(--bl-warning)'
: 'var(--bl-danger)',
}}
/>
</div>
@ -1026,11 +1028,11 @@ export const TradeProfileManager = ({ botState = DEFAULT_BOT_STATE }: TradeProfi
<div
className="w-8 h-8 rounded-lg flex items-center justify-center transition-all"
style={{
background: active ? `${rule.color}15` : 'rgba(255,255,255,0.02)',
border: `1px solid ${active ? `${rule.color}30` : 'rgba(255,255,255,0.04)'}`,
background: active ? `color-mix(in oklab, ${rule.color} 15%, transparent)` : 'color-mix(in oklab, var(--foreground) 2%, transparent)',
border: `1px solid ${active ? `color-mix(in oklab, ${rule.color} 30%, transparent)` : 'color-mix(in oklab, var(--foreground) 4%, transparent)'}`,
}}
>
<Icon size={14} style={{ color: active ? rule.color : '#52525b' }} />
<Icon size={14} style={{ color: active ? rule.color : 'var(--bl-text-faint)' }} />
</div>
<div>
<div className="flex items-center gap-2 mb-0.5">