Back to Nofx

NOFX 策略模块技术文档

docs/architecture/STRATEGY_MODULE.zh-CN.md

latest20.8 KB
Original Source

NOFX 策略模块技术文档

语言: English | 中文

概述

本文档详细描述 NOFX 策略模块的完整数据流程,包括币种选择、数据组装、提示词构建、AI 请求、响应解析和决策执行。


完整数据流程图

┌─────────────────────────────────────────────────────────────────┐
│                    交易周期 (每 N 分钟)                          │
└─────────────────────────────────────────────────────────────────┘

1. 币种选择 (GetCandidateCoins)
   ├─ Static (静态列表)
   ├─ AI500 Pool (AI评分池)
   ├─ OI Top (持仓增长榜)
   └─ Mixed (混合模式)
        ↓
2. 数据组装 (buildTradingContext)
   ├─ 账户余额 → equity, available, unrealizedPnL
   ├─ 当前持仓 → symbol, side, entry, mark, qty, leverage
   ├─ K线数据 → OHLCV (5m, 15m, 1h, 4h)
   ├─ 技术指标 → EMA, MACD, RSI, ATR, Volume
   ├─ 链上数据 → OI, Funding Rate
   ├─ 量化数据 → 资金流向, OI变化 (可选)
   └─ 最近交易 → 最近10笔已平仓
        ↓
3. 系统提示词 (BuildSystemPrompt)
   ├─ 角色定义
   ├─ 交易模式 (aggressive/conservative/scalping)
   ├─ 硬性约束 (代码强制执行)
   ├─ AI引导 (建议值)
   ├─ 交易频率
   ├─ 入场标准
   ├─ 决策流程
   └─ 输出格式 (XML + JSON)
        ↓
4. 用户提示词 (BuildUserPrompt)
   ├─ 系统状态 (时间, 周期号)
   ├─ BTC市场概览
   ├─ 账户信息
   ├─ 当前持仓 (含技术指标)
   ├─ 候选币种 (完整市场数据)
   └─ "请分析并输出决策..."
        ↓
5. AI请求 (CallWithMessages)
   ├─ 选择AI模型
   ├─ POST: system_prompt + user_prompt
   ├─ 超时: 120秒, 重试: 3次
   └─ 返回原始响应
        ↓
6. AI解析 (parseFullDecisionResponse)
   ├─ 提取思维链 <reasoning>
   ├─ 提取JSON决策 <decision>
   ├─ 修复字符编码
   ├─ 验证JSON格式
   ├─ 解析决策数组
   └─ 验证风控参数
        ↓
7. 决策执行
   ├─ 排序: 平仓优先 → 开仓 → hold/wait
   ├─ 风控强制执行
   ├─ 提交订单
   ├─ 确认成交
   └─ 记录到数据库

1. 币种选择 (Coin Selection)

核心文件: decision/engine.go:380-454

入口方法: StrategyEngine.GetCandidateCoins()

1.1 静态币种列表 (Static)

go
// decision/engine.go:395-403
if config.CoinSource.SourceType == "static" {
    for _, symbol := range config.CoinSource.StaticCoins {
        coins = append(coins, CandidateCoin{
            Symbol:  market.Normalize(symbol),
            Sources: []string{"static"},
        })
    }
}
  • 配置: StrategyConfig.CoinSource.StaticCoins
  • 用途: 手动指定交易币种
  • 标签: ["static"]

1.2 AI500 币种池 (CoinPool)

go
// decision/engine.go:405-406, 456-474
func (e *StrategyEngine) getCoinPoolCoins(limit int) []CandidateCoin {
    coins, err := e.provider.GetTopRatedCoins(limit)
    // ...
    for _, coin := range coins {
        result = append(result, CandidateCoin{
            Symbol:  coin.Symbol,
            Sources: []string{"ai500"},
        })
    }
}
  • API: config.CoinSource.CoinPoolAPIURL (默认: https://nofxos.ai/api/ai500/list)
  • 用途: 获取 AI 评分最高的 N 个币种
  • 标签: ["ai500"]

1.3 OI Top 币种 (持仓增长榜)

go
// decision/engine.go:408-409, 476-498
func (e *StrategyEngine) getOITopCoins() []CandidateCoin {
    positions, err := e.provider.GetOITopPositions()
    // ...
    for _, pos := range positions {
        result = append(result, CandidateCoin{
            Symbol:  pos.Symbol,
            Sources: []string{"oi_top"},
        })
    }
}
  • API: config.CoinSource.OITopAPIURL
  • 用途: 获取持仓量增长最快的币种
  • 标签: ["oi_top"]

1.4 混合模式 (Mixed)

go
// decision/engine.go:411-449
if config.CoinSource.SourceType == "mixed" {
    if config.CoinSource.UseCoinPool {
        // 添加 AI500 币种
    }
    if config.CoinSource.UseOITop {
        // 添加 OI Top 币种
    }
    if len(config.CoinSource.StaticCoins) > 0 {
        // 添加静态币种
    }
    // 去重合并,保留多来源标签
}
  • 特点: 同时使用多个数据源
  • 标签示例: ["ai500", "oi_top"] (双信号币种)

2. 数据组装 (Data Assembly)

核心文件: trader/auto_trader.go:562-791, decision/engine.go:299-374

入口方法: AutoTrader.buildTradingContext()

2.1 账户数据

go
// trader/auto_trader.go:565-583
balance, err := at.trader.GetBalance()
equity := balance["total_equity"].(float64)
available := balance["available_balance"].(float64)
unrealizedPnL := balance["total_pnl"].(float64)

提取字段:

  • total_equity - 账户总权益
  • available_balance - 可用余额
  • total_pnl - 未实现盈亏

2.2 持仓数据

go
// trader/auto_trader.go:588-682
positions, err := at.trader.GetPositions()
for _, pos := range positions {
    position := decision.Position{
        Symbol:           pos.Symbol,
        Side:             pos.Side,          // "long" / "short"
        EntryPrice:       pos.EntryPrice,
        MarkPrice:        pos.MarkPrice,
        Quantity:         pos.Quantity,
        Leverage:         pos.Leverage,
        UnrealizedPnL:    pos.UnrealizedPnL,
        LiquidationPrice: pos.LiquidationPrice,
    }
}

2.3 市场数据获取

go
// decision/engine.go:299-374
func (e *StrategyEngine) fetchMarketDataWithStrategy(symbols []string) map[string]*market.Data {
    timeframes := config.Indicators.Klines.SelectedTimeframes  // ["5m", "15m", "1h", "4h"]
    primaryTF := config.Indicators.Klines.PrimaryTimeframe     // "5m"
    count := config.Indicators.Klines.PrimaryCount             // 30

    for _, symbol := range symbols {
        data := market.GetWithTimeframes(symbol, timeframes, primaryTF, count)
        result[symbol] = data
    }
}

2.4 技术指标计算

文件: market/data.go:59-98

指标配置计算方法
EMAEnableEMA, EMAPeriodscalculateEMA(klines, period)
MACDEnableMACDcalculateMACD(klines) - 12/26/9
RSIEnableRSI, RSIPeriodscalculateRSI(klines, period)
ATREnableATR, ATRPeriodscalculateATR(klines, period)
VolumeEnableVolume原始成交量数据
OIEnableOI持仓量数据
Funding RateEnableFundingRate资金费率

2.5 量化数据 (可选)

go
// trader/auto_trader.go:759-778
if config.Indicators.EnableQuantData {
    quantData := provider.GetQuantData(symbol)
    // 包含: 资金流向、OI变化、价格变化
}

数据结构:

go
QuantData {
    Netflow {
        Institution: {Future, Spot},  // 机构资金流
        Personal: {Future, Spot}      // 散户资金流
    },
    OI {
        CurrentOI: float64,
        Delta: {1h, 4h, 24h}          // OI变化
    },
    PriceChange {
        "1h", "4h", "24h": float64    // 价格变化百分比
    }
}

3. 系统提示词 (System Prompt)

核心文件: decision/engine.go:700-818

入口方法: StrategyEngine.BuildSystemPrompt(accountEquity, variant)

3.1 提示词结构 (8个部分)

1. 角色定义          [可编辑]
2. 交易模式变体      [运行时确定]
3. 硬性约束          [代码强制 + AI引导]
4. 交易频率          [可编辑]
5. 入场标准          [可编辑]
6. 决策流程          [可编辑]
7. 输出格式          [固定XML + JSON结构]
8. 自定义提示词      [可选]

3.2 角色定义

go
// decision/engine.go:706-713
roleDefinition := config.PromptSections.RoleDefinition
if roleDefinition == "" {
    roleDefinition = "You are a professional cryptocurrency trading AI..."
}

3.3 交易模式变体

模式特点
aggressive趋势突破,较高仓位容忍度
conservative多信号确认,保守资金管理
scalping短线动量,紧止盈

3.4 硬性约束

代码强制执行 (CODE ENFORCED):

go
// decision/engine.go:725-749
maxPositions := config.RiskControl.MaxPositions           // 默认: 3
altcoinMaxRatio := config.RiskControl.AltcoinMaxPositionValueRatio  // 默认: 1.0
btcethMaxRatio := config.RiskControl.BTCETHMaxPositionValueRatio    // 默认: 5.0
maxMarginUsage := config.RiskControl.MaxMarginUsage       // 默认: 90%
minPositionSize := config.RiskControl.MinPositionSize     // 默认: 12 USDT

AI引导 (建议值):

go
altcoinMaxLeverage := config.RiskControl.AltcoinMaxLeverage  // 默认: 5x
btcethMaxLeverage := config.RiskControl.BTCETHMaxLeverage    // 默认: 5x
minRiskRewardRatio := config.RiskControl.MinRiskRewardRatio  // 默认: 1:3
minConfidence := config.RiskControl.MinConfidence            // 默认: 75

3.5 输出格式要求

xml
<reasoning>
[思维链分析过程]
</reasoning>

<decision>
```json
[
  {
    "symbol": "BTCUSDT",
    "action": "open_long",
    "leverage": 5,
    "position_size_usd": 100.00,
    "stop_loss": 65000.00,
    "take_profit": 72000.00,
    "confidence": 85,
    "risk_usd": 20.00,
    "reasoning": "..."
  }
]
</decision> ```

4. 用户提示词 (User Prompt)

核心文件: decision/engine.go:884-1007

入口方法: StrategyEngine.BuildUserPrompt(ctx)

4.1 提示词内容结构

1. 系统状态          [时间, 周期号, 运行时长]
2. BTC市场概览      [价格, 涨跌幅, MACD, RSI]
3. 账户信息          [权益, 余额%, 盈亏%, 保证金%, 持仓数]
4. 最近成交          [最近10笔已平仓交易]
5. 当前持仓          [详细持仓数据 + 技术指标]
6. 候选币种          [完整市场数据]
7. 量化数据          [资金流向, OI数据] (可选)
8. OI排行数据        [市场OI变化排行] (可选)

4.2 账户信息格式

Account: Equity 1000.00 | Balance 800.00 (80.0%) | PnL +5.5% | Margin 20.0% | Positions 2

4.3 持仓信息格式

1. BTCUSDT LONG | Entry 68000.0000 Current 69500.0000
   Qty 0.0100 | Position Value $695.00
   PnL +2.21% | Amount +$15.00
   Peak PnL +3.50% | Leverage 5x
   Margin $139.00 | Liquidation Price 55000.0000
   Holding Duration 2 hours 30 minutes

   Market: price=69500, ema20=68800, macd=150.5, rsi7=62.3
   OI: Latest=15000000, Avg=14500000
   Funding Rate: 0.0100%

4.4 候选币种格式

### 1. ETHUSDT (AI500+OI_Top dual signal)

current_price = 3500.00, current_ema20 = 3450.00, current_macd = 25.5, current_rsi7 = 58.0

Open Interest: Latest: 8500000.00 Average: 8200000.00
Funding Rate: 0.0050

=== 5M TIMEFRAME (oldest → latest) ===
Prices: [3480, 3485, 3490, 3495, 3500]
Volumes: [1000, 1200, 1100, 1300, 1150]
EMA20: [3470, 3475, 3478, 3482, 3485]
MACD: [20.1, 21.5, 22.8, 24.0, 25.5]
RSI7: [55.0, 56.2, 57.1, 57.8, 58.0]

=== 15M TIMEFRAME ===
...

5. AI请求 (AI Request)

核心文件: decision/engine.go:222-293, mcp/client.go:136-150

5.1 请求流程

go
// decision/engine.go:263-268
aiCallStart := time.Now()
aiResponse, err := mcpClient.CallWithMessages(systemPrompt, userPrompt)
aiCallDuration := time.Since(aiCallStart)

5.2 支持的AI模型

模型客户端文件默认模型
DeepSeekmcp/deepseek_client.godeepseek-chat
Qwenmcp/qwen_client.goqwen-max
Claudemcp/claude_client.goclaude-3-5-sonnet
Geminimcp/gemini_client.gogemini-pro
Grokmcp/grok_client.gogrok-beta
OpenAImcp/openai_client.gogpt-5.2
Kimimcp/kimi_client.gomoonshot-v1-8k

5.3 请求参数

go
// mcp/client.go
Timeout: 120 seconds
MaxRetries: 3
RetryDelay: 2 seconds (exponential backoff)

6. AI响应解析 (Response Parsing)

核心文件: decision/engine.go:1303-1604

入口方法: parseFullDecisionResponse(response, accountEquity, leverage, ratio)

6.1 解析流程

原始AI响应 (文本)
    ↓
1. 提取思维链  [extractCoTTrace()]
    ↓
2. 提取JSON决策  [extractDecisions()]
    ↓
3. 验证JSON格式  [validateJSONFormat()]
    ↓
4. 解析JSON  [json.Unmarshal()]
    ↓
5. 验证决策  [validateDecisions()]
    ↓
6. 构建FullDecision  [返回结构化结果]

6.2 思维链提取

go
// decision/engine.go:1327-1345
func extractCoTTrace(response string) string {
    // 优先级1: <reasoning> XML标签
    if match := reReasoningTag.FindStringSubmatch(response); len(match) > 1 {
        return strings.TrimSpace(match[1])
    }
    // 优先级2: <decision>标签之前的文本
    // 优先级3: JSON [ 之前的文本
    // 优先级4: 完整响应
}

6.3 JSON决策提取

go
// decision/engine.go:1347-1408
func extractDecisions(response string) (string, error) {
    // 1. 移除不可见字符
    response = removeInvisibleRunes(response)

    // 2. 修复字符编码
    response = fixMissingQuotes(response)

    // 3. 提取JSON (优先级)
    //    - <decision> XML标签 + ```json
    //    - 独立 ```json 代码块
    //    - 裸JSON数组
}

6.4 字符编码修复

go
// decision/engine.go:1410-1432
func fixMissingQuotes(s string) string {
    // 中文引号 → ASCII
    s = strings.ReplaceAll(s, """, "\"")
    s = strings.ReplaceAll(s, """, "\"")

    // 中文括号 → ASCII
    s = strings.ReplaceAll(s, "[", "[")
    s = strings.ReplaceAll(s, "]", "]")
    s = strings.ReplaceAll(s, "{", "{")
    s = strings.ReplaceAll(s, "}", "}")

    // 中文标点 → ASCII
    s = strings.ReplaceAll(s, ":", ":")
    s = strings.ReplaceAll(s, ",", ",")
}

6.5 决策验证

go
// decision/engine.go:1480-1602
func validateDecisions(decisions []Decision, equity, leverage, ratio float64) error {
    for _, d := range decisions {
        // 1. 验证action类型
        validActions := []string{"open_long", "open_short", "close_long", "close_short", "hold", "wait"}

        // 2. 开仓验证
        if isOpenAction(d.Action) {
            // 杠杆范围检查
            // 仓位大小检查
            // 止损止盈检查
            // 风险回报比检查
            // 置信度检查
        }

        // 3. 平仓验证
        if isCloseAction(d.Action) {
            // Symbol必须存在
        }
    }
}

6.6 Decision结构体

go
// decision/engine.go:128-143
type Decision struct {
    Symbol          string   // 交易对: "BTCUSDT"
    Action          string   // "open_long", "open_short", "close_long", "close_short", "hold", "wait"
    Leverage        int      // 杠杆倍数
    PositionSizeUSD float64  // 仓位价值 (USDT)
    StopLoss        float64  // 止损价格
    TakeProfit      float64  // 止盈价格
    Confidence      int      // 置信度 0-100
    RiskUSD         float64  // 最大风险 (USDT)
    Reasoning       string   // 决策理由
}

7. 决策执行 (Execution)

核心文件: trader/auto_trader.go:392-560

7.1 决策排序

go
// trader/auto_trader.go:519-526
sort.SliceStable(decisions, func(i, j int) bool {
    priority := map[string]int{
        "close_long": 1, "close_short": 1,  // 最高优先级
        "open_long": 2, "open_short": 2,    // 次优先级
        "hold": 3, "wait": 3,               // 最低优先级
    }
    return priority[decisions[i].Action] < priority[decisions[j].Action]
})

7.2 风控强制执行

文件: trader/auto_trader.go:1769-1851

检查项方法动作
最大持仓数enforceMaxPositions()拒绝新开仓
仓位价值上限enforcePositionValueRatio()自动缩减仓位
最小仓位enforceMinPositionSize()拒绝过小订单
保证金调整自动计算根据可用余额调整

7.3 订单执行

go
// trader/auto_trader.go:1631-1767
func (at *AutoTrader) recordAndConfirmOrder(orderID, symbol, side, action string) {
    // 1. 轮询订单状态 (5次重试, 500ms间隔)
    for i := 0; i < 5; i++ {
        status := at.trader.GetOrderStatus(orderID)
        if status.Status == "FILLED" {
            break
        }
        time.Sleep(500 * time.Millisecond)
    }

    // 2. 提取成交信息
    filledPrice := status.AvgPrice
    filledQty := status.FilledQty
    fee := status.Fee

    // 3. 记录到数据库
    at.store.Position().SaveOrder(...)
}

7.4 决策日志保存

go
// trader/auto_trader.go:1235-1256
record := &store.DecisionRecord{
    CycleNumber:    cycleNumber,
    TraderID:       traderID,
    Timestamp:      time.Now(),
    SystemPrompt:   systemPrompt,     // 完整系统提示词
    InputPrompt:    userPrompt,       // 完整用户提示词
    CoTTrace:       cotTrace,         // AI思维链
    DecisionJSON:   decisionsJSON,    // 解析后的决策
    RawResponse:    rawResponse,      // 原始AI响应
    ExecutionLog:   executionResults, // 执行结果
    CandidateCoins: candidateCoins,   // 候选币种
    Success:        success,          // 执行状态
}
at.store.Decision().LogDecision(record)

核心文件索引

模块文件关键方法
主循环trader/auto_trader.goRun(), runCycle(), buildTradingContext()
币种选择decision/engine.go:380-454GetCandidateCoins()
数据获取market/data.goGet(), GetWithTimeframes()
指标计算market/data.go:59-98calculateEMA(), calculateMACD(), calculateRSI()
系统提示词decision/engine.go:700-818BuildSystemPrompt()
用户提示词decision/engine.go:884-1007BuildUserPrompt()
市场数据格式化decision/engine.go:1029-1099formatMarketData()
AI请求decision/engine.go:222-293GetFullDecisionWithStrategy()
MCP客户端mcp/client.go:136-150CallWithMessages()
响应解析decision/engine.go:1303-1604parseFullDecisionResponse()
思维链提取decision/engine.go:1327-1345extractCoTTrace()
JSON提取decision/engine.go:1347-1408extractDecisions()
决策验证decision/engine.go:1480-1602validateDecisions()
风控执行trader/auto_trader.go:1769-1851enforceMaxPositions(), enforcePositionValueRatio()
策略配置store/strategy.goStrategyConfig, RiskControlConfig
数据提供者provider/data_provider.goGetAI500Data(), GetOITopPositions()

配置参考

策略配置结构

go
// store/strategy.go
type StrategyConfig struct {
    // 币种来源
    CoinSource struct {
        SourceType     string   // "static", "coinpool", "oi_top", "mixed"
        StaticCoins    []string // 静态币种列表
        UseCoinPool    bool     // 是否使用AI500
        UseOITop       bool     // 是否使用OI排行
        CoinPoolLimit  int      // AI500获取数量
        CoinPoolAPIURL string   // AI500 API地址
        OITopAPIURL    string   // OI排行 API地址
    }

    // 技术指标
    Indicators struct {
        EnableEMA         bool
        EMAPeriods        []int   // [20, 50]
        EnableMACD        bool
        EnableRSI         bool
        RSIPeriods        []int   // [7, 14]
        EnableATR         bool
        ATRPeriods        []int   // [14]
        EnableVolume      bool
        EnableOI          bool
        EnableFundingRate bool
        EnableQuantData   bool
        EnableOIRanking   bool

        Klines struct {
            PrimaryTimeframe   string   // "5m"
            SelectedTimeframes []string // ["5m", "15m", "1h", "4h"]
            PrimaryCount       int      // 30
        }
    }

    // 风控配置
    RiskControl struct {
        MaxPositions               int     // 最大持仓数
        BTCETHMaxLeverage          int     // BTC/ETH最大杠杆
        AltcoinMaxLeverage         int     // 山寨币最大杠杆
        BTCETHMaxPositionValueRatio float64 // BTC/ETH仓位比例上限
        AltcoinMaxPositionValueRatio float64 // 山寨币仓位比例上限
        MaxMarginUsage             float64 // 最大保证金使用率
        MinPositionSize            float64 // 最小仓位
        MinRiskRewardRatio         float64 // 最小风险回报比
        MinConfidence              int     // 最小置信度
    }

    // 提示词部分
    PromptSections struct {
        RoleDefinition   string
        TradingFrequency string
        EntryStandards   string
        DecisionProcess  string
    }

    // 自定义提示词
    CustomPrompt string
}

文档版本: 1.0.0 最后更新: 2025-01-15