本文提供的 Pine Script 旨在将策略参数动态转换为 JSON 格式,从而与 WunderTrading 机器人无缝集成。该脚本允许您为每一笔交易自定义和调整关键交易变量,例如止盈、止损、追踪止损等。
这种灵活性确保每笔交易都可以根据自身具体要求进行单独配置,使策略能够高度适应不断变化的市场环境,并贴合个性化交易偏好。
下面我们一步一步来了解它的使用方式和可能性。
如何使用 JSON 创建信号机器人
要开始设置信号机器人,请前往左侧的信号机器人标签页,并选择创建机器人。
打开信号机器人设置窗口后,您就可以开始根据自己的具体需求调整配置。
通用设置
1. 首先配置机器人的名称和描述。
2. 选择交易所及对应的 API。
您最多可以同时选择 50 个 API,并将它们统一归入同一个策略。要查看详情,只需点击对应行展开该策略。
3. 从列表中找到您的交易对,或使用搜索框进行查找。
您最多可以选择 10 个交易对。这意味着当提醒触发时,每个已选交易对都会分别执行一笔交易。
4. 选择您需要的时间周期。该设置只会更改提醒备注的名称,并允许您在信号机器人列表中按时间周期筛选机器人。它与 TradingView 的时间周期相互独立。
5. 多次入场选项允许您在连续收到入场信号时逐步加仓。如果您希望同一交易对同时持有多个未平仓仓位,请启用该设置。
6. 波段交易功能允许仅使用做空入场和做多入场信号来切换交易方向。启用后,它会将提醒备注简化为三类:做多入场、做空入场和全部出场。请注意,波段交易功能仅适用于合约市场。
入场设置
在表单的入场设置部分,请先选择以下选项:
机器人启动条件(来源):TradingView
机器人设置格式:JSON
将机器人设置格式切换为 JSON 后,右侧的提醒区域会随之更新。该区域提供一个可用的基础策略示例,您可以将其复制到 TradingView Pine Editor 中,以帮助理解代码的运行方式。下面我们来详细查看代码。
代码主要分为两个部分:策略逻辑和 WunderTrading 执行。
🔵 TradingView Pine Script 策略示例
您可以直接将这段代码复制并粘贴到 TradingView PineScript 编辑器中,将其应用到图表并观察其运行方式。它是创建您自己的策略并将其与 WunderTrading 集成的基础示例。
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © WunderTrading
//@version=6
strategy('Test Strategy', overlay = true, margin_long=0, margin_short=0)//, initial_capital = 10000, default_qty_type = strategy.fixed) //, commission_type = strategy.commission.percent, commission_value = 0.075)
// ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――}
// 🔵 STRATEGY LOGIC
// ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――{
// Inputs
capital = input.int(title = 'Capital $', defval = 1000, step = 1, minval=1, maxval=1000000, group="Risk and Money Management")
risk_per_trade = input.float(title = 'Risk per trade', defval = 2.0, step = 0.1,group="Risk and Money Management")
riskReward = input.float(title = 'Risk:Reward', defval = 1.0, step = 0.1, group="Risk and Money Management")
// Backtest period
testStartYear = input(2025, "Backtest Start Year", group="Backtest Starting period")
testStartMonth = input(1, "Backtest Start Month",group="Backtest Starting period")
testStartDay = input(26, "Backtest Start Day",group="Backtest Starting period")
testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay,0,0)
testPeriod() =>
time >= testPeriodStart
// Variables to store the value of the price when the condition will be met
var entry_price = 0.0
var stop = 0.0
var take1 = 0.0
var entry_amount = 0.0
longCondition = close > open[1]
// Logic of trade execution
if testPeriod()
if longCondition and strategy.position_size == 0 or (strategy.position_size == 0)[1]
entry_price := open
long_stop_prc = (entry_price - low[1]) / entry_price
long_stop_price = entry_price - (entry_price - low[1])
long_tp1_prc = long_stop_prc * riskReward
long_tp1_price = entry_price * (1 + (long_stop_prc * riskReward))
stop := long_stop_price
take1 := long_tp1_price
entry_amount := math.round(math.abs((capital * (risk_per_trade/100)) / long_stop_prc))
if longCondition and strategy.position_size ==0
strategy.entry('Long', strategy.long, qty = entry_amount )
if strategy.position_size > 0
strategy.exit(id = 'Long', from_entry = 'Long', limit = take1, stop=stop)
// Visual representation of your strategy
plot(strategy.position_size > 0 ? stop : na, style = plot.style_linebr, color = color.red, title = 'SL Long')
plot(strategy.position_size > 0 ? take1 : na, style = plot.style_linebr, color = color.green, title = 'TP1 Long')
// ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――}
// 🔵 WUNDERTRADING EXECUTION
// ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――{
// Comment inputs
enter_Long_Comment = input.string(defval = "CHANGE-THIS-ENTER-LONG-COMMENT", tooltip = "Your personal Enter signal from WunderTrading bot settings", group="Comment to WunderTrading Bot")
exit_Long_Comment = input.string(defval = "CHANGE-THIS-EXIT-LONG-COMMENT", tooltip = "Your personal Enter signal from WunderTrading bot settings", group="Comment to WunderTrading Bot")
enter_Short_Comment = input.string(defval = "CHANGE-THIS-ENTER-SHORT-COMMENT", tooltip = "Your personal Enter signal from WunderTrading bot settings", group="Comment to WunderTrading Bot")
exit_Short_Comment = input.string(defval = "CHANGE-THIS-EXIT-SHORT-COMMENT", tooltip = "Your personal Enter signal from WunderTrading bot settings", group="Comment to WunderTrading Bot")
exit_All_Comment = input.string(defval = "CHANGE-THIS-EXIT-ALL-COMMENT", tooltip = "Your personal Enter signal from WunderTrading bot settings", group="Comment to WunderTrading Bot")
// json custom alerts signal bot ----------------------------------------------------------------------------------------
// str : str
styleToJson(name, value) =>
'"' + str.tostring(name) + '"' + ': ' + '"' + str.tostring(value) + '"'
// str : int
styleToJson_num(name, value) =>
'"' + str.tostring(name) + '"' + ': ' + (na(value) ? '"NaN"' : str.tostring(value))
styleToJson_takeProfits(priceDeviation, portfolio) =>
'{' + styleToJson_num("price", priceDeviation) + ',' + styleToJson_num("portfolio", portfolio) + '}'
conditions_for_signal(comment) =>
alert_text = array.new_string()
// SETTINGS PARAMS
// Entry cooment code
entry_comment = '"code": ' + '"' + str.tostring(comment) + '"'
array.push(alert_text, entry_comment)
// Entry Parameters
order_type = styleToJson("orderType", "market")
amount_per_trade_type = styleToJson("amountPerTradeType", "quote")
amount_per_trade = styleToJson_num("amountPerTrade", entry_amount)
leverage = styleToJson_num("leverage", 1)
array.push(alert_text, order_type)
array.push(alert_text, amount_per_trade_type)
array.push(alert_text, amount_per_trade)
array.push(alert_text, leverage)
// Parameters for Limit Orders Only
// time_in_force = styleToJson_num("timeInForce", 1)
// price_deviation = '"priceDeviation": {' +
// styleToJson_num("deviation", 0.01) + ',' +
// styleToJson("deviationType", "percents") + ',' +
// styleToJson("priceType", "last") + '}'
// array.push(alert_text, time_in_force)
// array.push(alert_text, price_deviation)
// Parameters for Best Bid/Ask Limit Orders Only (set "orderType" above to "best_bid_ask_limit")
// order_type_settings = '"orderTypeSettings": {' +
// '"postOnly": false' + ',' +
// styleToJson_num("maxAttempts", 5) + ',' +
// styleToJson("afterMaxAttemptsReached", "cancel") + ',' +
// styleToJson_num("maxChaseDistance", 0.05) + '}'
// array.push(alert_text, order_type_settings)
// Take Profit
take_profits = '"takeProfits": [' +
// styleToJson_takeProfits(take1, 0.5) + ',' +
styleToJson_takeProfits(take1, 1) + ']'
array.push(alert_text, take_profits)
// take_profit_order_type = styleToJson("takeProfitOrderType", "best_bid_ask_limit")
// array.push(alert_text, take_profit_order_type)
// Stop Loss
stop_loss = '"stopLoss": {' + styleToJson_num("price", stop) + '}'
array.push(alert_text, stop_loss)
// stop_loss_order_type = styleToJson("stopLossOrderType", "best_bid_ask_limit")
// array.push(alert_text, stop_loss_order_type)
// Move Stop Loss to breakeven
// move_to_breakeven = '"moveToBreakeven": {' + styleToJson_num("activationPriceDeviation", 0.05) + '}'
// array.push(alert_text, move_to_breakeven)
// Trailing Stop
// trailing_stop = '"trailingStop": {' +
// styleToJson_num("activation", 0.05) + ',' +
// styleToJson_num("execute", 0.005) + '}'
// array.push(alert_text, trailing_stop)
// Additional Parameters
// keep_position_open = styleToJson("keepPositionOpen", true)
reduce_only = styleToJson("reduceOnly", true)
place_conditional_orders = styleToJson("placeConditionalOrdersOnExchange", false)
// array.push(alert_text, keep_position_open)
array.push(alert_text, reduce_only)
array.push(alert_text, place_conditional_orders)
// DCA Parameters
// dca = '"dca": {' +
// styleToJson_num("extraOrderCount", 10) + ',' +
// styleToJson_num("extraOrderDeviation", 0.005) + ',' +
// styleToJson_num("extraOrderVolumeMultiplier", 1.1) + ',' +
// styleToJson_num("extraOrderDeviationMultiplier", 1.1) + ',' +
// styleToJson("takeProfitsBasedOn", "average_price") + ',' +
// styleToJson("stopLossBasedOn", "average_price") + '}'
// array.push(alert_text, dca)
// Pass Parameters
messageJson = "{" + array.join(alert_text, ', ') + "}"
//
// ALERT SIGNALS
signal_alert_long = conditions_for_signal(enter_Long_Comment)
signal_alert_short = conditions_for_signal(enter_Short_Comment)
signal_aler_exit_long = conditions_for_signal(exit_Long_Comment)
signal_aler_exit_short = conditions_for_signal(exit_Short_Comment)
signal_aler_exit_all = conditions_for_signal(exit_All_Comment)
if longCondition and strategy.position_size == 0
alert(signal_alert_long, alert.freq_once_per_bar_close)
策略逻辑部分代表您希望策略如何运行的自定义方法。在这里,您可以定义任何设想中的策略或条件。例如,当两条简单移动平均线交叉时触发入场,或当 RSI 显示超买或超卖状态时触发入场。
WunderTrading 执行部分提供了将提醒转换为 JSON 格式所需的代码,并负责将这些提醒发送到 WunderTrading,以实现自动化交易执行。
可通过 JSON 格式传递的单交易对机器人变量
入场备注代码
字段 | 必填 | 类型 | 说明 |
code | 是 | string | 这是入场备注代码,用于从您的备注中传递做多入场或做空入场信号。 |
入场参数
字段 | 必填 | 类型 | 说明 |
orderType | 是 | string | 可选值:"market"、"limit"、"best_bid_ask_limit" |
amountPerTradeType | 是 | string | 可选值:"quote"、"percents"、"contracts"、"base" |
amountPerTrade | 是 | num | 范围:(0; +Inf) |
leverage | 否 | num | 范围:[1, 125] |
仅限限价单的参数
字段 | 必填 | 类型 | 说明 |
timeInForce | 否 | num | 范围:[5, 20160] |
price | 否 | num | 范围:(0; +Inf) |
priceDeviation | 否 | object | 价格偏差设置。 |
deviation | 是 | num | 范围: |
deviationType | 否 | string | 可选值:"percents" |
priceType | 否 | string | 可选值:"bid"、"ask"、"last" |
仅限最优买卖价限价单的参数
当设置 "orderType": "best_bid_ask_limit" 时,入场订单将以限价单形式挂在最优买价(做多)或最优卖价(做空)。如果 40 秒内未成交,订单将被撤销并按新的最优价格重新挂出,直至成交或达到 maxAttempts 上限。如果订单仅部分成交,剩余部分将在 40 秒后以市价单提交。详情请参阅最优买卖价限价单如何运作。
字段 | 必填 | 类型 | 说明 |
orderTypeSettings | 否 | object | 最优买卖价限价单入场的设置。仅在 |
postOnly | 否 | bool | 默认值:false 仅以挂单方式下单(只做Maker)。如果订单会以吃单方式立即成交,交易所将拒绝该订单,机器人会按新的最优价格重试。每次重试消耗一次尝试次数。 |
maxAttempts | 否 | num | 范围:[1, 5] 默认值:5 订单在最优买卖价挂出或重新挂出的次数。每次尝试持续 40 秒。 |
afterMaxAttemptsReached | 否 | string | 可选值:"market"、"cancel" 默认值:"cancel" 所有尝试次数用尽后的处理方式:"market" 表示以市价单成交剩余部分(未成交转市价);"cancel" 表示撤销订单。 |
maxChaseDistance | 否 | num | 范围:[0.0001, 0.05] 订单相对首次挂单价格可跟随市场的最大距离,以 |
重要提示:最优买卖价限价单入场不保证成交。在默认设置 "afterMaxAttemptsReached": "cancel" 下,当尝试次数用尽或价格超出 maxChaseDistance 时,订单将被撤销,仓位可能无法开立。如果必须确保在任何情况下都能开仓,请使用 "market"。
包含最优买卖价限价单入场、止盈和止损的 JSON 消息示例:
{
"code": "CHANGE-THIS-ENTER-LONG-COMMENT",
"orderType": "best_bid_ask_limit",
"orderTypeSettings": {
"postOnly": true,
"maxAttempts": 3,
"afterMaxAttemptsReached": "market",
"maxChaseDistance": 0.01
},
"amountPerTradeType": "quote",
"amountPerTrade": 100,
"takeProfits": [{"priceDeviation": 0.02, "portfolio": 1}],
"takeProfitOrderType": "best_bid_ask_limit",
"stopLoss": {"priceDeviation": 0.01},
"stopLossOrderType": "market"
}注意:对于启动条件为 TradingView 策略 的信号机器人,最优买卖价限价单仅支持用于入场。
止盈参数
字段 | 必填 | 类型 | 说明 |
takeProfits | 否 | array | 数组值类型:object |
price | 否 | num | 范围:(0; +Inf) |
priceDeviation | 否 | num | 范围: |
portfolio | 否 | num|null | 范围:(0; 1] |
takeProfitOrderType | 否 | string | 可选值:"market"、"best_bid_ask_limit" 默认值:"market" 在止盈时用于平仓的订单类型。"best_bid_ask_limit"(条件限价单)会以限价单形式在最优买卖价挂出出场订单,并持续重新挂单,即使价格已越过您的止盈价。出场订单从不使用只做Maker。 |
止损参数
字段 | 必填 | 类型 | 说明 |
stopLoss | 否 | object | 可选值:"price" 或 "priceDeviation" |
price | 是 | num | 范围:(0; +Inf) |
priceDeviation | 是 | num | 范围: |
stopLossOrderType | 否 | string | 可选值:"market"、"best_bid_ask_limit" 默认值:"market" 在止损时用于平仓的订单类型。使用 "best_bid_ask_limit"(条件限价单)时,止损需要等待订单簿成交,因此在行情快速波动时,实际平仓价格可能远超您的止损价。如需全面保护,"market" 是更安全的选择。 不适用于追踪止损和将止损移动至保本,二者始终使用市价单。 |
将止损移动至保本
字段 | 必填 | 类型 | 说明 |
activationPrice | 是 | num | 范围:(0; +Inf) |
executePrice | 否 | num|null | 范围:(0; +Inf) |
activationPriceDeviation | 是 | num | 范围: |
executePriceDeviation | 是 | num | 范围:(-1; activationPriceDeviation) |
追踪止损
字段 | 必填 | 类型 | 说明 |
activation | 是 | num | 范围: |
execute | 是 | num | 范围: |
其他参数
字段 | 必填 | 类型 | 说明 |
keepPositionOpen | 否 | bool | 默认值:true |
reduceOnly | 否 | bool | 默认值:true |
placeConditionalOrdersOnExchange | 否 | bool | 默认值:false |
定投参数
字段 | 必填 | 类型 | 说明 |
dca | 否 | object |
|
extraOrderCount | 是 | num | 范围:[1; 30] |
extraOrderDeviation | 是 | num | 范围:[0.001; 0.2] |
extraOrderVolumeMultiplier | 是 | num | 范围:[1; 10] |
extraOrderDeviationMultiplier | 否 | num | 为数字时:范围 [1; 10] |
takeProfitsBasedOn | 否 | string | 可选值:"average_price"、"entry_order" |
stopLossBasedOn | 否 | string | 可选值:"average_price"、"entry_order" |
如何在 TradingView 中创建提醒
首先点击“更新到图表”按钮更新策略,然后点击“提醒”按钮创建提醒。
现在开始设置提醒:
选择策略 - 在条件下拉菜单中选择您的策略。
启用提醒函数调用 - 选择“仅 alert() 函数调用”,以根据脚本条件触发提醒。
前往通知标签页 - 进入通知部分。
粘贴 Webhook URL - 插入 WunderTrading 提供的 Webhook URL。
点击创建 - 完成提醒设置,以实现自动化交易执行。
完成!等待入场提醒触发,并检查一切是否正常。您可以进入信号机器人列表,点击所创建信号机器人的“日志”按钮进行查看。在那里,您可以确认提醒是否已成功执行且没有错误。最后,前往仓位标签页查看已开仓仓位。
机器人设置确认
设置好机器人提醒后,您将看到确认页面,表示机器人已成功配置。此时,机器人会等待提醒触发,并自动开仓。
如果您希望立即入场,请点击“立即入场”,并选择与该机器人关联的做多或做空交易。
您可以随时编辑机器人设置,或在仪表盘中查看提醒消息。










