mirror of
https://github.com/laoxong/nofx.git
synced 2026-06-04 09:58:22 +08:00
refactor: optimize codebase encoding
This commit is contained in:
+6
-6
@@ -247,7 +247,7 @@ func (e *StrategyEngine) GetCandidateCoins() ([]CandidateCoin, error) {
|
||||
return e.filterExcludedCoins(candidates), nil
|
||||
|
||||
case "ai500":
|
||||
// 检查 use_ai500 标志,如果为 false 则回退到静态币种
|
||||
// Check use_ai500 flag; if false, fall back to static coins
|
||||
if !coinSource.UseAI500 {
|
||||
logger.Infof("⚠️ source_type is 'ai500' but use_ai500 is false, falling back to static coins")
|
||||
for _, symbol := range coinSource.StaticCoins {
|
||||
@@ -263,11 +263,11 @@ func (e *StrategyEngine) GetCandidateCoins() ([]CandidateCoin, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 空列表是正常情况,直接返回
|
||||
// Empty list is a normal condition, return directly
|
||||
return e.filterExcludedCoins(coins), nil
|
||||
|
||||
case "oi_top":
|
||||
// 检查 use_oi_top 标志,如果为 false 则回退到静态币种
|
||||
// Check use_oi_top flag; if false, fall back to static coins
|
||||
if !coinSource.UseOITop {
|
||||
logger.Infof("⚠️ source_type is 'oi_top' but use_oi_top is false, falling back to static coins")
|
||||
for _, symbol := range coinSource.StaticCoins {
|
||||
@@ -283,11 +283,11 @@ func (e *StrategyEngine) GetCandidateCoins() ([]CandidateCoin, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 空列表是正常情况,直接返回
|
||||
// Empty list is a normal condition, return directly
|
||||
return e.filterExcludedCoins(coins), nil
|
||||
|
||||
case "oi_low":
|
||||
// 持仓减少榜,适合做空
|
||||
// OI decrease ranking, suitable for short positions
|
||||
if !coinSource.UseOILow {
|
||||
logger.Infof("⚠️ source_type is 'oi_low' but use_oi_low is false, falling back to static coins")
|
||||
for _, symbol := range coinSource.StaticCoins {
|
||||
@@ -303,7 +303,7 @@ func (e *StrategyEngine) GetCandidateCoins() ([]CandidateCoin, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 空列表是正常情况,直接返回
|
||||
// Empty list is a normal condition, return directly
|
||||
return e.filterExcludedCoins(coins), nil
|
||||
|
||||
case "hyper_all":
|
||||
|
||||
@@ -441,7 +441,7 @@ func (e *StrategyEngine) formatPositionInfo(index int, pos PositionInfo, ctx *Co
|
||||
|
||||
func (e *StrategyEngine) formatCoinSourceTag(sources []string) string {
|
||||
if len(sources) > 1 {
|
||||
// 多信号源组合
|
||||
// Multiple signal source combination
|
||||
hasAI500 := false
|
||||
hasOITop := false
|
||||
hasOILow := false
|
||||
@@ -482,9 +482,9 @@ func (e *StrategyEngine) formatCoinSourceTag(sources []string) string {
|
||||
case "ai500":
|
||||
return " (AI500)"
|
||||
case "oi_top":
|
||||
return " (OI_Top 持仓增加)"
|
||||
return " (OI_Top OI increase)"
|
||||
case "oi_low":
|
||||
return " (OI_Low 持仓减少)"
|
||||
return " (OI_Low OI decrease)"
|
||||
case "static":
|
||||
return " (Manual selection)"
|
||||
case "hyper_all":
|
||||
@@ -504,7 +504,7 @@ func (e *StrategyEngine) formatMarketData(data *market.Data) string {
|
||||
var sb strings.Builder
|
||||
indicators := e.config.Indicators
|
||||
|
||||
// 明确标注币种
|
||||
// Clearly label the coin symbol
|
||||
sb.WriteString(fmt.Sprintf("=== %s Market Data ===\n\n", data.Symbol))
|
||||
sb.WriteString(fmt.Sprintf("current_price = %.4f", data.CurrentPrice))
|
||||
|
||||
|
||||
+49
-48
@@ -10,49 +10,50 @@ import (
|
||||
)
|
||||
|
||||
// ============================================================================
|
||||
// AI Data Formatter - AI数据格式化器
|
||||
// AI Data Formatter
|
||||
// ============================================================================
|
||||
// 将交易上下文转换为AI友好的格式,确保AI能够100%理解数据
|
||||
// Converts trading context into AI-friendly format, ensuring AI fully
|
||||
// understands the data regardless of language.
|
||||
// ============================================================================
|
||||
|
||||
// FormatContextForAI 将交易上下文格式化为AI可理解的文本(包含Schema)
|
||||
// FormatContextForAI formats trading context into AI-readable text (including schema)
|
||||
func FormatContextForAI(ctx *Context, lang Language) string {
|
||||
var sb strings.Builder
|
||||
|
||||
// 1. 添加Schema说明(让AI理解数据格式)
|
||||
// 1. Add schema description (so AI understands data format)
|
||||
sb.WriteString(GetSchemaPrompt(lang))
|
||||
sb.WriteString("\n---\n\n")
|
||||
|
||||
// 2. 当前状态概览
|
||||
// 2. Current state overview
|
||||
sb.WriteString(formatContextData(ctx, lang))
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// FormatContextDataOnly 仅格式化上下文数据,不包含Schema(用于已有Schema的场景)
|
||||
// FormatContextDataOnly formats context data only, without schema (for use when schema is already present)
|
||||
func FormatContextDataOnly(ctx *Context, lang Language) string {
|
||||
return formatContextData(ctx, lang)
|
||||
}
|
||||
|
||||
// formatContextData 格式化核心数据部分
|
||||
// formatContextData formats the core data section
|
||||
func formatContextData(ctx *Context, lang Language) string {
|
||||
var sb strings.Builder
|
||||
|
||||
// 1. 当前状态概览
|
||||
// 1. Current state overview
|
||||
if lang == LangChinese {
|
||||
sb.WriteString(formatHeaderZH(ctx))
|
||||
} else {
|
||||
sb.WriteString(formatHeaderEN(ctx))
|
||||
}
|
||||
|
||||
// 3. 账户信息
|
||||
// 3. Account information
|
||||
if lang == LangChinese {
|
||||
sb.WriteString(formatAccountZH(ctx))
|
||||
} else {
|
||||
sb.WriteString(formatAccountEN(ctx))
|
||||
}
|
||||
|
||||
// 4. 历史交易统计
|
||||
// 4. Historical trading statistics
|
||||
if ctx.TradingStats != nil && ctx.TradingStats.TotalTrades > 0 {
|
||||
if lang == LangChinese {
|
||||
sb.WriteString(formatTradingStatsZH(ctx.TradingStats))
|
||||
@@ -61,7 +62,7 @@ func formatContextData(ctx *Context, lang Language) string {
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 最近交易记录
|
||||
// 5. Recent trade records
|
||||
if len(ctx.RecentOrders) > 0 {
|
||||
if lang == LangChinese {
|
||||
sb.WriteString(formatRecentTradesZH(ctx.RecentOrders))
|
||||
@@ -70,7 +71,7 @@ func formatContextData(ctx *Context, lang Language) string {
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 当前持仓
|
||||
// 5. Current positions
|
||||
if len(ctx.Positions) > 0 {
|
||||
if lang == LangChinese {
|
||||
sb.WriteString(formatCurrentPositionsZH(ctx))
|
||||
@@ -79,7 +80,7 @@ func formatContextData(ctx *Context, lang Language) string {
|
||||
}
|
||||
}
|
||||
|
||||
// 6. 候选币种(带市场数据)
|
||||
// 6. Candidate coins (with market data)
|
||||
if len(ctx.CandidateCoins) > 0 {
|
||||
if lang == LangChinese {
|
||||
sb.WriteString(formatCandidateCoinsZH(ctx))
|
||||
@@ -88,7 +89,7 @@ func formatContextData(ctx *Context, lang Language) string {
|
||||
}
|
||||
}
|
||||
|
||||
// 7. OI排名数据(如果有)
|
||||
// 7. OI ranking data (if available)
|
||||
if ctx.OIRankingData != nil {
|
||||
nofxosLang := nofxos.LangEnglish
|
||||
if lang == LangChinese {
|
||||
@@ -100,15 +101,15 @@ func formatContextData(ctx *Context, lang Language) string {
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// ========== 中文格式化函数 ==========
|
||||
// ========== Chinese Formatting Functions ==========
|
||||
|
||||
// formatHeaderZH 格式化头部信息(中文)
|
||||
// formatHeaderZH formats header information (Chinese)
|
||||
func formatHeaderZH(ctx *Context) string {
|
||||
return fmt.Sprintf("# 📊 交易决策请求\n\n时间: %s | 周期: #%d | 运行时长: %d 分钟\n\n",
|
||||
ctx.CurrentTime, ctx.CallCount, ctx.RuntimeMinutes)
|
||||
}
|
||||
|
||||
// formatAccountZH 格式化账户信息(中文)
|
||||
// formatAccountZH formats account information (Chinese)
|
||||
func formatAccountZH(ctx *Context) string {
|
||||
acc := ctx.Account
|
||||
var sb strings.Builder
|
||||
@@ -120,7 +121,7 @@ func formatAccountZH(ctx *Context) string {
|
||||
sb.WriteString(fmt.Sprintf("保证金使用率: %.1f%% | ", acc.MarginUsedPct))
|
||||
sb.WriteString(fmt.Sprintf("持仓数: %d\n\n", acc.PositionCount))
|
||||
|
||||
// 添加风险提示
|
||||
// Add risk warnings
|
||||
if acc.MarginUsedPct > 70 {
|
||||
sb.WriteString("⚠️ **风险警告**: 保证金使用率 > 70%,处于高风险状态!\n\n")
|
||||
} else if acc.MarginUsedPct > 50 {
|
||||
@@ -130,25 +131,25 @@ func formatAccountZH(ctx *Context) string {
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// formatTradingStatsZH 格式化历史交易统计(中文)
|
||||
// formatTradingStatsZH formats historical trading statistics (Chinese)
|
||||
func formatTradingStatsZH(stats *TradingStats) string {
|
||||
var sb strings.Builder
|
||||
sb.WriteString("## 历史交易统计\n\n")
|
||||
|
||||
// 盈亏比计算
|
||||
// Win/loss ratio calculation
|
||||
var winLossRatio float64
|
||||
if stats.AvgLoss > 0 {
|
||||
winLossRatio = stats.AvgWin / stats.AvgLoss
|
||||
}
|
||||
|
||||
// 指标定义说明(去掉胜率,聚焦核心指标)
|
||||
// Metric definitions (focusing on core metrics, excluding win rate)
|
||||
sb.WriteString("**指标说明**:\n")
|
||||
sb.WriteString("- 盈利因子: 总盈利 ÷ 总亏损(>1表示盈利,>1.5为良好,>2为优秀)\n")
|
||||
sb.WriteString("- 夏普比率: (平均收益 - 无风险收益) ÷ 收益标准差(>1良好,>2优秀)\n")
|
||||
sb.WriteString("- 盈亏比: 平均盈利 ÷ 平均亏损(>1.5为良好,>2为优秀)\n")
|
||||
sb.WriteString("- 最大回撤: 资金曲线从峰值到谷底的最大跌幅(<20%为低风险)\n\n")
|
||||
|
||||
// 数据值
|
||||
// Data values
|
||||
sb.WriteString("**当前数据**:\n")
|
||||
sb.WriteString(fmt.Sprintf("- 总交易: %d 笔\n", stats.TotalTrades))
|
||||
sb.WriteString(fmt.Sprintf("- 盈利因子: %.2f\n", stats.ProfitFactor))
|
||||
@@ -159,10 +160,10 @@ func formatTradingStatsZH(stats *TradingStats) string {
|
||||
sb.WriteString(fmt.Sprintf("- 平均亏损: -%.2f USDT\n", stats.AvgLoss))
|
||||
sb.WriteString(fmt.Sprintf("- 最大回撤: %.1f%%\n\n", stats.MaxDrawdownPct))
|
||||
|
||||
// 综合分析和决策建议
|
||||
// Comprehensive analysis and decision guidance
|
||||
sb.WriteString("**决策参考**:\n")
|
||||
|
||||
// 根据统计数据给出具体建议
|
||||
// Provide specific recommendations based on statistics
|
||||
if stats.TotalTrades < 10 {
|
||||
sb.WriteString("- 样本量较小(<10笔),统计结果参考意义有限\n")
|
||||
}
|
||||
@@ -191,13 +192,13 @@ func formatTradingStatsZH(stats *TradingStats) string {
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// formatRecentTradesZH 格式化最近交易(中文)
|
||||
// formatRecentTradesZH formats recent trades (Chinese)
|
||||
func formatRecentTradesZH(orders []RecentOrder) string {
|
||||
var sb strings.Builder
|
||||
sb.WriteString("## 最近完成的交易\n\n")
|
||||
|
||||
for i, order := range orders {
|
||||
// 判断盈亏
|
||||
// Determine profit or loss
|
||||
profitOrLoss := "盈利"
|
||||
if order.RealizedPnL < 0 {
|
||||
profitOrLoss = "亏损"
|
||||
@@ -222,13 +223,13 @@ func formatRecentTradesZH(orders []RecentOrder) string {
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// formatCurrentPositionsZH 格式化当前持仓(中文)
|
||||
// formatCurrentPositionsZH formats current positions (Chinese)
|
||||
func formatCurrentPositionsZH(ctx *Context) string {
|
||||
var sb strings.Builder
|
||||
sb.WriteString("## 当前持仓\n\n")
|
||||
|
||||
for i, pos := range ctx.Positions {
|
||||
// 计算回撤
|
||||
// Calculate drawdown
|
||||
drawdown := pos.UnrealizedPnLPct - pos.PeakPnLPct
|
||||
|
||||
sb.WriteString(fmt.Sprintf("%d. %s %s | ", i+1, pos.Symbol, strings.ToUpper(pos.Side)))
|
||||
@@ -242,7 +243,7 @@ func formatCurrentPositionsZH(ctx *Context) string {
|
||||
sb.WriteString(fmt.Sprintf("保证金 %.0f USDT | ", pos.MarginUsed))
|
||||
sb.WriteString(fmt.Sprintf("强平价 %.4f\n", pos.LiquidationPrice))
|
||||
|
||||
// 添加分析提示
|
||||
// Add analysis hints
|
||||
if drawdown < -0.30*pos.PeakPnLPct && pos.PeakPnLPct > 0.02 {
|
||||
sb.WriteString(fmt.Sprintf(" ⚠️ **止盈提示**: 当前盈亏从峰值 %.2f%% 回撤到 %.2f%%,回撤幅度 %.2f%%,建议考虑止盈\n",
|
||||
pos.PeakPnLPct, pos.UnrealizedPnLPct, (drawdown/pos.PeakPnLPct)*100))
|
||||
@@ -252,7 +253,7 @@ func formatCurrentPositionsZH(ctx *Context) string {
|
||||
sb.WriteString(" ⚠️ **止损提示**: 亏损接近-5%止损线,建议考虑止损\n")
|
||||
}
|
||||
|
||||
// 显示当前价格(如果有市场数据)
|
||||
// Show current price (if market data available)
|
||||
if ctx.MarketDataMap != nil {
|
||||
if mdata, ok := ctx.MarketDataMap[pos.Symbol]; ok {
|
||||
sb.WriteString(fmt.Sprintf(" 📈 当前价格: %.4f\n", mdata.CurrentPrice))
|
||||
@@ -265,7 +266,7 @@ func formatCurrentPositionsZH(ctx *Context) string {
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// formatCandidateCoinsZH 格式化候选币种(中文)
|
||||
// formatCandidateCoinsZH formats candidate coins (Chinese)
|
||||
func formatCandidateCoinsZH(ctx *Context) string {
|
||||
var sb strings.Builder
|
||||
sb.WriteString("## 候选币种\n\n")
|
||||
@@ -273,19 +274,19 @@ func formatCandidateCoinsZH(ctx *Context) string {
|
||||
for i, coin := range ctx.CandidateCoins {
|
||||
sb.WriteString(fmt.Sprintf("### %d. %s\n\n", i+1, coin.Symbol))
|
||||
|
||||
// 当前价格
|
||||
// Current price
|
||||
if ctx.MarketDataMap != nil {
|
||||
if mdata, ok := ctx.MarketDataMap[coin.Symbol]; ok {
|
||||
sb.WriteString(fmt.Sprintf("当前价格: %.4f\n\n", mdata.CurrentPrice))
|
||||
|
||||
// K线数据(多时间框架)
|
||||
// Kline data (multi-timeframe)
|
||||
if mdata.TimeframeData != nil {
|
||||
sb.WriteString(formatKlineDataZH(coin.Symbol, mdata.TimeframeData, ctx.Timeframes))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OI数据(如果有)
|
||||
// OI data (if available)
|
||||
if ctx.OITopDataMap != nil {
|
||||
if oiData, ok := ctx.OITopDataMap[coin.Symbol]; ok {
|
||||
sb.WriteString(fmt.Sprintf("**持仓量变化**: OI排名 #%d | 变化 %+.2f%% (%+.2fM USDT) | 价格变化 %+.2f%%\n\n",
|
||||
@@ -295,7 +296,7 @@ func formatCandidateCoinsZH(ctx *Context) string {
|
||||
oiData.PriceDeltaPercent,
|
||||
))
|
||||
|
||||
// OI解读
|
||||
// OI interpretation
|
||||
oiChange := "增加"
|
||||
if oiData.OIDeltaPercent < 0 {
|
||||
oiChange = "减少"
|
||||
@@ -314,7 +315,7 @@ func formatCandidateCoinsZH(ctx *Context) string {
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// formatKlineDataZH 格式化K线数据(中文)
|
||||
// formatKlineDataZH formats kline data (Chinese)
|
||||
func formatKlineDataZH(symbol string, tfData map[string]*market.TimeframeSeriesData, timeframes []string) string {
|
||||
var sb strings.Builder
|
||||
|
||||
@@ -324,7 +325,7 @@ func formatKlineDataZH(symbol string, tfData map[string]*market.TimeframeSeriesD
|
||||
sb.WriteString("```\n")
|
||||
sb.WriteString("时间(UTC) 开盘 最高 最低 收盘 成交量\n")
|
||||
|
||||
// 只显示最近30根K线
|
||||
// Only show the latest 30 klines
|
||||
startIdx := 0
|
||||
if len(data.Klines) > 30 {
|
||||
startIdx = len(data.Klines) - 30
|
||||
@@ -343,7 +344,7 @@ func formatKlineDataZH(symbol string, tfData map[string]*market.TimeframeSeriesD
|
||||
))
|
||||
}
|
||||
|
||||
// 标记最后一根K线
|
||||
// Mark the last kline
|
||||
if len(data.Klines) > 0 {
|
||||
sb.WriteString(" <- 当前\n")
|
||||
}
|
||||
@@ -356,7 +357,7 @@ func formatKlineDataZH(symbol string, tfData map[string]*market.TimeframeSeriesD
|
||||
}
|
||||
|
||||
|
||||
// getOIInterpretationZH 获取OI变化解读(中文)
|
||||
// getOIInterpretationZH returns OI change interpretation (Chinese)
|
||||
func getOIInterpretationZH(oiChange, priceChange string) string {
|
||||
if oiChange == "增加" && priceChange == "上涨" {
|
||||
return OIInterpretation.OIUp_PriceUp.ZH
|
||||
@@ -369,15 +370,15 @@ func getOIInterpretationZH(oiChange, priceChange string) string {
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 英文格式化函数 ==========
|
||||
// ========== English Formatting Functions ==========
|
||||
|
||||
// formatHeaderEN 格式化头部信息(英文)
|
||||
// formatHeaderEN formats header information (English)
|
||||
func formatHeaderEN(ctx *Context) string {
|
||||
return fmt.Sprintf("# 📊 Trading Decision Request\n\nTime: %s | Period: #%d | Runtime: %d minutes\n\n",
|
||||
ctx.CurrentTime, ctx.CallCount, ctx.RuntimeMinutes)
|
||||
}
|
||||
|
||||
// formatAccountEN 格式化账户信息(英文)
|
||||
// formatAccountEN formats account information (English)
|
||||
func formatAccountEN(ctx *Context) string {
|
||||
acc := ctx.Account
|
||||
var sb strings.Builder
|
||||
@@ -399,7 +400,7 @@ func formatAccountEN(ctx *Context) string {
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// formatTradingStatsEN 格式化历史交易统计(英文)
|
||||
// formatTradingStatsEN formats historical trading statistics (English)
|
||||
func formatTradingStatsEN(stats *TradingStats) string {
|
||||
var sb strings.Builder
|
||||
sb.WriteString("## Historical Trading Statistics\n\n")
|
||||
@@ -460,7 +461,7 @@ func formatTradingStatsEN(stats *TradingStats) string {
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// formatRecentTradesEN 格式化最近交易(英文)
|
||||
// formatRecentTradesEN formats recent trades (English)
|
||||
func formatRecentTradesEN(orders []RecentOrder) string {
|
||||
var sb strings.Builder
|
||||
sb.WriteString("## Recent Completed Trades\n\n")
|
||||
@@ -490,7 +491,7 @@ func formatRecentTradesEN(orders []RecentOrder) string {
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// formatCurrentPositionsEN 格式化当前持仓(英文)
|
||||
// formatCurrentPositionsEN formats current positions (English)
|
||||
func formatCurrentPositionsEN(ctx *Context) string {
|
||||
var sb strings.Builder
|
||||
sb.WriteString("## Current Positions\n\n")
|
||||
@@ -531,7 +532,7 @@ func formatCurrentPositionsEN(ctx *Context) string {
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// formatCandidateCoinsEN 格式化候选币种(英文)
|
||||
// formatCandidateCoinsEN formats candidate coins (English)
|
||||
func formatCandidateCoinsEN(ctx *Context) string {
|
||||
var sb strings.Builder
|
||||
sb.WriteString("## Candidate Coins\n\n")
|
||||
@@ -576,7 +577,7 @@ func formatCandidateCoinsEN(ctx *Context) string {
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// formatKlineDataEN 格式化K线数据(英文)
|
||||
// formatKlineDataEN formats kline data (English)
|
||||
func formatKlineDataEN(symbol string, tfData map[string]*market.TimeframeSeriesData, timeframes []string) string {
|
||||
var sb strings.Builder
|
||||
|
||||
@@ -621,7 +622,7 @@ func formatKlineDataEN(symbol string, tfData map[string]*market.TimeframeSeriesD
|
||||
}
|
||||
|
||||
|
||||
// getOIInterpretationEN 获取OI变化解读(英文)
|
||||
// getOIInterpretationEN returns OI change interpretation (English)
|
||||
func getOIInterpretationEN(oiChange, priceChange string) string {
|
||||
if oiChange == "increase" && priceChange == "up" {
|
||||
return OIInterpretation.OIUp_PriceUp.EN
|
||||
|
||||
+24
-24
@@ -6,22 +6,22 @@ import (
|
||||
)
|
||||
|
||||
// ============================================================================
|
||||
// AI Prompt Builder - AI提示词构建器
|
||||
// AI Prompt Builder
|
||||
// ============================================================================
|
||||
// 构建完整的AI提示词,包括系统提示词和用户提示词
|
||||
// Builds complete AI prompts including system prompts and user prompts.
|
||||
// ============================================================================
|
||||
|
||||
// PromptBuilder 提示词构建器
|
||||
// PromptBuilder builds AI prompts in the configured language
|
||||
type PromptBuilder struct {
|
||||
lang Language
|
||||
}
|
||||
|
||||
// NewPromptBuilder 创建提示词构建器
|
||||
// NewPromptBuilder creates a new prompt builder for the given language
|
||||
func NewPromptBuilder(lang Language) *PromptBuilder {
|
||||
return &PromptBuilder{lang: lang}
|
||||
}
|
||||
|
||||
// BuildSystemPrompt 构建系统提示词
|
||||
// BuildSystemPrompt builds the system prompt
|
||||
func (pb *PromptBuilder) BuildSystemPrompt() string {
|
||||
if pb.lang == LangChinese {
|
||||
return pb.buildSystemPromptZH()
|
||||
@@ -29,19 +29,19 @@ func (pb *PromptBuilder) BuildSystemPrompt() string {
|
||||
return pb.buildSystemPromptEN()
|
||||
}
|
||||
|
||||
// BuildUserPrompt 构建用户提示词(包含完整的交易上下文)
|
||||
// BuildUserPrompt builds the user prompt with full trading context
|
||||
func (pb *PromptBuilder) BuildUserPrompt(ctx *Context) string {
|
||||
// 使用Formatter格式化交易上下文
|
||||
// Use Formatter to format the trading context
|
||||
formattedData := FormatContextForAI(ctx, pb.lang)
|
||||
|
||||
// 添加决策要求
|
||||
// Append decision requirements
|
||||
if pb.lang == LangChinese {
|
||||
return formattedData + pb.getDecisionRequirementsZH()
|
||||
}
|
||||
return formattedData + pb.getDecisionRequirementsEN()
|
||||
}
|
||||
|
||||
// ========== 中文提示词 ==========
|
||||
// ========== Chinese Prompts ==========
|
||||
|
||||
func (pb *PromptBuilder) buildSystemPromptZH() string {
|
||||
return `你是一个专业的量化交易AI助手,负责分析市场数据并做出交易决策。
|
||||
@@ -176,7 +176,7 @@ func (pb *PromptBuilder) getDecisionRequirementsZH() string {
|
||||
**请立即输出你的决策(JSON格式)**:`
|
||||
}
|
||||
|
||||
// ========== 英文提示词 ==========
|
||||
// ========== English Prompts ==========
|
||||
|
||||
func (pb *PromptBuilder) buildSystemPromptEN() string {
|
||||
return `You are a professional quantitative trading AI assistant responsible for analyzing market data and making trading decisions.
|
||||
@@ -311,9 +311,9 @@ func (pb *PromptBuilder) getDecisionRequirementsEN() string {
|
||||
**Please output your decision (JSON format) immediately**:`
|
||||
}
|
||||
|
||||
// ========== 辅助函数 ==========
|
||||
// ========== Helper Functions ==========
|
||||
|
||||
// FormatDecisionExample 格式化决策示例(用于文档)
|
||||
// FormatDecisionExample formats a decision example (for documentation)
|
||||
func FormatDecisionExample(lang Language) string {
|
||||
example := Decision{
|
||||
Symbol: "BTCUSDT",
|
||||
@@ -323,32 +323,32 @@ func FormatDecisionExample(lang Language) string {
|
||||
StopLoss: 42000,
|
||||
TakeProfit: 48000,
|
||||
Confidence: 85,
|
||||
Reasoning: "详细的推理过程...",
|
||||
Reasoning: "Detailed reasoning process...",
|
||||
}
|
||||
|
||||
data, _ := json.MarshalIndent([]Decision{example}, "", " ")
|
||||
return string(data)
|
||||
}
|
||||
|
||||
// ValidateDecisionFormat 验证决策格式是否正确
|
||||
// ValidateDecisionFormat validates that the decision format is correct
|
||||
func ValidateDecisionFormat(decisions []Decision) error {
|
||||
if len(decisions) == 0 {
|
||||
return fmt.Errorf("决策列表不能为空")
|
||||
return fmt.Errorf("decision list cannot be empty")
|
||||
}
|
||||
|
||||
for i, d := range decisions {
|
||||
// 必需字段检查
|
||||
// Required field checks
|
||||
if d.Symbol == "" {
|
||||
return fmt.Errorf("决策#%d: symbol不能为空", i+1)
|
||||
return fmt.Errorf("decision #%d: symbol cannot be empty", i+1)
|
||||
}
|
||||
if d.Action == "" {
|
||||
return fmt.Errorf("决策#%d: action不能为空", i+1)
|
||||
return fmt.Errorf("decision #%d: action cannot be empty", i+1)
|
||||
}
|
||||
if d.Reasoning == "" {
|
||||
return fmt.Errorf("决策#%d: reasoning不能为空", i+1)
|
||||
return fmt.Errorf("decision #%d: reasoning cannot be empty", i+1)
|
||||
}
|
||||
|
||||
// 动作类型检查
|
||||
// Action type validation
|
||||
validActions := map[string]bool{
|
||||
"HOLD": true,
|
||||
"PARTIAL_CLOSE": true,
|
||||
@@ -358,16 +358,16 @@ func ValidateDecisionFormat(decisions []Decision) error {
|
||||
"WAIT": true,
|
||||
}
|
||||
if !validActions[d.Action] {
|
||||
return fmt.Errorf("决策#%d: 无效的action类型: %s", i+1, d.Action)
|
||||
return fmt.Errorf("decision #%d: invalid action type: %s", i+1, d.Action)
|
||||
}
|
||||
|
||||
// 开新仓位的必需参数检查
|
||||
// Required parameters for opening new positions
|
||||
if d.Action == "OPEN_NEW" {
|
||||
if d.Leverage == 0 {
|
||||
return fmt.Errorf("决策#%d: OPEN_NEW动作需要提供leverage", i+1)
|
||||
return fmt.Errorf("decision #%d: OPEN_NEW action requires leverage", i+1)
|
||||
}
|
||||
if d.PositionSizeUSD == 0 {
|
||||
return fmt.Errorf("决策#%d: OPEN_NEW动作需要提供position_size_usd", i+1)
|
||||
return fmt.Errorf("decision #%d: OPEN_NEW action requires position_size_usd", i+1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,8 +170,8 @@ func TestValidateDecisionFormat(t *testing.T) {
|
||||
t.Error("Empty decisions should return error")
|
||||
}
|
||||
|
||||
if !strings.Contains(err.Error(), "不能为空") {
|
||||
t.Errorf("Error message should mention '不能为空', got: %v", err)
|
||||
if !strings.Contains(err.Error(), "cannot be empty") {
|
||||
t.Errorf("Error message should mention 'cannot be empty', got: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -238,8 +238,8 @@ func TestValidateDecisionFormat(t *testing.T) {
|
||||
t.Error("Invalid action should return error")
|
||||
}
|
||||
|
||||
if !strings.Contains(err.Error(), "无效的action") {
|
||||
t.Errorf("Error should mention '无效的action', got: %v", err)
|
||||
if !strings.Contains(err.Error(), "invalid action") {
|
||||
t.Errorf("Error should mention 'invalid action', got: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
+39
-39
@@ -1,17 +1,17 @@
|
||||
package kernel
|
||||
|
||||
// ============================================================================
|
||||
// Trading Data Schema - 交易数据字典
|
||||
// Trading Data Schema
|
||||
// ============================================================================
|
||||
// 双语数据字典,支持中文和英文
|
||||
// 确保AI能够100%理解数据格式,无论使用哪种语言
|
||||
// Bilingual data dictionary supporting Chinese and English.
|
||||
// Ensures AI can fully understand data formats regardless of language.
|
||||
// ============================================================================
|
||||
|
||||
const (
|
||||
SchemaVersion = "1.0.0"
|
||||
)
|
||||
|
||||
// Language 语言类型
|
||||
// Language represents the language type
|
||||
type Language string
|
||||
|
||||
const (
|
||||
@@ -19,20 +19,20 @@ const (
|
||||
LangEnglish Language = "en-US"
|
||||
)
|
||||
|
||||
// ========== 双语字段定义 ==========
|
||||
// ========== Bilingual Field Definitions ==========
|
||||
|
||||
// BilingualFieldDef 双语字段定义
|
||||
// BilingualFieldDef defines a field with bilingual name, formula, and description
|
||||
type BilingualFieldDef struct {
|
||||
NameZH string // 中文名称
|
||||
NameZH string // Chinese name
|
||||
NameEN string // English name
|
||||
Unit string // 单位
|
||||
FormulaZH string // 中文公式
|
||||
Unit string // unit of measurement
|
||||
FormulaZH string // Chinese formula
|
||||
FormulaEN string // English formula
|
||||
DescZH string // 中文描述
|
||||
DescZH string // Chinese description
|
||||
DescEN string // English description
|
||||
}
|
||||
|
||||
// GetName 获取字段名称(根据语言)
|
||||
// GetName returns the field name based on language
|
||||
func (d BilingualFieldDef) GetName(lang Language) string {
|
||||
if lang == LangChinese {
|
||||
return d.NameZH
|
||||
@@ -40,7 +40,7 @@ func (d BilingualFieldDef) GetName(lang Language) string {
|
||||
return d.NameEN
|
||||
}
|
||||
|
||||
// GetFormula 获取公式(根据语言)
|
||||
// GetFormula returns the formula based on language
|
||||
func (d BilingualFieldDef) GetFormula(lang Language) string {
|
||||
if lang == LangChinese {
|
||||
return d.FormulaZH
|
||||
@@ -48,7 +48,7 @@ func (d BilingualFieldDef) GetFormula(lang Language) string {
|
||||
return d.FormulaEN
|
||||
}
|
||||
|
||||
// GetDesc 获取描述(根据语言)
|
||||
// GetDesc returns the description based on language
|
||||
func (d BilingualFieldDef) GetDesc(lang Language) string {
|
||||
if lang == LangChinese {
|
||||
return d.DescZH
|
||||
@@ -56,9 +56,9 @@ func (d BilingualFieldDef) GetDesc(lang Language) string {
|
||||
return d.DescEN
|
||||
}
|
||||
|
||||
// ========== 数据字典 ==========
|
||||
// ========== Data Dictionary ==========
|
||||
|
||||
// DataDictionary 数据字典:定义所有字段的含义
|
||||
// DataDictionary defines the meaning of all fields
|
||||
var DataDictionary = map[string]map[string]BilingualFieldDef{
|
||||
"AccountMetrics": {
|
||||
"Equity": {
|
||||
@@ -217,18 +217,18 @@ var DataDictionary = map[string]map[string]BilingualFieldDef{
|
||||
},
|
||||
}
|
||||
|
||||
// ========== 双语规则定义 ==========
|
||||
// ========== Bilingual Rule Definitions ==========
|
||||
|
||||
// BilingualRuleDef 双语规则定义
|
||||
// BilingualRuleDef defines a trading rule with bilingual description and reason
|
||||
type BilingualRuleDef struct {
|
||||
Value interface{} // 规则值
|
||||
DescZH string // 中文描述
|
||||
Value interface{} // rule value
|
||||
DescZH string // Chinese description
|
||||
DescEN string // English description
|
||||
ReasonZH string // 中文原因
|
||||
ReasonZH string // Chinese reason
|
||||
ReasonEN string // English reason
|
||||
}
|
||||
|
||||
// GetDesc 获取描述(根据语言)
|
||||
// GetDesc returns the description based on language
|
||||
func (d BilingualRuleDef) GetDesc(lang Language) string {
|
||||
if lang == LangChinese {
|
||||
return d.DescZH
|
||||
@@ -236,7 +236,7 @@ func (d BilingualRuleDef) GetDesc(lang Language) string {
|
||||
return d.DescEN
|
||||
}
|
||||
|
||||
// GetReason 获取原因(根据语言)
|
||||
// GetReason returns the reason based on language
|
||||
func (d BilingualRuleDef) GetReason(lang Language) string {
|
||||
if lang == LangChinese {
|
||||
return d.ReasonZH
|
||||
@@ -244,9 +244,9 @@ func (d BilingualRuleDef) GetReason(lang Language) string {
|
||||
return d.ReasonEN
|
||||
}
|
||||
|
||||
// ========== 交易规则 ==========
|
||||
// ========== Trading Rules ==========
|
||||
|
||||
// TradingRules 交易规则定义
|
||||
// TradingRules defines the trading rules
|
||||
var TradingRules = struct {
|
||||
RiskManagement map[string]BilingualRuleDef
|
||||
EntrySignals map[string]BilingualRuleDef
|
||||
@@ -340,9 +340,9 @@ var TradingRules = struct {
|
||||
},
|
||||
}
|
||||
|
||||
// ========== OI解读 ==========
|
||||
// ========== OI Interpretation ==========
|
||||
|
||||
// OIInterpretation OI变化的市场解读(双语)
|
||||
// OIInterpretation defines bilingual market interpretations for OI changes
|
||||
type OIInterpretationType struct {
|
||||
OIUp_PriceUp struct {
|
||||
ZH string
|
||||
@@ -393,9 +393,9 @@ var OIInterpretation = OIInterpretationType{
|
||||
},
|
||||
}
|
||||
|
||||
// ========== 常见错误 ==========
|
||||
// ========== Common Mistakes ==========
|
||||
|
||||
// CommonMistake 常见错误定义
|
||||
// CommonMistake defines a common mistake with bilingual fields
|
||||
type CommonMistake struct {
|
||||
ErrorZH string
|
||||
ErrorEN string
|
||||
@@ -440,9 +440,9 @@ var CommonMistakes = []CommonMistake{
|
||||
},
|
||||
}
|
||||
|
||||
// ========== Prompt生成函数 ==========
|
||||
// ========== Prompt Generation Functions ==========
|
||||
|
||||
// GetSchemaPrompt 生成Schema说明文本,用于AI Prompt
|
||||
// GetSchemaPrompt generates schema description text for AI prompts
|
||||
func GetSchemaPrompt(lang Language) string {
|
||||
if lang == LangChinese {
|
||||
return getSchemaPromptZH()
|
||||
@@ -450,36 +450,36 @@ func GetSchemaPrompt(lang Language) string {
|
||||
return getSchemaPromptEN()
|
||||
}
|
||||
|
||||
// getSchemaPromptZH 生成中文Prompt
|
||||
// getSchemaPromptZH generates the Chinese prompt
|
||||
func getSchemaPromptZH() string {
|
||||
prompt := "# 📖 数据字典与交易规则\n\n"
|
||||
prompt += "## 📊 字段含义说明\n\n"
|
||||
|
||||
// 账户指标
|
||||
// Account metrics
|
||||
prompt += "### 账户指标\n"
|
||||
for key, field := range DataDictionary["AccountMetrics"] {
|
||||
prompt += formatFieldDefZH(key, field)
|
||||
}
|
||||
|
||||
// 交易指标
|
||||
// Trade metrics
|
||||
prompt += "\n### 交易指标\n"
|
||||
for key, field := range DataDictionary["TradeMetrics"] {
|
||||
prompt += formatFieldDefZH(key, field)
|
||||
}
|
||||
|
||||
// 持仓指标
|
||||
// Position metrics
|
||||
prompt += "\n### 持仓指标\n"
|
||||
for key, field := range DataDictionary["PositionMetrics"] {
|
||||
prompt += formatFieldDefZH(key, field)
|
||||
}
|
||||
|
||||
// 市场数据
|
||||
// Market data
|
||||
prompt += "\n### 市场数据\n"
|
||||
for key, field := range DataDictionary["MarketData"] {
|
||||
prompt += formatFieldDefZH(key, field)
|
||||
}
|
||||
|
||||
// OI解读
|
||||
// OI interpretation
|
||||
prompt += "\n## 💹 持仓量(OI)变化解读\n\n"
|
||||
prompt += "- **OI增加 + 价格上涨**: " + OIInterpretation.OIUp_PriceUp.ZH + "\n"
|
||||
prompt += "- **OI增加 + 价格下跌**: " + OIInterpretation.OIUp_PriceDown.ZH + "\n"
|
||||
@@ -489,7 +489,7 @@ func getSchemaPromptZH() string {
|
||||
return prompt
|
||||
}
|
||||
|
||||
// getSchemaPromptEN 生成英文Prompt
|
||||
// getSchemaPromptEN generates the English prompt
|
||||
func getSchemaPromptEN() string {
|
||||
prompt := "# 📖 Data Dictionary & Trading Rules\n\n"
|
||||
prompt += "## 📊 Field Definitions\n\n"
|
||||
@@ -528,7 +528,7 @@ func getSchemaPromptEN() string {
|
||||
return prompt
|
||||
}
|
||||
|
||||
// formatFieldDefZH 格式化中文字段定义
|
||||
// formatFieldDefZH formats a field definition in Chinese
|
||||
func formatFieldDefZH(key string, field BilingualFieldDef) string {
|
||||
result := "- **" + key + "**(" + field.NameZH + "): " + field.DescZH
|
||||
if field.FormulaZH != "" {
|
||||
@@ -541,7 +541,7 @@ func formatFieldDefZH(key string, field BilingualFieldDef) string {
|
||||
return result
|
||||
}
|
||||
|
||||
// formatFieldDefEN 格式化英文字段定义
|
||||
// formatFieldDefEN formats a field definition in English
|
||||
func formatFieldDefEN(key string, field BilingualFieldDef) string {
|
||||
result := "- **" + key + "** (" + field.NameEN + "): " + field.DescEN
|
||||
if field.FormulaEN != "" {
|
||||
|
||||
Reference in New Issue
Block a user