diff --git a/docs/architecture/BACKTEST_MODULE.md b/docs/architecture/BACKTEST_MODULE.md new file mode 100644 index 00000000..f8f580c1 --- /dev/null +++ b/docs/architecture/BACKTEST_MODULE.md @@ -0,0 +1,622 @@ +# NOFX 回测模块技术文档 + +## 概述 + +本文档详细描述 NOFX 回测模块的完整技术实现,包括配置、历史数据加载、模拟引擎、AI 决策、性能指标计算和结果存储。 + +--- + +## 完整回测流程图 + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 回测执行流程 │ +└─────────────────────────────────────────────────────────────────┘ + +1. API 请求: /backtest/start + ↓ +2. Manager.Start() + ├─ 验证配置 + ├─ 解析 AI 模型 + ├─ 创建 Runner 实例 + └─ 启动 runner.Start() (goroutine) + ↓ +3. Runner.Start() → Runner.loop() + └─ 遍历每个决策时间点: + ├─ DataFeed.BuildMarketData() [构建市场数据] + ├─ 检查决策触发条件 [每 N 根 K 线] + ├─ buildDecisionContext() [构建决策上下文] + ├─ invokeAIWithRetry() [调用 AI + 缓存] + ├─ executeDecision() [执行交易] + ├─ checkLiquidation() [检查爆仓] + ├─ updateState() [更新状态] + ├─ appendEquityPoint() [记录权益] + ├─ appendTradeEvent() [记录交易] + ├─ maybeCheckpoint() [保存检查点] + └─ persistMetrics() [持久化指标] + ↓ +4. 完成/失败 + ├─ 计算最终指标 + ├─ 持久化所有结果 + └─ 释放锁 + ↓ +5. API 查询: /backtest/metrics, /backtest/equity, /backtest/trades + └─ 加载并返回结果 +``` + +--- + +## 1. 回测配置 (Configuration) + +**核心文件:** `backtest/config.go` + +### 1.1 配置参数 + +| 参数 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `RunID` | string | (必填) | 回测运行唯一标识 | +| `UserID` | string | "default" | 用户 ID | +| `Symbols` | []string | (必填) | 交易币种列表 | +| `Timeframes` | []string | ["3m", "15m", "4h"] | K 线周期 | +| `DecisionTimeframe` | string | Symbols[0] | 主决策周期 | +| `DecisionCadenceNBars` | int | 20 | 每 N 根 K 线触发一次决策 | +| `StartTS`, `EndTS` | int64 | (必填) | 回测时间范围 (Unix 时间戳) | +| `InitialBalance` | float64 | 1000 | 初始资金 (USD) | +| `FeeBps` | float64 | 5 | 手续费 (基点) | +| `SlippageBps` | float64 | 2 | 滑点 (基点) | +| `FillPolicy` | string | "next_open" | 成交策略 | +| `PromptVariant` | string | "baseline" | AI 提示词变体 | +| `CacheAI` | bool | false | 是否缓存 AI 决策 | +| `Leverage` | LeverageConfig | BTC/ETH:5, Altcoin:5 | 杠杆设置 | + +### 1.2 成交策略 (Fill Policy) + +```go +// backtest/config.go:163-179 +switch fillPolicy { +case "next_open": // 下一根 K 线开盘价 +case "bar_vwap": // 当前 K 线 VWAP +case "mid": // 当前 K 线 (High+Low)/2 +default: // Mark Price +} +``` + +### 1.3 配置示例 + +```go +cfg := backtest.BacktestConfig{ + RunID: "bt_20231215_150405", + Symbols: []string{"BTCUSDT", "ETHUSDT"}, + Timeframes: []string{"3m", "15m", "4h"}, + DecisionTimeframe: "3m", + DecisionCadenceNBars: 20, + StartTS: 1702566000, + EndTS: 1702652400, + InitialBalance: 10000, + FeeBps: 5, + SlippageBps: 2, + FillPolicy: "next_open", +} +``` + +--- + +## 2. 历史数据加载 (Data Loading) + +**核心文件:** `backtest/datafeed.go` + +### 2.1 数据加载流程 + +``` +1. NewDataFeed() - 初始化 + ↓ +2. loadAll() - 加载所有历史数据 + ├─ 计算缓冲区 (StartTS 前 200 根 K 线) + ├─ 调用 market.GetKlinesRange() 获取数据 + ├─ 存储到 symbolSeries map + └─ 从主周期构建决策时间线 + ↓ +3. BuildMarketData() - 构建市场数据快照 + ├─ 切片 K 线数据到当前时间戳 + ├─ 计算技术指标 (EMA, MACD, RSI, ATR) + └─ 返回 market.Data 结构 +``` + +### 2.2 数据结构 + +```go +// DataFeed 核心结构 +type DataFeed struct { + decisionTimes []int64 // 决策时间点列表 + symbolSeries map[string]*symbolSeries // 按币种存储的数据 +} + +// 单币种时间序列 +type symbolSeries struct { + timeframes map[string]*timeframeSeries // 按周期存储 +} + +// 单周期数据 +type timeframeSeries struct { + klines []market.Kline // K 线数据 + closeTimes []int64 // 收盘时间索引 +} +``` + +### 2.3 关键代码引用 + +- 数据获取: `backtest/datafeed.go:48-93` +- 时间线生成: `backtest/datafeed.go:96-115` +- 市场数据组装: `backtest/datafeed.go:141-171` + +--- + +## 3. 模拟引擎 (Simulation Engine) + +**核心文件:** `backtest/runner.go` + +### 3.1 主循环 + +```go +// backtest/runner.go:232-264 +func (r *Runner) loop() { + for _, ts := range r.feed.DecisionTimes() { + if r.isPaused() { + break + } + r.stepOnce(ts) + } +} +``` + +### 3.2 单步执行 + +```go +// backtest/runner.go:266-471 +func (r *Runner) stepOnce(ts int64) { + // 1. 获取当前 K 线时间戳 + // 2. 构建市场数据 + // 3. 检查决策触发条件 (每 N 根 K 线) + // 4. 执行决策周期 (如果触发) + // 5. 检查爆仓 + // 6. 更新状态并记录 +} +``` + +### 3.3 状态管理 + +```go +// backtest/types.go:31-47 +type BacktestState struct { + BarIndex int // 当前 K 线索引 + Cash float64 // 可用余额 + Equity float64 // 总权益 + UnrealizedPnL float64 // 未实现盈亏 + RealizedPnL float64 // 已实现盈亏 + MaxEquity float64 // 最高权益 + MinEquity float64 // 最低权益 + MaxDrawdownPct float64 // 最大回撤 + Positions map[string]*position // 持仓 +} +``` + +--- + +## 4. AI 决策 (AI Decision Making) + +**核心文件:** `backtest/runner.go` + +### 4.1 决策上下文构建 + +```go +// backtest/runner.go:473-532 +func (r *Runner) buildDecisionContext() *decision.Context { + return &decision.Context{ + CurrentTime: "2023-12-15 10:30:00 UTC", + RuntimeMinutes: elapsed, + CallCount: cycleNumber, + Account: { + TotalEquity, AvailableBalance, TotalPnL, MarginUsedPct + }, + Positions: []PositionInfo{...}, + CandidateCoins: []string{symbols...}, + MarketDataMap: map[symbol]*market.Data{...}, + MultiTFMarket: map[symbol]map[timeframe]*market.Data{...}, + } +} +``` + +### 4.2 AI 调用 + +```go +// backtest/runner.go:544-563 +func (r *Runner) invokeAIWithRetry() (*decision.FullDecision, error) { + // 最多重试 3 次 + // 指数退避: 500ms, 1000ms, 1500ms + // 使用 decision.GetFullDecisionWithStrategy() 统一提示词生成 +} +``` + +### 4.3 AI 缓存 + +```go +// backtest/aicache.go:127-168 +// 缓存键: SHA256(context payload) +// 包含: variant, timestamp, account, positions, market data +``` + +### 4.4 支持的 AI 模型 + +| 模型 | 客户端文件 | +|------|-----------| +| DeepSeek | `mcp/deepseek_client.go` | +| Qwen | `mcp/qwen_client.go` | +| Claude | `mcp/claude_client.go` | +| Gemini | `mcp/gemini_client.go` | +| Grok | `mcp/grok_client.go` | +| OpenAI | `mcp/openai_client.go` | +| Kimi | `mcp/kimi_client.go` | + +--- + +## 5. 性能指标 (Performance Metrics) + +**核心文件:** `backtest/metrics.go` + +### 5.1 指标计算 + +| 指标 | 公式 | 代码位置 | +|------|------|----------| +| **总收益率** | (最终权益 - 初始资金) / 初始资金 × 100 | metrics.go:36-42 | +| **最大回撤** | max((峰值 - 当前) / 峰值 × 100) | metrics.go:64-91 | +| **夏普比率** | 平均收益 / 收益标准差 | metrics.go:94-138 | +| **胜率** | 盈利交易数 / 总交易数 × 100 | metrics.go:180-181 | +| **盈亏比** | 总盈利 / 总亏损 | metrics.go:189-193 | + +### 5.2 交易统计 + +```go +// backtest/metrics.go:141-225 +type TradeMetrics struct { + TotalTrades int + WinningTrades int + LosingTrades int + AvgWin float64 + AvgLoss float64 + BestSymbol string + WorstSymbol string + SymbolStats map[string]*SymbolStat +} +``` + +--- + +## 6. 权益曲线 (Equity Curve) + +**核心文件:** `backtest/equity.go` + +### 6.1 权益点结构 + +```json +{ + "ts": 1702566000000, + "equity": 10500.50, + "available": 8000.00, + "pnl": 500.50, + "pnl_pct": 5.005, + "dd_pct": 2.34, + "cycle": 42 +} +``` + +### 6.2 权益更新 + +```go +// backtest/runner.go:829-872 +func (r *Runner) updateState() { + // 1. 计算总权益: cash + margin + 未实现盈亏 + // 2. 追踪峰值 (MaxEquity) + // 3. 追踪谷值 (MinEquity) + // 4. 重新计算回撤: (MaxEquity - Equity) / MaxEquity × 100 +} +``` + +### 6.3 数据重采样 + +```go +// backtest/equity.go:10-50 +func ResampleEquity(points []EquityPoint, timeframe string) []EquityPoint { + // 按时间周期分桶 + // 保留每个桶的最后一个点 +} +``` + +--- + +## 7. 结果存储 (Result Storage) + +**核心文件:** `backtest/storage.go`, `store/backtest.go` + +### 7.1 文件存储结构 + +``` +backtests/ +├── / +│ ├── run.json # 运行元数据 +│ ├── checkpoint.json # 检查点 (用于恢复) +│ ├── equity.jsonl # 权益曲线 (逐行 JSON) +│ ├── trades.jsonl # 交易记录 (逐行 JSON) +│ ├── metrics.json # 性能指标 +│ ├── progress.json # 进度信息 +│ ├── ai_cache.json # AI 决策缓存 +│ └── decision_logs/ # 决策日志 +│ ├── 0.json +│ ├── 1.json +│ └── ... +``` + +### 7.2 数据库表结构 + +```sql +-- 回测运行元数据 +CREATE TABLE backtest_runs ( + run_id TEXT PRIMARY KEY, + user_id TEXT, + config_json TEXT, + state TEXT, -- pending, running, completed, failed + processed_bars INTEGER, + progress_pct REAL, + equity_last REAL, + max_drawdown_pct REAL, + liquidated BOOLEAN, + ai_provider TEXT, + ai_model TEXT, + created_at DATETIME, + updated_at DATETIME +); + +-- 权益曲线 +CREATE TABLE backtest_equity ( + id INTEGER PRIMARY KEY, + run_id TEXT, + ts INTEGER, + equity REAL, + available REAL, + pnl REAL, + pnl_pct REAL, + dd_pct REAL, + cycle INTEGER +); + +-- 交易记录 +CREATE TABLE backtest_trades ( + id INTEGER PRIMARY KEY, + run_id TEXT, + ts INTEGER, + symbol TEXT, + action TEXT, + side TEXT, + qty REAL, + price REAL, + fee REAL, + slippage REAL, + realized_pnl REAL, + leverage INTEGER, + liquidation BOOLEAN +); + +-- 性能指标 +CREATE TABLE backtest_metrics ( + run_id TEXT PRIMARY KEY, + payload BLOB, + updated_at DATETIME +); + +-- 检查点 (暂停/恢复) +CREATE TABLE backtest_checkpoints ( + run_id TEXT PRIMARY KEY, + payload BLOB, + updated_at DATETIME +); +``` + +--- + +## 8. API 接口 + +**核心文件:** `api/backtest.go` + +### 8.1 接口列表 + +| 接口 | 方法 | 说明 | +|------|------|------| +| `/backtest/start` | POST | 开始回测 | +| `/backtest/pause` | POST | 暂停回测 | +| `/backtest/resume` | POST | 恢复回测 | +| `/backtest/stop` | POST | 停止回测 | +| `/backtest/status` | GET | 获取状态 | +| `/backtest/runs` | GET | 列出所有回测 | +| `/backtest/equity` | GET | 获取权益曲线 | +| `/backtest/trades` | GET | 获取交易记录 | +| `/backtest/metrics` | GET | 获取性能指标 | +| `/backtest/trace` | GET | 获取决策日志 | +| `/backtest/export` | GET | 导出 ZIP | +| `/backtest/delete` | POST | 删除回测 | + +### 8.2 请求示例 + +```bash +# 开始回测 +POST /backtest/start +{ + "config": { + "run_id": "bt_20231215", + "symbols": ["BTCUSDT", "ETHUSDT"], + "timeframes": ["3m", "15m", "4h"], + "start_ts": 1702566000, + "end_ts": 1702652400, + "initial_balance": 10000, + "ai_model_id": "model_001" + } +} + +# 获取权益曲线 +GET /backtest/equity?run_id=bt_20231215&tf=1h&limit=1000 + +# 获取指标 +GET /backtest/metrics?run_id=bt_20231215 +``` + +### 8.3 响应示例 + +```json +// 状态响应 +{ + "run_id": "bt_20231215", + "state": "running", + "progress_pct": 45.5, + "processed_bars": 1234, + "equity": 10234.50, + "unrealized_pnl": 234.50 +} + +// 指标响应 +{ + "total_return_pct": 12.34, + "max_drawdown_pct": 5.67, + "sharpe_ratio": 1.89, + "profit_factor": 2.34, + "win_rate": 65.5, + "trades": 123 +} +``` + +--- + +## 9. 账户与持仓管理 + +**核心文件:** `backtest/account.go` + +### 9.1 持仓结构 + +```go +type position struct { + Symbol string + Side string // "long" 或 "short" + Quantity float64 + EntryPrice float64 + Leverage int + Margin float64 // 保证金 + Notional float64 // 名义价值 + LiquidationPrice float64 // 爆仓价格 + OpenTime int64 +} +``` + +### 9.2 开仓逻辑 + +```go +// backtest/account.go:61-104 +func (a *BacktestAccount) Open(symbol, side string, qty, price float64, leverage int) { + // 1. 应用滑点 + // 2. 计算名义价值 (qty × price) + // 3. 计算保证金 (notional / leverage) + // 4. 扣除保证金 + 手续费 + // 5. 创建/加仓 + // 6. 计算爆仓价格 +} +``` + +### 9.3 平仓逻辑 + +```go +// backtest/account.go:106-140 +func (a *BacktestAccount) Close(symbol, side string, qty, price float64) { + // 1. 验证持仓存在 + // 2. 应用滑点 (反向) + // 3. 计算已实现盈亏 + // long: (exit - entry) × qty + // short: (entry - exit) × qty + // 4. 返还保证金 + 盈亏 - 手续费 + // 5. 更新/删除持仓 +} +``` + +### 9.4 爆仓价格计算 + +```go +// backtest/account.go:177-186 +func computeLiquidation(entry float64, leverage int, side string) float64 { + if side == "long" { + return entry * (1 - 1.0/float64(leverage)) // 做多: 下跌爆仓 + } + return entry * (1 + 1.0/float64(leverage)) // 做空: 上涨爆仓 +} +``` + +--- + +## 10. 检查点与恢复 + +**核心文件:** `backtest/runner.go` + +### 10.1 检查点结构 + +```json +{ + "bar_index": 1234, + "bar_ts": 1702609200000, + "cash": 8000.00, + "equity": 10234.50, + "max_equity": 10500.00, + "max_drawdown_pct": 5.67, + "positions": [...], + "decision_cycle": 62, + "liquidated": false +} +``` + +### 10.2 检查点触发 + +```go +// backtest/runner.go:874-898 +func (r *Runner) maybeCheckpoint() { + // 每 N 根 K 线保存 + // 或每 N 秒保存 +} +``` + +### 10.3 恢复流程 + +```go +func (r *Runner) RestoreFromCheckpoint() { + // 1. 加载检查点 + // 2. 恢复账户状态 + // 3. 恢复 K 线索引 (从下一根继续) + // 4. 恢复权益曲线、交易记录 +} +``` + +--- + +## 核心文件索引 + +| 模块 | 文件 | 关键方法 | +|------|------|----------| +| **配置** | `backtest/config.go` | `BacktestConfig`, `Validate()` | +| **数据加载** | `backtest/datafeed.go` | `NewDataFeed()`, `loadAll()`, `BuildMarketData()` | +| **模拟引擎** | `backtest/runner.go` | `Start()`, `loop()`, `stepOnce()` | +| **决策** | `backtest/runner.go` | `buildDecisionContext()`, `invokeAIWithRetry()` | +| **执行** | `backtest/runner.go` | `executeDecision()` | +| **账户** | `backtest/account.go` | `Open()`, `Close()`, `TotalEquity()` | +| **指标** | `backtest/metrics.go` | `CalculateMetrics()` | +| **权益** | `backtest/equity.go` | `ResampleEquity()`, `LimitEquityPoints()` | +| **存储** | `backtest/storage.go` | `SaveCheckpoint()`, `appendEquityPoint()` | +| **数据库** | `store/backtest.go` | 表结构和 CRUD 操作 | +| **API** | `api/backtest.go` | HTTP 处理器 | +| **AI 缓存** | `backtest/aicache.go` | `Get()`, `Put()`, `save()` | + +--- + +**文档版本:** 1.0.0 +**最后更新:** 2025-01-15 diff --git a/docs/architecture/DEBATE_MODULE.md b/docs/architecture/DEBATE_MODULE.md new file mode 100644 index 00000000..089fa56d --- /dev/null +++ b/docs/architecture/DEBATE_MODULE.md @@ -0,0 +1,907 @@ +# Debate Arena Module - Technical Documentation + +## Overview + +The Debate Arena is a collaborative AI decision-making system where multiple AI models with different personalities debate market conditions and reach consensus on trading decisions. The system supports multi-round debates, real-time streaming, voting mechanisms, and automatic trade execution. + +## Table of Contents + +1. [Architecture Overview](#1-architecture-overview) +2. [Backend Components](#2-backend-components) +3. [Debate Execution Flow](#3-debate-execution-flow) +4. [Personality System](#4-personality-system) +5. [Consensus Algorithm](#5-consensus-algorithm) +6. [Auto-Execution](#6-auto-execution) +7. [API Reference](#7-api-reference) +8. [Real-Time Updates (SSE)](#8-real-time-updates-sse) +9. [Database Schema](#9-database-schema) +10. [Frontend Components](#10-frontend-components) +11. [Integration Points](#11-integration-points) +12. [Error Handling](#12-error-handling) + +--- + +## 1. Architecture Overview + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ Debate Arena System │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ +│ │ Bull AI │ │ Bear AI │ │ Analyst AI │ │ Risk Mgr AI │ │ +│ │ 🐂 │ │ 🐻 │ │ 📊 │ │ 🛡️ │ │ +│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ +│ │ │ │ │ │ +│ └──────────────────┴──────────────────┴──────────────────┘ │ +│ │ │ +│ ┌─────────▼─────────┐ │ +│ │ Debate Engine │ │ +│ │ (debate/engine) │ │ +│ └─────────┬─────────┘ │ +│ │ │ +│ ┌──────────────────────────┼──────────────────────────┐ │ +│ │ │ │ │ +│ ┌──────▼──────┐ ┌─────────▼─────────┐ ┌────────▼────────┐ │ +│ │ Market Data │ │ Voting System │ │ Auto-Executor │ │ +│ │ Assembly │ │ & Consensus │ │ (optional) │ │ +│ └─────────────┘ └───────────────────┘ └─────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### File Structure + +``` +├── debate/ +│ └── engine.go # Core debate engine logic +├── api/ +│ └── debate.go # HTTP handlers and SSE streaming +├── store/ +│ └── debate.go # Database operations and schema +└── web/src/pages/ + └── DebateArenaPage.tsx # Frontend UI +``` + +--- + +## 2. Backend Components + +### 2.1 Core Files + +| File | Purpose | Key Functions | +|------|---------|---------------| +| `debate/engine.go` | Core debate logic | `StartDebate()`, `runDebate()`, `collectVotes()`, `determineConsensus()` | +| `api/debate.go` | HTTP handlers | `HandleCreateDebate()`, `HandleStartDebate()`, `HandleDebateStream()` | +| `store/debate.go` | Database ops | `CreateSession()`, `AddMessage()`, `AddVote()`, `GetSessionWithDetails()` | + +### 2.2 Debate Engine Structure + +```go +// debate/engine.go + +type DebateEngine struct { + store *store.DebateStore + aiClients map[string]ai.Client + strategyEngine *strategy.Engine + subscribers map[string]map[chan []byte]bool +} + +// Event callbacks for real-time updates +var OnRoundStart func(sessionID string, round int) +var OnMessage func(sessionID string, msg *DebateMessage) +var OnVote func(sessionID string, vote *DebateVote) +var OnConsensus func(sessionID string, decision *DebateDecision) +var OnError func(sessionID string, err error) +``` + +--- + +## 3. Debate Execution Flow + +### 3.1 Session Creation + +``` +POST /api/debates + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 1. Validate user authentication │ +│ 2. Parse CreateDebateRequest: │ +│ - name, strategy_id, symbol, max_rounds, participants │ +│ - interval_minutes, prompt_variant, auto_execute │ +│ 3. Validate strategy ownership │ +│ 4. Auto-select symbol if not provided: │ +│ - Static coins → Use first coin from strategy │ +│ - CoinPool → Fetch from AI500 API │ +│ - OI Top → Fetch from OI ranking API │ +│ - Mixed → Try pool first, fallback to OI │ +│ 5. Set defaults: │ +│ - max_rounds: 3 (range 2-5) │ +│ - interval_minutes: 5 │ +│ - prompt_variant: "balanced" │ +│ 6. Create DebateSession in database │ +│ 7. Add participants with AI models and personalities │ +│ 8. Return full session with participants │ +└─────────────────────────────────────────────────────────────┘ +``` + +### 3.2 Debate Start + +**Location:** `debate/engine.go:StartDebate()` (Lines 114-154) + +``` +POST /api/debates/:id/start + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 1. Validate session status (must be pending) │ +│ 2. Validate participants (minimum 2) │ +│ 3. Initialize AI clients for all participants │ +│ 4. Get strategy configuration │ +│ 5. Update status to "running" │ +│ 6. Launch goroutine: runDebate() │ +└─────────────────────────────────────────────────────────────┘ +``` + +### 3.3 Market Context Building + +**Location:** `debate/engine.go:buildMarketContext()` (Lines 292-362) + +``` +┌─────────────────────────────────────────────────────────────┐ +│ buildMarketContext() │ +├─────────────────────────────────────────────────────────────┤ +│ 1. Get candidate coins from strategy engine │ +│ 2. Fetch market data for each candidate: │ +│ - Multiple timeframes (15m, 1h, 4h) │ +│ - K-line count from strategy config │ +│ - OHLCV data, indicators │ +│ 3. Fetch quantitative data batch: │ +│ - Capital flow │ +│ - Position changes │ +│ 4. Fetch OI ranking data (market-wide) │ +│ 5. Build Context object with: │ +│ - Account info (simulated: $1000 equity) │ +│ - Candidate coins │ +│ - Market data map │ +│ - Quant data map │ +│ - OI ranking data │ +└─────────────────────────────────────────────────────────────┘ +``` + +### 3.4 Debate Rounds + +**Location:** `debate/engine.go:runDebate()` (Lines 157-289) + +``` +┌─────────────────────────────────────────────────────────────┐ +│ For each round (1 to max_rounds): │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ 1. Broadcast "round_start" event │ │ +│ │ 2. For each participant (in speak_order): │ │ +│ │ ┌─────────────────────────────────────────────────┐ │ │ +│ │ │ a. Build personality-enhanced system prompt │ │ │ +│ │ │ b. Build user prompt with: │ │ │ +│ │ │ - Market data (from strategy engine) │ │ │ +│ │ │ - Previous debate messages (if round > 1) │ │ │ +│ │ │ c. Call AI model with 60s timeout │ │ │ +│ │ │ d. Parse multi-coin decisions from response │ │ │ +│ │ │ e. Save message to database │ │ │ +│ │ │ f. Broadcast "message" event │ │ │ +│ │ └─────────────────────────────────────────────────┘ │ │ +│ │ 3. Broadcast "round_end" event │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ After all rounds: │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ 1. Enter voting phase (status = "voting") │ │ +│ │ 2. Collect final votes from all participants │ │ +│ │ 3. Determine multi-coin consensus │ │ +│ │ 4. Store final decisions │ │ +│ │ 5. Update status to "completed" │ │ +│ │ 6. Broadcast "consensus" event │ │ +│ └─────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────┘ +``` + +--- + +## 4. Personality System + +### 4.1 Available Personalities + +| Personality | Emoji | Name | Description | Trading Bias | +|------------|-------|------|-------------|--------------| +| Bull | 🐂 | Aggressive Bull | Looks for long opportunities | Optimistic, trend-following | +| Bear | 🐻 | Cautious Bear | Skeptical, focuses on risks | Pessimistic, short bias | +| Analyst | 📊 | Data Analyst | Neutral, purely data-driven | No bias, objective analysis | +| Contrarian | 🔄 | Contrarian | Challenges majority view | Alternative perspectives | +| Risk Manager | 🛡️ | Risk Manager | Focus on risk control | Position sizing, stop loss | + +### 4.2 Personality Prompt Enhancement + +**Location:** `debate/engine.go:buildDebateSystemPrompt()` (Lines 365-426) + +``` +## DEBATE MODE - ROUND {round}/{max_rounds} + +You are participating as {emoji} {personality}. + +### Your Debate Role: +{personality_description} + +### Debate Rules: +1. Analyze ALL candidate coins +2. Support arguments with specific data +3. Respond to other participants (round > 1) +4. Be persuasive but data-driven +5. Can recommend multiple coins with different actions + +### Output Format (STRICT JSON): + + - Market analysis with data references + - Main trading thesis + - Response to others (if round > 1) + + + +[ + {"symbol": "BTCUSDT", "action": "open_long", "confidence": 75, ...}, + {"symbol": "ETHUSDT", "action": "open_short", "confidence": 80, ...} +] + +``` + +### 4.3 Personality-Specific Prompts + +**Bull (🐂):** +``` +As a bull, you are optimistic about market trends. +Look for long opportunities, identify bullish patterns, +and support your thesis with technical and fundamental data. +Focus on: breakout patterns, momentum, support levels. +``` + +**Bear (🐻):** +``` +As a bear, you are cautious and skeptical. +Look for short opportunities, identify bearish patterns, +and highlight risks and potential downside. +Focus on: resistance levels, divergences, overbought conditions. +``` + +**Analyst (📊):** +``` +As a data analyst, you are completely neutral. +Provide objective analysis based purely on data. +No emotional bias - let the numbers speak. +Focus on: key metrics, statistical patterns, historical comparisons. +``` + +**Contrarian (🔄):** +``` +As a contrarian, challenge the majority view. +Look for overlooked opportunities and hidden risks. +Play devil's advocate to strengthen the debate. +Focus on: crowd positioning, sentiment extremes, neglected signals. +``` + +**Risk Manager (🛡️):** +``` +As a risk manager, focus on capital preservation. +Evaluate position sizing, stop loss levels, and risk/reward ratios. +Ensure all decisions have appropriate risk controls. +Focus on: max drawdown, position limits, volatility-adjusted sizing. +``` + +--- + +## 5. Consensus Algorithm + +### 5.1 Vote Collection + +**Location:** `debate/engine.go:collectVotes()` (Lines 542-567) + +``` +For each participant: +┌─────────────────────────────────────────────────────────────┐ +│ 1. Build voting system prompt │ +│ 2. Build voting user prompt with debate summary │ +│ 3. Call AI model for final vote │ +│ 4. Parse multi-coin decisions │ +│ 5. Validate/fix symbols against session.Symbol │ +│ 6. Save vote to database │ +│ 7. Broadcast "vote" event │ +└─────────────────────────────────────────────────────────────┘ +``` + +### 5.2 Multi-Coin Consensus Determination + +**Location:** `debate/engine.go:determineMultiCoinConsensus()` (Lines 752-924) + +**Algorithm:** + +``` +1. Collect all coin decisions from all votes +2. Group by: symbol → action → aggregated data + +3. For each vote decision: + weight = confidence / 100.0 + Accumulate: + ┌─────────────────────────────────────────────────────────┐ + │ score += weight │ + │ total_confidence += confidence │ + │ total_leverage += leverage │ + │ total_position_pct += position_pct │ + │ total_stop_loss += stop_loss │ + │ total_take_profit += take_profit │ + │ count++ │ + └─────────────────────────────────────────────────────────┘ + +4. For each symbol: + Find winning action (max score) + Calculate averages: + ┌─────────────────────────────────────────────────────────┐ + │ avg_confidence = total_confidence / count │ + │ avg_leverage = clamp(total_leverage / count, 1, 20) │ + │ avg_position_pct = clamp(total_pct / count, 0.1, 1.0) │ + │ avg_stop_loss = default 3% if not set │ + │ avg_take_profit = default 6% if not set │ + └─────────────────────────────────────────────────────────┘ + +5. Return array of consensus decisions +``` + +### 5.3 Consensus Example + +**Input Votes:** +``` +AI1 (Bull): BTC open_long (conf=80, lev=10, pos=0.3) +AI2 (Bear): BTC open_short (conf=60, lev=5, pos=0.2) +AI3 (Analyst): BTC open_long (conf=70, lev=8, pos=0.25) +``` + +**Calculation:** +``` +open_long: + score = 0.80 + 0.70 = 1.50 + avg_conf = (80 + 70) / 2 = 75 + avg_lev = (10 + 8) / 2 = 9 + avg_pos = (0.3 + 0.25) / 2 = 0.275 + +open_short: + score = 0.60 + avg_conf = 60 + avg_lev = 5 + avg_pos = 0.2 + +Winner: open_long (score 1.50 > 0.60) +``` + +**Output:** +```json +{ + "symbol": "BTCUSDT", + "action": "open_long", + "confidence": 75, + "leverage": 9, + "position_pct": 0.275, + "stop_loss": 0.03, + "take_profit": 0.06 +} +``` + +--- + +## 6. Auto-Execution + +### 6.1 Execution Flow + +**Location:** `debate/engine.go:ExecuteConsensus()` (Lines 932-1052) + +``` +POST /api/debates/:id/execute + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 1. Validate session status = completed │ +│ 2. Validate final_decision exists and not executed │ +│ 3. Validate action is open_long or open_short │ +│ 4. Get current market price │ +│ 5. Get account balance: │ +│ - Try available_balance │ +│ - Fallback to total_equity or wallet_balance │ +│ 6. Calculate position size: │ +│ position_size_usd = available_balance × position_pct │ +│ (minimum $12 to meet exchange requirements) │ +│ 7. Calculate stop loss and take profit prices: │ +│ ┌───────────────────────────────────────────────────┐ │ +│ │ open_long: │ │ +│ │ SL = price × (1 - stop_loss_pct) │ │ +│ │ TP = price × (1 + take_profit_pct) │ │ +│ │ open_short: │ │ +│ │ SL = price × (1 + stop_loss_pct) │ │ +│ │ TP = price × (1 - take_profit_pct) │ │ +│ └───────────────────────────────────────────────────┘ │ +│ 8. Create Decision object │ +│ 9. Call executor.ExecuteDecision() │ +│ 10. Update final_decision: │ +│ - executed = true/false │ +│ - executed_at = timestamp │ +│ - error message if failed │ +└─────────────────────────────────────────────────────────────┘ +``` + +### 6.2 Position Size Calculation + +```go +// Calculate position value +position_size_usd := available_balance * position_pct + +// Ensure minimum size for exchange +if position_size_usd < 12 { + position_size_usd = 12 +} + +// Calculate quantity +quantity := position_size_usd / market_price +``` + +--- + +## 7. API Reference + +### 7.1 Endpoints + +| Method | Path | Description | +|--------|------|-------------| +| GET | `/api/debates` | List all debates for user | +| GET | `/api/debates/personalities` | Get AI personality configs | +| GET | `/api/debates/:id` | Get debate with full details | +| POST | `/api/debates` | Create new debate | +| POST | `/api/debates/:id/start` | Start debate execution | +| POST | `/api/debates/:id/cancel` | Cancel running debate | +| POST | `/api/debates/:id/execute` | Execute consensus trade | +| DELETE | `/api/debates/:id` | Delete debate | +| GET | `/api/debates/:id/messages` | Get all messages | +| GET | `/api/debates/:id/votes` | Get all votes | +| GET | `/api/debates/:id/stream` | SSE live stream | + +### 7.2 Create Debate Request + +```json +POST /api/debates +{ + "name": "BTC Market Debate", + "strategy_id": "strategy-uuid", + "symbol": "BTCUSDT", + "max_rounds": 3, + "interval_minutes": 5, + "prompt_variant": "balanced", + "auto_execute": false, + "trader_id": "trader-uuid", + "enable_oi_ranking": true, + "oi_ranking_limit": 10, + "oi_duration": "1h", + "participants": [ + {"ai_model_id": "deepseek-v3", "personality": "bull"}, + {"ai_model_id": "qwen-max", "personality": "bear"}, + {"ai_model_id": "gpt-5.2", "personality": "analyst"} + ] +} +``` + +### 7.3 Create Debate Response + +```json +{ + "id": "debate-uuid", + "user_id": "user-uuid", + "name": "BTC Market Debate", + "strategy_id": "strategy-uuid", + "status": "pending", + "symbol": "BTCUSDT", + "max_rounds": 3, + "current_round": 0, + "participants": [ + { + "id": "participant-uuid", + "ai_model_id": "deepseek-v3", + "ai_model_name": "DeepSeek V3", + "provider": "deepseek", + "personality": "bull", + "color": "#22C55E", + "speak_order": 0 + } + ], + "messages": [], + "votes": [], + "created_at": "2025-12-15T12:00:00Z" +} +``` + +### 7.4 Execute Consensus Request + +```json +POST /api/debates/:id/execute +{ + "trader_id": "trader-uuid" +} +``` + +--- + +## 8. Real-Time Updates (SSE) + +### 8.1 SSE Endpoint + +**Location:** `api/debate.go:HandleDebateStream()` (Lines 407-453) + +``` +GET /api/debates/:id/stream + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 1. Validate user ownership │ +│ 2. Set SSE headers: │ +│ Content-Type: text/event-stream │ +│ Cache-Control: no-cache │ +│ Connection: keep-alive │ +│ 3. Send initial state │ +│ 4. Subscribe to events │ +│ 5. Stream updates until client disconnects │ +└─────────────────────────────────────────────────────────────┘ +``` + +### 8.2 Event Types + +| Event | Trigger | Data | +|-------|---------|------| +| `initial` | Connection start | Full session state | +| `round_start` | Round begins | `{round, status}` | +| `message` | AI speaks | DebateMessage object | +| `round_end` | Round complete | `{round, status}` | +| `vote` | AI votes | DebateVote object | +| `consensus` | Debate complete | DebateDecision object | +| `error` | Error occurs | `{error: string}` | + +### 8.3 SSE Message Format + +``` +event: message +data: {"id":"msg-uuid","session_id":"session-uuid","round":1,"ai_model_name":"DeepSeek V3","personality":"bull","content":"...","decision":{"action":"open_long","symbol":"BTCUSDT","confidence":75}} + +event: vote +data: {"id":"vote-uuid","session_id":"session-uuid","ai_model_name":"DeepSeek V3","action":"open_long","symbol":"BTCUSDT","confidence":80,"reasoning":"..."} + +event: consensus +data: {"action":"open_long","symbol":"BTCUSDT","confidence":75,"leverage":8,"position_pct":0.25,"stop_loss":0.03,"take_profit":0.06} +``` + +--- + +## 9. Database Schema + +### 9.1 Tables + +**debate_sessions:** +```sql +CREATE TABLE debate_sessions ( + id TEXT PRIMARY KEY, + user_id TEXT NOT NULL, + name TEXT NOT NULL, + strategy_id TEXT NOT NULL, + status TEXT NOT NULL DEFAULT 'pending', + symbol TEXT NOT NULL, + max_rounds INTEGER DEFAULT 3, + current_round INTEGER DEFAULT 0, + interval_minutes INTEGER DEFAULT 5, + prompt_variant TEXT DEFAULT 'balanced', + final_decision TEXT, + final_decisions TEXT, + auto_execute BOOLEAN DEFAULT 0, + trader_id TEXT, + enable_oi_ranking BOOLEAN DEFAULT 0, + oi_ranking_limit INTEGER DEFAULT 10, + oi_duration TEXT DEFAULT '1h', + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP +); +``` + +**debate_participants:** +```sql +CREATE TABLE debate_participants ( + id TEXT PRIMARY KEY, + session_id TEXT NOT NULL, + ai_model_id TEXT NOT NULL, + ai_model_name TEXT NOT NULL, + provider TEXT NOT NULL, + personality TEXT NOT NULL, + color TEXT NOT NULL, + speak_order INTEGER DEFAULT 0, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (session_id) REFERENCES debate_sessions(id) ON DELETE CASCADE +); +``` + +**debate_messages:** +```sql +CREATE TABLE debate_messages ( + id TEXT PRIMARY KEY, + session_id TEXT NOT NULL, + round INTEGER NOT NULL, + ai_model_id TEXT NOT NULL, + ai_model_name TEXT NOT NULL, + provider TEXT NOT NULL, + personality TEXT NOT NULL, + message_type TEXT NOT NULL, + content TEXT NOT NULL, + decision TEXT, + decisions TEXT, + confidence INTEGER DEFAULT 0, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (session_id) REFERENCES debate_sessions(id) ON DELETE CASCADE +); +``` + +**debate_votes:** +```sql +CREATE TABLE debate_votes ( + id TEXT PRIMARY KEY, + session_id TEXT NOT NULL, + ai_model_id TEXT NOT NULL, + ai_model_name TEXT NOT NULL, + action TEXT NOT NULL, + symbol TEXT NOT NULL, + confidence INTEGER DEFAULT 0, + leverage INTEGER DEFAULT 5, + position_pct REAL DEFAULT 0.2, + stop_loss_pct REAL DEFAULT 0.03, + take_profit_pct REAL DEFAULT 0.06, + reasoning TEXT, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (session_id) REFERENCES debate_sessions(id) ON DELETE CASCADE +); +``` + +### 9.2 Key Store Methods + +| Method | Description | +|--------|-------------| +| `CreateSession()` | Create new debate session | +| `GetSession()` | Get session by ID | +| `GetSessionWithDetails()` | Get session with participants, messages, votes | +| `UpdateSessionStatus()` | Update session status | +| `UpdateSessionRound()` | Update current round | +| `UpdateSessionFinalDecisions()` | Store consensus decisions | +| `AddParticipant()` | Add AI participant | +| `AddMessage()` | Store debate message | +| `AddVote()` | Store final vote | + +--- + +## 10. Frontend Components + +### 10.1 Page Structure + +**Location:** `web/src/pages/DebateArenaPage.tsx` + +``` +DebateArenaPage +├── Left Sidebar (w-56) +│ ├── New Debate Button +│ ├── Debate Sessions List +│ │ └── SessionItem (status, name, timestamp) +│ └── Online Traders List +│ └── TraderItem (name, status, AI model) +│ +├── Main Content +│ ├── Header Bar +│ │ ├── Session Info (name, status, symbol) +│ │ ├── Participants Avatars +│ │ └── Vote Summary +│ │ +│ ├── Content Area (two-column) +│ │ ├── Left: Discussion Records +│ │ │ ├── Round Headers +│ │ │ └── MessageCards (expandable) +│ │ │ +│ │ └── Right: Final Votes +│ │ └── VoteCards (action, confidence, reasoning) +│ │ +│ └── Consensus Bar +│ ├── Final Decision Display +│ └── Execute Button (if auto_execute disabled) +│ +└── Modals + ├── CreateModal + │ ├── Name Input + │ ├── Strategy Selector + │ ├── Symbol Input (auto-filled) + │ ├── Max Rounds Selector + │ └── Participant Picker (AI model + personality) + │ + └── ExecuteModal + └── Trader Selector +``` + +### 10.2 UI Components + +**MessageCard:** +- Expandable message display +- Shows AI avatar, personality emoji, decision +- Parses reasoning/analysis sections from content +- Displays decision details (leverage, position, SL/TP) +- Supports multi-coin decisions + +**VoteCard:** +- Confidence bar visualization +- Action indicator (long/short/hold/wait) +- Leverage and position size display +- Stop loss and take profit display +- Reasoning preview + +### 10.3 Status Colors + +```typescript +const STATUS_COLOR = { + pending: 'bg-gray-500', + running: 'bg-blue-500 animate-pulse', + voting: 'bg-yellow-500 animate-pulse', + completed: 'bg-green-500', + cancelled: 'bg-red-500', +} +``` + +### 10.4 Action Styling + +```typescript +const ACT = { + open_long: { + color: 'text-green-400', + bg: 'bg-green-500/20', + icon: , + label: 'LONG' + }, + open_short: { + color: 'text-red-400', + bg: 'bg-red-500/20', + icon: , + label: 'SHORT' + }, + hold: { + color: 'text-blue-400', + bg: 'bg-blue-500/20', + icon: , + label: 'HOLD' + }, + wait: { + color: 'text-gray-400', + bg: 'bg-gray-500/20', + icon: , + label: 'WAIT' + }, +} +``` + +### 10.5 Personality Colors + +```typescript +const PERS = { + bull: { emoji: '🐂', color: '#22C55E', name: '多头', nameEn: 'Bull' }, + bear: { emoji: '🐻', color: '#EF4444', name: '空头', nameEn: 'Bear' }, + analyst: { emoji: '📊', color: '#3B82F6', name: '分析', nameEn: 'Analyst' }, + contrarian: { emoji: '🔄', color: '#F59E0B', name: '逆势', nameEn: 'Contrarian' }, + risk_manager: { emoji: '🛡️', color: '#8B5CF6', name: '风控', nameEn: 'Risk Mgr' }, +} +``` + +--- + +## 11. Integration Points + +### 11.1 Strategy System + +Debate sessions depend on saved strategies for: +- **Coin source configuration:** static/pool/OI top +- **Market data indicators:** K-lines, timeframes, technical indicators +- **Risk control parameters:** leverage limits, position sizing +- **Custom prompts:** role definition, trading rules + +### 11.2 AI Model System + +Each participant requires: +- AI model configuration (provider, API key, custom URL) +- Supported providers: deepseek, qwen, openai, claude, gemini, grok, kimi +- Client initialization with timeout handling (60s per call) + +### 11.3 Trader System + +For auto-execution: +- Requires active trader with running status +- Trader must have valid exchange connection +- Executor interface: `ExecuteDecision()`, `GetBalance()` + +### 11.4 Market Data + +Market context building uses: +- Market data service (K-lines, OHLCV) +- Quantitative data (capital flow, position changes) +- OI ranking data (market-wide position changes) + +--- + +## 12. Error Handling + +### 12.1 Cleanup on Startup + +**Location:** `debate/engine.go:cleanupStaleDebates()` (Lines 58-71) + +```go +// On server restart, cancel all running/voting debates +func cleanupStaleDebates() { + sessions := debateStore.ListAllSessions() + for _, session := range sessions { + if session.Status == running || session.Status == voting { + debateStore.UpdateSessionStatus(session.ID, cancelled) + } + } +} +``` + +### 12.2 AI Call Timeout + +```go +// 60 seconds per participant response +select { +case res := <-resultCh: + response = res.response +case <-time.After(60 * time.Second): + return nil, fmt.Errorf("AI call timeout") +} +``` + +### 12.3 Symbol Validation + +```go +// Force all decisions to use session symbol if specified +if session.Symbol != "" { + for _, d := range decisions { + if d.Symbol == "" || d.Symbol != session.Symbol { + logger.Warnf("Fixing invalid symbol '%s' -> '%s'", d.Symbol, session.Symbol) + d.Symbol = session.Symbol + } + } +} +``` + +### 12.4 Panic Recovery + +```go +defer func() { + if r := recover(); r != nil { + logger.Errorf("Debate panic: %v", r) + debateStore.UpdateSessionStatus(sessionID, cancelled) + if OnError != nil { + OnError(sessionID, fmt.Errorf("panic: %v", r)) + } + } +}() +``` + +--- + +## Summary + +The Debate Arena module provides a sophisticated multi-AI collaborative decision system with: + +- **Multi-Personality Debate:** 5 distinct AI personalities (Bull, Bear, Analyst, Contrarian, Risk Manager) with unique trading biases +- **Consensus Mechanism:** Weighted voting based on confidence levels to determine final decisions +- **Real-Time Updates:** SSE streaming for live debate progress +- **Auto-Execution:** Optional automatic trade execution based on consensus +- **Strategy Integration:** Deep integration with strategy configuration for market data and risk parameters +- **Multi-Coin Support:** Ability to analyze and decide on multiple coins simultaneously + +The system enables users to leverage multiple AI perspectives for more robust trading decisions while maintaining full control over execution.