import useSWR from 'swr'; import { api } from '../lib/api'; import type { CompetitionData } from '../types'; import { ComparisonChart } from './ComparisonChart'; export function CompetitionPage() { const { data: competition } = useSWR( 'competition', api.getCompetition, { refreshInterval: 15000, // 15秒刷新(竞赛数据不需要太频繁更新) revalidateOnFocus: false, dedupingInterval: 10000, } ); if (!competition || !competition.traders) { return (
); } // 按收益率排序 const sortedTraders = [...competition.traders].sort( (a, b) => b.total_pnl_pct - a.total_pnl_pct ); // 找出领先者 const leader = sortedTraders[0]; return (
{/* Competition Header - 精简版 */}
🏆

AI竞赛 {competition.count} 交易员

实时对战

领先者
{leader?.trader_name}
= 0 ? '#0ECB81' : '#F6465D' }}> {(leader?.total_pnl ?? 0) >= 0 ? '+' : ''}{leader?.total_pnl_pct?.toFixed(2) || '0.00'}%
{/* Left/Right Split: Performance Chart + Leaderboard */}
{/* Left: Performance Comparison Chart */}

表现对比

实时收益率
{/* Right: Leaderboard */}

排行榜

实时
{sortedTraders.map((trader, index) => { const isLeader = index === 0; const aiModelColor = trader.ai_model === 'qwen' ? '#c084fc' : '#60a5fa'; return (
{/* Rank & Name */}
{index === 0 ? '🥇' : index === 1 ? '🥈' : '🥉'}
{trader.trader_name}
{trader.ai_model.toUpperCase()}
{/* Stats */}
{/* Total Equity */}
权益
{trader.total_equity?.toFixed(2) || '0.00'}
{/* P&L */}
收益
= 0 ? '#0ECB81' : '#F6465D' }} > {(trader.total_pnl ?? 0) >= 0 ? '+' : ''} {trader.total_pnl_pct?.toFixed(2) || '0.00'}%
{(trader.total_pnl ?? 0) >= 0 ? '+' : ''}{trader.total_pnl?.toFixed(2) || '0.00'}
{/* Positions */}
持仓
{trader.position_count}
{trader.margin_used_pct.toFixed(1)}%
{/* Status */}
{trader.is_running ? '●' : '○'}
); })}
{/* Head-to-Head Stats */} {competition.traders.length === 2 && (

正面对决

{sortedTraders.map((trader, index) => { const isWinning = index === 0; const opponent = sortedTraders[1 - index]; const gap = trader.total_pnl_pct - opponent.total_pnl_pct; return (
{trader.trader_name}
= 0 ? '#0ECB81' : '#F6465D' }}> {(trader.total_pnl ?? 0) >= 0 ? '+' : ''}{trader.total_pnl_pct?.toFixed(2) || '0.00'}%
{isWinning && gap > 0 && (
领先 {gap.toFixed(2)}%
)} {!isWinning && gap < 0 && (
落后 {Math.abs(gap).toFixed(2)}%
)}
); })}
)}
); }