策略源码
{"type":"n8n","content":"{\"workflowData\":{\"nodes\":[{\"parameters\":{\"notice\":\"\",\"rule\":{\"interval\":[{\"field\":\"minutes\",\"minutesInterval\":10}]}},\"type\":\"n8n-nodes-base.scheduleTrigger\",\"typeVersion\":1.2,\"position\":[-1824,1056],\"id\":\"e69bb228-4a53-4b4e-9c25-fd6dd5a6f78b\",\"name\":\"定时触发器\"},{\"parameters\":{\"model\":{\"__rl\":true,\"value\":\"anthropic/claude-sonnet-4.5\",\"mode\":\"list\",\"cachedResultName\":\"anthropic/claude-sonnet-4.5\"}},\"type\":\"n8n-nodes-base.lmOpenAi\",\"typeVersion\":1,\"position\":[-1152,1008],\"id\":\"350178d0-645f-427f-86c4-f1e6adc22635\",\"name\":\"Claude4.5\",\"credentials\":{\"openAiApi\":{\"id\":\"54d0b567-b3fc-4c6a-b6be-546e0b9cd83f\",\"name\":\"openrouter\"}}},{\"parameters\":{\"model\":{\"__rl\":true,\"value\":\"deepseek/deepseek-chat-v3.1\",\"mode\":\"list\",\"cachedResultName\":\"deepseek/deepseek-chat-v3.1\"}},\"type\":\"n8n-nodes-base.lmOpenAi\",\"typeVersion\":1,\"position\":[-1152,752],\"id\":\"7b70e6b3-3473-4316-8cdc-0ec26bd89fd6\",\"name\":\"DS3.1\",\"credentials\":{\"openAiApi\":{\"id\":\"54d0b567-b3fc-4c6a-b6be-546e0b9cd83f\",\"name\":\"openrouter\"}}},{\"parameters\":{\"text\":\"=你是一位专业的加密货币量化交易分析师。请基于以下多时间框架技术指标、当前持仓信息和竞争排名,提供交易决策建议。\\n\\n## 竞争状态\\n你是{{ $json.ranking.currentModel }}大模型,在{{ $json.ranking.totalModels }}个AI模型的交易竞赛中,你目前排名第{{ $json.ranking.currentRank }}位。\\n{{$json.ranking.currentPnl === 0 && $json.ranking.totalTrades === 0 ? '比赛刚开始!这是建立收益基础的好机会!起始阶段积极寻找优质交易机会!' : ''}}\\n\\n### 当前表现\\n- 你的已实现盈亏: {{ $json.ranking.currentPnl }} USDT {{ $json.ranking.currentPnl === 0 ? '(起始状态)' : '' }}\\n- 你的总资产价值: {{ $json.ranking.currentTotalValue }} USDT\\n- 总交易次数: {{ $json.ranking.totalTrades }} {{ $json.ranking.totalTrades === 0 ? '(尚未开始交易)' : '' }}\\n- 胜率: {{ $json.ranking.winRate }}%{{ $json.ranking.totalTrades === 0 ? ' (暂无数据)' : '' }}\\n\\n### 竞争对手排名\\n{{ $json.ranking.rankingText }}\\n{{ $json.ranking.currentPnl === 0 && $json.ranking.totalTrades === 0 ? '比赛开始!!!' : $json.ranking.gapInfo}}\\n\\n## 当前数据概览\\n- 交易对: {{ $json.symbol }}\\n- 分析时间: {{ new Date($json.timestamp).toLocaleString() }}\\n- 当前持仓: {{ $json.position && $json.position.length > 0 ? '有持仓' : '无持仓' }}\\n\\n## 技术指标数据(OLDEST-NEWEST)\\n### 日线级别 (趋势判断)\\n- 价格: {{ $json.timeframes.day?.lastPrice || 'N/A' }}\\n- RSI(14): {{ $json.timeframes.day?.RSI || 'N/A' }} \\n- MACD柱: {{ $json.timeframes.day?.MACD.histogram || 'N/A' }} \\n- ATR: {{ $json.timeframes.day?.ATR || 'N/A' }} \\n- OBV: {{ $json.timeframes.day?.OBV || 'N/A' }} \\n\\n### 小时线级别 (中期趋势)\\n- 价格: {{ $json.timeframes.hour?.lastPrice || 'N/A' }}\\n- RSI(14): {{ $json.timeframes.hour?.RSI || 'N/A' }}\\n- MACD柱: {{ $json.timeframes.hour?.MACD.histogram || 'N/A' }}\\n- ATR: {{ $json.timeframes.hour?.ATR || 'N/A' }}\\n- OBV: {{ $json.timeframes.hour?.OBV || 'N/A' }}\\n\\n### 5分钟线级别 (入场时机)\\n- 价格: {{ $json.timeframes.min5?.lastPrice || 'N/A' }}\\n- RSI(14): {{ $json.timeframes.min5?.RSI || 'N/A' }}\\n- MACD柱: {{ $json.timeframes.min5?.MACD.histogram || 'N/A' }}\\n- ATR: {{ $json.timeframes.min5?.ATR || 'N/A' }}\\n- OBV: {{ $json.timeframes.min5?.OBV || 'N/A' }}\\n\\n### 当前持仓信息\\n{{JSON.stringify($json.position, null, 2)}}\\n\\n## 分析要求\\n基于技术指标和你的竞争排名情况,制定最优交易策略。你的目标是持续创造更多收益,而非单纯保持排名。{{ $json.ranking.totalTrades === 0 ? '作为比赛开始阶段,积极寻找高质量交易机会来建立收益基础.' : '继续寻找优质交易机会来扩大收益,避免因过度保守而错失盈利机会.' }}\\n\\n### 策略建议:\\n{{ $json.ranking.totalTrades === 0 ? '- 比赛刚开始,积极寻找最佳入场时机建立收益基础' : $json.ranking.currentRank > 1 ? '- 你目前落后,积极寻找更多优质交易机会来追赶并创造收益' : '- 你目前表现良好,继续保持积极交易来扩大收益优势' }}\\n- 仔细分析多时间框架指标的一致性\\n- 在技术信号明确时果断执行交易\\n- {{ $json.ranking.totalTrades === 0 ? '首次交易要建立良好开局' : '持续寻找盈利机会,避免过度保守' }}\\n- 重点关注风险回报比,而非排名保护\\n\\n### 可执行的动作:\\n- **OPEN_LONG**: 开多单(无持仓的状态下)\\n- **OPEN_SHORT**: 开空单(无持仓的状态下) \\n- **CLOSE_LONG**: 平多单(持有多仓的状态下)\\n- **CLOSE_SHORT**: 平空单(持有空仓的状态下)\\n- **NO_ACTION**: 观望(当技术信号不明确时)\\n\\n### 执行标准:\\n- 优先考虑收益创造机会\\n- {{ $json.ranking.totalTrades === 0 ? '首次交易要求建立收益基础' : '持续寻找高质量交易机会来扩大总收益' }}\\n- 风险控制与收益追求并重\\n- 只有在技术信号明显冲突时才选择NO_ACTION\\n\\n## 返回格式\\n```json\\n{\\n \\\"action\\\": \\\"OPEN_LONG | OPEN_SHORT | CLOSE_LONG | CLOSE_SHORT | NO_ACTION\\\",\\n \\\"reasoning\\\": \\\"结合技术指标和收益创造目标的极其简洁决策依据\\\",\\n \\\"modelname\\\": \\\"{{ $json.ranking.currentModel }}\\\"\\n}\\n```\\n请直接给出判断结果。\",\"options\":{}},\"type\":\"@n8n/n8n-nodes-langchain.agent\",\"typeVersion\":1,\"position\":[-1152,592],\"id\":\"63b30c5e-df14-4a0a-ac58-17ce39cceef8\",\"name\":\"DeepSeek\",\"retryOnFail\":true,\"onError\":\"continueRegularOutput\"},{\"parameters\":{\"text\":\"=你是一位专业的加密货币量化交易分析师。请基于以下多时间框架技术指标、当前持仓信息和竞争排名,提供交易决策建议。\\n\\n## 竞争状态\\n你是{{ $json.ranking.currentModel }}大模型,在{{ $json.ranking.totalModels }}个AI模型的交易竞赛中,你目前排名第{{ $json.ranking.currentRank }}位。\\n{{$json.ranking.currentPnl === 0 && $json.ranking.totalTrades === 0 ? '比赛刚开始!这是建立收益基础的好机会!起始阶段积极寻找优质交易机会!' : ''}}\\n\\n### 当前表现\\n- 你的已实现盈亏: {{ $json.ranking.currentPnl }} USDT {{ $json.ranking.currentPnl === 0 ? '(起始状态)' : '' }}\\n- 你的总资产价值: {{ $json.ranking.currentTotalValue }} USDT\\n- 总交易次数: {{ $json.ranking.totalTrades }} {{ $json.ranking.totalTrades === 0 ? '(尚未开始交易)' : '' }}\\n- 胜率: {{ $json.ranking.winRate }}%{{ $json.ranking.totalTrades === 0 ? ' (暂无数据)' : '' }}\\n\\n### 竞争对手排名\\n{{ $json.ranking.rankingText }}\\n{{ $json.ranking.currentPnl === 0 && $json.ranking.totalTrades === 0 ? '比赛开始!!!' : $json.ranking.gapInfo}}\\n\\n## 当前数据概览\\n- 交易对: {{ $json.symbol }}\\n- 分析时间: {{ new Date($json.timestamp).toLocaleString() }}\\n- 当前持仓: {{ $json.position && $json.position.length > 0 ? '有持仓' : '无持仓' }}\\n\\n## 技术指标数据(OLDEST-NEWEST)\\n### 日线级别 (趋势判断)\\n- 价格: {{ $json.timeframes.day?.lastPrice || 'N/A' }}\\n- RSI(14): {{ $json.timeframes.day?.RSI || 'N/A' }} \\n- MACD柱: {{ $json.timeframes.day?.MACD.histogram || 'N/A' }} \\n- ATR: {{ $json.timeframes.day?.ATR || 'N/A' }} \\n- OBV: {{ $json.timeframes.day?.OBV || 'N/A' }} \\n\\n### 小时线级别 (中期趋势)\\n- 价格: {{ $json.timeframes.hour?.lastPrice || 'N/A' }}\\n- RSI(14): {{ $json.timeframes.hour?.RSI || 'N/A' }}\\n- MACD柱: {{ $json.timeframes.hour?.MACD.histogram || 'N/A' }}\\n- ATR: {{ $json.timeframes.hour?.ATR || 'N/A' }}\\n- OBV: {{ $json.timeframes.hour?.OBV || 'N/A' }}\\n\\n### 5分钟线级别 (入场时机)\\n- 价格: {{ $json.timeframes.min5?.lastPrice || 'N/A' }}\\n- RSI(14): {{ $json.timeframes.min5?.RSI || 'N/A' }}\\n- MACD柱: {{ $json.timeframes.min5?.MACD.histogram || 'N/A' }}\\n- ATR: {{ $json.timeframes.min5?.ATR || 'N/A' }}\\n- OBV: {{ $json.timeframes.min5?.OBV || 'N/A' }}\\n\\n### 当前持仓信息\\n{{JSON.stringify($json.position, null, 2)}}\\n\\n## 分析要求\\n基于技术指标和你的竞争排名情况,制定最优交易策略。你的目标是持续创造更多收益,而非单纯保持排名。{{ $json.ranking.totalTrades === 0 ? '作为比赛开始阶段,积极寻找高质量交易机会来建立收益基础.' : '继续寻找优质交易机会来扩大收益,避免因过度保守而错失盈利机会.' }}\\n\\n### 策略建议:\\n{{ $json.ranking.totalTrades === 0 ? '- 比赛刚开始,积极寻找最佳入场时机建立收益基础' : $json.ranking.currentRank > 1 ? '- 你目前落后,积极寻找更多优质交易机会来追赶并创造收益' : '- 你目前表现良好,继续保持积极交易来扩大收益优势' }}\\n- 仔细分析多时间框架指标的一致性\\n- 在技术信号明确时果断执行交易\\n- {{ $json.ranking.totalTrades === 0 ? '首次交易要建立良好开局' : '持续寻找盈利机会,避免过度保守' }}\\n- 重点关注风险回报比,而非排名保护\\n\\n### 可执行的动作:\\n- **OPEN_LONG**: 开多单(无持仓的状态下)\\n- **OPEN_SHORT**: 开空单(无持仓的状态下) \\n- **CLOSE_LONG**: 平多单(持有多仓的状态下)\\n- **CLOSE_SHORT**: 平空单(持有空仓的状态下)\\n- **NO_ACTION**: 观望(当技术信号不明确时)\\n\\n### 执行标准:\\n- 优先考虑收益创造机会\\n- {{ $json.ranking.totalTrades === 0 ? '首次交易要求建立收益基础' : '持续寻找高质量交易机会来扩大总收益' }}\\n- 风险控制与收益追求并重\\n- 只有在技术信号明显冲突时才选择NO_ACTION\\n\\n## 返回格式\\n```json\\n{\\n \\\"action\\\": \\\"OPEN_LONG | OPEN_SHORT | CLOSE_LONG | CLOSE_SHORT | NO_ACTION\\\",\\n \\\"reasoning\\\": \\\"结合技术指标和收益创造目标的极其简洁决策依据\\\",\\n \\\"modelname\\\": \\\"{{ $json.ranking.currentModel }}\\\"\\n}\\n```\\n请直接给出判断结果。\",\"options\":{}},\"type\":\"@n8n/n8n-nodes-langchain.agent\",\"typeVersion\":1,\"position\":[-1152,864],\"id\":\"477e56cb-fc70-44a1-8488-ff917bd82bec\",\"name\":\"Claude\",\"retryOnFail\":true,\"onError\":\"continueRegularOutput\"},{\"parameters\":{\"text\":\"=你是一位专业的加密货币量化交易分析师。请基于以下多时间框架技术指标、当前持仓信息和竞争排名,提供交易决策建议。\\n\\n## 竞争状态\\n你是{{ $json.ranking.currentModel }}大模型,在{{ $json.ranking.totalModels }}个AI模型的交易竞赛中,你目前排名第{{ $json.ranking.currentRank }}位。\\n{{$json.ranking.currentPnl === 0 && $json.ranking.totalTrades === 0 ? '比赛刚开始!这是建立收益基础的好机会!起始阶段积极寻找优质交易机会!' : ''}}\\n\\n### 当前表现\\n- 你的已实现盈亏: {{ $json.ranking.currentPnl }} USDT {{ $json.ranking.currentPnl === 0 ? '(起始状态)' : '' }}\\n- 你的总资产价值: {{ $json.ranking.currentTotalValue }} USDT\\n- 总交易次数: {{ $json.ranking.totalTrades }} {{ $json.ranking.totalTrades === 0 ? '(尚未开始交易)' : '' }}\\n- 胜率: {{ $json.ranking.winRate }}%{{ $json.ranking.totalTrades === 0 ? ' (暂无数据)' : '' }}\\n\\n### 竞争对手排名\\n{{ $json.ranking.rankingText }}\\n{{ $json.ranking.currentPnl === 0 && $json.ranking.totalTrades === 0 ? '比赛开始!!!' : $json.ranking.gapInfo}}\\n\\n## 当前数据概览\\n- 交易对: {{ $json.symbol }}\\n- 分析时间: {{ new Date($json.timestamp).toLocaleString() }}\\n- 当前持仓: {{ $json.position && $json.position.length > 0 ? '有持仓' : '无持仓' }}\\n\\n## 技术指标数据(OLDEST-NEWEST)\\n### 日线级别 (趋势判断)\\n- 价格: {{ $json.timeframes.day?.lastPrice || 'N/A' }}\\n- RSI(14): {{ $json.timeframes.day?.RSI || 'N/A' }} \\n- MACD柱: {{ $json.timeframes.day?.MACD.histogram || 'N/A' }} \\n- ATR: {{ $json.timeframes.day?.ATR || 'N/A' }} \\n- OBV: {{ $json.timeframes.day?.OBV || 'N/A' }} \\n\\n### 小时线级别 (中期趋势)\\n- 价格: {{ $json.timeframes.hour?.lastPrice || 'N/A' }}\\n- RSI(14): {{ $json.timeframes.hour?.RSI || 'N/A' }}\\n- MACD柱: {{ $json.timeframes.hour?.MACD.histogram || 'N/A' }}\\n- ATR: {{ $json.timeframes.hour?.ATR || 'N/A' }}\\n- OBV: {{ $json.timeframes.hour?.OBV || 'N/A' }}\\n\\n### 5分钟线级别 (入场时机)\\n- 价格: {{ $json.timeframes.min5?.lastPrice || 'N/A' }}\\n- RSI(14): {{ $json.timeframes.min5?.RSI || 'N/A' }}\\n- MACD柱: {{ $json.timeframes.min5?.MACD.histogram || 'N/A' }}\\n- ATR: {{ $json.timeframes.min5?.ATR || 'N/A' }}\\n- OBV: {{ $json.timeframes.min5?.OBV || 'N/A' }}\\n\\n### 当前持仓信息\\n{{JSON.stringify($json.position, null, 2)}}\\n\\n## 分析要求\\n基于技术指标和你的竞争排名情况,制定最优交易策略。你的目标是持续创造更多收益,而非单纯保持排名。{{ $json.ranking.totalTrades === 0 ? '作为比赛开始阶段,积极寻找高质量交易机会来建立收益基础.' : '继续寻找优质交易机会来扩大收益,避免因过度保守而错失盈利机会.' }}\\n\\n### 策略建议:\\n{{ $json.ranking.totalTrades === 0 ? '- 比赛刚开始,积极寻找最佳入场时机建立收益基础' : $json.ranking.currentRank > 1 ? '- 你目前落后,积极寻找更多优质交易机会来追赶并创造收益' : '- 你目前表现良好,继续保持积极交易来扩大收益优势' }}\\n- 仔细分析多时间框架指标的一致性\\n- 在技术信号明确时果断执行交易\\n- {{ $json.ranking.totalTrades === 0 ? '首次交易要建立良好开局' : '持续寻找盈利机会,避免过度保守' }}\\n- 重点关注风险回报比,而非排名保护\\n\\n### 可执行的动作:\\n- **OPEN_LONG**: 开多单(无持仓的状态下)\\n- **OPEN_SHORT**: 开空单(无持仓的状态下) \\n- **CLOSE_LONG**: 平多单(持有多仓的状态下)\\n- **CLOSE_SHORT**: 平空单(持有空仓的状态下)\\n- **NO_ACTION**: 观望(当技术信号不明确时)\\n\\n### 执行标准:\\n- 优先考虑收益创造机会\\n- {{ $json.ranking.totalTrades === 0 ? '首次交易要求建立收益基础' : '持续寻找高质量交易机会来扩大总收益' }}\\n- 风险控制与收益追求并重\\n- 只有在技术信号明显冲突时才选择NO_ACTION\\n\\n## 返回格式\\n```json\\n{\\n \\\"action\\\": \\\"OPEN_LONG | OPEN_SHORT | CLOSE_LONG | CLOSE_SHORT | NO_ACTION\\\",\\n \\\"reasoning\\\": \\\"结合技术指标和收益创造目标的极其简洁决策依据\\\",\\n \\\"modelname\\\": \\\"{{ $json.ranking.currentModel }}\\\"\\n}\\n```\\n请直接给出判断结果。\",\"options\":{}},\"type\":\"@n8n/n8n-nodes-langchain.agent\",\"typeVersion\":1,\"position\":[-1152,1152],\"id\":\"58e65b3e-2230-4b3c-820b-4aad2aea7f85\",\"name\":\"QWEN\",\"retryOnFail\":true,\"onError\":\"continueRegularOutput\"},{\"parameters\":{\"model\":{\"__rl\":true,\"value\":\"qwen/qwen3-max\",\"mode\":\"list\",\"cachedResultName\":\"qwen/qwen3-max\"}},\"type\":\"n8n-nodes-base.lmOpenAi\",\"typeVersion\":1,\"position\":[-1152,1296],\"id\":\"50e76e0f-8f71-4cb8-9aeb-f0d0b38f9587\",\"name\":\"OpenAI 模型\",\"credentials\":{\"openAiApi\":{\"id\":\"54d0b567-b3fc-4c6a-b6be-546e0b9cd83f\",\"name\":\"openrouter\"}}},{\"parameters\":{\"text\":\"=你是一位专业的加密货币量化交易分析师。请基于以下多时间框架技术指标、当前持仓信息和竞争排名,提供交易决策建议。\\n\\n## 竞争状态\\n你是{{ $json.ranking.currentModel }}大模型,在{{ $json.ranking.totalModels }}个AI模型的交易竞赛中,你目前排名第{{ $json.ranking.currentRank }}位。\\n{{$json.ranking.currentPnl === 0 && $json.ranking.totalTrades === 0 ? '比赛刚开始!这是建立收益基础的好机会!起始阶段积极寻找优质交易机会!' : ''}}\\n\\n### 当前表现\\n- 你的已实现盈亏: {{ $json.ranking.currentPnl }} USDT {{ $json.ranking.currentPnl === 0 ? '(起始状态)' : '' }}\\n- 你的总资产价值: {{ $json.ranking.currentTotalValue }} USDT\\n- 总交易次数: {{ $json.ranking.totalTrades }} {{ $json.ranking.totalTrades === 0 ? '(尚未开始交易)' : '' }}\\n- 胜率: {{ $json.ranking.winRate }}%{{ $json.ranking.totalTrades === 0 ? ' (暂无数据)' : '' }}\\n\\n### 竞争对手排名\\n{{ $json.ranking.rankingText }}\\n{{ $json.ranking.currentPnl === 0 && $json.ranking.totalTrades === 0 ? '比赛开始!!!' : $json.ranking.gapInfo}}\\n\\n## 当前数据概览\\n- 交易对: {{ $json.symbol }}\\n- 分析时间: {{ new Date($json.timestamp).toLocaleString() }}\\n- 当前持仓: {{ $json.position && $json.position.length > 0 ? '有持仓' : '无持仓' }}\\n\\n## 技术指标数据(OLDEST-NEWEST)\\n### 日线级别 (趋势判断)\\n- 价格: {{ $json.timeframes.day?.lastPrice || 'N/A' }}\\n- RSI(14): {{ $json.timeframes.day?.RSI || 'N/A' }} \\n- MACD柱: {{ $json.timeframes.day?.MACD.histogram || 'N/A' }} \\n- ATR: {{ $json.timeframes.day?.ATR || 'N/A' }} \\n- OBV: {{ $json.timeframes.day?.OBV || 'N/A' }} \\n\\n### 小时线级别 (中期趋势)\\n- 价格: {{ $json.timeframes.hour?.lastPrice || 'N/A' }}\\n- RSI(14): {{ $json.timeframes.hour?.RSI || 'N/A' }}\\n- MACD柱: {{ $json.timeframes.hour?.MACD.histogram || 'N/A' }}\\n- ATR: {{ $json.timeframes.hour?.ATR || 'N/A' }}\\n- OBV: {{ $json.timeframes.hour?.OBV || 'N/A' }}\\n\\n### 5分钟线级别 (入场时机)\\n- 价格: {{ $json.timeframes.min5?.lastPrice || 'N/A' }}\\n- RSI(14): {{ $json.timeframes.min5?.RSI || 'N/A' }}\\n- MACD柱: {{ $json.timeframes.min5?.MACD.histogram || 'N/A' }}\\n- ATR: {{ $json.timeframes.min5?.ATR || 'N/A' }}\\n- OBV: {{ $json.timeframes.min5?.OBV || 'N/A' }}\\n\\n### 当前持仓信息\\n{{JSON.stringify($json.position, null, 2)}}\\n\\n## 分析要求\\n基于技术指标和你的竞争排名情况,制定最优交易策略。你的目标是持续创造更多收益,而非单纯保持排名。{{ $json.ranking.totalTrades === 0 ? '作为比赛开始阶段,积极寻找高质量交易机会来建立收益基础.' : '继续寻找优质交易机会来扩大收益,避免因过度保守而错失盈利机会.' }}\\n\\n### 策略建议:\\n{{ $json.ranking.totalTrades === 0 ? '- 比赛刚开始,积极寻找最佳入场时机建立收益基础' : $json.ranking.currentRank > 1 ? '- 你目前落后,积极寻找更多优质交易机会来追赶并创造收益' : '- 你目前表现良好,继续保持积极交易来扩大收益优势' }}\\n- 仔细分析多时间框架指标的一致性\\n- 在技术信号明确时果断执行交易\\n- {{ $json.ranking.totalTrades === 0 ? '首次交易要建立良好开局' : '持续寻找盈利机会,避免过度保守' }}\\n- 重点关注风险回报比,而非排名保护\\n\\n### 可执行的动作:\\n- **OPEN_LONG**: 开多单(无持仓的状态下)\\n- **OPEN_SHORT**: 开空单(无持仓的状态下) \\n- **CLOSE_LONG**: 平多单(持有多仓的状态下)\\n- **CLOSE_SHORT**: 平空单(持有空仓的状态下)\\n- **NO_ACTION**: 观望(当技术信号不明确时)\\n\\n### 执行标准:\\n- 优先考虑收益创造机会\\n- {{ $json.ranking.totalTrades === 0 ? '首次交易要求建立收益基础' : '持续寻找高质量交易机会来扩大总收益' }}\\n- 风险控制与收益追求并重\\n- 只有在技术信号明显冲突时才选择NO_ACTION\\n\\n## 返回格式\\n```json\\n{\\n \\\"action\\\": \\\"OPEN_LONG | OPEN_SHORT | CLOSE_LONG | CLOSE_SHORT | NO_ACTION\\\",\\n \\\"reasoning\\\": \\\"结合技术指标和收益创造目标的极其简洁决策依据\\\",\\n \\\"modelname\\\": \\\"{{ $json.ranking.currentModel }}\\\"\\n}\\n```\\n请直接给出判断结果。\",\"options\":{}},\"type\":\"@n8n/n8n-nodes-langchain.agent\",\"typeVersion\":1,\"position\":[-1152,1424],\"id\":\"1cc9371f-8390-47cd-a79e-beb030c10781\",\"name\":\"Grok\",\"retryOnFail\":true,\"onError\":\"continueRegularOutput\"},{\"parameters\":{\"model\":{\"__rl\":true,\"value\":\"x-ai/grok-4\",\"mode\":\"list\",\"cachedResultName\":\"x-ai/grok-4\"}},\"type\":\"n8n-nodes-base.lmOpenAi\",\"typeVersion\":1,\"position\":[-1152,1584],\"id\":\"31929d64-519e-4635-b321-c95f917429c2\",\"name\":\"Grok4\",\"credentials\":{\"openAiApi\":{\"id\":\"54d0b567-b3fc-4c6a-b6be-546e0b9cd83f\",\"name\":\"openrouter\"}}},{\"parameters\":{\"mode\":\"append\",\"numberInputs\":4},\"type\":\"n8n-nodes-base.merge\",\"typeVersion\":3.2,\"position\":[-752,1024],\"id\":\"b24faeb3-319a-49bc-a130-fb150f2ec64b\",\"name\":\"合并\"},{\"parameters\":{\"operation\":\"csv\",\"binaryPropertyName\":\"data\",\"options\":{}},\"type\":\"n8n-nodes-base.convertToFile\",\"typeVersion\":1.1,\"position\":[-80,1152],\"id\":\"f0c9ec35-299b-4244-897d-5dbe10a9768c\",\"name\":\"转换为文件\"},{\"parameters\":{\"info\":\"\",\"fileName\":\"tradelog.csv\",\"dataPropertyName\":\"data\",\"options\":{}},\"type\":\"n8n-nodes-base.writeFile\",\"typeVersion\":1,\"position\":[144,1152],\"id\":\"b871fce4-554f-46df-bfbd-7e67bee688fd\",\"name\":\"写入文件到磁盘\"},{\"parameters\":{\"mode\":\"runOnceForAllItems\",\"language\":\"javaScript\",\"jsCode\":\"// 获取AI决策结果并清洗数据\\nconst aiResults = $input.all().map(item => {\\n if (item.json && item.json.output) {\\n return { output: item.json.output };\\n } else if (item.output) {\\n return { output: item.output };\\n }\\n return null;\\n}).filter(item => item !== null);\\n\\nexchange.SetContractType('swap') \\nconst ticker = _C(exchange.GetTicker);\\nconst fixedSize = $vars.size || 0.01; // 固定交易数量\\n\\nif (!ticker || !ticker.Last) {\\n Log(\\\"获取价格失败\\\");\\n return $input.all();\\n}\\n\\nconst currentPrice = ticker.Last;\\nconst timestamp = Date.now();\\n\\n// 获取合约价值\\nconst markets = _G('markets');\\nconst ctVal = markets ? markets.CtVal : 1;\\n\\n// 获取模型数据 - 使用深拷贝避免修改原始数据\\nconst models = JSON.parse(JSON.stringify($node['策略初始化'].json));\\n\\n// 处理每个AI的决策\\naiResults.forEach(item => {\\n Log('当前item:', item)\\n if (!item.output){\\n return;\\n }\\n \\n try {\\n let decision;\\n \\n // 尝试提取markdown包裹的JSON\\n const jsonMatch = item.output.match(/```json\\\\s*([\\\\s\\\\S]*?)\\\\s*```/);\\n \\n if (jsonMatch) {\\n // Claude格式:```json ... ```\\n decision = JSON.parse(jsonMatch[1]);\\n } else {\\n // DS格式:直接就是JSON\\n decision = JSON.parse(item.output);\\n }\\n \\n const modelKey = decision.modelname;\\n\\n if (!models || !models[modelKey]) {\\n Log(`未找到模型: ${modelKey}`);\\n return;\\n }\\n \\n const model = models[modelKey];\\n \\n // 记录决策\\n model.decisions.push({\\n timestamp,\\n action: decision.action,\\n reasoning: decision.reasoning,\\n price: currentPrice\\n });\\n \\n // ============ 虚拟持仓交易逻辑 ============\\n \\n if (decision.action === 'OPEN_LONG') {\\n // 检查是否已有持仓(虚拟持仓)\\n if (model.positions.length === 0) {\\n model.positions.push({\\n side: 'long',\\n size: fixedSize,\\n entryPrice: currentPrice,\\n ctVal: ctVal,\\n timestamp: timestamp\\n });\\n \\n model.account.totalTrades++;\\n \\n model.tradeHistory.push({\\n action: 'OPEN_LONG',\\n price: currentPrice,\\n size: fixedSize,\\n ctVal: ctVal,\\n timestamp: timestamp\\n });\\n \\n Log(`${modelKey} 虚拟开多: ${currentPrice}, 数量: ${fixedSize}`);\\n }\\n }\\n \\n else if (decision.action === 'OPEN_SHORT') {\\n // 检查是否已有持仓(虚拟持仓)\\n if (model.positions.length === 0) {\\n model.positions.push({\\n side: 'short',\\n size: fixedSize,\\n entryPrice: currentPrice,\\n ctVal: ctVal,\\n timestamp: timestamp\\n });\\n \\n model.account.totalTrades++;\\n \\n model.tradeHistory.push({\\n action: 'OPEN_SHORT',\\n price: currentPrice,\\n size: fixedSize,\\n ctVal: ctVal,\\n timestamp: timestamp\\n });\\n \\n Log(`${modelKey} 虚拟开空: ${currentPrice}, 数量: ${fixedSize}`);\\n }\\n }\\n \\n else if (decision.action === 'CLOSE_LONG' || decision.action === 'CLOSE_SHORT') {\\n // 平仓(虚拟持仓)\\n const targetSide = decision.action === 'CLOSE_LONG' ? 'long' : 'short';\\n const posIndex = model.positions.findIndex(pos => pos.side === targetSide);\\n \\n if (posIndex !== -1) {\\n const position = model.positions[posIndex];\\n \\n // ✅ 修复:计算绝对盈亏(不除以entryPrice)\\n const pnl = position.side === 'long' \\n ? (currentPrice - position.entryPrice) * position.size * position.ctVal\\n : (position.entryPrice - currentPrice) * position.size * position.ctVal;\\n \\n // 开仓和平仓手续费\\n const openFee = position.size * position.ctVal * 0.001;\\n const closeFee = position.size * position.ctVal * 0.001;\\n const totalFee = openFee + closeFee;\\n \\n const netPnl = pnl - totalFee;\\n \\n // 累计到总盈亏\\n model.account.realizedPnl += netPnl;\\n \\n if (netPnl > 0) model.account.winTrades++;\\n \\n model.tradeHistory.push({\\n action: decision.action,\\n price: currentPrice,\\n size: position.size,\\n ctVal: position.ctVal,\\n entryPrice: position.entryPrice,\\n pnl: netPnl,\\n fee: totalFee,\\n timestamp: timestamp\\n });\\n \\n Log(`${modelKey} 虚拟平仓: ${currentPrice}, 盈亏: ${netPnl.toFixed(2)}`);\\n \\n // 移除虚拟持仓\\n model.positions.splice(posIndex, 1);\\n }\\n }\\n \\n // ✅ 修复:计算未实现盈亏(不除以entryPrice)\\n let unrealizedPnl = 0;\\n model.positions.forEach(pos => {\\n if (pos.side === 'long') {\\n unrealizedPnl += (currentPrice - pos.entryPrice) * pos.size * pos.ctVal;\\n } else {\\n unrealizedPnl += (pos.entryPrice - currentPrice) * pos.size * pos.ctVal;\\n }\\n });\\n \\n model.account.totalValue = model.account.initialBalance + model.account.realizedPnl + unrealizedPnl;\\n model.account.balance = model.account.totalValue;\\n \\n } catch (error) {\\n Log(`处理决策时出错: ${error.message}`);\\n Log(`原始输出: ${item.output}`);\\n }\\n});\\n\\n// 保存更新后的models到_G\\n_G('models', models);\\n\\nreturn models;\\n\",\"notice\":\"\"},\"type\":\"n8n-nodes-base.code\",\"typeVersion\":2,\"position\":[-528,1056],\"id\":\"a94826bd-46be-4cdc-aff9-e8c71e40d680\",\"name\":\"结果核算\"},{\"parameters\":{\"mode\":\"runOnceForAllItems\",\"language\":\"javaScript\",\"jsCode\":\"// 提取并格式化所有模型的交易数据\\nconst inputData = $input.all()[0].json;\\n\\n// ✅ 自动从数据中获取模型列表\\nconst models = Object.keys(inputData);\\n\\n// 构建结果数组\\nconst results = models.map(model => {\\n const data = inputData[model];\\n \\n // ✅ 安全检查\\n if (!data || !data.account) {\\n Log(`警告: 模型 ${model} 数据不完整,跳过`);\\n return null;\\n }\\n \\n // 获取最新决策\\n const latestDecision = data.decisions && data.decisions.length > 0 \\n ? data.decisions[data.decisions.length - 1] \\n : null;\\n \\n // 获取当前持仓\\n const currentPosition = data.positions && data.positions.length > 0\\n ? data.positions[0]\\n : null;\\n \\n return {\\n // 模型名称\\n model: model,\\n \\n // 账户信息\\n initialBalance: data.account.initialBalance,\\n balance: data.account.balance,\\n totalValue: data.account.totalValue,\\n realizedPnl: data.account.realizedPnl,\\n totalTrades: data.account.totalTrades,\\n winTrades: data.account.winTrades,\\n winRate: data.account.totalTrades > 0 \\n ? ((data.account.winTrades / data.account.totalTrades) * 100).toFixed(2) + '%'\\n : '0%',\\n \\n // 持仓信息\\n hasPosition: currentPosition ? 'YES' : 'NO',\\n positionType: currentPosition?.type || '-',\\n positionSize: currentPosition?.size || 0,\\n entryPrice: currentPosition?.entryPrice || 0,\\n currentPrice: currentPosition?.currentPrice || 0,\\n unrealizedPnl: currentPosition?.unrealizedPnl || 0,\\n \\n // 最新决策\\n latestAction: latestDecision?.action || 'NO_DECISION',\\n latestPrice: latestDecision?.price || 0,\\n latestTimestamp: latestDecision?.timestamp || 0,\\n latestReasoning: latestDecision?.reasoning || '-',\\n \\n // 交易历史统计\\n tradeHistoryCount: data.tradeHistory.length,\\n decisionsCount: data.decisions.length,\\n \\n // 添加时间戳\\n recordTime: new Date().toISOString()\\n };\\n}).filter(item => item !== null); // ✅ 过滤无效数据\\n\\nlet tradelog = _G('tradelog') || [];\\n\\n// 添加当前所有模型的记录\\ntradelog.push({\\n timestamp: new Date().toISOString(),\\n models: results\\n});\\n\\n_G('tradelog', tradelog);\\n\\n// 返回数据用于下一个节点\\nreturn tradelog;\\n\",\"notice\":\"\"},\"type\":\"n8n-nodes-base.code\",\"typeVersion\":2,\"position\":[-304,1056],\"id\":\"a6280d67-b499-4a9b-9a9b-cd15397f7f4a\",\"name\":\"交易记录保存\"},{\"parameters\":{\"mode\":\"runOnceForAllItems\",\"language\":\"javaScript\",\"jsCode\":\"// 获取所有模型数据\\nconst inputData = $node['结果核算'].json;\\n\\n// 获取当前真实交易使用的模型(如果有)\\nlet activeModel = _G('activeModel') || null;\\nlet highestPnl = _G('highestPnl') || 15; // 初始阈值\\n\\nLog('highestPnl:', highestPnl)\\n\\n// 遍历所有模型,找出最优模型\\nlet bestModel = null;\\nlet bestPnl = highestPnl;\\n\\nObject.keys(inputData).forEach(modelName => {\\n const model = inputData[modelName];\\n const realizedPnl = model.account.realizedPnl;\\n \\n // 找出盈亏最高的模型\\n if (realizedPnl > bestPnl) {\\n bestPnl = realizedPnl;\\n bestModel = modelName;\\n }\\n});\\n\\n// 决策逻辑\\nlet shouldTrade = false;\\nlet tradeAction = null;\\nlet modelChanged = false;\\n\\nif (bestModel) {\\n // 如果没有激活模型,且找到盈利的模型\\n if (!activeModel) {\\n activeModel = bestModel;\\n highestPnl = bestPnl;\\n modelChanged = true;\\n Log(`🎯 启动真实交易!选择模型: ${activeModel}, 盈亏: ${bestPnl.toFixed(2)} USDT`);\\n } \\n // 如果当前模型不是最优模型,切换到最优模型\\n else if (bestModel !== activeModel) {\\n Log(`🔄 模型切换: ${activeModel} (${highestPnl.toFixed(2)}) -> ${bestModel} (${bestPnl.toFixed(2)})`);\\n activeModel = bestModel;\\n highestPnl = bestPnl;\\n modelChanged = true;\\n }\\n \\n // 获取激活模型的纸面持仓状态\\n const activeModelData = inputData[activeModel];\\n const paperPositions = activeModelData.positions || [];\\n \\n // 获取真实持仓状态\\n const realPositions = exchange.GetPosition();\\n const hasRealLong = realPositions && realPositions.some(p => p.Type === PD_LONG && p.Amount > 0);\\n const hasRealShort = realPositions && realPositions.some(p => p.Type === PD_SHORT && p.Amount > 0);\\n \\n // 纸面持仓状态\\n const hasPaperLong = paperPositions.some(p => p.side === 'long');\\n const hasPaperShort = paperPositions.some(p => p.side === 'short');\\n \\n // 同步逻辑:让真实持仓与纸面持仓一致\\n if (hasPaperLong && !hasRealLong) {\\n // 纸面有多单,真实没有多单\\n if (hasRealShort) {\\n // 如果真实有空单,先平空单\\n shouldTrade = true;\\n tradeAction = {\\n model: activeModel,\\n action: 'CLOSE_SHORT',\\n reason: '同步持仓:先平空单',\\n paperPosition: paperPositions[0],\\n modelPnl: activeModelData.account.realizedPnl\\n };\\n } else {\\n // 真实无持仓,开多单\\n shouldTrade = true;\\n tradeAction = {\\n model: activeModel,\\n action: 'OPEN_LONG',\\n reason: '同步持仓:开多单',\\n paperPosition: paperPositions[0],\\n modelPnl: activeModelData.account.realizedPnl\\n };\\n }\\n } \\n else if (hasPaperShort && !hasRealShort) {\\n // 纸面有空单,真实没有空单\\n if (hasRealLong) {\\n // 如果真实有多单,先平多单\\n shouldTrade = true;\\n tradeAction = {\\n model: activeModel,\\n action: 'CLOSE_LONG',\\n reason: '同步持仓:先平多单',\\n paperPosition: paperPositions[0],\\n modelPnl: activeModelData.account.realizedPnl\\n };\\n } else {\\n // 真实无持仓,开空单\\n shouldTrade = true;\\n tradeAction = {\\n model: activeModel,\\n action: 'OPEN_SHORT',\\n reason: '同步持仓:开空单',\\n paperPosition: paperPositions[0],\\n modelPnl: activeModelData.account.realizedPnl\\n };\\n }\\n }\\n else if (!hasPaperLong && !hasPaperShort && (hasRealLong || hasRealShort)) {\\n // 纸面无持仓,但真实有持仓,需要平仓\\n if (hasRealLong) {\\n shouldTrade = true;\\n tradeAction = {\\n model: activeModel,\\n action: 'CLOSE_LONG',\\n reason: '同步持仓:纸面已平仓',\\n modelPnl: activeModelData.account.realizedPnl\\n };\\n } else if (hasRealShort) {\\n shouldTrade = true;\\n tradeAction = {\\n model: activeModel,\\n action: 'CLOSE_SHORT',\\n reason: '同步持仓:纸面已平仓',\\n modelPnl: activeModelData.account.realizedPnl\\n };\\n }\\n }\\n}\\n\\n// 保存状态\\n_G('activeModel', activeModel);\\n_G('highestPnl', highestPnl);\\n\\n// 执行真实交易\\nif (shouldTrade && tradeAction) {\\n const symbol = $vars.coin + \\\"_USDT.swap\\\";\\n const size = $vars.size || 0.01;\\n \\n Log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);\\n Log(`🤖 真实交易执行(同步纸面持仓)`);\\n Log(`模型: ${tradeAction.model}`);\\n Log(`动作: ${tradeAction.action}`);\\n Log(`原因: ${tradeAction.reason}`);\\n Log(`数量: ${size}`);\\n Log(`模型盈亏: ${tradeAction.modelPnl.toFixed(2)} USDT`);\\n if (tradeAction.paperPosition) {\\n Log(`纸面持仓: ${tradeAction.paperPosition.side}, 入场价: ${tradeAction.paperPosition.entryPrice}`);\\n }\\n Log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);\\n \\n try {\\n // 获取当前持仓\\n const positions = exchange.GetPosition();\\n const hasLongPosition = positions && positions.some(p => p.Type === PD_LONG && p.Amount > 0);\\n const hasShortPosition = positions && positions.some(p => p.Type === PD_SHORT && p.Amount > 0);\\n \\n // 执行交易\\n if (tradeAction.action === 'OPEN_LONG' && !hasLongPosition && !hasShortPosition) {\\n exchange.SetDirection(\\\"buy\\\");\\n const orderId = exchange.Buy(-1, size);\\n Log(`✅ 开多单成功, 订单ID: ${orderId}`);\\n } \\n else if (tradeAction.action === 'OPEN_SHORT' && !hasLongPosition && !hasShortPosition) {\\n exchange.SetDirection(\\\"sell\\\");\\n const orderId = exchange.Sell(-1, size);\\n Log(`✅ 开空单成功, 订单ID: ${orderId}`);\\n }\\n else if (tradeAction.action === 'CLOSE_LONG' && hasLongPosition) {\\n const longPos = positions.find(p => p.Type === PD_LONG && p.Amount > 0);\\n exchange.SetDirection(\\\"closebuy\\\");\\n const orderId = exchange.Sell(-1, longPos.Amount);\\n Log(`✅ 平多单成功, 订单ID: ${orderId}`);\\n }\\n else if (tradeAction.action === 'CLOSE_SHORT' && hasShortPosition) {\\n const shortPos = positions.find(p => p.Type === PD_SHORT && p.Amount > 0);\\n exchange.SetDirection(\\\"closesell\\\");\\n const orderId = exchange.Buy(-1, shortPos.Amount);\\n Log(`✅ 平空单成功, 订单ID: ${orderId}`);\\n }\\n else {\\n Log(`⚠️ 无法执行交易: 持仓状态不匹配`);\\n }\\n } catch (error) {\\n Log(`❌ 交易执行失败: ${error.message}`);\\n }\\n}\\n\\n// 返回状态信息\\nreturn [{\\n json: {\\n activeModel: activeModel,\\n highestPnl: highestPnl,\\n shouldTrade: shouldTrade,\\n modelChanged: modelChanged,\\n tradeAction: tradeAction,\\n allModelsStatus: Object.keys(inputData).map(modelName => {\\n const model = inputData[modelName];\\n return {\\n model: modelName,\\n realizedPnl: model.account.realizedPnl,\\n totalValue: model.account.totalValue,\\n isActive: modelName === activeModel,\\n paperPosition: model.positions.length > 0 ? model.positions[0].side : 'none'\\n };\\n }).sort((a, b) => b.realizedPnl - a.realizedPnl)\\n }\\n}];\\n\",\"notice\":\"\"},\"type\":\"n8n-nodes-base.code\",\"typeVersion\":2,\"position\":[-80,960],\"id\":\"51e667f8-000e-40e2-bc38-8b885260cb94\",\"name\":\"最优交易\"},{\"parameters\":{\"mode\":\"runOnceForAllItems\",\"language\":\"javaScript\",\"jsCode\":\"api_base = \\\"https://testnet.binancefuture.com\\\"\\nexchange.SetBase(api_base)\\n\\n\\n// 获取并分割模型列表\\nconst modelListStr = $vars.modelList || '';\\nconst modelList = modelListStr.split(',').filter(name => name.trim());\\n\\nif (modelList.length === 0) {\\n return {};\\n}\\n\\n// 初始化全局容器\\nif (!_G('models')) {\\n _G('models', {});\\n _G('tradelog')\\n\\n let allMarkets = null;\\n for (let i = 0; i < 5; i++) {\\n allMarkets = exchange.GetMarkets();\\n if (allMarkets && Object.keys(allMarkets).length > 0) {\\n break;\\n }\\n Sleep(1000);\\n }\\n \\n const symbol = $vars.coin + '_USDT.swap';\\n _G('markets', allMarkets[symbol]);\\n Log(_G('markets'))\\n \\n\\n const initAccount = exchange.GetAccount();\\n _G('initmoney', initAccount.Balance);\\n}\\n\\n// 为每个模型创建交易系统\\nmodelList.forEach(modelName => {\\n const key = modelName.trim();\\n const models = _G('models');\\n \\n if (!models[key]) {\\n models[key] = {\\n account: {\\n initialBalance: 10000, // 添加初始资金\\n balance: 10000,\\n totalValue: 10000,\\n realizedPnl: 0,\\n totalTrades: 0,\\n winTrades: 0\\n },\\n positions: [],\\n tradeHistory: [],\\n decisions: []\\n };\\n _G('models', models);\\n }\\n});\\n\\nreturn _G('models');\",\"notice\":\"\"},\"type\":\"n8n-nodes-base.code\",\"typeVersion\":2,\"position\":[-1600,1056],\"id\":\"722030a0-2be6-438f-b8bc-2f6396045b79\",\"name\":\"策略初始化\"},{\"parameters\":{\"mode\":\"runOnceForAllItems\",\"language\":\"javaScript\",\"jsCode\":\"// ========== AI模型竞赛可视化仪表板 ==========\\n\\n/**\\n * 安全格式化辅助函数\\n */\\nfunction safeFormat(value, decimals = 2, prefix = '') {\\n if (value === null || value === undefined || isNaN(value)) {\\n return prefix + '0';\\n }\\n return prefix + _N(value, decimals);\\n}\\n\\nfunction safePercentage(numerator, denominator, decimals = 1) {\\n if (!denominator || denominator === 0) return '0%';\\n const result = (numerator / denominator) * 100;\\n return safeFormat(result, decimals) + '%';\\n}\\n\\n/**\\n * 表格1: 模型运行状态\\n */\\nfunction createModelStatusTable(allModelsStatus, models) {\\n const statusTable = {\\n type: \\\"table\\\",\\n title: \\\"🤖 AI模型实时运行状态\\\",\\n cols: [\\\"模型\\\", \\\"激活\\\", \\\"初始\\\", \\\"当前\\\", \\\"已实现\\\", \\\"盈利率\\\", \\\"纸面仓\\\", \\\"交易数\\\", \\\"胜率\\\", \\\"最新决策\\\", \\\"决策价格\\\", \\\"决策原因\\\"],\\n rows: []\\n };\\n \\n try {\\n allModelsStatus.forEach(model => {\\n const modelData = models[model.model];\\n if (!modelData) {\\n Log(`警告: 未找到模型数据 ${model.model}`);\\n return;\\n }\\n \\n const latestDecision = modelData.decisions && modelData.decisions.length > 0\\n ? modelData.decisions[modelData.decisions.length - 1]\\n : null;\\n \\n const profitRate = ((modelData.account.realizedPnl || 0) / (modelData.account.initialBalance || 1)) * 100;\\n \\n // 盈利率显示\\n let profitRateDisplay = \\\"\\\";\\n if (profitRate > 5) {\\n profitRateDisplay = `🔥 +${safeFormat(profitRate)}%`;\\n } else if (profitRate > 0) {\\n profitRateDisplay = `🟢 +${safeFormat(profitRate)}%`;\\n } else if (profitRate < 0) {\\n profitRateDisplay = `🔴 ${safeFormat(profitRate)}%`;\\n } else {\\n profitRateDisplay = `⚪ 0%`;\\n }\\n \\n // 持仓显示\\n let positionDisplay = \\\"\\\";\\n if (model.paperPosition === 'none') {\\n positionDisplay = \\\"📭 空\\\";\\n } else if (model.paperPosition === 'long') {\\n positionDisplay = \\\"📈 多\\\";\\n } else {\\n positionDisplay = \\\"📉 空\\\";\\n }\\n \\n // 决策显示\\n let actionDisplay = latestDecision?.action || \\\"无\\\";\\n switch(actionDisplay) {\\n case 'OPEN_LONG':\\n actionDisplay = \\\"🟢 开多\\\";\\n break;\\n case 'OPEN_SHORT':\\n actionDisplay = \\\"🔴 开空\\\";\\n break;\\n case 'CLOSE_LONG':\\n actionDisplay = \\\"⏹️ 平多\\\";\\n break;\\n case 'CLOSE_SHORT':\\n actionDisplay = \\\"⏹️ 平空\\\";\\n break;\\n case 'NO_ACTION':\\n actionDisplay = \\\"⏸️ 观望\\\";\\n break;\\n }\\n \\n const realizedPnl = modelData.account.realizedPnl || 0;\\n let pnlDisplay = \\\"\\\";\\n if (realizedPnl > 0) {\\n pnlDisplay = `🟢 ${safeFormat(realizedPnl, 2, \\\"$\\\")}`;\\n } else if (realizedPnl < 0) {\\n pnlDisplay = `🔴 ${safeFormat(realizedPnl, 2, \\\"$\\\")}`;\\n } else {\\n pnlDisplay = `⚪ $0`;\\n }\\n \\n statusTable.rows.push([\\n `${model.isActive ? '⭐' : '💎'} ${model.model}`,\\n model.isActive ? \\\"✅\\\" : \\\"❌\\\",\\n safeFormat(modelData.account.initialBalance, 2, \\\"$\\\"),\\n safeFormat(modelData.account.totalValue, 2, \\\"$\\\"),\\n pnlDisplay,\\n profitRateDisplay,\\n positionDisplay,\\n modelData.account.totalTrades || 0,\\n safePercentage(modelData.account.winTrades || 0, modelData.account.totalTrades || 1),\\n actionDisplay,\\n latestDecision?.price ? safeFormat(latestDecision.price, 2, \\\"$\\\") : '-',\\n latestDecision?.reasoning ? latestDecision.reasoning : '-'\\n ]);\\n });\\n \\n } catch (e) {\\n Log(`❌ 创建模型状态表失败: ${e.message}`);\\n Log(`错误堆栈: ${e.stack}`);\\n statusTable.rows.push([\\n \\\"❌ 错误\\\", \\\"获取数据失败\\\", \\\"-\\\", \\\"-\\\", \\\"-\\\", \\\"-\\\", \\\"-\\\", \\\"-\\\", \\\"-\\\", \\\"-\\\", \\\"-\\\", e.message\\n ]);\\n }\\n \\n return statusTable;\\n}\\n\\n/**\\n * 表格2: 模型性能对比分析\\n */\\nfunction createPerformanceComparisonTable(allModelsStatus, models) {\\n const perfTable = {\\n type: \\\"table\\\",\\n title: \\\"📊 AI模型性能对比分析 (按盈亏排序)\\\",\\n cols: [\\\"排名\\\", \\\"模型\\\", \\\"已实现\\\", \\\"总资产\\\", \\\"最大盈利\\\", \\\"最大亏损\\\", \\\"最大回撤\\\", \\\"夏普比率\\\", \\\"盈亏比\\\", \\\"交易数\\\", \\\"胜率\\\", \\\"平均盈\\\", \\\"平均亏\\\"],\\n rows: []\\n };\\n \\n try {\\n const performanceData = allModelsStatus.map((model, index) => {\\n const modelData = models[model.model];\\n if (!modelData) {\\n return null;\\n }\\n \\n const tradeHistory = modelData.tradeHistory || [];\\n \\n // 筛选平仓交易(有pnl的记录)\\n const closedTrades = tradeHistory.filter(trade => \\n trade.pnl !== undefined && trade.pnl !== null\\n );\\n \\n // 计算最大盈利\\n const maxProfit = closedTrades.length > 0\\n ? Math.max(...closedTrades.map(t => t.pnl || 0))\\n : 0;\\n \\n // 计算最大亏损\\n const maxLoss = closedTrades.length > 0\\n ? Math.min(...closedTrades.map(t => t.pnl || 0))\\n : 0;\\n \\n // 计算最大回撤\\n let maxDrawdown = 0;\\n let peak = modelData.account.initialBalance || 10000;\\n let cumulativePnl = 0;\\n \\n closedTrades.forEach(trade => {\\n cumulativePnl += (trade.pnl || 0);\\n const currentValue = (modelData.account.initialBalance || 10000) + cumulativePnl;\\n \\n if (currentValue > peak) {\\n peak = currentValue;\\n }\\n \\n const drawdown = peak > 0 ? ((peak - currentValue) / peak) * 100 : 0;\\n if (drawdown > maxDrawdown) {\\n maxDrawdown = drawdown;\\n }\\n });\\n \\n // 计算夏普比率\\n let sharpeRatio = 0;\\n if (closedTrades.length > 1) {\\n const initialBalance = modelData.account.initialBalance || 10000;\\n const returns = closedTrades.map(t => (t.pnl || 0) / initialBalance);\\n const avgReturn = returns.reduce((a, b) => a + b, 0) / returns.length;\\n \\n const variance = returns.reduce((sum, r) => sum + Math.pow(r - avgReturn, 2), 0) / returns.length;\\n const stdDev = Math.sqrt(variance);\\n \\n sharpeRatio = stdDev !== 0 ? (avgReturn / stdDev) : 0;\\n }\\n \\n // 盈亏比\\n const winTrades = closedTrades.filter(t => (t.pnl || 0) > 0);\\n const lossTrades = closedTrades.filter(t => (t.pnl || 0) < 0);\\n \\n const avgWin = winTrades.length > 0\\n ? winTrades.reduce((sum, t) => sum + (t.pnl || 0), 0) / winTrades.length\\n : 0;\\n \\n const avgLoss = lossTrades.length > 0\\n ? Math.abs(lossTrades.reduce((sum, t) => sum + (t.pnl || 0), 0) / lossTrades.length)\\n : 0;\\n \\n const profitLossRatio = avgLoss !== 0 ? (avgWin / avgLoss) : 0;\\n \\n return {\\n model: model.model,\\n rank: index + 1,\\n realizedPnl: modelData.account.realizedPnl || 0,\\n totalValue: modelData.account.totalValue || 0,\\n maxProfit: maxProfit,\\n maxLoss: maxLoss,\\n maxDrawdown: maxDrawdown,\\n sharpeRatio: sharpeRatio,\\n profitLossRatio: profitLossRatio,\\n totalTrades: closedTrades.length,\\n winRate: (modelData.account.totalTrades || 0) > 0 \\n ? (((modelData.account.winTrades || 0) / modelData.account.totalTrades) * 100)\\n : 0,\\n avgWin: avgWin,\\n avgLoss: avgLoss\\n };\\n }).filter(perf => perf !== null).sort((a, b) => b.realizedPnl - a.realizedPnl);\\n \\n performanceData.forEach((perf, index) => {\\n // 排名显示\\n let rankDisplay = \\\"\\\";\\n if (index === 0) {\\n rankDisplay = \\\"🥇\\\";\\n } else if (index === 1) {\\n rankDisplay = \\\"🥈\\\";\\n } else if (index === 2) {\\n rankDisplay = \\\"🥉\\\";\\n } else {\\n rankDisplay = `${index + 1}`;\\n }\\n \\n // 夏普比率显示\\n let sharpeDisplay = \\\"\\\";\\n if (perf.sharpeRatio > 2) {\\n sharpeDisplay = `🔥 ${safeFormat(perf.sharpeRatio)}`;\\n } else if (perf.sharpeRatio > 1) {\\n sharpeDisplay = `✅ ${safeFormat(perf.sharpeRatio)}`;\\n } else if (perf.sharpeRatio > 0) {\\n sharpeDisplay = `⚡ ${safeFormat(perf.sharpeRatio)}`;\\n } else {\\n sharpeDisplay = `⚠️ ${safeFormat(perf.sharpeRatio)}`;\\n }\\n \\n perfTable.rows.push([\\n rankDisplay,\\n `💎 ${perf.model}`,\\n perf.realizedPnl > 0 \\n ? `🟢 ${safeFormat(perf.realizedPnl, 2, \\\"$\\\")}`\\n : perf.realizedPnl < 0\\n ? `🔴 ${safeFormat(perf.realizedPnl, 2, \\\"$\\\")}`\\n : `⚪ $0`,\\n safeFormat(perf.totalValue, 2, \\\"$\\\"),\\n perf.maxProfit > 0 ? `🟢 ${safeFormat(perf.maxProfit, 2, \\\"$\\\")}` : '$0',\\n perf.maxLoss < 0 ? `🔴 ${safeFormat(perf.maxLoss, 2, \\\"$\\\")}` : '$0',\\n perf.maxDrawdown > 0 ? `⚠️ ${safeFormat(perf.maxDrawdown)}%` : '0%',\\n sharpeDisplay,\\n perf.profitLossRatio > 0 ? safeFormat(perf.profitLossRatio) : '0',\\n perf.totalTrades,\\n `${safeFormat(perf.winRate, 1)}%`,\\n perf.avgWin > 0 ? safeFormat(perf.avgWin, 2, \\\"$\\\") : '$0',\\n perf.avgLoss > 0 ? safeFormat(perf.avgLoss, 2, \\\"$\\\") : '$0'\\n ]);\\n });\\n \\n // 添加汇总行\\n if (performanceData.length > 0) {\\n const avgPnl = performanceData.reduce((sum, p) => sum + p.realizedPnl, 0) / performanceData.length;\\n const avgSharpe = performanceData.reduce((sum, p) => sum + p.sharpeRatio, 0) / performanceData.length;\\n const totalTrades = performanceData.reduce((sum, p) => sum + p.totalTrades, 0);\\n \\n perfTable.rows.push([\\n \\\"📊\\\",\\n \\\"平均\\\",\\n avgPnl > 0 ? `🟢 ${safeFormat(avgPnl, 2, \\\"$\\\")}` : avgPnl < 0 ? `🔴 ${safeFormat(avgPnl, 2, \\\"$\\\")}` : `⚪ $0`,\\n \\\"-\\\",\\n \\\"-\\\",\\n \\\"-\\\",\\n \\\"-\\\",\\n safeFormat(avgSharpe),\\n \\\"-\\\",\\n totalTrades,\\n \\\"-\\\",\\n \\\"-\\\",\\n \\\"-\\\"\\n ]);\\n }\\n \\n } catch (e) {\\n Log(`❌ 创建性能对比表失败: ${e.message}`);\\n Log(`错误堆栈: ${e.stack}`);\\n perfTable.rows.push([\\n \\\"❌\\\", \\\"错误\\\", \\\"获取数据失败\\\", \\\"-\\\", \\\"-\\\", \\\"-\\\", \\\"-\\\", \\\"-\\\", \\\"-\\\", \\\"-\\\", \\\"-\\\", \\\"-\\\", e.message\\n ]);\\n }\\n \\n return perfTable;\\n}\\n\\n/**\\n * 表格3: 实际交易状态\\n */\\nfunction createRealTradingTable(inputData, models) {\\n const realTable = {\\n type: \\\"table\\\",\\n title: \\\"💼 实盘交易状态\\\",\\n cols: [\\\"项目\\\", \\\"数值\\\", \\\"状态\\\", \\\"说明\\\"],\\n rows: []\\n };\\n \\n try {\\n const activeModel = inputData.activeModel;\\n const realAccount = exchange.GetAccount();\\n const realPositions = exchange.GetPosition();\\n \\n // 获取真实持仓信息\\n let realPositionInfo = {\\n type: '无',\\n size: 0,\\n entryPrice: 0,\\n currentPrice: 0,\\n unrealizedPnl: 0\\n };\\n \\n if (realPositions && realPositions.length > 0) {\\n const pos = realPositions[0];\\n const ticker = exchange.GetTicker();\\n const currentPrice = ticker ? ticker.Last : 0;\\n \\n realPositionInfo = {\\n type: pos.Type === PD_LONG ? '多' : '空',\\n size: pos.Amount || 0,\\n entryPrice: pos.Price || 0,\\n currentPrice: currentPrice,\\n unrealizedPnl: pos.Profit || 0\\n };\\n }\\n \\n // 计算实际账户的累计收益\\n const initMoney = _G('initmoney') || 10000;\\n const currentBalance = realAccount ? (realAccount.Balance || 0) : 0;\\n const currentEquity = realAccount ? (realAccount.Equity || 0) : 0;\\n const realizedProfit = currentBalance - initMoney;\\n const totalProfit = currentEquity - initMoney;\\n const returnRate = initMoney > 0 ? ((totalProfit / initMoney) * 100) : 0;\\n\\n LogProfit(totalProfit, \\\"&\\\");\\n \\n // 激活模型信息\\n realTable.rows.push([\\n \\\"🤖 激活模型\\\",\\n activeModel || \\\"未启动\\\",\\n activeModel ? \\\"✅ 运行中\\\" : \\\"⏸️ 待启动\\\",\\n activeModel && models[activeModel] \\n ? `盈亏: ${safeFormat(models[activeModel].account.realizedPnl, 2, \\\"$\\\")}` \\n : \\\"等待盈利大于阈值触发\\\"\\n ]);\\n \\n // 账户信息\\n realTable.rows.push([\\n \\\"💰 初始资金\\\",\\n safeFormat(initMoney, 2, \\\"$\\\"),\\n \\\"📊\\\",\\n \\\"实盘起始金额\\\"\\n ]);\\n \\n realTable.rows.push([\\n \\\"💵 当前余额\\\",\\n safeFormat(currentBalance, 2, \\\"$\\\"),\\n \\\"📊\\\",\\n \\\"可用资金\\\"\\n ]);\\n \\n realTable.rows.push([\\n \\\"💎 账户权益\\\",\\n safeFormat(currentEquity, 2, \\\"$\\\"),\\n \\\"📊\\\",\\n \\\"余额 + 持仓盈亏\\\"\\n ]);\\n \\n // 盈亏信息\\n let profitDisplay = \\\"\\\";\\n let profitStatus = \\\"\\\";\\n if (totalProfit > 0) {\\n profitDisplay = `🟢 +${safeFormat(totalProfit, 2, \\\"$\\\")}`;\\n profitStatus = \\\"✅ 盈利中\\\";\\n } else if (totalProfit < 0) {\\n profitDisplay = `🔴 ${safeFormat(totalProfit, 2, \\\"$\\\")}`;\\n profitStatus = \\\"⚠️ 亏损中\\\";\\n } else {\\n profitDisplay = `⚪ $0`;\\n profitStatus = \\\"⚪ 持平\\\";\\n }\\n \\n realTable.rows.push([\\n \\\"📈 累计盈亏\\\",\\n profitDisplay,\\n profitStatus,\\n `收益率: ${returnRate > 0 ? '+' : ''}${safeFormat(returnRate)}%`\\n ]);\\n \\n // 持仓信息\\n realTable.rows.push([\\n \\\"💼 当前持仓\\\",\\n realPositionInfo.type === '无' ? \\\"📭 空仓\\\" : `${realPositionInfo.type === '多' ? '📈' : '📉'} ${realPositionInfo.type}单`,\\n realPositionInfo.type === '无' ? \\\"⚪ 无持仓\\\" : \\\"✅ 持仓中\\\",\\n realPositionInfo.type === '无' ? \\\"-\\\" : `数量: ${safeFormat(realPositionInfo.size, 4)}`\\n ]);\\n \\n if (realPositionInfo.type !== '无') {\\n realTable.rows.push([\\n \\\"💰 持仓均价\\\",\\n safeFormat(realPositionInfo.entryPrice, 4, \\\"$\\\"),\\n \\\"📊\\\",\\n `当前: ${safeFormat(realPositionInfo.currentPrice, 4, \\\"$\\\")}`\\n ]);\\n \\n let positionPnlDisplay = \\\"\\\";\\n let positionPnlStatus = \\\"\\\";\\n if (realPositionInfo.unrealizedPnl > 0) {\\n positionPnlDisplay = `🟢 +${safeFormat(realPositionInfo.unrealizedPnl, 2, \\\"$\\\")}`;\\n positionPnlStatus = \\\"✅ 浮盈\\\";\\n } else if (realPositionInfo.unrealizedPnl < 0) {\\n positionPnlDisplay = `🔴 ${safeFormat(realPositionInfo.unrealizedPnl, 2, \\\"$\\\")}`;\\n positionPnlStatus = \\\"⚠️ 浮亏\\\";\\n } else {\\n positionPnlDisplay = `⚪ $0`;\\n positionPnlStatus = \\\"⚪ 持平\\\";\\n }\\n \\n realTable.rows.push([\\n \\\"📊 持仓盈亏\\\",\\n positionPnlDisplay,\\n positionPnlStatus,\\n \\\"未实现盈亏\\\"\\n ]);\\n }\\n \\n // 同步状态\\n realTable.rows.push([\\n \\\"🔄 同步状态\\\",\\n inputData.shouldTrade ? \\\"待同步\\\" : \\\"已同步\\\",\\n inputData.shouldTrade ? \\\"🔄 执行中\\\" : \\\"✅ 同步\\\",\\n inputData.tradeAction?.reason || \\\"纸面与实盘一致\\\"\\n ]);\\n \\n // 上次交易\\n if (inputData.tradeAction) {\\n let actionDisplay = inputData.tradeAction.action;\\n switch(actionDisplay) {\\n case 'OPEN_LONG':\\n actionDisplay = \\\"🟢 开多\\\";\\n break;\\n case 'OPEN_SHORT':\\n actionDisplay = \\\"🔴 开空\\\";\\n break;\\n case 'CLOSE_LONG':\\n actionDisplay = \\\"⏹️ 平多\\\";\\n break;\\n case 'CLOSE_SHORT':\\n actionDisplay = \\\"⏹️ 平空\\\";\\n break;\\n }\\n \\n realTable.rows.push([\\n \\\"📝 上次交易\\\",\\n actionDisplay,\\n \\\"📊\\\",\\n inputData.tradeAction.reason || \\\"-\\\"\\n ]);\\n }\\n \\n // 模型对比\\n if (activeModel && models[activeModel]) {\\n const modelPnl = models[activeModel].account.realizedPnl || 0;\\n const gap = realizedProfit - modelPnl;\\n \\n realTable.rows.push([\\n \\\"📊 与模型差距\\\",\\n gap > 0 ? `🟢 领先 ${safeFormat(gap, 2, \\\"$\\\")}` : gap < 0 ? `🔴 落后 ${safeFormat(Math.abs(gap), 2, \\\"$\\\")}` : `⚪ 一致`,\\n gap > 0 ? \\\"✅ 超越\\\" : gap < 0 ? \\\"⚠️ 追赶\\\" : \\\"⚪ 同步\\\",\\n `模型纸面: ${safeFormat(modelPnl, 2, \\\"$\\\")}`\\n ]);\\n }\\n \\n } catch (e) {\\n Log(`❌ 创建实盘交易表失败: ${e.message}`);\\n Log(`错误堆栈: ${e.stack}`);\\n realTable.rows.push([\\n \\\"❌ 错误\\\",\\n \\\"获取数据失败\\\",\\n \\\"🚨\\\",\\n e.message\\n ]);\\n }\\n \\n return realTable;\\n}\\n\\n/**\\n * 表格4: 系统统计信息\\n */\\nfunction createSystemStatsTable(allModelsStatus, models, inputData) {\\n const statsTable = {\\n type: \\\"table\\\",\\n title: \\\"📊 系统整体统计\\\",\\n cols: [\\\"统计项\\\", \\\"数值\\\", \\\"评级\\\", \\\"备注\\\"],\\n rows: []\\n };\\n \\n try {\\n // 模型总数\\n statsTable.rows.push([\\n \\\"🤖 参赛模型\\\",\\n `${allModelsStatus.length} 个`,\\n \\\"📊\\\",\\n \\\"AI模型竞赛\\\"\\n ]);\\n \\n // 最优模型\\n if (allModelsStatus.length > 0) {\\n const bestModel = allModelsStatus[0];\\n statsTable.rows.push([\\n \\\"🥇 最优模型\\\",\\n bestModel.model,\\n bestModel.realizedPnl > 0 ? \\\"✅ 盈利\\\" : \\\"⚠️ 亏损\\\",\\n `盈亏: ${safeFormat(bestModel.realizedPnl, 2, \\\"$\\\")}`\\n ]);\\n }\\n \\n // 平均表现\\n if (allModelsStatus.length > 0) {\\n const avgPnl = allModelsStatus.reduce((sum, m) => sum + (m.realizedPnl || 0), 0) / allModelsStatus.length;\\n statsTable.rows.push([\\n \\\"📊 平均盈亏\\\",\\n avgPnl > 0 ? `🟢 ${safeFormat(avgPnl, 2, \\\"$\\\")}` : avgPnl < 0 ? `🔴 ${safeFormat(avgPnl, 2, \\\"$\\\")}` : `⚪ $0`,\\n avgPnl > 0 ? \\\"✅ 正收益\\\" : \\\"⚠️ 负收益\\\",\\n \\\"所有模型平均\\\"\\n ]);\\n }\\n \\n // 盈利模型数\\n const profitableModels = allModelsStatus.filter(m => (m.realizedPnl || 0) > 0).length;\\n statsTable.rows.push([\\n \\\"✅ 盈利模型\\\",\\n `${profitableModels} / ${allModelsStatus.length}`,\\n profitableModels > allModelsStatus.length / 2 ? \\\"✅ 良好\\\" : \\\"⚠️ 偏少\\\",\\n `占比: ${safePercentage(profitableModels, allModelsStatus.length)}`\\n ]);\\n \\n // 总交易次数\\n const totalTrades = allModelsStatus.reduce((sum, m) => {\\n const modelData = models[m.model];\\n return sum + (modelData ? (modelData.account.totalTrades || 0) : 0);\\n }, 0);\\n \\n statsTable.rows.push([\\n \\\"🎲 总交易数\\\",\\n totalTrades,\\n totalTrades > 50 ? \\\"✅ 充足\\\" : totalTrades > 10 ? \\\"✅ 适中\\\" : \\\"⚠️ 偏少\\\",\\n `所有模型合计`\\n ]);\\n \\n // 平均胜率\\n let totalWinRate = 0;\\n let validModels = 0;\\n allModelsStatus.forEach(m => {\\n const modelData = models[m.model];\\n if (modelData && (modelData.account.totalTrades || 0) > 0) {\\n totalWinRate += ((modelData.account.winTrades || 0) / modelData.account.totalTrades) * 100;\\n validModels++;\\n }\\n });\\n const avgWinRate = validModels > 0 ? totalWinRate / validModels : 0;\\n \\n statsTable.rows.push([\\n \\\"🎯 平均胜率\\\",\\n `${safeFormat(avgWinRate, 1)}%`,\\n avgWinRate > 60 ? \\\"🔥 优秀\\\" : avgWinRate > 45 ? \\\"✅ 良好\\\" : \\\"⚠️ 需改进\\\",\\n \\\"有效交易模型平均\\\"\\n ]);\\n \\n // 持仓模型数\\n const modelsWithPosition = allModelsStatus.filter(m => m.paperPosition !== 'none').length;\\n statsTable.rows.push([\\n \\\"💼 持仓模型\\\",\\n `${modelsWithPosition} / ${allModelsStatus.length}`,\\n modelsWithPosition > 0 ? \\\"✅ 活跃\\\" : \\\"📭 空仓\\\",\\n `占比: ${safePercentage(modelsWithPosition, allModelsStatus.length)}`\\n ]);\\n \\n // 实盘状态\\n const isRealTrading = inputData.activeModel ? true : false;\\n statsTable.rows.push([\\n \\\"🚀 实盘状态\\\",\\n isRealTrading ? \\\"运行中\\\" : \\\"未启动\\\",\\n isRealTrading ? \\\"✅ 激活\\\" : \\\"⏸️ 待命\\\",\\n isRealTrading ? `跟随: ${inputData.activeModel}` : \\\"等待盈利>500\\\"\\n ]);\\n \\n // 最后更新时间\\n const updateTime = new Date().toLocaleString();\\n statsTable.rows.push([\\n \\\"🕐 更新时间\\\",\\n updateTime,\\n \\\"📊\\\",\\n \\\"实时监控中\\\"\\n ]);\\n \\n } catch (e) {\\n Log(`❌ 创建统计表失败: ${e.message}`);\\n Log(`错误堆栈: ${e.stack}`);\\n statsTable.rows.push([\\n \\\"❌ 错误\\\",\\n \\\"计算失败\\\",\\n \\\"🚨\\\",\\n e.message\\n ]);\\n }\\n \\n return statsTable;\\n}\\n\\n/**\\n * 主函数 - 显示完整仪表板\\n */\\nfunction main() {\\n try {\\n Log('可视化节点开始执行');\\n \\n // 获取输入数据\\n const inputData = $input.all()[0].json;\\n Log('inputData keys:', Object.keys(inputData));\\n \\n const allModelsStatus = inputData.allModelsStatus;\\n if (!allModelsStatus || !Array.isArray(allModelsStatus)) {\\n throw new Error('allModelsStatus 数据无效或不是数组');\\n }\\n \\n Log(`模型数量: ${allModelsStatus.length}`);\\n \\n // 获取详细的模型数据\\n const models = $node['结果核算'].json;\\n if (!models) {\\n throw new Error('无法获取结果核算节点的数据');\\n }\\n \\n Log('models keys:', Object.keys(models));\\n \\n // 创建4个表格\\n const table1 = createModelStatusTable(allModelsStatus, models);\\n const table2 = createPerformanceComparisonTable(allModelsStatus, models);\\n const table3 = createRealTradingTable(inputData, models);\\n const table4 = createSystemStatsTable(allModelsStatus, models, inputData);\\n \\n // 组合显示\\n const dashboardDisplay = \\n '`' + JSON.stringify(table1) + '`\\\\n\\\\n' +\\n '`' + JSON.stringify(table2) + '`\\\\n\\\\n' +\\n '`' + JSON.stringify(table3) + '`\\\\n\\\\n' +\\n '`' + JSON.stringify(table4) + '`';\\n \\n LogStatus(dashboardDisplay);\\n \\n Log('✅ 可视化显示成功');\\n \\n // 返回完整数据\\n return [{\\n json: {\\n ...inputData,\\n tables: {\\n modelStatus: table1,\\n performance: table2,\\n realTrading: table3,\\n systemStats: table4\\n },\\n timestamp: Date.now(),\\n updateTime: new Date().toLocaleString()\\n }\\n }];\\n \\n } catch (e) {\\n Log(`❌ 显示仪表板失败: ${e.message}`);\\n Log(`❌ 错误堆栈: ${e.stack}`);\\n \\n // 错误时显示简单状态\\n const errorTable = {\\n type: \\\"table\\\",\\n title: \\\"❌ 系统错误\\\",\\n cols: [\\\"错误类型\\\", \\\"错误信息\\\", \\\"时间\\\"],\\n rows: [[\\n \\\"可视化错误\\\",\\n e.message,\\n new Date().toLocaleString()\\n ]]\\n };\\n \\n LogStatus('`' + JSON.stringify(errorTable) + '`');\\n \\n return [{\\n json: {\\n error: e.message,\\n stack: e.stack,\\n timestamp: Date.now()\\n }\\n }];\\n }\\n}\\n\\n// 执行主函数\\nreturn main();\\n\",\"notice\":\"\"},\"type\":\"n8n-nodes-base.code\",\"typeVersion\":2,\"position\":[144,960],\"id\":\"30d90c04-224e-442c-a72d-31a8a1792835\",\"name\":\"可视化\"},{\"parameters\":{\"mode\":\"runOnceForAllItems\",\"language\":\"javaScript\",\"jsCode\":\"const symbol = $vars.coin + \\\"_USDT.swap\\\"\\nconst timeframes = {\\n day: PERIOD_D1,\\n hour: PERIOD_H1,\\n min5: PERIOD_M5\\n}\\n\\nfunction getIndicatorsForPeriod(symbol, period, periodName) {\\n const records = exchange.GetRecords(symbol, period)\\n \\n if (!records || records.length <= 10) {\\n Log(`警告: ${periodName}周期数据不足,仅有 ${records ? records.length : 0} 条记录`)\\n return null\\n }\\n \\n const macd = talib.MACD(records)\\n const rsi = talib.RSI(records, 14)\\n const atr = talib.ATR(records, 14)\\n const obv = talib.OBV(records)\\n \\n function getLast10Values(arr) {\\n if (!arr || arr.length === 0) return []\\n return arr.slice(-10)\\n }\\n \\n return {\\n period: periodName,\\n recordsCount: records.length,\\n lastPrice: records[records.length - 1].Close,\\n MACD: {\\n macd: getLast10Values(macd[0]),\\n signal: getLast10Values(macd[1]), \\n histogram: getLast10Values(macd[2])\\n },\\n RSI: getLast10Values(rsi),\\n ATR: getLast10Values(atr),\\n OBV: getLast10Values(obv)\\n }\\n}\\n\\nconst models = _G('models')\\nconst modelPnlData = Object.keys(models).map(modelName => ({\\n name: modelName,\\n realizedPnl: models[modelName].account.realizedPnl,\\n totalValue: models[modelName].account.totalValue\\n}))\\n\\nconst sortedModels = modelPnlData.sort((a, b) => b.realizedPnl - a.realizedPnl)\\n\\nconst rankedModels = []\\nlet currentRank = 1\\nlet previousPnl = null\\n\\nsortedModels.forEach((model, index) => {\\n if (previousPnl !== null && model.realizedPnl < previousPnl) {\\n currentRank = index + 1\\n }\\n \\n rankedModels.push({\\n ...model,\\n rank: currentRank\\n })\\n \\n previousPnl = model.realizedPnl\\n})\\n\\nconst currentModelName = Object.keys(models)[0] // DS是第一个模型\\nconst currentModelRank = rankedModels.find(model => model.name === currentModelName)\\n\\nconst rankingText = rankedModels.map(model => \\n `${model.rank}. ${model.name}: ${model.realizedPnl} USDT${model.name === currentModelName ? ' ← 你的位置' : ''}`\\n).join('\\\\n')\\n\\nlet gapInfo = ''\\nif (currentModelRank.rank > 1) {\\n const firstPlace = rankedModels[0]\\n const gap = (firstPlace.realizedPnl - currentModelRank.realizedPnl).toFixed(2)\\n gapInfo = `### 与第一名差距\\\\n第一名盈亏: ${firstPlace.realizedPnl} USDT\\\\n你需要追赶: ${gap} USDT`\\n} else {\\n gapInfo = '🏆 恭喜!你目前领先!保持优势!'\\n}\\n\\nconst result = {\\n symbol: symbol,\\n timestamp: Date.now(),\\n timeframes: {\\n day: getIndicatorsForPeriod(symbol, timeframes.day, '日线'),\\n hour: getIndicatorsForPeriod(symbol, timeframes.hour, '小时线'),\\n min5: getIndicatorsForPeriod(symbol, timeframes.min5, '5分钟线')\\n },\\n // ⚠️ 修改点:使用模型自己的虚拟持仓,而不是真实持仓\\n position: models[currentModelName].positions || [],\\n ranking: {\\n currentModel: currentModelName,\\n currentRank: currentModelRank.rank,\\n currentPnl: currentModelRank.realizedPnl,\\n currentTotalValue: currentModelRank.totalValue,\\n totalTrades: models[currentModelName].account.totalTrades,\\n winTrades: models[currentModelName].account.winTrades,\\n winRate: models[currentModelName].account.totalTrades > 0 ? \\n (models[currentModelName].account.winTrades / models[currentModelName].account.totalTrades * 100).toFixed(2) : '0',\\n rankingText: rankingText,\\n gapInfo: gapInfo,\\n totalModels: Object.keys(models).length,\\n allRankings: rankedModels\\n }\\n}\\n\\nreturn result\",\"notice\":\"\"},\"type\":\"n8n-nodes-base.code\",\"typeVersion\":2,\"position\":[-1360,592],\"id\":\"2326b0ac-9d46-4170-a4ec-49700cd11310\",\"name\":\"DS处理\"},{\"parameters\":{\"mode\":\"runOnceForAllItems\",\"language\":\"javaScript\",\"jsCode\":\"const symbol = $vars.coin + \\\"_USDT.swap\\\"\\nconst timeframes = {\\n day: PERIOD_D1,\\n hour: PERIOD_H1,\\n min5: PERIOD_M5\\n}\\n\\nfunction getIndicatorsForPeriod(symbol, period, periodName) {\\n const records = exchange.GetRecords(symbol, period)\\n \\n if (!records || records.length <= 10) {\\n Log(`警告: ${periodName}周期数据不足,仅有 ${records ? records.length : 0} 条记录`)\\n return null\\n }\\n \\n const macd = talib.MACD(records)\\n const rsi = talib.RSI(records, 14)\\n const atr = talib.ATR(records, 14)\\n const obv = talib.OBV(records)\\n \\n function getLast10Values(arr) {\\n if (!arr || arr.length === 0) return []\\n return arr.slice(-10)\\n }\\n \\n return {\\n period: periodName,\\n recordsCount: records.length,\\n lastPrice: records[records.length - 1].Close,\\n MACD: {\\n macd: getLast10Values(macd[0]),\\n signal: getLast10Values(macd[1]), \\n histogram: getLast10Values(macd[2])\\n },\\n RSI: getLast10Values(rsi),\\n ATR: getLast10Values(atr),\\n OBV: getLast10Values(obv)\\n }\\n}\\n\\nconst models = _G('models')\\nconst modelPnlData = Object.keys(models).map(modelName => ({\\n name: modelName,\\n realizedPnl: models[modelName].account.realizedPnl,\\n totalValue: models[modelName].account.totalValue\\n}))\\n\\nconst sortedModels = modelPnlData.sort((a, b) => b.realizedPnl - a.realizedPnl)\\n\\nconst rankedModels = []\\nlet currentRank = 1\\nlet previousPnl = null\\n\\nsortedModels.forEach((model, index) => {\\n if (previousPnl !== null && model.realizedPnl < previousPnl) {\\n currentRank = index + 1\\n }\\n \\n rankedModels.push({\\n ...model,\\n rank: currentRank\\n })\\n \\n previousPnl = model.realizedPnl\\n})\\n\\nconst currentModelName = Object.keys(models)[1] // DS是第一个模型\\nconst currentModelRank = rankedModels.find(model => model.name === currentModelName)\\n\\nconst rankingText = rankedModels.map(model => \\n `${model.rank}. ${model.name}: ${model.realizedPnl} USDT${model.name === currentModelName ? ' ← 你的位置' : ''}`\\n).join('\\\\n')\\n\\nlet gapInfo = ''\\nif (currentModelRank.rank > 1) {\\n const firstPlace = rankedModels[0]\\n const gap = (firstPlace.realizedPnl - currentModelRank.realizedPnl).toFixed(2)\\n gapInfo = `### 与第一名差距\\\\n第一名盈亏: ${firstPlace.realizedPnl} USDT\\\\n你需要追赶: ${gap} USDT`\\n} else {\\n gapInfo = '🏆 恭喜!你目前领先!保持优势!'\\n}\\n\\nconst result = {\\n symbol: symbol,\\n timestamp: Date.now(),\\n timeframes: {\\n day: getIndicatorsForPeriod(symbol, timeframes.day, '日线'),\\n hour: getIndicatorsForPeriod(symbol, timeframes.hour, '小时线'),\\n min5: getIndicatorsForPeriod(symbol, timeframes.min5, '5分钟线')\\n },\\n // ⚠️ 修改点:使用模型自己的虚拟持仓,而不是真实持仓\\n position: models[currentModelName].positions || [],\\n ranking: {\\n currentModel: currentModelName,\\n currentRank: currentModelRank.rank,\\n currentPnl: currentModelRank.realizedPnl,\\n currentTotalValue: currentModelRank.totalValue,\\n totalTrades: models[currentModelName].account.totalTrades,\\n winTrades: models[currentModelName].account.winTrades,\\n winRate: models[currentModelName].account.totalTrades > 0 ? \\n (models[currentModelName].account.winTrades / models[currentModelName].account.totalTrades * 100).toFixed(2) : '0',\\n rankingText: rankingText,\\n gapInfo: gapInfo,\\n totalModels: Object.keys(models).length,\\n allRankings: rankedModels\\n }\\n}\\n\\nreturn result\",\"notice\":\"\"},\"type\":\"n8n-nodes-base.code\",\"typeVersion\":2,\"position\":[-1376,864],\"id\":\"39896a53-f6a8-459f-ab90-c22834514b2f\",\"name\":\"Claude处理\"},{\"parameters\":{\"mode\":\"runOnceForAllItems\",\"language\":\"javaScript\",\"jsCode\":\"const symbol = $vars.coin + \\\"_USDT.swap\\\"\\nconst timeframes = {\\n day: PERIOD_D1,\\n hour: PERIOD_H1,\\n min5: PERIOD_M5\\n}\\n\\nfunction getIndicatorsForPeriod(symbol, period, periodName) {\\n const records = exchange.GetRecords(symbol, period)\\n \\n if (!records || records.length <= 10) {\\n Log(`警告: ${periodName}周期数据不足,仅有 ${records ? records.length : 0} 条记录`)\\n return null\\n }\\n \\n const macd = talib.MACD(records)\\n const rsi = talib.RSI(records, 14)\\n const atr = talib.ATR(records, 14)\\n const obv = talib.OBV(records)\\n \\n function getLast10Values(arr) {\\n if (!arr || arr.length === 0) return []\\n return arr.slice(-10)\\n }\\n \\n return {\\n period: periodName,\\n recordsCount: records.length,\\n lastPrice: records[records.length - 1].Close,\\n MACD: {\\n macd: getLast10Values(macd[0]),\\n signal: getLast10Values(macd[1]), \\n histogram: getLast10Values(macd[2])\\n },\\n RSI: getLast10Values(rsi),\\n ATR: getLast10Values(atr),\\n OBV: getLast10Values(obv)\\n }\\n}\\n\\nconst models = _G('models')\\nconst modelPnlData = Object.keys(models).map(modelName => ({\\n name: modelName,\\n realizedPnl: models[modelName].account.realizedPnl,\\n totalValue: models[modelName].account.totalValue\\n}))\\n\\nconst sortedModels = modelPnlData.sort((a, b) => b.realizedPnl - a.realizedPnl)\\n\\nconst rankedModels = []\\nlet currentRank = 1\\nlet previousPnl = null\\n\\nsortedModels.forEach((model, index) => {\\n if (previousPnl !== null && model.realizedPnl < previousPnl) {\\n currentRank = index + 1\\n }\\n \\n rankedModels.push({\\n ...model,\\n rank: currentRank\\n })\\n \\n previousPnl = model.realizedPnl\\n})\\n\\nconst currentModelName = Object.keys(models)[2] // DS是第一个模型\\nconst currentModelRank = rankedModels.find(model => model.name === currentModelName)\\n\\nconst rankingText = rankedModels.map(model => \\n `${model.rank}. ${model.name}: ${model.realizedPnl} USDT${model.name === currentModelName ? ' ← 你的位置' : ''}`\\n).join('\\\\n')\\n\\nlet gapInfo = ''\\nif (currentModelRank.rank > 1) {\\n const firstPlace = rankedModels[0]\\n const gap = (firstPlace.realizedPnl - currentModelRank.realizedPnl).toFixed(2)\\n gapInfo = `### 与第一名差距\\\\n第一名盈亏: ${firstPlace.realizedPnl} USDT\\\\n你需要追赶: ${gap} USDT`\\n} else {\\n gapInfo = '🏆 恭喜!你目前领先!保持优势!'\\n}\\n\\nconst result = {\\n symbol: symbol,\\n timestamp: Date.now(),\\n timeframes: {\\n day: getIndicatorsForPeriod(symbol, timeframes.day, '日线'),\\n hour: getIndicatorsForPeriod(symbol, timeframes.hour, '小时线'),\\n min5: getIndicatorsForPeriod(symbol, timeframes.min5, '5分钟线')\\n },\\n // ⚠️ 修改点:使用模型自己的虚拟持仓,而不是真实持仓\\n position: models[currentModelName].positions || [],\\n ranking: {\\n currentModel: currentModelName,\\n currentRank: currentModelRank.rank,\\n currentPnl: currentModelRank.realizedPnl,\\n currentTotalValue: currentModelRank.totalValue,\\n totalTrades: models[currentModelName].account.totalTrades,\\n winTrades: models[currentModelName].account.winTrades,\\n winRate: models[currentModelName].account.totalTrades > 0 ? \\n (models[currentModelName].account.winTrades / models[currentModelName].account.totalTrades * 100).toFixed(2) : '0',\\n rankingText: rankingText,\\n gapInfo: gapInfo,\\n totalModels: Object.keys(models).length,\\n allRankings: rankedModels\\n }\\n}\\n\\nreturn result\\n\",\"notice\":\"\"},\"type\":\"n8n-nodes-base.code\",\"typeVersion\":2,\"position\":[-1376,1152],\"id\":\"00a89176-edaf-4f84-ab7e-72e0f3da8cf4\",\"name\":\"QWEN处理\"},{\"parameters\":{\"mode\":\"runOnceForAllItems\",\"language\":\"javaScript\",\"jsCode\":\"const symbol = $vars.coin + \\\"_USDT.swap\\\"\\nconst timeframes = {\\n day: PERIOD_D1,\\n hour: PERIOD_H1,\\n min5: PERIOD_M5\\n}\\n\\nfunction getIndicatorsForPeriod(symbol, period, periodName) {\\n const records = exchange.GetRecords(symbol, period)\\n \\n if (!records || records.length <= 10) {\\n Log(`警告: ${periodName}周期数据不足,仅有 ${records ? records.length : 0} 条记录`)\\n return null\\n }\\n \\n const macd = talib.MACD(records)\\n const rsi = talib.RSI(records, 14)\\n const atr = talib.ATR(records, 14)\\n const obv = talib.OBV(records)\\n \\n function getLast10Values(arr) {\\n if (!arr || arr.length === 0) return []\\n return arr.slice(-10)\\n }\\n \\n return {\\n period: periodName,\\n recordsCount: records.length,\\n lastPrice: records[records.length - 1].Close,\\n MACD: {\\n macd: getLast10Values(macd[0]),\\n signal: getLast10Values(macd[1]), \\n histogram: getLast10Values(macd[2])\\n },\\n RSI: getLast10Values(rsi),\\n ATR: getLast10Values(atr),\\n OBV: getLast10Values(obv)\\n }\\n}\\n\\nconst models = _G('models')\\nconst modelPnlData = Object.keys(models).map(modelName => ({\\n name: modelName,\\n realizedPnl: models[modelName].account.realizedPnl,\\n totalValue: models[modelName].account.totalValue\\n}))\\n\\nconst sortedModels = modelPnlData.sort((a, b) => b.realizedPnl - a.realizedPnl)\\n\\nconst rankedModels = []\\nlet currentRank = 1\\nlet previousPnl = null\\n\\nsortedModels.forEach((model, index) => {\\n if (previousPnl !== null && model.realizedPnl < previousPnl) {\\n currentRank = index + 1\\n }\\n \\n rankedModels.push({\\n ...model,\\n rank: currentRank\\n })\\n \\n previousPnl = model.realizedPnl\\n})\\n\\nconst currentModelName = Object.keys(models)[3] // DS是第一个模型\\nconst currentModelRank = rankedModels.find(model => model.name === currentModelName)\\n\\nconst rankingText = rankedModels.map(model => \\n `${model.rank}. ${model.name}: ${model.realizedPnl} USDT${model.name === currentModelName ? ' ← 你的位置' : ''}`\\n).join('\\\\n')\\n\\nlet gapInfo = ''\\nif (currentModelRank.rank > 1) {\\n const firstPlace = rankedModels[0]\\n const gap = (firstPlace.realizedPnl - currentModelRank.realizedPnl).toFixed(2)\\n gapInfo = `### 与第一名差距\\\\n第一名盈亏: ${firstPlace.realizedPnl} USDT\\\\n你需要追赶: ${gap} USDT`\\n} else {\\n gapInfo = '🏆 恭喜!你目前领先!保持优势!'\\n}\\n\\nconst result = {\\n symbol: symbol,\\n timestamp: Date.now(),\\n timeframes: {\\n day: getIndicatorsForPeriod(symbol, timeframes.day, '日线'),\\n hour: getIndicatorsForPeriod(symbol, timeframes.hour, '小时线'),\\n min5: getIndicatorsForPeriod(symbol, timeframes.min5, '5分钟线')\\n },\\n // ⚠️ 修改点:使用模型自己的虚拟持仓,而不是真实持仓\\n position: models[currentModelName].positions || [],\\n ranking: {\\n currentModel: currentModelName,\\n currentRank: currentModelRank.rank,\\n currentPnl: currentModelRank.realizedPnl,\\n currentTotalValue: currentModelRank.totalValue,\\n totalTrades: models[currentModelName].account.totalTrades,\\n winTrades: models[currentModelName].account.winTrades,\\n winRate: models[currentModelName].account.totalTrades > 0 ? \\n (models[currentModelName].account.winTrades / models[currentModelName].account.totalTrades * 100).toFixed(2) : '0',\\n rankingText: rankingText,\\n gapInfo: gapInfo,\\n totalModels: Object.keys(models).length,\\n allRankings: rankedModels\\n }\\n}\\n\\nreturn result\\n\",\"notice\":\"\"},\"type\":\"n8n-nodes-base.code\",\"typeVersion\":2,\"position\":[-1360,1424],\"id\":\"9ffa443e-8335-4be5-acc9-c7d34c5de9f2\",\"name\":\"Grok处理\"}],\"pinData\":{\"合并\":[{\"json\":{\"output\":\"```json\\n{\\n \\\"action\\\": \\\"NO_ACTION\\\",\\n \\\"reasoning\\\": \\\"日线RSI从超买区域回落(72→57)但仍处中性区间,MACD柱状线显著收缩(391→-393)显示动能减弱;小时线RSI46-49无明确方向信号,MACD持续负值;5分钟级别同样缺乏清晰入场信号。比赛初期需等待更明确的高质量交易机会\\\",\\n \\\"modelname\\\": \\\"DS\\\"\\n}\\n```\"}},{\"json\":{\"output\":\"```json\\n{\\n \\\"action\\\": \\\"NO_ACTION\\\",\\n \\\"reasoning\\\": \\\"多时间框架信号冲突:日线RSI从72回落至49显示上涨动能衰竭,MACD柱由正转负呈现死叉形态;小时线和5分钟线RSI在42-47区间徘徊,MACD持续负值但未见明显反转信号;OBV各周期分化严重。当前处于方向不明的震荡整理阶段,不符合高质量首次交易的标准,等待更清晰的趋势确认信号。\\\",\\n \\\"modelname\\\": \\\"Claude\\\"\\n}\\n```\"}},{\"json\":{\"output\":\"{\\n \\\"action\\\": \\\"OPEN_SHORT\\\",\\n \\\"reasoning\\\": \\\"日线RSI跌破50且MACD柱深度为负、OBV走低;小时/5分RSI均<50且MACD柱为负,多周期一致偏空且无反转信号。\\\"\\n}\"}},{\"json\":{\"output\":\"```json\\n{\\n \\\"action\\\": \\\"NO_ACTION\\\",\\n \\\"reasoning\\\": \\\"日线RSI从超买回落且MACD柱转负,显示上涨动能减弱;但小时和5分钟级别指标未出现明确方向性信号,OBV持续流出且价格缺乏有力突破,整体处于趋势转换不明朗阶段,不宜贸然开仓。\\\"\\n}\\n```\"}},{\"json\":{\"output\":\"```json\\n{\\n \\\"action\\\": \\\"NO_ACTION\\\",\\n \\\"reasoning\\\": \\\"日线RSI下降、MACD负值、OBV卖压增加显示整体熊市趋势;小时/5min MACD负柱缩小暗示短期动量减弱但未明确反转信号,疑虑存在,优先风险控制。\\\"\\n}\\n```\"}},{\"json\":{\"output\":\"```json\\n{\\n \\\"action\\\": \\\"NO_ACTION\\\",\\n \\\"reasoning\\\": \\\"日线级别虽呈明显空头趋势(RSI<50, MACD为负, OBV下降),但小时线MACD负柱缩短,显示下跌动能减弱,可能存在短期反弹或盘整。多时间框架信号未完全统一,未出现高确定性入场点,故选择观望。\\\"\\n}\\n```\"}}]},\"connections\":{\"定时触发器\":{\"main\":[[{\"node\":\"策略初始化\",\"type\":\"main\",\"index\":0}]]},\"Claude4.5\":{\"ai_languageModel\":[[{\"node\":\"Claude\",\"type\":\"ai_languageModel\",\"index\":0}]]},\"DS3.1\":{\"ai_languageModel\":[[{\"node\":\"DeepSeek\",\"type\":\"ai_languageModel\",\"index\":0}]]},\"DeepSeek\":{\"main\":[[{\"node\":\"合并\",\"type\":\"main\",\"index\":0}]]},\"Claude\":{\"main\":[[{\"node\":\"合并\",\"type\":\"main\",\"index\":1}]]},\"QWEN\":{\"main\":[[{\"node\":\"合并\",\"type\":\"main\",\"index\":2}]]},\"OpenAI 模型\":{\"ai_languageModel\":[[{\"node\":\"QWEN\",\"type\":\"ai_languageModel\",\"index\":0}]]},\"Grok\":{\"main\":[[{\"node\":\"合并\",\"type\":\"main\",\"index\":3}]]},\"Grok4\":{\"ai_languageModel\":[[{\"node\":\"Grok\",\"type\":\"ai_languageModel\",\"index\":0}]]},\"合并\":{\"main\":[[{\"node\":\"结果核算\",\"type\":\"main\",\"index\":0}]]},\"转换为文件\":{\"main\":[[{\"node\":\"写入文件到磁盘\",\"type\":\"main\",\"index\":0}]]},\"结果核算\":{\"main\":[[{\"node\":\"交易记录保存\",\"type\":\"main\",\"index\":0}]]},\"交易记录保存\":{\"main\":[[{\"node\":\"转换为文件\",\"type\":\"main\",\"index\":0},{\"node\":\"最优交易\",\"type\":\"main\",\"index\":0}]]},\"最优交易\":{\"main\":[[{\"node\":\"可视化\",\"type\":\"main\",\"index\":0}]]},\"策略初始化\":{\"main\":[[{\"node\":\"DS处理\",\"type\":\"main\",\"index\":0},{\"node\":\"Claude处理\",\"type\":\"main\",\"index\":0},{\"node\":\"QWEN处理\",\"type\":\"main\",\"index\":0},{\"node\":\"Grok处理\",\"type\":\"main\",\"index\":0}]]},\"DS处理\":{\"main\":[[{\"node\":\"DeepSeek\",\"type\":\"main\",\"index\":0}]]},\"Claude处理\":{\"main\":[[{\"node\":\"Claude\",\"type\":\"main\",\"index\":0}]]},\"QWEN处理\":{\"main\":[[{\"node\":\"QWEN\",\"type\":\"main\",\"index\":0}]]},\"Grok处理\":{\"main\":[[{\"node\":\"Grok\",\"type\":\"main\",\"index\":0}]]}},\"active\":false,\"settings\":{\"timezone\":\"Asia/Shanghai\",\"executionOrder\":\"v1\"},\"tags\":[],\"meta\":{\"templateCredsSetupCompleted\":true},\"credentials\":{},\"id\":\"6c8dfda8-4657-42fa-b4dc-8f723e88aaa7\",\"plugins\":{},\"mcpClients\":{}},\"startNodes\":[],\"triggerToStartFrom\":{\"name\":\"定时触发器\"}}"}