import useSWR from 'swr' import { useLanguage } from '../contexts/LanguageContext' import { t } from '../i18n/translations' import { api } from '../lib/api' import { Brain, BarChart3, TrendingUp, TrendingDown, Sparkles, Coins, Trophy, ScrollText, Lightbulb, } from 'lucide-react' interface TradeOutcome { symbol: string side: string quantity: number leverage: number open_price: number close_price: number position_value: number margin_used: number pn_l: number pn_l_pct: number duration: string open_time: string close_time: string was_stop_loss: boolean } interface SymbolPerformance { symbol: string total_trades: number winning_trades: number losing_trades: number win_rate: number total_pn_l: number avg_pn_l: number } interface PerformanceAnalysis { total_trades: number winning_trades: number losing_trades: number win_rate: number avg_win: number avg_loss: number profit_factor: number sharpe_ratio: number recent_trades: TradeOutcome[] symbol_stats: { [key: string]: SymbolPerformance } best_symbol: string worst_symbol: string } interface AILearningProps { traderId: string } export default function AILearning({ traderId }: AILearningProps) { const { language } = useLanguage() const { data: performance, error } = useSWR( traderId ? `performance-${traderId}` : 'performance', () => api.getPerformance(traderId), { refreshInterval: 30000, // 30秒刷新(AI学习分析数据更新频率较低) revalidateOnFocus: false, dedupingInterval: 20000, } ) if (error) { return (
{t('loadingError', language)}
) } if (!performance) { return (
{t('loading', language)}
) } if (!performance || performance.total_trades === 0) { return (

{t('aiLearning', language)}

{t('noCompleteData', language)}
) } const symbolStats = performance.symbol_stats || {} const symbolStatsList = Object.values(symbolStats) .filter((stat) => stat != null) .sort((a, b) => (b.total_pn_l || 0) - (a.total_pn_l || 0)) return (
{/* 标题区 - 优化设计 */}

{t('aiLearning', language)}

{t('tradesAnalyzed', language, { count: performance.total_trades, })}

{/* 核心指标卡片 - 4列网格 */}
{/* 总交易数 */}
{t('totalTrades', language)}
{performance.total_trades}
Trades
{/* 胜率 */}
= 50 ? 'linear-gradient(135deg, rgba(16, 185, 129, 0.2) 0%, rgba(30, 35, 41, 0.8) 100%)' : 'linear-gradient(135deg, rgba(248, 113, 113, 0.2) 0%, rgba(30, 35, 41, 0.8) 100%)', border: `1px solid ${(performance.win_rate || 0) >= 50 ? 'rgba(16, 185, 129, 0.4)' : 'rgba(248, 113, 113, 0.4)'}`, boxShadow: `0 4px 16px ${(performance.win_rate || 0) >= 50 ? 'rgba(16, 185, 129, 0.2)' : 'rgba(248, 113, 113, 0.2)'}`, }} >
= 50 ? '#10B981' : '#F87171'} 0%, transparent 70%)`, filter: 'blur(20px)', }} />
= 50 ? '#6EE7B7' : '#FCA5A5', }} > {t('winRate', language)}
= 50 ? '#10B981' : '#F87171', }} > {(performance.win_rate || 0).toFixed(1)}%
{performance.winning_trades || 0}W /{' '} {performance.losing_trades || 0}L
{/* 平均盈利 */}
{t('avgWin', language)}
+{(performance.avg_win || 0).toFixed(2)}
USDT Average
{/* 平均亏损 */}
{t('avgLoss', language)}
{(performance.avg_loss || 0).toFixed(2)}
USDT Average
{/* 关键指标:夏普比率 & 盈亏比 - 2列网格 */}
{/* 夏普比率 */}
夏普比率
风险调整后收益 · AI自我进化指标
= 2 ? '#10B981' : (performance.sharpe_ratio || 0) >= 1 ? '#22D3EE' : (performance.sharpe_ratio || 0) >= 0 ? '#F0B90B' : '#F87171', textShadow: '0 4px 12px rgba(0, 0, 0, 0.3)', }} > {performance.sharpe_ratio ? performance.sharpe_ratio.toFixed(2) : 'N/A'}
{performance.sharpe_ratio !== undefined && (
= 2 ? '#10B981' : (performance.sharpe_ratio || 0) >= 1 ? '#22D3EE' : (performance.sharpe_ratio || 0) >= 0 ? '#F0B90B' : '#F87171', background: (performance.sharpe_ratio || 0) >= 2 ? 'rgba(16, 185, 129, 0.2)' : (performance.sharpe_ratio || 0) >= 1 ? 'rgba(34, 211, 238, 0.2)' : (performance.sharpe_ratio || 0) >= 0 ? 'rgba(240, 185, 11, 0.2)' : 'rgba(248, 113, 113, 0.2)', }} > {performance.sharpe_ratio >= 2 ? '🟢 卓越表现' : performance.sharpe_ratio >= 1 ? '🟢 良好表现' : performance.sharpe_ratio >= 0 ? '🟡 波动较大' : '🔴 需要调整'}
)}
{performance.sharpe_ratio !== undefined && (
{performance.sharpe_ratio >= 2 && '✨ AI策略非常有效!风险调整后收益优异,可适度扩大仓位但保持纪律。'} {performance.sharpe_ratio >= 1 && performance.sharpe_ratio < 2 && '✅ 策略表现稳健,风险收益平衡良好,继续保持当前策略。'} {performance.sharpe_ratio >= 0 && performance.sharpe_ratio < 1 && '⚠️ 收益为正但波动较大,AI正在优化策略,降低风险。'} {performance.sharpe_ratio < 0 && '🚨 当前策略需要调整!AI已自动进入保守模式,减少仓位和交易频率。'}
)}
{/* 盈亏比 */}
{t('profitFactor', language)}
{t('avgWinDivLoss', language)}
= 2.0 ? '#10B981' : (performance.profit_factor || 0) >= 1.5 ? '#F0B90B' : (performance.profit_factor || 0) >= 1.0 ? '#FB923C' : '#F87171', textShadow: '0 4px 12px rgba(0, 0, 0, 0.3)', }} > {(performance.profit_factor || 0) > 0 ? (performance.profit_factor || 0).toFixed(2) : 'N/A'}
= 2.0 ? '#10B981' : (performance.profit_factor || 0) >= 1.5 ? '#F0B90B' : '#94A3B8', background: (performance.profit_factor || 0) >= 2.0 ? 'rgba(16, 185, 129, 0.2)' : (performance.profit_factor || 0) >= 1.5 ? 'rgba(240, 185, 11, 0.2)' : 'rgba(148, 163, 184, 0.2)', }} > {(performance.profit_factor || 0) >= 2.0 && t('excellent', language)} {(performance.profit_factor || 0) >= 1.5 && (performance.profit_factor || 0) < 2.0 && t('good', language)} {(performance.profit_factor || 0) >= 1.0 && (performance.profit_factor || 0) < 1.5 && t('fair', language)} {(performance.profit_factor || 0) > 0 && (performance.profit_factor || 0) < 1.0 && t('poor', language)}
{(performance.profit_factor || 0) >= 2.0 && '🔥 盈利能力出色!每亏1元能赚' + (performance.profit_factor || 0).toFixed(1) + '元,AI策略表现优异。'} {(performance.profit_factor || 0) >= 1.5 && (performance.profit_factor || 0) < 2.0 && '✓ 策略稳定盈利,盈亏比健康,继续保持纪律性交易。'} {(performance.profit_factor || 0) >= 1.0 && (performance.profit_factor || 0) < 1.5 && '⚠️ 策略略有盈利但需优化,AI正在调整仓位和止损策略。'} {(performance.profit_factor || 0) > 0 && (performance.profit_factor || 0) < 1.0 && '❌ 平均亏损大于盈利,需要调整策略或降低交易频率。'}
{/* 最佳/最差币种 - 独立行 */} {(performance.best_symbol || performance.worst_symbol) && (
{performance.best_symbol && (
{t('bestPerformer', language)}
{performance.best_symbol}
{symbolStats[performance.best_symbol] && (
{symbolStats[performance.best_symbol].total_pn_l > 0 ? '+' : ''} {symbolStats[performance.best_symbol].total_pn_l.toFixed(2)}{' '} USDT {t('pnl', language)}
)}
)} {performance.worst_symbol && (
{t('worstPerformer', language)}
{performance.worst_symbol}
{symbolStats[performance.worst_symbol] && (
{symbolStats[performance.worst_symbol].total_pn_l > 0 ? '+' : ''} {symbolStats[performance.worst_symbol].total_pn_l.toFixed(2)}{' '} USDT {t('pnl', language)}
)}
)}
)} {/* 币种表现 & 历史成交 - 左右分屏 2列布局 */}
{/* 左侧:币种表现统计表格 */} {symbolStatsList.length > 0 && (

{' '} {t('symbolPerformance', language)}

{symbolStatsList.map((stat, idx) => ( 0 ? '1px solid rgba(99, 102, 241, 0.1)' : 'none', }} > ))}
Symbol Trades Win Rate Total P&L (USDT) Avg P&L (USDT)
{stat.symbol} {stat.total_trades} = 50 ? '#10B981' : '#F87171', }} > {(stat.win_rate || 0).toFixed(1)}% 0 ? '#10B981' : '#F87171', }} > {(stat.total_pn_l || 0) > 0 ? '+' : ''} {(stat.total_pn_l || 0).toFixed(2)} 0 ? '#10B981' : '#F87171', }} > {(stat.avg_pn_l || 0) > 0 ? '+' : ''} {(stat.avg_pn_l || 0).toFixed(2)}
)} {/* 右侧:历史成交记录 */}

{t('tradeHistory', language)}

{performance?.recent_trades && performance.recent_trades.length > 0 ? t('completedTrades', language, { count: performance.recent_trades.length, }) : t('completedTradesWillAppear', language)}

{performance?.recent_trades && performance.recent_trades.length > 0 ? ( performance.recent_trades.map( (trade: TradeOutcome, idx: number) => { const isProfitable = trade.pn_l >= 0 const isRecent = idx === 0 return (
{trade.symbol} {trade.side.toUpperCase()} {isRecent && ( {t('latest', language)} )}
{isProfitable ? '+' : ''} {trade.pn_l_pct.toFixed(2)}%
{t('entry', language)}
{trade.open_price.toFixed(4)}
{t('exit', language)}
{trade.close_price.toFixed(4)}
{/* Position Details */}
Quantity
{trade.quantity ? trade.quantity.toFixed(4) : '-'}
Leverage
{trade.leverage ? `${trade.leverage}x` : '-'}
Position Value
{trade.position_value ? `$${trade.position_value.toFixed(2)}` : '-'}
Margin Used
{trade.margin_used ? `$${trade.margin_used.toFixed(2)}` : '-'}
P&L {isProfitable ? '+' : ''} {trade.pn_l.toFixed(2)} USDT
⏱️ {formatDuration(trade.duration)} {trade.was_stop_loss && ( {t('stopLoss', language)} )}
{new Date(trade.close_time).toLocaleString('en-US', { month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit', })}
) } ) ) : (
{t('noCompletedTrades', language)}
)}
{/* AI学习说明 - 现代化设计 */}

{t('howAILearns', language)}

{t('aiLearningPoint1', language)}
{t('aiLearningPoint2', language)}
{t('aiLearningPoint3', language)}
{t('aiLearningPoint4', language)}
) } // 格式化持仓时长 function formatDuration(duration: string | undefined): string { if (!duration) return '-' const match = duration.match(/(\d+h)?(\d+m)?(\d+\.?\d*s)?/) if (!match) return duration const hours = match[1] || '' const minutes = match[2] || '' const seconds = match[3] || '' let result = '' if (hours) result += hours.replace('h', '小时') if (minutes) result += minutes.replace('m', '分') if (!hours && seconds) result += seconds.replace(/(\d+)\.?\d*s/, '$1秒') return result || duration }