Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions web/src/components/ComparisonChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,13 @@ export function ComparisonChart({ traders }: ComparisonChartProps) {
});
}

// 计算盈亏百分比:从total_pnl和balance计算
// 假设初始余额 = balance - total_pnl
const initialBalance = point.balance - point.total_pnl;
const pnlPct = initialBalance > 0 ? (point.total_pnl / initialBalance) * 100 : 0;

timestampMap.get(ts)!.traders.set(trader.trader_id, {
pnl_pct: point.total_pnl_pct,
pnl_pct: pnlPct,
equity: point.total_equity
});
});
Expand Down Expand Up @@ -228,7 +233,23 @@ export function ComparisonChart({ traders }: ComparisonChartProps) {

return (
<div>
<div style={{ borderRadius: '8px', overflow: 'hidden' }}>
<div style={{ borderRadius: '8px', overflow: 'hidden', position: 'relative' }}>
{/* NOFX Watermark */}
<div
style={{
position: 'absolute',
top: '20px',
right: '20px',
fontSize: '24px',
fontWeight: 'bold',
color: 'rgba(240, 185, 11, 0.15)',
zIndex: 10,
pointerEvents: 'none',
fontFamily: 'monospace'
}}
>
NOFX
</div>
<ResponsiveContainer width="100%" height={520}>
<LineChart data={displayData} margin={{ top: 20, right: 30, left: 20, bottom: 40 }}>
<defs>
Expand Down
43 changes: 42 additions & 1 deletion web/src/components/CompetitionPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function CompetitionPage() {
setSelectedTrader(null);
};

if (!competition || !competition.traders) {
if (!competition) {
return (
<div className="space-y-6">
<div className="binance-card p-8 animate-pulse">
Expand All @@ -64,6 +64,47 @@ export function CompetitionPage() {
);
}

// 如果有数据返回但没有交易员,显示空状态
if (!competition.traders || competition.traders.length === 0) {
return (
<div className="space-y-5 animate-fade-in">
{/* Competition Header - 精简版 */}
<div className="flex flex-col md:flex-row items-start md:items-center justify-between gap-3 md:gap-0">
<div className="flex items-center gap-3 md:gap-4">
<div className="w-10 h-10 md:w-12 md:h-12 rounded-xl flex items-center justify-center" style={{
background: 'linear-gradient(135deg, #F0B90B 0%, #FCD535 100%)',
boxShadow: '0 4px 14px rgba(240, 185, 11, 0.4)'
}}>
<Trophy className="w-6 h-6 md:w-7 md:h-7" style={{ color: '#000' }} />
</div>
<div>
<h1 className="text-xl md:text-2xl font-bold flex items-center gap-2" style={{ color: '#EAECEF' }}>
{t('aiCompetition', language)}
<span className="text-xs font-normal px-2 py-1 rounded" style={{ background: 'rgba(240, 185, 11, 0.15)', color: '#F0B90B' }}>
0 {t('traders', language)}
</span>
</h1>
<p className="text-xs" style={{ color: '#848E9C' }}>
{t('liveBattle', language)}
</p>
</div>
</div>
</div>

{/* Empty State */}
<div className="binance-card p-8 text-center">
<Trophy className="w-16 h-16 mx-auto mb-4 opacity-40" style={{ color: '#848E9C' }} />
<h3 className="text-lg font-bold mb-2" style={{ color: '#EAECEF' }}>
{t('noTraders', language)}
</h3>
<p className="text-sm" style={{ color: '#848E9C' }}>
{t('createFirstTrader', language)}
</p>
</div>
</div>
);
}

// 按收益率排序
const sortedTraders = [...competition.traders].sort(
(a, b) => b.total_pnl_pct - a.total_pnl_pct
Expand Down
18 changes: 17 additions & 1 deletion web/src/components/EquityChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,23 @@ export function EquityChart({ traderId }: EquityChartProps) {
</div>

{/* Chart */}
<div className='my-2' style={{ borderRadius: '8px', overflow: 'hidden' }}>
<div className='my-2' style={{ borderRadius: '8px', overflow: 'hidden', position: 'relative' }}>
{/* NOFX Watermark */}
<div
style={{
position: 'absolute',
top: '15px',
right: '15px',
fontSize: '20px',
fontWeight: 'bold',
color: 'rgba(240, 185, 11, 0.15)',
zIndex: 10,
pointerEvents: 'none',
fontFamily: 'monospace'
}}
>
NOFX
</div>
<ResponsiveContainer width='100%' height={280}>
<LineChart
data={chartData}
Expand Down