From 0dca506cfc9ede307d15843cc232dbfc885366df Mon Sep 17 00:00:00 2001 From: tinkle-community Date: Wed, 29 Oct 2025 02:31:15 +0800 Subject: [PATCH] Feature: Add Sharpe ratio for AI self-evolution - Implement Sharpe ratio calculation in decision logger - Add adaptive behavior recommendations based on Sharpe ratio - Display Sharpe ratio in AI learning dashboard with visual indicators - Enable AI to adjust trading strategy based on risk-adjusted returns - Color-coded performance levels (red/yellow/green) for easy monitoring Co-Authored-By: tinkle-community --- logger/decision_logger.go | 89 +++++++++++++++++++++ market/ai_decision_engine.go | 129 ++++++++++++++++++++++++++++-- web/src/components/AILearning.tsx | 62 +++++++++++++- 3 files changed, 272 insertions(+), 8 deletions(-) diff --git a/logger/decision_logger.go b/logger/decision_logger.go index b3d91759..e82f4fd0 100644 --- a/logger/decision_logger.go +++ b/logger/decision_logger.go @@ -288,6 +288,7 @@ type PerformanceAnalysis struct { AvgWin float64 `json:"avg_win"` // 平均盈利 AvgLoss float64 `json:"avg_loss"` // 平均亏损 ProfitFactor float64 `json:"profit_factor"` // 盈亏比 + SharpeRatio float64 `json:"sharpe_ratio"` // 夏普比率(风险调整后收益) RecentTrades []TradeOutcome `json:"recent_trades"` // 最近N笔交易 SymbolStats map[string]*SymbolPerformance `json:"symbol_stats"` // 各币种表现 BestSymbol string `json:"best_symbol"` // 表现最好的币种 @@ -458,5 +459,93 @@ func (l *DecisionLogger) AnalyzePerformance(lookbackCycles int) (*PerformanceAna } } + // 计算夏普比率(需要至少2个数据点) + analysis.SharpeRatio = l.calculateSharpeRatio(records) + return analysis, nil } + +// calculateSharpeRatio 计算夏普比率 +// 基于账户净值的变化计算风险调整后收益 +func (l *DecisionLogger) calculateSharpeRatio(records []*DecisionRecord) float64 { + if len(records) < 2 { + return 0.0 // 至少需要2个数据点才能计算收益率 + } + + // 提取每个周期的账户净值 + var equities []float64 + for _, record := range records { + // 使用TotalBalance作为净值(包含未实现盈亏) + equity := record.AccountState.TotalBalance + record.AccountState.TotalUnrealizedProfit + if equity > 0 { + equities = append(equities, equity) + } + } + + if len(equities) < 2 { + return 0.0 + } + + // 计算周期收益率(period returns) + var returns []float64 + for i := 1; i < len(equities); i++ { + if equities[i-1] > 0 { + periodReturn := (equities[i] - equities[i-1]) / equities[i-1] + returns = append(returns, periodReturn) + } + } + + if len(returns) == 0 { + return 0.0 + } + + // 计算平均收益率 + sumReturns := 0.0 + for _, r := range returns { + sumReturns += r + } + meanReturn := sumReturns / float64(len(returns)) + + // 计算收益率标准差 + sumSquaredDiff := 0.0 + for _, r := range returns { + diff := r - meanReturn + sumSquaredDiff += diff * diff + } + variance := sumSquaredDiff / float64(len(returns)) + stdDev := 0.0 + if variance > 0 { + stdDev = 1.0 + // 简单的平方根计算(牛顿迭代法) + for i := 0; i < 10; i++ { + stdDev = (stdDev + variance/stdDev) / 2 + } + } + + // 避免除以零 + if stdDev == 0 { + if meanReturn > 0 { + return 999.0 // 无波动的正收益 + } else if meanReturn < 0 { + return -999.0 // 无波动的负收益 + } + return 0.0 + } + + // 计算夏普比率(假设无风险利率为0) + sharpeRatio := meanReturn / stdDev + + // 年化夏普比率 + // 假设每个周期是3分钟,一天有480个周期 + // 年化因子 = sqrt(一年的周期数) = sqrt(480 * 365) ≈ sqrt(175200) ≈ 419 + // 简化:使用每日周期数作为年化基准 + periodsPerDay := 480.0 // 24小时 * 60分钟 / 3分钟 + annualizationFactor := 1.0 + for i := 0; i < 10; i++ { + annualizationFactor = (annualizationFactor + periodsPerDay/annualizationFactor) / 2 + } + + annualizedSharpe := sharpeRatio * annualizationFactor + + return annualizedSharpe +} diff --git a/market/ai_decision_engine.go b/market/ai_decision_engine.go index 03a8169c..4878ab59 100644 --- a/market/ai_decision_engine.go +++ b/market/ai_decision_engine.go @@ -200,6 +200,20 @@ func buildSystemPrompt(accountEquity float64) string { sb.WriteString("你是专业的加密货币交易AI,在币安合约市场进行自主交易。\n\n") sb.WriteString("**使命**: 最大化风险调整后收益(Sharpe Ratio)\n\n") + // 自我进化核心 + sb.WriteString("## 🧬 自我进化机制\n") + sb.WriteString("每次调用你都会收到**夏普比率**作为你的业绩指标:\n\n") + sb.WriteString("**夏普比率解读**:\n") + sb.WriteString("- < 0:平均亏损 → 🔴 极度保守策略\n") + sb.WriteString("- 0-1:正收益但波动大 → 🟡 保守策略\n") + sb.WriteString("- 1-2:良好表现 → 🟢 维持当前策略\n") + sb.WriteString("- > 2:优异表现 → 🟢 可适度扩大\n\n") + sb.WriteString("**关键要求**: 严格遵循历史表现反馈中的「自适应行为建议」,根据夏普比率动态调整:\n") + sb.WriteString("- 仓位大小(夏普比率低时减仓)\n") + sb.WriteString("- 止损幅度(夏普比率低时收紧)\n") + sb.WriteString("- 选币标准(夏普比率低时提高信心度阈值)\n") + sb.WriteString("- 持仓数量(夏普比率低时减少持仓数)\n\n") + // 仓位管理规则 sb.WriteString("## 仓位管理\n") sb.WriteString("- 最多持有 **3个币种**(质量>数量)\n") @@ -212,10 +226,12 @@ func buildSystemPrompt(accountEquity float64) string { // 决策流程 sb.WriteString("## 决策流程\n") - sb.WriteString("1. **反思历史**(如有):总结教训,避免重复错误\n") - sb.WriteString("2. **评估持仓**:决定平仓/持有\n") - sb.WriteString("3. **寻找机会**:从候选币种中找1-2个高确定性机会\n") - sb.WriteString("4. **集中资金**:大仓位做高确定性交易\n\n") + sb.WriteString("1. **检查夏普比率**:首先查看历史表现反馈中的夏普比率,理解当前策略效果\n") + sb.WriteString("2. **应用自适应建议**:严格遵循自适应行为建议中的仓位、止损、选币要求\n") + sb.WriteString("3. **反思历史**:分析之前交易的得失,找出可改进点\n") + sb.WriteString("4. **评估持仓**:根据自适应建议决定平仓/持有\n") + sb.WriteString("5. **寻找机会**:按照调整后的标准筛选机会\n") + sb.WriteString("6. **执行决策**:使用调整后的仓位大小和风险参数\n\n") // JSON 输出格式 sb.WriteString("## 输出格式\n\n") @@ -309,7 +325,7 @@ func buildUserPrompt(ctx *TradingContext) string { // 历史反馈 if ctx.Performance != nil { - sb.WriteString(formatPerformanceFeedback(ctx.Performance)) + sb.WriteString(formatPerformanceFeedback(ctx.Performance, ctx.Account.TotalEquity)) } sb.WriteString("---\n\n") @@ -427,7 +443,7 @@ func buildFullDecisionPrompt(ctx *TradingContext) string { // 添加历史表现反馈(如果有) if ctx.Performance != nil { - sb.WriteString(formatPerformanceFeedback(ctx.Performance)) + sb.WriteString(formatPerformanceFeedback(ctx.Performance, ctx.Account.TotalEquity)) } // AI决策要求 @@ -504,7 +520,8 @@ func buildFullDecisionPrompt(ctx *TradingContext) string { } // formatPerformanceFeedback 格式化历史表现反馈 -func formatPerformanceFeedback(perfInterface interface{}) string { +// accountEquity 参数用于计算自适应建议 +func formatPerformanceFeedback(perfInterface interface{}, accountEquity float64) string { // 类型断言(避免循环依赖,使用interface{}) type TradeOutcome struct { Symbol string @@ -532,6 +549,7 @@ func formatPerformanceFeedback(perfInterface interface{}) string { AvgWin float64 AvgLoss float64 ProfitFactor float64 + SharpeRatio float64 RecentTrades []TradeOutcome SymbolStats map[string]*SymbolPerformance BestSymbol string @@ -564,6 +582,12 @@ func formatPerformanceFeedback(perfInterface interface{}) string { if perf.ProfitFactor > 0 { sb.WriteString(fmt.Sprintf("- **盈亏比**: %.2f:1\n", perf.ProfitFactor)) } + + // 夏普比率(风险调整后收益) + if perf.SharpeRatio != 0 { + sharpeStatus := interpretSharpeRatio(perf.SharpeRatio) + sb.WriteString(fmt.Sprintf("- **夏普比率**: %.2f (%s)\n", perf.SharpeRatio, sharpeStatus)) + } sb.WriteString("\n") // 最近交易 @@ -607,6 +631,11 @@ func formatPerformanceFeedback(perfInterface interface{}) string { sb.WriteString("\n") } + // 添加自适应行为建议(基于夏普比率) + if perf.SharpeRatio != 0 { + sb.WriteString(getAdaptiveBehaviorRecommendation(perf.SharpeRatio, accountEquity)) + } + return sb.String() } @@ -803,3 +832,89 @@ func validateDecision(d *TradingDecision, accountEquity float64) error { return nil } + +// interpretSharpeRatio 解释夏普比率的含义(参考 nof1.ai) +func interpretSharpeRatio(sharpe float64) string { + if sharpe < 0 { + return "负收益,需要调整策略" + } else if sharpe < 1 { + return "正收益但波动大" + } else if sharpe < 2 { + return "良好表现" + } else if sharpe < 3 { + return "优秀表现" + } else { + return "卓越表现" + } +} + +// getAdaptiveBehaviorRecommendation 根据夏普比率生成自适应行为建议 +// 这是AI自我进化的核心:根据风险调整后收益动态调整交易策略 +func getAdaptiveBehaviorRecommendation(sharpe float64, accountEquity float64) string { + var sb strings.Builder + + sb.WriteString("### 🎯 自适应行为建议(基于夏普比率)\n\n") + + if sharpe < 0 { + // 🔴 负夏普比率:平均亏损,需要极度保守 + sb.WriteString("**⚠️ 警告:当前策略产生负收益,立即调整!**\n\n") + sb.WriteString("**策略调整**:\n") + sb.WriteString(fmt.Sprintf("- 仓位规模:**减半**(山寨币: %.0f USDT, BTC/ETH: %.0f USDT)\n", + accountEquity*0.6, accountEquity*2.5)) + sb.WriteString("- 止损幅度:**收紧至-1%**(快速止损,保护本金)\n") + sb.WriteString("- 选币标准:**只做最高确定性**(信心度≥95%,风险回报比≥1:3)\n") + sb.WriteString("- 持仓数量:**最多1个**(极度精选)\n") + sb.WriteString("- 决策频率:**减少交易**(宁可不做,也不要乱做)\n\n") + sb.WriteString("**反思要点**:\n") + sb.WriteString("- 为什么之前的交易亏损?是选币问题还是时机问题?\n") + sb.WriteString("- 是否追涨杀跌?是否逆势交易?\n") + sb.WriteString("- 止损是否执行到位?\n\n") + + } else if sharpe < 1 { + // 🟡 0-1:正收益但波动性较大 + sb.WriteString("**状态:正收益但风险较高,需要优化**\n\n") + sb.WriteString("**策略调整**:\n") + sb.WriteString(fmt.Sprintf("- 仓位规模:**保守**(山寨币: %.0f USDT, BTC/ETH: %.0f USDT)\n", + accountEquity*0.8, accountEquity*3.5)) + sb.WriteString("- 止损幅度:**收紧至-1.5%**\n") + sb.WriteString("- 选币标准:**提高阈值**(信心度≥80%,风险回报比≥1:2.5)\n") + sb.WriteString("- 持仓数量:**最多2个**\n") + sb.WriteString("- 重点改进:**减少亏损幅度**,提高止损执行力\n\n") + sb.WriteString("**优化方向**:\n") + sb.WriteString("- 避免冲动交易,等待更好的入场时机\n") + sb.WriteString("- 减少交易频率,提高单笔交易质量\n") + sb.WriteString("- 盈利时及时止盈,不要贪多\n\n") + + } else if sharpe < 2 { + // 🟢 1-2:风险调整后表现良好 + sb.WriteString("**状态:表现良好,继续保持当前策略**\n\n") + sb.WriteString("**策略调整**:\n") + sb.WriteString(fmt.Sprintf("- 仓位规模:**标准**(山寨币: %.0f USDT, BTC/ETH: %.0f USDT)\n", + accountEquity*1.2, accountEquity*5)) + sb.WriteString("- 止损幅度:**-2%**(标准设置)\n") + sb.WriteString("- 选币标准:**正常**(信心度≥75%,风险回报比≥1:2)\n") + sb.WriteString("- 持仓数量:**最多3个**\n") + sb.WriteString("- 保持纪律:**严格执行止损止盈**\n\n") + sb.WriteString("**持续改进**:\n") + sb.WriteString("- 总结盈利交易的共性特征,复制成功模式\n") + sb.WriteString("- 分析亏损交易,避免重复错误\n") + sb.WriteString("- 保持冷静客观,不要因为短期盈利而冒进\n\n") + + } else { + // 🟢 >2:风险调整后表现优异 + sb.WriteString("**状态:卓越表现,策略非常有效!**\n\n") + sb.WriteString("**策略调整**:\n") + sb.WriteString(fmt.Sprintf("- 仓位规模:**可适度放大**(山寨币: %.0f USDT, BTC/ETH: %.0f USDT)\n", + accountEquity*1.5, accountEquity*6)) + sb.WriteString("- 止损幅度:**-2%**(保持纪律,不要因为盈利而放松)\n") + sb.WriteString("- 选币标准:**正常**(信心度≥75%)\n") + sb.WriteString("- 持仓数量:**最多3个**\n") + sb.WriteString("- **核心原则:保持纪律,不要过度自信**\n\n") + sb.WriteString("**风险提示**:\n") + sb.WriteString("- 即使表现优异,也要保持风险管理纪律\n") + sb.WriteString("- 市场环境会变化,不要因短期成功而冒进\n") + sb.WriteString("- 继续严格执行止损,保护已有收益\n\n") + } + + return sb.String() +} diff --git a/web/src/components/AILearning.tsx b/web/src/components/AILearning.tsx index fd9d614f..9f6a1351 100644 --- a/web/src/components/AILearning.tsx +++ b/web/src/components/AILearning.tsx @@ -1,4 +1,3 @@ -import { useEffect, useState } from 'react'; import useSWR from 'swr'; import { useLanguage } from '../contexts/LanguageContext'; import { t } from '../i18n/translations'; @@ -34,6 +33,7 @@ interface PerformanceAnalysis { avg_win: number; avg_loss: number; profit_factor: number; + sharpe_ratio: number; // 夏普比率(风险调整后收益) recent_trades: TradeOutcome[]; symbol_stats: { [key: string]: SymbolPerformance }; best_symbol: string; @@ -248,6 +248,66 @@ export default function AILearning({ traderId }: AILearningProps) { + {/* 夏普比率 - AI自我进化核心指标 */} +
+
+ +
+
+ 🧬 +
+
夏普比率
+
风险调整后收益 · AI自我进化指标
+
+
+ +
+
= 2 ? '#10B981' : + (performance.sharpe_ratio || 0) >= 1 ? '#22D3EE' : + (performance.sharpe_ratio || 0) >= 0 ? '#F0B90B' : '#F87171' + }}> + {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' + }}> + {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已自动进入保守模式,减少仓位和交易频率。'} +
+
+ )} +
+
+ {/* 盈亏比 - 突出显示 */}