权益百分比+止盈止损工作流


创建日期: 2025-11-10 17:52:06 最后修改: 2025-11-14 10:49:35
复制: 0 点击次数: 137
avatar of ianzeng123 ianzeng123
2
关注
319
关注者
策略源码
{"type":"n8n","content":"{\"workflowData\":{\"nodes\":[{\"parameters\":{\"mode\":\"runOnceForAllItems\",\"language\":\"javaScript\",\"jsCode\":\"// 设置测试网基地址\\nexchange.SetBase(\\\"https://testnet.binancefuture.com\\\");\\n\\n// 权益百分比下单数量计算节点\\nconst symbol = $vars.coin + '_USDT.swap' || 'ETH_USDT.swap';\\nconst riskRatio = $vars.riskRatio || 0.05; // 5%风险比例\\nconst savestatus = _G('status')\\n\\nif(!savestatus){\\n  _G('status','unfinished')\\n}\\n\\nif(savestatus == 'monitor'){\\n  Log('监控止盈止损')\\n  return [{ \\n    json: { \\n      success: true,\\n      status: 'monitor'  // 添加状态信息传递\\n    } \\n  }];\\n}\\n\\ntry {\\n    // 1. 获取账户信息\\n    const accountInfo = exchange.GetAccount();\\n    if (!accountInfo) {\\n        return [{ \\n            json: { \\n                success: false, \\n                error: \\\"获取账户信息失败\\\" \\n            } \\n        }];\\n    }\\n    \\n    const availBalance = accountInfo.Balance;\\n    Log(\\\"账户可用余额:\\\", availBalance);\\n    \\n    // 2. 获取市场信息\\n    const allMarkets = exchange.GetMarkets();\\n    const marketsInfo = allMarkets[symbol];\\n    if (!marketsInfo) {\\n        return [{ \\n            json: { \\n                success: false, \\n                error: `未找到交易对信息: ${symbol}` \\n            } \\n        }];\\n    }\\n    \\n    // 3. 获取当前价格\\n    const ticker = exchange.GetTicker(symbol);\\n    if (!ticker) {\\n        return [{ \\n            json: { \\n                success: false, \\n                error: \\\"获取价格信息失败\\\" \\n            } \\n        }];\\n    }\\n    \\n    const currentPrice = ticker.Last;\\n    Log(\\\"当前价格:\\\", currentPrice);\\n    \\n    // 4. 计算合约张数\\n    let coinQuantity = availBalance * riskRatio / currentPrice;\\n    let contractQuantity = coinQuantity / marketsInfo.CtVal;\\n    contractQuantity = _N(contractQuantity, marketsInfo.AmountPrecision);\\n    \\n    Log(\\\"计算步骤:\\\");\\n    Log(\\\"- 风险金额:\\\", availBalance * riskRatio);\\n    Log(\\\"- 币种数量:\\\", coinQuantity);\\n    Log(\\\"- 合约面值:\\\", marketsInfo.CtVal);\\n    Log(\\\"- 原始合约张数:\\\", coinQuantity / marketsInfo.CtVal);\\n    Log(\\\"- 精度处理后:\\\", contractQuantity);\\n    \\n    // 5. 检查限制\\n    if (contractQuantity < marketsInfo.MinQty) {\\n        return [{ \\n            json: { \\n                success: false, \\n                error: `计算数量${contractQuantity}小于最小要求${marketsInfo.MinQty}`,\\n                calculatedQuantity: contractQuantity,\\n                minQty: marketsInfo.MinQty\\n            } \\n        }];\\n    }\\n    \\n    if (contractQuantity > marketsInfo.MaxQty) {\\n        Log(\\\"数量超过最大限制,使用最大值:\\\", marketsInfo.MaxQty);\\n        contractQuantity = marketsInfo.MaxQty;\\n    }\\n    \\n    Log(\\\"最终下单数量:\\\", contractQuantity);\\n    \\n    // 6. 返回计算结果\\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: \\\"下单数量计算完成\\\"\\n        } \\n    }];\\n    \\n} catch (error) {\\n    console.error(\\\"计算数量节点执行错误:\\\", error);\\n    return [{ \\n        json: { \\n            success: false, \\n            error: error.message || \\\"未知错误\\\" \\n        } \\n    }];\\n}\",\"notice\":\"\"},\"type\":\"n8n-nodes-base.code\",\"typeVersion\":2,\"position\":[208,0],\"id\":\"3cb8c762-ef19-4e70-9111-83d18fd17085\",\"name\":\"权益百分比下单数量计算\"},{\"parameters\":{\"mode\":\"runOnceForAllItems\",\"language\":\"javaScript\",\"jsCode\":\"// 智能空仓交易管理节点 - 状态管理修正版\\nconst positionData = $input.first().json;\\n\\n// 检查第一个节点是否成功\\nif (!positionData.success) {\\n    return [{ \\n        json: { \\n            success: false, \\n            error: \\\"上游节点计算失败: \\\" + positionData.error \\n        } \\n    }];\\n}\\n\\ntry {\\n    Log(\\\"=== 智能交易管理开始 ===\\\");\\n\\n    // 状态1: 未完成开仓\\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        // 交易参数配置\\n        const stopLossPercent = $vars.slRatio || 0.02;  // 2%止损\\n        const takeProfitPercent = $vars.tpRatio || 0.04; // 4%止盈\\n        Log(\\\"📈 开始开仓流程\\\");\\n        Log(\\\"当前状态:\\\", positionData.status);\\n        Log(\\\"交易对:\\\", symbol, \\\"开仓数量:\\\", positionSize, \\\"当前价格:\\\", currentPrice);\\n        \\n        const dir = openSide == 'openLong' ? 'buy' : 'sell';\\n        \\n        Log(\\\"开仓方向:\\\", dir, \\\"订单量:\\\", positionSize);\\n        \\n        // 开仓下单\\n        const openOrder = exchange.CreateOrder(symbol, dir, -1, positionSize); \\n        if (!openOrder) {\\n            Log(\\\"❌ 开仓失败\\\");\\n            return [{ \\n                json: { \\n                    success: false, \\n                    error: \\\"开仓失败\\\" \\n                } \\n            }];\\n        }\\n        \\n        Log(\\\"✅ 开仓订单提交成功 ID:\\\", openOrder);\\n        Sleep(3000); // 等待订单成交\\n        \\n        // 检查开仓订单状态\\n        const openOrderInfo = exchange.GetOrder(openOrder);\\n        if (!openOrderInfo) {\\n            Log(\\\"❌ 无法获取开仓订单信息\\\");\\n            return [{ \\n                json: { \\n                    success: false, \\n                    error: \\\"无法获取开仓订单信息\\\" \\n                } \\n            }];\\n        }\\n        \\n        Log(\\\"开仓订单状态:\\\", openOrderInfo.Status);\\n        \\n        if (openOrderInfo.Status == ORDER_STATE_CLOSED) { // 订单已成交\\n            Log(\\\"🎯 开仓成功,开始设置止盈止损\\\");\\n            \\n            // 计算止盈止损价格\\n            const entryPrice = openOrderInfo.AvgPrice;\\n            let stopLossPrice, takeProfitPrice;\\n            \\n            if (openSide == 'openShort') {\\n                // 空仓:止损价格上涨,止盈价格下跌\\n                stopLossPrice = _N(entryPrice * (1 + stopLossPercent), positionData.marketInfo.pricePrecision);\\n                takeProfitPrice = _N(entryPrice * (1 - takeProfitPercent), positionData.marketInfo.pricePrecision);\\n            } else {\\n                // 多仓:止损价格下跌,止盈价格上涨\\n                stopLossPrice = _N(entryPrice * (1 - stopLossPercent), positionData.marketInfo.pricePrecision);\\n                takeProfitPrice = _N(entryPrice * (1 + takeProfitPercent), positionData.marketInfo.pricePrecision);\\n            }\\n            \\n            Log(\\\"入场价格:\\\", entryPrice);\\n            Log(\\\"止损价格:\\\", stopLossPrice);\\n            Log(\\\"止盈价格:\\\", takeProfitPrice);\\n            \\n            // 设置止损单\\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                \\\"止损单\\\"\\n            );\\n            \\n            // 设置止盈单\\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                \\\"止盈单\\\"\\n            );\\n            \\n            Log(\\\"止损单ID:\\\", stopLossOrderId);\\n            Log(\\\"止盈单ID:\\\", takeProfitOrderId);\\n            \\n            if (stopLossOrderId && takeProfitOrderId) {\\n                // 验证止盈止损单状态\\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(\\\"✅ 止盈止损单设置成功,进入监控状态\\\");\\n                    \\n                    // 保存订单ID和状态\\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: \\\"开仓成功,止盈止损单已设置,进入监控状态\\\"\\n                        } \\n                    }];\\n                } else {\\n                    Log(\\\"❌ 止盈止损单设置失败\\\");\\n                    // 取消可能成功的订单\\n                    if (stopLossOrderId) exchange.CancelConditionOrder(stopLossOrderId);\\n                    if (takeProfitOrderId) exchange.CancelConditionOrder(takeProfitOrderId);\\n                    \\n                    return [{ \\n                        json: { \\n                            success: false,\\n                            error: \\\"止盈止损单设置失败\\\"\\n                        } \\n                    }];\\n                }\\n            } else {\\n                Log(\\\"❌ 止盈止损单ID获取失败\\\");\\n                return [{ \\n                    json: { \\n                        success: false,\\n                        error: \\\"止盈止损单ID获取失败\\\"\\n                    } \\n                }];\\n            }\\n            \\n        } else {\\n            // 开仓订单未成交,取消订单\\n            Log(\\\"⚠️ 开仓订单未成交,取消订单\\\");\\n            exchange.CancelOrder(openOrder);\\n            \\n            return [{ \\n                json: { \\n                    success: false,\\n                    error: \\\"开仓订单未成交,已取消订单\\\"\\n                } \\n            }];\\n        }\\n    }\\n    \\n    // 状态2: 监控持仓和止盈止损单\\n    if (positionData.status == 'monitor') {\\n        Log(\\\"📊 监控止盈止损单状态\\\");\\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: \\\"获取价格信息失败\\\" \\n                } \\n            }];\\n        }\\n        \\n        const currentPrice = ticker.Last;\\n\\n        if (!stopLossOrderId || !takeProfitOrderId) {\\n            Log(\\\"❌ 缺少止盈止损单ID信息\\\");\\n            return [{ \\n                json: { \\n                    success: false,\\n                    error: \\\"缺少止盈止损单ID信息\\\"\\n                } \\n            }];\\n        }\\n        \\n        Log(\\\"监控订单 - 止损ID:\\\", stopLossOrderId, \\\"止盈ID:\\\", takeProfitOrderId);\\n        \\n        // 检查止盈止损单状态\\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(\\\"止损单状态:\\\", slStatus, \\\"止盈单状态:\\\", tpStatus);\\n        Log(\\\"状态说明: 0=活跃, 1=已触发, -1=不存在\\\");\\n        \\n        // 检查是否有订单被触发\\n        if (slStatus == 1 && tpStatus == 0) {\\n            // 止损被触发,取消止盈单\\n            Log(\\\"🛑 止损单已触发,取消止盈单\\\");\\n            const cancelResult = exchange.CancelConditionOrder(takeProfitOrderId);\\n            Log(\\\"取消止盈单结果:\\\", 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: \\\"止损\\\",\\n                    message: \\\"止损单触发,交易结束\\\"\\n                } \\n            }];\\n            \\n        } else if (tpStatus == 1 && slStatus == 0) {\\n            // 止盈被触发,取消止损单\\n            Log(\\\"🎯 止盈单已触发,取消止损单\\\");\\n            const cancelResult = exchange.CancelConditionOrder(stopLossOrderId);\\n            Log(\\\"取消止损单结果:\\\", 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: \\\"止盈\\\",\\n                    message: \\\"止盈单触发,交易结束\\\"\\n                } \\n            }];\\n            \\n        } else if (slStatus == 1 && tpStatus == 1) {\\n            // 两个单都触发了(异常情况)\\n            Log(\\\"⚠️ 止盈止损单都已触发\\\");\\n            _G('status', 'finished');\\n            \\n            return [{ \\n                json: { \\n                    success: true,\\n                    action: \\\"both_triggered\\\",\\n                    status: \\\"finished\\\",\\n                    message: \\\"止盈止损单都已触发,交易结束\\\"\\n                } \\n            }];\\n            \\n        } else if (slStatus == 0 && tpStatus == 0) {\\n            // 两个单都还活跃,继续监控\\n            Log(\\\"⏳ 止盈止损单都活跃,继续监控\\\");\\n            \\n            // 显示当前价格和距离止盈止损的百分比\\n            const currentPricePercent = openSide == 'openShort' ? \\n                ((entryPrice - currentPrice) / entryPrice * 100).toFixed(2) :\\n                ((currentPrice - entryPrice) / entryPrice * 100).toFixed(2);\\n            \\n            Log(\\\"当前\\\", openSide == 'openShort' ? \\\"空仓\\\" : \\\"多仓\\\", \\\"盈亏:\\\", 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: \\\"持仓监控中\\\"\\n                } \\n            }];\\n            \\n        } else {\\n            // 异常情况:单子状态异常\\n            Log(\\\"❌ 止盈止损单状态异常,重置状态\\\");\\n            _G('status', 'finished');\\n            \\n            return [{ \\n                json: { \\n                    success: false,\\n                    error: \\\"止盈止损单状态异常,已重置状态\\\"\\n                } \\n            }];\\n        }\\n    }\\n    \\n    // 状态3: 交易完成\\n    if (positionData.status == 'finished') {\\n        Log(\\\"✅ 交易周期完成,准备下次交易\\\");\\n        _G('status', 'unfinished'); // 重置状态为未完成,准备下次交易\\n        \\n        return [{ \\n            json: { \\n                success: true,\\n                action: \\\"cycle_completed\\\",\\n                status: \\\"unfinished\\\",\\n                message: \\\"交易周期完成,状态已重置\\\"\\n            } \\n        }];\\n    }\\n    \\n    // 默认返回\\n    return [{ \\n        json: { \\n            success: true,\\n            action: \\\"default\\\",\\n            status: positionData.status,\\n            message: \\\"默认处理完成\\\"\\n        } \\n    }];\\n    \\n} catch (error) {\\n    Log(\\\"❌ 智能交易管理节点执行错误:\\\", error);\\n    Log(\\\"错误堆栈:\\\", error.stack);\\n    \\n    return [{ \\n        json: { \\n            success: false, \\n            error: error.message || \\\"未知错误\\\",\\n            details: error.stack || \\\"无堆栈信息\\\"\\n        } \\n    }];\\n}\",\"notice\":\"\"},\"type\":\"n8n-nodes-base.code\",\"typeVersion\":2,\"position\":[416,0],\"id\":\"b176d8f6-f9ae-4c72-b17b-93a745f8f599\",\"name\":\"止盈止损模块\"},{\"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\":[0,0],\"id\":\"fdd0b24a-79a7-45a0-beeb-70f39acb43b5\",\"name\":\"K线收盘触发器\"}],\"pinData\":{},\"connections\":{\"权益百分比下单数量计算\":{\"main\":[[{\"node\":\"止盈止损模块\",\"type\":\"main\",\"index\":0}]]},\"K线收盘触发器\":{\"main\":[[{\"node\":\"权益百分比下单数量计算\",\"type\":\"main\",\"index\":0}]]},\"止盈止损模块\":{\"main\":[[]]}},\"active\":false,\"settings\":{\"timezone\":\"Asia/Shanghai\",\"executionOrder\":\"v1\"},\"tags\":[],\"credentials\":{},\"id\":\"42d34c52-c2ab-4512-b74b-9eac4f4e97a4\",\"plugins\":{},\"mcpClients\":{}},\"startNodes\":[],\"triggerToStartFrom\":{\"name\":\"K线收盘触发器\"}}"}