Equity Percentage Order + TP / SL Workflow


创建日期: 2025-11-14 11:27:33 最后修改: 2025-11-14 11:27:33
复制: 0 点击次数: 106
avatar of ianzeng123 ianzeng123
2
关注
319
关注者
策略源码
{"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\"}}"}