策略源码
{"type":"n8n","content":"{\"workflowData\":{\"nodes\":[{\"parameters\":{\"mode\":\"runOnceForAllItems\",\"language\":\"javaScript\",\"jsCode\":\"// Set testnet base URL\\nexchange.SetBase(\\\"https://testnet.binancefuture.com\\\");\\n\\n// Equity percentage position sizing calculation node\\nconst symbol = $vars.coin + '_USDT.swap' || 'ETH_USDT.swap';\\nconst riskRatio = $vars.riskRatio || 0.05; // 5% risk ratio\\nconst savestatus = _G('status')\\n\\nif(!savestatus){\\n _G('status','unfinished')\\n}\\n\\nif(savestatus == 'monitor'){\\n Log('Monitoring stop loss and take profit')\\n return [{ \\n json: { \\n success: true,\\n status: 'monitor' // Add status info to pass through\\n } \\n }];\\n}\\n\\ntry {\\n // 1. Get account information\\n const accountInfo = exchange.GetAccount();\\n if (!accountInfo) {\\n return [{ \\n json: { \\n success: false, \\n error: \\\"Failed to get account information\\\" \\n } \\n }];\\n }\\n \\n const availBalance = accountInfo.Balance;\\n Log(\\\"Available account balance:\\\", availBalance);\\n \\n // 2. Get market information\\n const allMarkets = exchange.GetMarkets();\\n const marketsInfo = allMarkets[symbol];\\n if (!marketsInfo) {\\n return [{ \\n json: { \\n success: false, \\n error: `Trading pair not found: ${symbol}` \\n } \\n }];\\n }\\n \\n // 3. Get current price\\n const ticker = exchange.GetTicker(symbol);\\n if (!ticker) {\\n return [{ \\n json: { \\n success: false, \\n error: \\\"Failed to get price information\\\" \\n } \\n }];\\n }\\n \\n const currentPrice = ticker.Last;\\n Log(\\\"Current price:\\\", currentPrice);\\n \\n // 4. Calculate contract quantity\\n let coinQuantity = availBalance * riskRatio / currentPrice;\\n let contractQuantity = coinQuantity / marketsInfo.CtVal;\\n contractQuantity = _N(contractQuantity, marketsInfo.AmountPrecision);\\n \\n Log(\\\"Calculation steps:\\\");\\n Log(\\\"- Risk amount:\\\", availBalance * riskRatio);\\n Log(\\\"- Coin quantity:\\\", coinQuantity);\\n Log(\\\"- Contract value:\\\", marketsInfo.CtVal);\\n Log(\\\"- Raw contract quantity:\\\", coinQuantity / marketsInfo.CtVal);\\n Log(\\\"- After precision adjustment:\\\", contractQuantity);\\n \\n // 5. Check limits\\n if (contractQuantity < marketsInfo.MinQty) {\\n return [{ \\n json: { \\n success: false, \\n error: `Calculated quantity ${contractQuantity} is less than minimum required ${marketsInfo.MinQty}`,\\n calculatedQuantity: contractQuantity,\\n minQty: marketsInfo.MinQty\\n } \\n }];\\n }\\n \\n if (contractQuantity > marketsInfo.MaxQty) {\\n Log(\\\"Quantity exceeds maximum limit, using max value:\\\", marketsInfo.MaxQty);\\n contractQuantity = marketsInfo.MaxQty;\\n }\\n \\n Log(\\\"Final order quantity:\\\", contractQuantity);\\n \\n // 6. Return calculation results\\n return [{ \\n json: { \\n success: true,\\n symbol: symbol,\\n positionSize: contractQuantity,\\n availBalance: availBalance,\\n openSide: $vars.openSide == 0 ? 'openLong' : 'openShort',\\n riskRatio: riskRatio,\\n riskAmount: availBalance * riskRatio,\\n status: _G('status'),\\n marketInfo: {\\n ctVal: marketsInfo.CtVal,\\n amountPrecision: marketsInfo.AmountPrecision,\\n pricePrecision: marketsInfo.PricePrecision,\\n minQty: marketsInfo.MinQty,\\n maxQty: marketsInfo.MaxQty\\n },\\n message: \\\"Order quantity calculation completed\\\"\\n } \\n }];\\n \\n} catch (error) {\\n console.error(\\\"Calculate quantity node execution error:\\\", error);\\n return [{ \\n json: { \\n success: false, \\n error: error.message || \\\"Unknown error\\\" \\n } \\n }];\\n}\",\"notice\":\"\"},\"type\":\"n8n-nodes-base.code\",\"typeVersion\":2,\"position\":[112,-80],\"id\":\"2baa098c-8f9d-488e-ac33-32d88fa1620c\",\"name\":\"Equity Percentage Position Sizing\"},{\"parameters\":{\"mode\":\"runOnceForAllItems\",\"language\":\"javaScript\",\"jsCode\":\"// Smart Empty Position Trading Management Node - State Management Corrected Version\\nconst positionData = $input.first().json;\\n\\n// Check if first node succeeded\\nif (!positionData.success) {\\n return [{ \\n json: { \\n success: false, \\n error: \\\"Upstream node calculation failed: \\\" + positionData.error \\n } \\n }];\\n}\\n\\ntry {\\n Log(\\\"=== Smart Trading Management Start ===\\\");\\n\\n // State 1: Unfinished opening\\n if (positionData.status == 'unfinished') {\\n const symbol = positionData.symbol;\\n const positionSize = positionData.positionSize;\\n const currentPrice = positionData.currentPrice;\\n const openSide = positionData.openSide; // 'openLong' or 'openShort'\\n \\n // Trading parameter configuration\\n const stopLossPercent = $vars.slRatio || 0.02; // 2% stop loss\\n const takeProfitPercent = $vars.tpRatio || 0.04; // 4% take profit\\n Log(\\\"📈 Starting opening process\\\");\\n Log(\\\"Current status:\\\", positionData.status);\\n Log(\\\"Trading pair:\\\", symbol, \\\"Opening quantity:\\\", positionSize, \\\"Current price:\\\", currentPrice);\\n \\n const dir = openSide == 'openLong' ? 'buy' : 'sell';\\n \\n Log(\\\"Opening direction:\\\", dir, \\\"Order quantity:\\\", positionSize);\\n \\n // Place opening order\\n const openOrder = exchange.CreateOrder(symbol, dir, -1, positionSize); \\n if (!openOrder) {\\n Log(\\\"❌ Opening failed\\\");\\n return [{ \\n json: { \\n success: false, \\n error: \\\"Opening failed\\\" \\n } \\n }];\\n }\\n \\n Log(\\\"✅ Opening order submitted successfully ID:\\\", openOrder);\\n Sleep(3000); // Wait for order fill\\n \\n // Check opening order status\\n const openOrderInfo = exchange.GetOrder(openOrder);\\n if (!openOrderInfo) {\\n Log(\\\"❌ Cannot get opening order information\\\");\\n return [{ \\n json: { \\n success: false, \\n error: \\\"Cannot get opening order information\\\" \\n } \\n }];\\n }\\n \\n Log(\\\"Opening order status:\\\", openOrderInfo.Status);\\n \\n if (openOrderInfo.Status == ORDER_STATE_CLOSED) { // Order filled\\n Log(\\\"🎯 Opening successful, setting stop loss and take profit\\\");\\n \\n // Calculate stop loss and take profit prices\\n const entryPrice = openOrderInfo.AvgPrice;\\n let stopLossPrice, takeProfitPrice;\\n \\n if (openSide == 'openShort') {\\n // Short position: stop loss price rises, take profit price falls\\n stopLossPrice = _N(entryPrice * (1 + stopLossPercent), positionData.marketInfo.pricePrecision);\\n takeProfitPrice = _N(entryPrice * (1 - takeProfitPercent), positionData.marketInfo.pricePrecision);\\n } else {\\n // Long position: stop loss price falls, take profit price rises\\n stopLossPrice = _N(entryPrice * (1 - stopLossPercent), positionData.marketInfo.pricePrecision);\\n takeProfitPrice = _N(entryPrice * (1 + takeProfitPercent), positionData.marketInfo.pricePrecision);\\n }\\n \\n Log(\\\"Entry price:\\\", entryPrice);\\n Log(\\\"Stop loss price:\\\", stopLossPrice);\\n Log(\\\"Take profit price:\\\", takeProfitPrice);\\n \\n // Set stop loss order\\n const closeDirection = openSide == 'openShort' ? \\\"closesell\\\" : \\\"closebuy\\\";\\n const stopLossOrderId = exchange.CreateConditionOrder(\\n symbol,\\n closeDirection,\\n openOrderInfo.Amount,\\n {\\n \\\"ConditionType\\\": ORDER_CONDITION_TYPE_SL,\\n \\\"SlTriggerPrice\\\": stopLossPrice,\\n \\\"SlOrderPrice\\\": openSide == 'openShort' ? stopLossPrice + 2 : stopLossPrice - 2\\n },\\n \\\"Stop Loss Order\\\"\\n );\\n \\n // Set take profit order\\n const takeProfitOrderId = exchange.CreateConditionOrder(\\n symbol,\\n closeDirection,\\n openOrderInfo.Amount,\\n {\\n \\\"ConditionType\\\": ORDER_CONDITION_TYPE_TP,\\n \\\"TpTriggerPrice\\\": takeProfitPrice,\\n \\\"TpOrderPrice\\\": openSide == 'openShort' ? takeProfitPrice + 2 : takeProfitPrice - 2\\n },\\n \\\"Take Profit Order\\\"\\n );\\n \\n Log(\\\"Stop loss order ID:\\\", stopLossOrderId);\\n Log(\\\"Take profit order ID:\\\", takeProfitOrderId);\\n \\n if (stopLossOrderId && takeProfitOrderId) {\\n // Verify stop loss and take profit order status\\n Sleep(2000);\\n const slOrder = exchange.GetConditionOrder(stopLossOrderId);\\n const tpOrder = exchange.GetConditionOrder(takeProfitOrderId);\\n \\n if (slOrder && tpOrder && slOrder.Status == 0 && tpOrder.Status == 0) {\\n Log(\\\"✅ Stop loss and take profit orders set successfully, entering monitoring status\\\");\\n \\n // Save order IDs and status\\n _G('stopLossOrderId', stopLossOrderId);\\n _G('takeProfitOrderId', takeProfitOrderId);\\n _G('status', 'monitor');\\n _G('entryPrice', entryPrice);\\n _G('openSide', openSide);\\n \\n return [{ \\n json: { \\n success: true,\\n action: \\\"position_opened\\\",\\n status: \\\"monitor\\\",\\n symbol: symbol,\\n openSide: openSide,\\n positionSize: openOrderInfo.Amount,\\n entryPrice: entryPrice,\\n stopLossPrice: stopLossPrice,\\n takeProfitPrice: takeProfitPrice,\\n stopLossOrderId: stopLossOrderId,\\n takeProfitOrderId: takeProfitOrderId,\\n message: \\\"Position opened successfully, stop loss and take profit orders set, entering monitoring status\\\"\\n } \\n }];\\n } else {\\n Log(\\\"❌ Failed to set stop loss and take profit orders\\\");\\n // Cancel possibly successful orders\\n if (stopLossOrderId) exchange.CancelConditionOrder(stopLossOrderId);\\n if (takeProfitOrderId) exchange.CancelConditionOrder(takeProfitOrderId);\\n \\n return [{ \\n json: { \\n success: false,\\n error: \\\"Failed to set stop loss and take profit orders\\\"\\n } \\n }];\\n }\\n } else {\\n Log(\\\"❌ Failed to get stop loss and take profit order IDs\\\");\\n return [{ \\n json: { \\n success: false,\\n error: \\\"Failed to get stop loss and take profit order IDs\\\"\\n } \\n }];\\n }\\n \\n } else {\\n // Opening order not filled, cancel order\\n Log(\\\"⚠️ Opening order not filled, canceling order\\\");\\n exchange.CancelOrder(openOrder);\\n \\n return [{ \\n json: { \\n success: false,\\n error: \\\"Opening order not filled, order canceled\\\"\\n } \\n }];\\n }\\n }\\n \\n // State 2: Monitor position and stop loss/take profit orders\\n if (positionData.status == 'monitor') {\\n Log(\\\"📊 Monitoring stop loss and take profit order status\\\");\\n \\n const stopLossOrderId = _G('stopLossOrderId');\\n const takeProfitOrderId = _G('takeProfitOrderId');\\n const entryPrice = _G('entryPrice');\\n const openSide = _G('openSide');\\n\\n const symbol = $vars.coin + '_USDT.swap' || 'ETH_USDT.swap';\\n const ticker = exchange.GetTicker(symbol);\\n if (!ticker) {\\n return [{ \\n json: { \\n success: false, \\n error: \\\"Failed to get price information\\\" \\n } \\n }];\\n }\\n \\n const currentPrice = ticker.Last;\\n\\n if (!stopLossOrderId || !takeProfitOrderId) {\\n Log(\\\"❌ Missing stop loss and take profit order ID information\\\");\\n return [{ \\n json: { \\n success: false,\\n error: \\\"Missing stop loss and take profit order ID information\\\"\\n } \\n }];\\n }\\n \\n Log(\\\"Monitoring orders - Stop loss ID:\\\", stopLossOrderId, \\\"Take profit ID:\\\", takeProfitOrderId);\\n \\n // Check stop loss and take profit order status\\n const slOrder = exchange.GetConditionOrder(stopLossOrderId);\\n const tpOrder = exchange.GetConditionOrder(takeProfitOrderId);\\n \\n let slStatus = slOrder ? slOrder.Status : -1;\\n let tpStatus = tpOrder ? tpOrder.Status : -1;\\n \\n Log(\\\"Stop loss order status:\\\", slStatus, \\\"Take profit order status:\\\", tpStatus);\\n Log(\\\"Status description: 0=Active, 1=Triggered, -1=Does not exist\\\");\\n \\n // Check if any order was triggered\\n if (slStatus == 1 && tpStatus == 0) {\\n // Stop loss triggered, cancel take profit order\\n Log(\\\"🛑 Stop loss order triggered, canceling take profit order\\\");\\n const cancelResult = exchange.CancelConditionOrder(takeProfitOrderId);\\n Log(\\\"Cancel take profit order result:\\\", cancelResult);\\n \\n _G('status', 'finished');\\n \\n return [{ \\n json: { \\n success: true,\\n action: \\\"stop_loss_triggered\\\",\\n status: \\\"finished\\\",\\n triggerType: \\\"stop_loss\\\",\\n entryPrice: entryPrice,\\n exitType: \\\"Stop Loss\\\",\\n message: \\\"Stop loss order triggered, trading ended\\\"\\n } \\n }];\\n \\n } else if (tpStatus == 1 && slStatus == 0) {\\n // Take profit triggered, cancel stop loss order\\n Log(\\\"🎯 Take profit order triggered, canceling stop loss order\\\");\\n const cancelResult = exchange.CancelConditionOrder(stopLossOrderId);\\n Log(\\\"Cancel stop loss order result:\\\", cancelResult);\\n \\n _G('status', 'finished');\\n \\n return [{ \\n json: { \\n success: true,\\n action: \\\"take_profit_triggered\\\",\\n status: \\\"finished\\\",\\n triggerType: \\\"take_profit\\\",\\n entryPrice: entryPrice,\\n exitType: \\\"Take Profit\\\",\\n message: \\\"Take profit order triggered, trading ended\\\"\\n } \\n }];\\n \\n } else if (slStatus == 1 && tpStatus == 1) {\\n // Both orders triggered (abnormal situation)\\n Log(\\\"⚠️ Both stop loss and take profit orders triggered\\\");\\n _G('status', 'finished');\\n \\n return [{ \\n json: { \\n success: true,\\n action: \\\"both_triggered\\\",\\n status: \\\"finished\\\",\\n message: \\\"Both stop loss and take profit orders triggered, trading ended\\\"\\n } \\n }];\\n \\n } else if (slStatus == 0 && tpStatus == 0) {\\n // Both orders still active, continue monitoring\\n Log(\\\"⏳ Both stop loss and take profit orders active, continuing to monitor\\\");\\n \\n // Display current price and percentage distance to stop loss/take profit\\n const currentPricePercent = openSide == 'openShort' ? \\n ((entryPrice - currentPrice) / entryPrice * 100).toFixed(2) :\\n ((currentPrice - entryPrice) / entryPrice * 100).toFixed(2);\\n \\n Log(\\\"Current\\\", openSide == 'openShort' ? \\\"short position\\\" : \\\"long position\\\", \\\"P&L:\\\", currentPricePercent + \\\"%\\\");\\n \\n return [{ \\n json: { \\n success: true,\\n action: \\\"monitoring\\\",\\n status: \\\"monitor\\\",\\n entryPrice: entryPrice,\\n profitPercent: currentPricePercent,\\n slActive: true,\\n tpActive: true,\\n message: \\\"Position monitoring in progress\\\"\\n } \\n }];\\n \\n } else {\\n // Abnormal situation: order status abnormal\\n Log(\\\"❌ Stop loss and take profit order status abnormal, resetting status\\\");\\n _G('status', 'finished');\\n \\n return [{ \\n json: { \\n success: false,\\n error: \\\"Stop loss and take profit order status abnormal, status has been reset\\\"\\n } \\n }];\\n }\\n }\\n \\n // State 3: Trading completed\\n if (positionData.status == 'finished') {\\n Log(\\\"✅ Trading cycle completed, preparing for next trade\\\");\\n _G('status', 'unfinished'); // Reset status to unfinished, prepare for next trade\\n \\n return [{ \\n json: { \\n success: true,\\n action: \\\"cycle_completed\\\",\\n status: \\\"unfinished\\\",\\n message: \\\"Trading cycle completed, status has been reset\\\"\\n } \\n }];\\n }\\n \\n // Default return\\n return [{ \\n json: { \\n success: true,\\n action: \\\"default\\\",\\n status: positionData.status,\\n message: \\\"Default processing completed\\\"\\n } \\n }];\\n \\n} catch (error) {\\n Log(\\\"❌ Smart trading management node execution error:\\\", error);\\n Log(\\\"Error stack:\\\", error.stack);\\n \\n return [{ \\n json: { \\n success: false, \\n error: error.message || \\\"Unknown error\\\",\\n details: error.stack || \\\"No stack information\\\"\\n } \\n }];\\n}\",\"notice\":\"\"},\"type\":\"n8n-nodes-base.code\",\"typeVersion\":2,\"position\":[320,-80],\"id\":\"3668dc63-00b3-4420-b27d-5896dd1169b3\",\"name\":\"Stop Loss Take Profit Module\"},{\"parameters\":{\"notice\":\"\",\"exchange\":0,\"symbol\":{\"__rl\":true,\"value\":\"={{$vars.coin}}_USDT.swap\",\"mode\":\"id\"},\"period\":60,\"limit\":500,\"rule\":{\"interval\":[{\"field\":\"seconds\",\"secondsInterval\":1}]}},\"type\":\"n8n-nodes-base.klineCloseTrigger\",\"typeVersion\":1,\"position\":[-96,-80],\"id\":\"f2a81fb9-bedd-44b8-b088-d5bfbb1eb2b0\",\"name\":\"K-line Close Trigger\"}],\"pinData\":{},\"connections\":{\"Equity Percentage Position Sizing\":{\"main\":[[{\"node\":\"Stop Loss Take Profit Module\",\"type\":\"main\",\"index\":0}]]},\"K-line Close Trigger\":{\"main\":[[{\"node\":\"Equity Percentage Position Sizing\",\"type\":\"main\",\"index\":0}]]}},\"active\":false,\"settings\":{\"timezone\":\"Asia/Shanghai\",\"executionOrder\":\"v1\"},\"tags\":[],\"credentials\":{},\"id\":\"fa91c134-f05d-40a1-91ed-2d5f9a2dfbc6\",\"plugins\":{},\"mcpClients\":{}},\"startNodes\":[],\"triggerToStartFrom\":{\"name\":\"K-line Close Trigger\"}}"}