策略源码
{"type":"n8n","content":"{\"workflowData\":{\"nodes\":[{\"parameters\":{\"notice\":\"\",\"exchange\":0,\"symbol\":{\"__rl\":true,\"mode\":\"list\",\"value\":\"\"},\"period\":60,\"limit\":500,\"rule\":{\"interval\":[{\"field\":\"seconds\",\"secondsInterval\":60}]}},\"type\":\"n8n-nodes-base.klineCloseTrigger\",\"typeVersion\":1,\"position\":[-64,-512],\"id\":\"f591a8ed-a49b-4b10-b428-6d0f1c70cba3\",\"name\":\"K线收盘触发器1\"},{\"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\":[1504,-240],\"id\":\"a79b39c6-6f65-4f22-9315-5c53b7f71db5\",\"name\":\"OpenAI 模型1\",\"credentials\":{\"openAiApi\":{\"id\":\"54d0b567-b3fc-4c6a-b6be-546e0b9cd83f\",\"name\":\"openrouter\"}}},{\"parameters\":{\"mode\":\"rules\",\"rules\":{\"values\":[{\"conditions\":{\"options\":{\"caseSensitive\":true,\"leftValue\":\"\",\"typeValidation\":\"strict\",\"version\":2},\"conditions\":[{\"leftValue\":\"={{ $json.aiTrigger.shouldTrigger }}\",\"rightValue\":\"false\",\"operator\":{\"type\":\"boolean\",\"operation\":\"false\",\"singleValue\":true},\"id\":\"0029cdc5-fc22-425f-82aa-bea90f32f866\"}],\"combinator\":\"and\"},\"renameOutput\":false},{\"conditions\":{\"options\":{\"caseSensitive\":true,\"leftValue\":\"\",\"typeValidation\":\"strict\",\"version\":2},\"conditions\":[{\"id\":\"64d4c904-c8d4-439b-a890-335ae87605ac\",\"leftValue\":\"={{ $json.aiTrigger.shouldTrigger }}\",\"rightValue\":\"\",\"operator\":{\"type\":\"boolean\",\"operation\":\"true\",\"singleValue\":true}}],\"combinator\":\"and\"},\"renameOutput\":false}]},\"looseTypeValidation\":false,\"options\":{}},\"type\":\"n8n-nodes-base.switch\",\"typeVersion\":3.2,\"position\":[832,-512],\"id\":\"7b630760-f7b8-48bc-8b69-c191eb4a2424\",\"name\":\"分支\"},{\"parameters\":{\"mode\":\"runOnceForAllItems\",\"language\":\"javaScript\",\"jsCode\":\"let grid = _G('grid');\\nlet initPrice = _G('initPrice');\\nlet initEquity = _G('initEquity');\\n\\n// ========== 从 n8n 变量读取配置参数 ==========\\nlet maxPositions = $vars.maxPositions; // 最大档位数\\nlet stepPercent = $vars.stepPercent; // 网格步长\\nlet volatilityThreshold = 0.02; // 波动率阈值(默认2%)\\nlet volatilityPeriod = 20; // 波动率计算周期(默认20根K线)\\n\\n// ========== 波动率检查函数 ==========\\nfunction checkVolatility() {\\n // 获取历史K线数据\\n let records = exchange.GetRecords();\\n if (!records || records.length < volatilityPeriod) {\\n Log('K线数据不足,无法计算波动率');\\n return { isHigh: false, value: 0 };\\n }\\n \\n // 计算最近N根K线的价格波动率\\n let prices = [];\\n for (let i = records.length - volatilityPeriod; i < records.length; i++) {\\n prices.push(records[i].Close);\\n }\\n \\n // 计算平均价格\\n let avgPrice = prices.reduce((a, b) => a + b, 0) / prices.length;\\n \\n // 计算标准差\\n let squareDiffs = prices.map(price => Math.pow(price - avgPrice, 2));\\n let avgSquareDiff = squareDiffs.reduce((a, b) => a + b, 0) / squareDiffs.length;\\n let stdDev = Math.sqrt(avgSquareDiff);\\n \\n // 计算波动率 (标准差/平均价格)\\n let volatility = stdDev / avgPrice;\\n \\n Log('当前波动率:', (volatility * 100).toFixed(2) + '%', \\n '阈值:', (volatilityThreshold * 100).toFixed(2) + '%');\\n \\n return {\\n isHigh: volatility > volatilityThreshold,\\n value: volatility\\n };\\n}\\n\\n// ========== 初始化前先检查波动率 ==========\\nif (!grid || Object.keys(grid).length === 0) {\\n \\n // 检查波动率\\n let volatilityCheck = checkVolatility();\\n \\n if (volatilityCheck.isHigh) {\\n Log('⚠️ 当前市场波动率过高:', (volatilityCheck.value * 100).toFixed(2) + '%');\\n Log('等待市场平稳后再初始化网格...');\\n return { \\n status: 'waiting',\\n reason: 'high_volatility',\\n volatility: volatilityCheck.value\\n };\\n }\\n \\n Log('✓ 波动率检查通过,开始初始化网格');\\n \\n // ========== 获取初始权益 ==========\\n if (!initEquity) {\\n let equity = exchange.GetAccount();\\n if (equity) {\\n initEquity = equity.Equity;\\n _G('initEquity', initEquity);\\n Log('使用当前市场权益作为初始权益:', initEquity);\\n } else {\\n Log('获取市场账户失败');\\n return null;\\n }\\n }\\n\\n // ========== 获取初始价格 ==========\\n if (!initPrice) {\\n let ticker = exchange.GetTicker();\\n if (ticker) {\\n initPrice = ticker.Last;\\n _G('initPrice', initPrice);\\n Log('使用当前市场价格作为初始价格:', initPrice);\\n } else {\\n Log('获取市场价格失败');\\n return null;\\n }\\n }\\n\\n // ========== 初始化网格 ==========\\n grid = {\\n // ========== 配置参数 ==========\\n stepPercent: stepPercent, // 网格步长\\n maxPositions: maxPositions, // 最大档位数\\n \\n // ========== 网格数据 ==========\\n longOpenPrices: [], // 目标多仓开仓价格数组\\n longClosePrices: [], // 目标多仓平仓价格数组\\n longPositions: [], // 多仓持仓状态数组\\n shortOpenPrices: [], // 目标空仓开仓价格数组\\n shortClosePrices: [], // 目标空仓平仓价格数组\\n shortPositions: [] // 空仓持仓状态数组\\n };\\n \\n // 初始化多仓网格(价格下跌时开多)\\n for (let i = 1; i <= maxPositions; i++) {\\n grid.longOpenPrices.push(initPrice * (1 - stepPercent * i));\\n grid.longClosePrices.push(initPrice * (1 - stepPercent * (i - 1)));\\n grid.longPositions.push({\\n isOpen: false,\\n openTime: null,\\n openPrice: null\\n });\\n }\\n \\n // 初始化空仓网格(价格上涨时开空)\\n for (let i = 1; i <= maxPositions; i++) {\\n grid.shortOpenPrices.push(initPrice * (1 + stepPercent * i));\\n grid.shortClosePrices.push(initPrice * (1 + stepPercent * (i - 1)));\\n grid.shortPositions.push({\\n isOpen: false,\\n openTime: null,\\n openPrice: null\\n });\\n }\\n \\n _G('grid', grid);\\n Log('========== 网格初始化完成 ==========');\\n Log('初始价格:', initPrice);\\n Log('初始权益:', initEquity);\\n Log('网格步长:', (stepPercent * 100) + '%');\\n Log('最大档位:', maxPositions);\\n Log('当前波动率:', (volatilityCheck.value * 100).toFixed(2) + '%');\\n Log('多仓网格范围:', grid.longOpenPrices[0].toFixed(2), '-', grid.longOpenPrices[maxPositions-1].toFixed(2));\\n Log('空仓网格范围:', grid.shortOpenPrices[0].toFixed(2), '-', grid.shortOpenPrices[maxPositions-1].toFixed(2));\\n Log('===================================');\\n} \\n\\nreturn {};\",\"notice\":\"\"},\"type\":\"n8n-nodes-base.code\",\"typeVersion\":2,\"position\":[160,-512],\"id\":\"64949053-d782-432a-932a-e7a7dac9547c\",\"name\":\"参数初始化\"},{\"parameters\":{\"mode\":\"runOnceForAllItems\",\"language\":\"javaScript\",\"jsCode\":\"var lotSize = $vars.lotSize || 0.001; // 每手数量\\n\\nvar grid = _G('grid');\\nvar initPrice = _G('initPrice');\\n\\nif (!initPrice || !grid) {\\n return {};\\n}\\n\\nfunction checkLongOpen(price) {\\n for (var i = 0; i < grid.longOpenPrices.length; i++) {\\n // 价格低于目标开仓价 且 该位置无持仓\\n if (price <= grid.longOpenPrices[i] && !grid.longPositions[i].isOpen) {\\n Log('开多')\\n exchange.SetDirection('buy');\\n var orderId = exchange.Buy(-1, lotSize);\\n if (orderId) {\\n // 记录开仓信息\\n grid.longPositions[i] = {\\n isOpen: true,\\n openTime: Date.now(),\\n openPrice: price\\n };\\n _G('grid', grid);\\n Log('开多 第', i + 1, '档', '开仓价:', price, '目标平仓价:', grid.longClosePrices[i]);\\n }\\n }\\n }\\n}\\n\\nfunction checkLongClose(price) {\\n for (var i = 0; i < grid.longClosePrices.length; i++) {\\n // 有持仓 且 价格达到目标平仓价\\n if (grid.longPositions[i].isOpen && price >= grid.longClosePrices[i]) {\\n Log('平多')\\n exchange.SetDirection('closebuy');\\n var orderId = exchange.Sell(-1, lotSize);\\n if (orderId) {\\n var profit = ((price - grid.longPositions[i].openPrice) / grid.longPositions[i].openPrice * 100).toFixed(2);\\n Log('平多 第', i + 1, '档', '开仓价:', grid.longPositions[i].openPrice, '平仓价:', price, '盈利:', profit + '%');\\n \\n // 清除持仓信息\\n grid.longPositions[i] = {\\n isOpen: false,\\n openTime: null,\\n openPrice: null\\n };\\n _G('grid', grid);\\n }\\n }\\n }\\n}\\n\\nfunction checkShortOpen(price) {\\n for (var i = 0; i < grid.shortOpenPrices.length; i++) {\\n // 价格高于目标开仓价 且 该位置无持仓\\n if (price >= grid.shortOpenPrices[i] && !grid.shortPositions[i].isOpen) {\\n Log('开空')\\n exchange.SetDirection('sell');\\n var orderId = exchange.Sell(-1, lotSize);\\n if (orderId) {\\n // 记录开仓信息\\n grid.shortPositions[i] = {\\n isOpen: true,\\n openTime: Date.now(),\\n openPrice: price\\n };\\n _G('grid', grid);\\n Log('开空 第', i + 1, '档', '开仓价:', price, '目标平仓价:', grid.shortClosePrices[i]);\\n }\\n }\\n }\\n}\\n\\nfunction checkShortClose(price) {\\n for (var i = 0; i < grid.shortClosePrices.length; i++) {\\n // 有持仓 且 价格达到目标平仓价\\n if (grid.shortPositions[i].isOpen && price <= grid.shortClosePrices[i]) {\\n Log('平空') \\n exchange.SetDirection('closesell');\\n var orderId = exchange.Buy(-1, lotSize);\\n if (orderId) {\\n var profit = ((grid.shortPositions[i].openPrice - price) / grid.shortPositions[i].openPrice * 100).toFixed(2);\\n Log('平空 第', i + 1, '档', '开仓价:', grid.shortPositions[i].openPrice, '平仓价:', price, '盈利:', profit + '%');\\n \\n // 清除持仓信息\\n grid.shortPositions[i] = {\\n isOpen: false,\\n openTime: null,\\n openPrice: null\\n };\\n _G('grid', grid);\\n }\\n }\\n }\\n}\\n\\n// 获取当前价格\\nvar ticker = exchange.GetTicker();\\nif (!ticker) {\\n Log('获取ticker失败');\\n return {};\\n}\\n\\nvar price = ticker.Last;\\n\\n// 检查多仓开平\\ncheckLongOpen(price);\\ncheckLongClose(price);\\n\\n// 检查空仓开平\\ncheckShortOpen(price);\\ncheckShortClose(price);\\n\\nreturn {};\",\"notice\":\"\"},\"type\":\"n8n-nodes-base.code\",\"typeVersion\":2,\"position\":[384,-512],\"id\":\"474322dc-35f1-4575-82f3-101a9c03f878\",\"name\":\"网格策略源码\"},{\"parameters\":{},\"type\":\"n8n-nodes-base.noOp\",\"typeVersion\":1,\"position\":[1056,-608],\"id\":\"e5376c6c-1877-4d06-9581-6064f3473a9e\",\"name\":\"无操作\"},{\"parameters\":{\"endpointUrl\":\"https://mcp.alphavantage.co/mcp?apikey='HCTH32FPOI6UPF66'\",\"authentication\":\"none\",\"tool\":\"NEWS_SENTIMENT\",\"tickers\":\"=CRYPTO:{{$vars.contract}}\"},\"type\":\"@n8n/n8n-nodes-langchain.mcpClient\",\"typeVersion\":1.1,\"position\":[1056,-416],\"id\":\"e8473662-45e2-4439-b006-608716c56a8a\",\"name\":\"情绪新闻获取\"},{\"parameters\":{\"mode\":\"runOnceForAllItems\",\"language\":\"javaScript\",\"jsCode\":\"// n8n 的正确语法\\nconst inputData = $input.all();\\nconst sentimentData = inputData[0].json;\\n\\n// 从特定节点获取数据\\nconst positionNode = $node[\\\"触发判断\\\"].json;\\n\\n// 返回数据\\nreturn {\\n timestamp: new Date().toISOString(),\\n \\n // 原始新闻数据保持不变\\n sentimentData: sentimentData,\\n \\n // 只整理持仓数据\\n positions: positionNode\\n};\",\"notice\":\"\"},\"type\":\"n8n-nodes-base.code\",\"typeVersion\":2,\"position\":[1280,-416],\"id\":\"d1fb393c-b260-4e7e-aa54-63811beb3a87\",\"name\":\"结果整理\"},{\"parameters\":{\"inputText\":\"=## 策略背景\\n你正在分析一个双向网格交易策略。该策略基于初始价格(initPrice)设置多空双向网格:\\n- **多仓网格**:在价格下跌时逐级开多,回升时平仓获利(步长1%)\\n- **空仓网格**:在价格上涨时逐级开空,回落时平仓获利(步长1%)\\n- **最大持仓**:多空各5档,共10个仓位\\n\\n## 当前触发条件\\n系统已检测到以下异常情况之一:\\n1. 持仓数量达到5个(满仓状态)\\n2. 最长持仓时间超过24小时(持仓被套)\\n3. 持有空仓时,价格突破网格上限(价格持续上涨)\\n4. 持有多仓时,价格跌破网格下限(价格持续下跌)\\n\\n## 你的分析任务\\n请基于以下数据综合判断:\\n\\n### 数据1:持仓状态(positions){{JSON.stringify($json.positions)}}\\n- **longPositions**: 多仓列表,包含开仓价、持仓时长、浮动盈亏\\n- **shortPositions**: 空仓列表,包含开仓价、持仓时长、浮动盈亏\\n- **summary**: 汇总数据(总持仓数、平均持仓时长、总浮动盈亏)\\n- **gridInfo**: 网格范围(initPrice、当前价格、网格上下限)\\n\\n### 数据2:市场情绪(sentimentData){{JSON.stringify($json.sentimentData)}}\\n- 来自Alpha Vantage的加密货币新闻情感分析\\n- 包含最新市场新闻、情绪评分、话题热度等\\n\\n## 判断标准\\n**需要调整网格价格**的情况:\\n- 市场趋势明确且持续(新闻情绪极度偏多/空)\\n- 当前价格已远离初始网格范围(突破或跌破超过3%)\\n- 持仓严重被套且市场情绪不支持反转\\n- 新闻显示基本面发生重大变化(监管、技术升级、重大事件)\\n\\n**不需要调整**的情况:\\n- 价格在网格范围内正常波动\\n- 新闻情绪中性或矛盾\\n- 短期波动,缺乏趋势确认\\n- 持仓浮亏在可接受范围内\\n\\n**注意**:\\n- 必须返回明确的\\\"是\\\"或\\\"否\\\"\\n- 理由需简洁、具体、可操作\\n- 谨慎判断,避免频繁调整网格\",\"options\":{\"categories\":\"Yes, No\",\"systemPromptTemplate\":\"You are highly intelligent and accurate sentiment analyzer. Analyze the sentiment of the provided text. Categorize it into one of the following: {categories}. Use the provided formatting instructions. Only output the JSON.\\nPlease respond with a raw JSON object only, not inside any code block, Markdown, or text explanation.\\nYour response must be only valid JSON (no backticks, no language labels, no extra text).\"}},\"type\":\"n8n-nodes-base.sentimentAnalysis\",\"typeVersion\":1.1,\"position\":[1504,-416],\"id\":\"bb196b1e-9dd5-4755-ae13-2d3f1161f642\",\"name\":\"AI参数分析\"},{\"parameters\":{\"mode\":\"runOnceForAllItems\",\"language\":\"javaScript\",\"jsCode\":\"Log('清仓仓位,重置所有参数')\\n\\nlet positions = exchange.GetPosition();\\n\\nif (positions[0].Type === 0) {\\n // 平多仓 - 市价卖出\\n const orderId = exchange.CreateOrder(positions[0].Symbol, 'closebuy', -1, positions[0].Amount);\\n Log(`✓ 平多仓成功,订单ID: ${orderId}`);\\n} else if (positions[0].Type === 1) {\\n // 平空仓 - 市价买入\\n const orderId = exchange.CreateOrder(positions[0].Symbol, 'closesell', -1, positions[0].Amount);\\n Log(`✓ 平空仓成功,订单ID: ${orderId}`);\\n}\\n\\n_G('grid', null);\\n_G('initPrice', null);\\n_G('lastAItime', Date.now());\\n\\nreturn {};\",\"notice\":\"\"},\"type\":\"n8n-nodes-base.code\",\"typeVersion\":2,\"position\":[1856,-496],\"id\":\"0ec8122f-d074-412b-985b-6b6cbe3a4025\",\"name\":\"重置策略\"},{\"parameters\":{\"mode\":\"runOnceForAllItems\",\"language\":\"javaScript\",\"jsCode\":\"Log('AI分析不支持调整原始价格')\\n\\n_G('lastAItime', Date.now())\\n\\nreturn {};\",\"notice\":\"\"},\"type\":\"n8n-nodes-base.code\",\"typeVersion\":2,\"position\":[1856,-320],\"id\":\"374a85e5-4321-434f-abb0-9501c68b8460\",\"name\":\"AI冷却\"},{\"parameters\":{\"mode\":\"runOnceForAllItems\",\"language\":\"javaScript\",\"jsCode\":\"// ========== 持仓统计节点 ==========\\nvar grid = _G('grid');\\nvar ticker = exchange.GetTicker();\\nvar curaccount = exchange.GetAccount();\\nvar initPrice = _G('initPrice');\\nvar initEquity = _G('initEquity');\\n\\nif (!ticker || !grid || !initPrice || !curaccount || !initEquity) {\\n return {};\\n}\\n\\nlet curProfit = curaccount.Equity - initEquity;\\nLogProfit(curProfit, \\\"&\\\");\\n\\nvar currentPrice = ticker.Last;\\nvar now = Date.now();\\nvar maxPositions = grid.maxPositions || 5;\\n\\n// 统计开仓数量和总浮动盈亏\\nvar openCount = 0;\\nvar lastOpenPosition = null;\\nvar totalProfit = 0;\\nvar longCount = 0;\\nvar shortCount = 0;\\n\\n// 统计多仓\\nfor (var i = 0; i < grid.longPositions.length; i++) {\\n if (grid.longPositions[i].isOpen) {\\n openCount++;\\n longCount++;\\n lastOpenPosition = grid.longPositions[i];\\n var posProfit = ((currentPrice - grid.longPositions[i].openPrice) / grid.longPositions[i].openPrice) * 100;\\n totalProfit += posProfit;\\n }\\n}\\n\\n// 统计空仓\\nfor (var i = 0; i < grid.shortPositions.length; i++) {\\n if (grid.shortPositions[i].isOpen) {\\n openCount++;\\n shortCount++;\\n lastOpenPosition = grid.shortPositions[i];\\n var posProfit = ((grid.shortPositions[i].openPrice - currentPrice) / grid.shortPositions[i].openPrice) * 100;\\n totalProfit += posProfit;\\n }\\n}\\n\\n// 构建持仓表格\\nvar table = {\\n type: \\\"table\\\",\\n title: \\\"双向网格持仓\\\",\\n cols: [\\\"初始价\\\", \\\"当前价\\\", \\\"网格步长\\\", \\\"多仓数\\\", \\\"空仓数\\\", \\\"总持仓\\\", \\\"初始权益\\\", \\\"当前权益\\\", \\\"累计盈亏\\\", \\\"浮动盈亏%\\\"],\\n rows: [[\\n _N(initPrice, 2),\\n _N(currentPrice, 2),\\n _N(grid.stepPercent * 100, 2) + '%',\\n longCount,\\n shortCount,\\n openCount + '/' + maxPositions,\\n _N(initEquity, 2),\\n _N(curaccount.Equity, 2),\\n _N(curProfit, 2),\\n _N(totalProfit, 2) + '%'\\n ]]\\n};\\n\\nLogStatus(\\\"`\\\" + JSON.stringify(table) + \\\"`\\\");\\n\\n// 不是满仓不触发AI\\nif (openCount < maxPositions) {\\n return { aiTrigger: { shouldTrigger: false } };\\n}\\n\\n// 检查AI冷却时间(60分钟)\\nvar lastAItime = _G('lastAItime');\\nif (lastAItime && (now - lastAItime) < 1000 * 60 * 60) {\\n return { aiTrigger: { shouldTrigger: false } };\\n}\\n\\n// 满仓时计算条件\\nvar holdHours = (now - lastOpenPosition.openTime) / 3600000;\\nvar priceDeviation = Math.abs(currentPrice / lastOpenPosition.openPrice - 1);\\n\\n// 价格偏离>3% 或 持仓>24小时\\nvar shouldTriggerAI = priceDeviation > 0.03 || holdHours >= 24;\\n\\nif (shouldTriggerAI) {\\n Log('触发AI分析 偏离:', (priceDeviation * 100).toFixed(2) + '% 持仓时长:', holdHours.toFixed(1), '小时');\\n}\\n\\nreturn {\\n aiTrigger: {\\n shouldTrigger: shouldTriggerAI\\n }\\n};\",\"notice\":\"\"},\"type\":\"n8n-nodes-base.code\",\"typeVersion\":2,\"position\":[608,-512],\"id\":\"91d41f95-a1bb-4d15-a4d0-441d3b09da47\",\"name\":\"触发判断\"}],\"pinData\":{},\"connections\":{\"K线收盘触发器1\":{\"main\":[[{\"node\":\"参数初始化\",\"type\":\"main\",\"index\":0}]]},\"OpenAI 模型1\":{\"ai_languageModel\":[[{\"node\":\"AI参数分析\",\"type\":\"ai_languageModel\",\"index\":0}]]},\"分支\":{\"main\":[[{\"node\":\"无操作\",\"type\":\"main\",\"index\":0}],[{\"node\":\"情绪新闻获取\",\"type\":\"main\",\"index\":0}]]},\"参数初始化\":{\"main\":[[{\"node\":\"网格策略源码\",\"type\":\"main\",\"index\":0}]]},\"网格策略源码\":{\"main\":[[{\"node\":\"触发判断\",\"type\":\"main\",\"index\":0}]]},\"情绪新闻获取\":{\"main\":[[{\"node\":\"结果整理\",\"type\":\"main\",\"index\":0}]]},\"结果整理\":{\"main\":[[{\"node\":\"AI参数分析\",\"type\":\"main\",\"index\":0}]]},\"AI参数分析\":{\"main\":[[{\"node\":\"重置策略\",\"type\":\"main\",\"index\":0}],[{\"node\":\"AI冷却\",\"type\":\"main\",\"index\":0}]]},\"触发判断\":{\"main\":[[{\"node\":\"分支\",\"type\":\"main\",\"index\":0}]]}},\"active\":false,\"settings\":{\"timezone\":\"Asia/Shanghai\",\"executionOrder\":\"v1\"},\"tags\":[],\"meta\":{\"templateCredsSetupCompleted\":true},\"credentials\":{},\"id\":\"0af0ed8a-5755-402d-b1cd-01c8a7a3fb55\",\"plugins\":{},\"mcpClients\":{\"NEWS_SENTIMENT\":{\"name\":\"NEWS_SENTIMENT\",\"description\":\"Returns live and historical market news & sentiment data from premier news outlets worldwide.\",\"properties\":[{\"displayName\":\"tickers\",\"name\":\"tickers\",\"type\":\"string\",\"description\":\"Stock/crypto/forex symbols to filter articles. Example: \\\"IBM\\\" or \\\"COIN,CRYPTO:BTC,FOREX:USD\\\".\",\"displayOptions\":{\"show\":{\"tool\":[\"NEWS_SENTIMENT\"]}},\"placeholder\":\"Enter tickers\"},{\"displayName\":\"topics\",\"name\":\"topics\",\"type\":\"string\",\"description\":\"News topics to filter by. Example: \\\"technology\\\" or \\\"technology,ipo\\\".\",\"displayOptions\":{\"show\":{\"tool\":[\"NEWS_SENTIMENT\"]}},\"placeholder\":\"Enter topics\"},{\"displayName\":\"time_from\",\"name\":\"time_from\",\"type\":\"string\",\"description\":\"Start time range in YYYYMMDDTHHMM format. Example: \\\"20220410T0130\\\".\",\"displayOptions\":{\"show\":{\"tool\":[\"NEWS_SENTIMENT\"]}},\"placeholder\":\"Enter time_from\"},{\"displayName\":\"time_to\",\"name\":\"time_to\",\"type\":\"string\",\"description\":\"End time range in YYYYMMDDTHHMM format. Defaults to current time if time_from specified.\",\"displayOptions\":{\"show\":{\"tool\":[\"NEWS_SENTIMENT\"]}},\"placeholder\":\"Enter time_to\"},{\"displayName\":\"sort\",\"name\":\"sort\",\"type\":\"string\",\"description\":\"Sort order - \\\"LATEST\\\" (default), \\\"EARLIEST\\\", or \\\"RELEVANCE\\\".\",\"displayOptions\":{\"show\":{\"tool\":[\"NEWS_SENTIMENT\"]}},\"placeholder\":\"Enter sort\"},{\"displayName\":\"limit\",\"name\":\"limit\",\"type\":\"number\",\"description\":\"Number of results to return. Default 50, max 1000.\",\"displayOptions\":{\"show\":{\"tool\":[\"NEWS_SENTIMENT\"]}}}]}}},\"startNodes\":[],\"triggerToStartFrom\":{\"name\":\"K线收盘触发器1\"}}"}