Files
nofx/market/ai_decision_engine.go
tinkle-community ceaedca253 Refactor: Improve AI decision system and Sharpe ratio calculation
Major improvements:
- Use period-level Sharpe ratio (range -2 to +2) instead of annualized
- Save full user prompt in decision logs for debugging
- Format complete market data (3m + 4h candles) for AI analysis
- Prevent position stacking with duplicate position checks
- Update Sharpe ratio interpretation thresholds
Market data enhancements:
- Display full technical indicators in user prompt
- Include 3-minute and 4-hour timeframe data
- Add OI (Open Interest) change and funding rate signals
Risk control:
- Block opening duplicate positions (same symbol + direction)
- Suggest close action first before opening new position
- Prevent margin usage from exceeding limits
UI improvements:
- Update multi-language translations
- Refine AI learning dashboard display
Co-Authored-By: tinkle-community <tinklefund@gmail.com>
2025-10-29 04:44:17 +08:00

614 lines
24 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package market
import (
"encoding/json"
"fmt"
"log"
"nofx/pool"
"strings"
"time"
)
// PositionInfo 持仓信息
type PositionInfo struct {
Symbol string `json:"symbol"`
Side string `json:"side"` // "long" or "short"
EntryPrice float64 `json:"entry_price"`
MarkPrice float64 `json:"mark_price"`
Quantity float64 `json:"quantity"`
Leverage int `json:"leverage"`
UnrealizedPnL float64 `json:"unrealized_pnl"`
UnrealizedPnLPct float64 `json:"unrealized_pnl_pct"`
LiquidationPrice float64 `json:"liquidation_price"`
MarginUsed float64 `json:"margin_used"`
}
// AccountInfo 账户信息
type AccountInfo struct {
TotalEquity float64 `json:"total_equity"` // 账户净值
AvailableBalance float64 `json:"available_balance"` // 可用余额
TotalPnL float64 `json:"total_pnl"` // 总盈亏
TotalPnLPct float64 `json:"total_pnl_pct"` // 总盈亏百分比
MarginUsed float64 `json:"margin_used"` // 已用保证金
MarginUsedPct float64 `json:"margin_used_pct"` // 保证金使用率
PositionCount int `json:"position_count"` // 持仓数量
}
// CandidateCoin 候选币种(来自币种池)
type CandidateCoin struct {
Symbol string `json:"symbol"`
Sources []string `json:"sources"` // 来源: "ai500" 和/或 "oi_top"
}
// OITopData 持仓量增长Top数据用于AI决策参考
type OITopData struct {
Rank int // OI Top排名
OIDeltaPercent float64 // 持仓量变化百分比1小时
OIDeltaValue float64 // 持仓量变化价值
PriceDeltaPercent float64 // 价格变化百分比
NetLong float64 // 净多仓
NetShort float64 // 净空仓
}
// TradingContext 交易上下文传递给AI的完整信息
type TradingContext struct {
CurrentTime string `json:"current_time"`
RuntimeMinutes int `json:"runtime_minutes"`
CallCount int `json:"call_count"`
Account AccountInfo `json:"account"`
Positions []PositionInfo `json:"positions"`
CandidateCoins []CandidateCoin `json:"candidate_coins"`
MarketDataMap map[string]*MarketData `json:"-"` // 不序列化,但内部使用
OITopDataMap map[string]*OITopData `json:"-"` // OI Top数据映射
Performance interface{} `json:"-"` // 历史表现分析logger.PerformanceAnalysis
}
// TradingDecision AI的交易决策
type TradingDecision struct {
Symbol string `json:"symbol"`
Action string `json:"action"` // "open_long", "open_short", "close_long", "close_short", "hold", "wait"
Leverage int `json:"leverage,omitempty"`
PositionSizeUSD float64 `json:"position_size_usd,omitempty"`
StopLoss float64 `json:"stop_loss,omitempty"`
TakeProfit float64 `json:"take_profit,omitempty"`
Confidence int `json:"confidence,omitempty"` // 信心度 (0-100)
RiskUSD float64 `json:"risk_usd,omitempty"` // 最大美元风险
Reasoning string `json:"reasoning"`
}
// AIFullDecision AI的完整决策包含思维链
type AIFullDecision struct {
UserPrompt string `json:"user_prompt"` // 发送给AI的输入prompt
CoTTrace string `json:"cot_trace"` // 思维链分析AI输出
Decisions []TradingDecision `json:"decisions"` // 具体决策列表
Timestamp time.Time `json:"timestamp"`
}
// GetFullTradingDecision 获取AI的完整交易决策批量分析所有币种和持仓
func GetFullTradingDecision(ctx *TradingContext) (*AIFullDecision, error) {
// 1. 为所有币种获取市场数据
if err := fetchMarketDataForContext(ctx); err != nil {
return nil, fmt.Errorf("获取市场数据失败: %w", err)
}
// 2. 构建 System Prompt固定规则和 User Prompt动态数据
systemPrompt := buildSystemPrompt(ctx.Account.TotalEquity)
userPrompt := buildUserPrompt(ctx)
// 3. 调用AI API使用 system + user prompt
aiResponse, err := callAIWithMessages(systemPrompt, userPrompt)
if err != nil {
return nil, fmt.Errorf("调用AI API失败: %w", err)
}
// 4. 解析AI响应
decision, err := parseFullDecisionResponse(aiResponse, ctx.Account.TotalEquity)
if err != nil {
return nil, fmt.Errorf("解析AI响应失败: %w", err)
}
decision.Timestamp = time.Now()
decision.UserPrompt = userPrompt // 保存输入prompt
return decision, nil
}
// fetchMarketDataForContext 为上下文中的所有币种获取市场数据和OI数据
func fetchMarketDataForContext(ctx *TradingContext) error {
ctx.MarketDataMap = make(map[string]*MarketData)
ctx.OITopDataMap = make(map[string]*OITopData)
// 收集所有需要获取数据的币种
symbolSet := make(map[string]bool)
// 1. 优先获取持仓币种的数据(这是必须的)
for _, pos := range ctx.Positions {
symbolSet[pos.Symbol] = true
}
// 2. 候选币种数量根据账户状态动态调整
maxCandidates := calculateMaxCandidates(ctx)
for i, coin := range ctx.CandidateCoins {
if i >= maxCandidates {
break
}
symbolSet[coin.Symbol] = true
}
// 并发获取市场数据
// 持仓币种集合用于判断是否跳过OI检查
positionSymbols := make(map[string]bool)
for _, pos := range ctx.Positions {
positionSymbols[pos.Symbol] = true
}
for symbol := range symbolSet {
data, err := GetMarketData(symbol)
if err != nil {
// 单个币种失败不影响整体,只记录错误
continue
}
// ⚠️ 流动性过滤持仓价值低于15M USD的币种不做多空都不做
// 持仓价值 = 持仓量 × 当前价格
// 但现有持仓必须保留(需要决策是否平仓)
isExistingPosition := positionSymbols[symbol]
if !isExistingPosition && data.OpenInterest != nil && data.CurrentPrice > 0 {
// 计算持仓价值USD= 持仓量 × 当前价格
oiValue := data.OpenInterest.Latest * data.CurrentPrice
oiValueInMillions := oiValue / 1_000_000 // 转换为百万美元单位
if oiValueInMillions < 15 {
log.Printf("⚠️ %s 持仓价值过低(%.2fM USD < 15M),跳过此币种 [持仓量:%.0f × 价格:%.4f]",
symbol, oiValueInMillions, data.OpenInterest.Latest, data.CurrentPrice)
continue
}
}
ctx.MarketDataMap[symbol] = data
}
// 加载OI Top数据不影响主流程
oiPositions, err := pool.GetOITopPositions()
if err == nil {
for _, pos := range oiPositions {
// 标准化符号匹配
symbol := pos.Symbol
ctx.OITopDataMap[symbol] = &OITopData{
Rank: pos.Rank,
OIDeltaPercent: pos.OIDeltaPercent,
OIDeltaValue: pos.OIDeltaValue,
PriceDeltaPercent: pos.PriceDeltaPercent,
NetLong: pos.NetLong,
NetShort: pos.NetShort,
}
}
}
return nil
}
// calculateMaxCandidates 根据账户状态计算需要分析的候选币种数量
func calculateMaxCandidates(ctx *TradingContext) int {
// 直接返回候选池的全部币种数量
// 因为候选池已经在 auto_trader.go 中筛选过了
// 固定分析前20个评分最高的币种来自AI500
return len(ctx.CandidateCoins)
}
// buildSystemPrompt 构建 System Prompt固定规则可缓存
func buildSystemPrompt(accountEquity float64) string {
var sb strings.Builder
// 角色定义
sb.WriteString("你是专业的加密货币交易AI在币安合约市场进行自主交易。\n\n")
sb.WriteString("**使命**: 最大化风险调整后收益Sharpe Ratio\n\n")
// 自我进化核心
sb.WriteString("## 🧬 自我进化机制\n")
sb.WriteString("每次调用你都会收到**夏普比率**作为你的业绩指标(周期级别,非年化):\n\n")
sb.WriteString("**夏普比率解读**(正常范围 -2 到 +2\n")
sb.WriteString("- < -0.5:持续亏损 → 🔴 极度保守策略(减仓、收紧止损、减少持仓数)\n")
sb.WriteString("- -0.5 到 0轻微亏损 → 🟡 优化策略(保守仓位、提高选币标准)\n")
sb.WriteString("- 0 到 0.7:正收益 → 🟢 维持/优化当前策略\n")
sb.WriteString("- > 0.7:优异表现 → 🟢 可适度扩大仓位\n\n")
// 仓位管理规则
sb.WriteString("## 仓位管理\n")
sb.WriteString("- 最多持有 **3个币种**(质量>数量)\n")
sb.WriteString(fmt.Sprintf("- 山寨币: %.0f-%.0f USDT/仓(推荐%.0f杠杆20x\n",
accountEquity*0.8, accountEquity*1.5, accountEquity*1.2))
sb.WriteString(fmt.Sprintf("- BTC/ETH: %.0f-%.0f USDT/仓(推荐%.0f杠杆50x\n",
accountEquity*3, accountEquity*10, accountEquity*5))
sb.WriteString("- 保证金使用率 ≤90%%\n")
sb.WriteString("- 风险回报比 ≥1:2\n\n")
// 决策流程
sb.WriteString("## 决策流程\n")
sb.WriteString("1. **检查夏普比率**:理解当前策略效果,根据夏普比率调整策略\n")
sb.WriteString("2. **评估持仓**:决定平仓/持有\n")
sb.WriteString("3. **寻找机会**:筛选候选币种\n")
sb.WriteString("4. **执行决策**输出思维链和JSON决策\n\n")
// JSON 输出格式
sb.WriteString("## 输出格式\n\n")
sb.WriteString("**先输出思维链纯文本再输出JSON数组**\n\n")
sb.WriteString("JSON示例\n")
sb.WriteString("```json\n")
sb.WriteString("[\n")
sb.WriteString(fmt.Sprintf(" {\"symbol\": \"BTCUSDT\", \"action\": \"open_long\", \"leverage\": 50, \"position_size_usd\": %.0f, \"stop_loss\": 92000, \"take_profit\": 98000, \"confidence\": 85, \"risk_usd\": 200, \"reasoning\": \"强势突破\"},\n", accountEquity*5))
sb.WriteString(" {\"symbol\": \"ETHUSDT\", \"action\": \"close_long\", \"reasoning\": \"止盈\"}\n")
sb.WriteString("]\n")
sb.WriteString("```\n\n")
sb.WriteString("**字段说明**:\n")
sb.WriteString("- `action`: open_long | open_short | close_long | close_short | hold | wait\n")
sb.WriteString("- `confidence`: 信心度0-100必填即使不确定也要给出\n")
sb.WriteString("- `risk_usd`: 最大美元风险 = (entry_price - stop_loss) × quantity开仓时必填\n")
sb.WriteString("- 开仓时必填: leverage, position_size_usd, stop_loss, take_profit, confidence, risk_usd\n\n")
// DeepSeek/Qwen 特定优化
sb.WriteString("**提示**: 运用技术分析原理,趋势确认>指标信号,不要过度依赖单一指标\n")
return sb.String()
}
// buildUserPrompt 构建 User Prompt动态数据
func buildUserPrompt(ctx *TradingContext) string {
var sb strings.Builder
// 系统状态
sb.WriteString(fmt.Sprintf("**时间**: %s | **周期**: #%d | **运行**: %d分钟\n\n",
ctx.CurrentTime, ctx.CallCount, ctx.RuntimeMinutes))
// BTC 市场
if btcData, hasBTC := ctx.MarketDataMap["BTCUSDT"]; hasBTC {
sb.WriteString(fmt.Sprintf("**BTC**: %.2f (1h: %+.2f%%, 4h: %+.2f%%) | MACD: %.4f | RSI: %.2f\n\n",
btcData.CurrentPrice, btcData.PriceChange1h, btcData.PriceChange4h,
btcData.CurrentMACD, btcData.CurrentRSI7))
}
// 账户
sb.WriteString(fmt.Sprintf("**账户**: 净值%.2f | 余额%.2f (%.1f%%) | 盈亏%+.2f%% | 保证金%.1f%% | 持仓%d个\n\n",
ctx.Account.TotalEquity,
ctx.Account.AvailableBalance,
(ctx.Account.AvailableBalance/ctx.Account.TotalEquity)*100,
ctx.Account.TotalPnLPct,
ctx.Account.MarginUsedPct,
ctx.Account.PositionCount))
// 持仓(完整市场数据)
if len(ctx.Positions) > 0 {
sb.WriteString("## 当前持仓\n")
for i, pos := range ctx.Positions {
sb.WriteString(fmt.Sprintf("%d. %s %s | 入场价%.4f 当前价%.4f | 盈亏%+.2f%% | 杠杆%dx | 保证金%.0f | 强平价%.4f\n\n",
i+1, pos.Symbol, strings.ToUpper(pos.Side),
pos.EntryPrice, pos.MarkPrice, pos.UnrealizedPnLPct,
pos.Leverage, pos.MarginUsed, pos.LiquidationPrice))
// 使用FormatMarketData输出完整市场数据
if marketData, ok := ctx.MarketDataMap[pos.Symbol]; ok {
sb.WriteString(FormatMarketData(marketData))
sb.WriteString("\n")
}
}
} else {
sb.WriteString("**当前持仓**: 无\n\n")
}
// 候选币种(完整市场数据)
sb.WriteString(fmt.Sprintf("## 候选币种 (%d个)\n\n", len(ctx.MarketDataMap)))
displayedCount := 0
for _, coin := range ctx.CandidateCoins {
marketData, hasData := ctx.MarketDataMap[coin.Symbol]
if !hasData {
continue
}
displayedCount++
sourceTags := ""
if len(coin.Sources) > 1 {
sourceTags = " (AI500+OI_Top双重信号)"
} else if len(coin.Sources) == 1 && coin.Sources[0] == "oi_top" {
sourceTags = " (OI_Top持仓增长)"
}
// 使用FormatMarketData输出完整市场数据
sb.WriteString(fmt.Sprintf("### %d. %s%s\n\n", displayedCount, coin.Symbol, sourceTags))
sb.WriteString(FormatMarketData(marketData))
sb.WriteString("\n")
}
sb.WriteString("\n")
// 夏普比率(直接传值,不要复杂格式化)
if ctx.Performance != nil {
// 直接从interface{}中提取SharpeRatio
type PerformanceData struct {
SharpeRatio float64 `json:"sharpe_ratio"`
}
var perfData PerformanceData
if jsonData, err := json.Marshal(ctx.Performance); err == nil {
if err := json.Unmarshal(jsonData, &perfData); err == nil {
sb.WriteString(fmt.Sprintf("## 📊 夏普比率: %.2f\n\n", perfData.SharpeRatio))
}
}
}
sb.WriteString("---\n\n")
sb.WriteString("现在请分析并输出决策(思维链 + JSON\n")
return sb.String()
}
// parseFullDecisionResponse 解析AI的完整决策响应
func parseFullDecisionResponse(aiResponse string, accountEquity float64) (*AIFullDecision, error) {
// 1. 提取思维链
cotTrace := extractCoTTrace(aiResponse)
// 2. 提取JSON决策列表
decisions, err := extractDecisions(aiResponse)
if err != nil {
return &AIFullDecision{
CoTTrace: cotTrace,
Decisions: []TradingDecision{},
}, fmt.Errorf("提取决策失败: %w\n\n=== AI思维链分析 ===\n%s", err, cotTrace)
}
// 3. 验证决策
if err := validateDecisions(decisions, accountEquity); err != nil {
return &AIFullDecision{
CoTTrace: cotTrace,
Decisions: decisions,
}, fmt.Errorf("决策验证失败: %w\n\n=== AI思维链分析 ===\n%s", err, cotTrace)
}
return &AIFullDecision{
CoTTrace: cotTrace,
Decisions: decisions,
}, nil
}
// extractCoTTrace 提取思维链分析
func extractCoTTrace(response string) string {
// 查找JSON数组的开始位置
jsonStart := strings.Index(response, "[")
if jsonStart > 0 {
// 思维链是JSON数组之前的内容
return strings.TrimSpace(response[:jsonStart])
}
// 如果找不到JSON整个响应都是思维链
return strings.TrimSpace(response)
}
// extractDecisions 提取JSON决策列表
func extractDecisions(response string) ([]TradingDecision, error) {
// 直接查找JSON数组 - 找第一个完整的JSON数组
arrayStart := strings.Index(response, "[")
if arrayStart == -1 {
return nil, fmt.Errorf("无法找到JSON数组起始")
}
// 从 [ 开始,匹配括号找到对应的 ]
arrayEnd := findMatchingBracket(response, arrayStart)
if arrayEnd == -1 {
return nil, fmt.Errorf("无法找到JSON数组结束")
}
jsonContent := strings.TrimSpace(response[arrayStart : arrayEnd+1])
// 🔧 修复常见的JSON格式错误缺少引号的字段值
// 匹配: "reasoning": 内容"} 或 "reasoning": 内容} (没有引号)
// 修复为: "reasoning": "内容"}
// 使用简单的字符串扫描而不是正则表达式
jsonContent = fixMissingQuotes(jsonContent)
// 解析JSON
var decisions []TradingDecision
if err := json.Unmarshal([]byte(jsonContent), &decisions); err != nil {
return nil, fmt.Errorf("JSON解析失败: %w\nJSON内容: %s", err, jsonContent)
}
return decisions, nil
}
// fixMissingQuotes 替换中文引号为英文引号(避免输入法自动转换)
func fixMissingQuotes(jsonStr string) string {
jsonStr = strings.ReplaceAll(jsonStr, "\u201c", "\"") // "
jsonStr = strings.ReplaceAll(jsonStr, "\u201d", "\"") // "
jsonStr = strings.ReplaceAll(jsonStr, "\u2018", "'") // '
jsonStr = strings.ReplaceAll(jsonStr, "\u2019", "'") // '
return jsonStr
}
// validateDecisions 验证所有决策(需要账户信息)
func validateDecisions(decisions []TradingDecision, accountEquity float64) error {
for i, decision := range decisions {
if err := validateDecision(&decision, accountEquity); err != nil {
return fmt.Errorf("决策 #%d 验证失败: %w", i+1, err)
}
}
return nil
}
// findMatchingBracket 查找匹配的右括号
func findMatchingBracket(s string, start int) int {
if start >= len(s) || s[start] != '[' {
return -1
}
depth := 0
for i := start; i < len(s); i++ {
switch s[i] {
case '[':
depth++
case ']':
depth--
if depth == 0 {
return i
}
}
}
return -1
}
// validateDecision 验证单个决策的有效性
func validateDecision(d *TradingDecision, accountEquity float64) error {
// 验证action
validActions := map[string]bool{
"open_long": true,
"open_short": true,
"close_long": true,
"close_short": true,
"hold": true,
"wait": true,
}
if !validActions[d.Action] {
return fmt.Errorf("无效的action: %s", d.Action)
}
// 开仓操作必须提供完整参数
if d.Action == "open_long" || d.Action == "open_short" {
// 根据币种判断杠杆上限和仓位价值上限
maxLeverage := 20 // 山寨币固定20倍
maxPositionValue := accountEquity * 1.5 // 山寨币最多1.5倍账户净值
if d.Symbol == "BTCUSDT" || d.Symbol == "ETHUSDT" {
maxLeverage = 50 // BTC和ETH固定50倍
maxPositionValue = accountEquity * 10 // BTC/ETH最多10倍账户净值
}
if d.Leverage <= 0 || d.Leverage > maxLeverage {
return fmt.Errorf("杠杆必须在1-%d之间%s: %d", maxLeverage, d.Symbol, d.Leverage)
}
if d.PositionSizeUSD <= 0 {
return fmt.Errorf("仓位大小必须大于0: %.2f", d.PositionSizeUSD)
}
// 验证仓位价值上限加1%容差以避免浮点数精度问题)
tolerance := maxPositionValue * 0.01 // 1%容差
if d.PositionSizeUSD > maxPositionValue+tolerance {
if d.Symbol == "BTCUSDT" || d.Symbol == "ETHUSDT" {
return fmt.Errorf("BTC/ETH单币种仓位价值不能超过%.0f USDT10倍账户净值实际: %.0f", maxPositionValue, d.PositionSizeUSD)
} else {
return fmt.Errorf("山寨币单币种仓位价值不能超过%.0f USDT1.5倍账户净值),实际: %.0f", maxPositionValue, d.PositionSizeUSD)
}
}
if d.StopLoss <= 0 || d.TakeProfit <= 0 {
return fmt.Errorf("止损和止盈必须大于0")
}
// 验证止损止盈的合理性
if d.Action == "open_long" {
if d.StopLoss >= d.TakeProfit {
return fmt.Errorf("做多时止损价必须小于止盈价")
}
} else {
if d.StopLoss <= d.TakeProfit {
return fmt.Errorf("做空时止损价必须大于止盈价")
}
}
}
return nil
}
// interpretSharpeRatio 解释夏普比率的含义
// 注:这里是周期级别(非年化)的夏普比率,正常范围在 -2 到 +2
func interpretSharpeRatio(sharpe float64) string {
if sharpe < -0.5 {
return "持续亏损,策略需大幅调整"
} else if sharpe < 0 {
return "轻微亏损,需优化策略"
} else if sharpe < 0.3 {
return "正收益但波动大"
} else if sharpe < 0.7 {
return "良好表现"
} else if sharpe < 1.0 {
return "优秀表现"
} else {
return "卓越表现"
}
}
// getAdaptiveBehaviorRecommendation 根据夏普比率生成自适应行为建议
// 这是AI自我进化的核心根据风险调整后收益动态调整交易策略
// 注sharpe是周期级别非年化正常范围 -2 到 +2
func getAdaptiveBehaviorRecommendation(sharpe float64, accountEquity float64) string {
var sb strings.Builder
sb.WriteString("### 🎯 自适应行为建议(基于夏普比率)\n\n")
if sharpe < -0.5 {
// 🔴 持续亏损:需要极度保守
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 < 0 {
// 🟡 -0.5 到 0轻微亏损
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")
} else if sharpe < 0.7 {
// 🟢 0-0.7:正收益但可继续优化
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 < 1.0 {
// 🟢 0.7-1.0:优秀表现
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 {
// 🟢 >1.0:卓越表现
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()
}