Pine Script, представленный в данной статье, предназначен для динамического преобразования параметров стратегии в формат JSON, что позволяет легко интегрировать его с ботами WunderTrading. Скрипт дает возможность настраивать и изменять ключевые переменные торговли, такие как Take Profit, Stop Loss, Trailing Stop и другие, для каждой отдельной сделки.
Такая гибкость позволяет уникально конфигурировать каждую сделку в соответствии с ее конкретными требованиями, делая стратегию максимально адаптивной к изменяющимся рыночным условиям и индивидуальным торговым предпочтениям.
Давайте разберемся во всем шаг за шагом и изучим возможные варианты.
Как создать сигнального бота с использованием JSON
Чтобы создать сигнального бота, перейдите на вкладку Сигнальный бот в левом меню и выберите Создать бота.
После открытия окна настроек Сигнального бота вы можете настроить параметры в соответствии с вашими требованиями.
Общие настройки
Начните с указания названия бота.
Условие запуска бота – источник сигнала. В настоящее время JSON совместим с TradingView Indicator, API-запросами и Other – для других инструментов автоматизации, таких как Make, IFTTT, Zapier, n8n и т. д. Доступные функции зависят от источника.
После включения JSON раздел алертов обновится. В нём будет представлена базовая рабочая стратегия, которую можно скопировать в Pine Editor на TradingView, чтобы разобраться в принципах работы кода. Рассмотрим его подробнее.
Выберите биржу и соответствующий API.
Можно выбрать до 50 API одновременно, объединенных в единую стратегию.Чтобы выбрать демо-аккаунт, включите режим DEMO.
Выберите торговую пару из списка для каждого API либо введите её напрямую в поле поиска.
Расширенные настройки позволяют отдельно задать кредитное плечо для каждой пары, а также API-множители. Это даёт больше гибкости при управлении несколькими API в рамках одного бота.Для каждого профиля API можно выбрать до 10 различных пар. Когда сигнал инициирует сделку, для каждой выбранной пары будет создана отдельная сделка.
Выберите желаемый таймфрейм. Этот параметр влияет только на название комментариев в сигналах и фильтрацию списка ботов по таймфрейму. Он не влияет на таймфрейм в TradingView.
Функция Множественные входы позволяет постепенно увеличивать позицию при получении нескольких последовательных сигналов на вход. Включите, если хотите одновременно иметь более одной открытой позиции по каждой торговой паре.
Свинг-трейдинг позволяет менять направление сделки, используя только сигналы Enter Short и Enter Long. При включении этой функции комментарии к алертам объединяются в пять категорий: Enter-Long, Enter-Short, Exit-All, Partial Exit Long и Partial Exit Short. Функция доступна только для фьючерсных рынков.
🔵 Пример стратегии на Pine Script для TradingView
🔵 Пример стратегии на Pine Script для TradingView
Вы можете напрямую скопировать и вставить этот код в свой 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)
// Take Profit
take_profits = '"takeProfits": [' +
// styleToJson_takeProfits(take1, 0.5) + ',' +
styleToJson_takeProfits(take1, 1) + ']'
array.push(alert_text, take_profits)
// Stop Loss
stop_loss = '"stopLoss": {' + styleToJson_num("price", stop) + '}'
array.push(alert_text, stop_loss)
// 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)
Код состоит из двух основных частей: STRATEGY LOGIC (ЛОГИКА СТРАТЕГИИ) и WUNDERTRADING EXECUTION (ИСПОЛНЕНИЕ WUNDERTRADING).
Раздел логики стратегии представляет ваш собственный подход к тому, как должна функционировать стратегия. Здесь вы можете определить любую стратегию или условия, которые считаете нужными. Например, вход может срабатывать при пересечении двух простых скользящих средних или когда RSI указывает на перекупленность или перепроданность.
Раздел исполнения WunderTrading фокусируется на предоставлении кода, который преобразует ваши алерты в формат JSON и отвечает за их отправку в WunderTrading.
Переменные бота для одной торговой пары, передаваемые в JSON-формате
Код комментария для входа
Поле | Обязательно | Тип | Описание |
code | True | string | Код комментария для входа, передающий сигнал Enter Long или Enter Short из ваших комментариев. |
Параметры входа
Поле | Обязательно | Тип | Описание |
orderType | True | string | Возможные значения: "market", "limit". |
amountPerTradeType | True | string | Возможные значения: "quote", "percents", "contracts", "base".
|
amountPerTrade | True | num | Диапазон: (0; +Inf).
|
leverage | False | num | Диапазон: [1, 125]. По умолчанию: 1. |
Параметры только для лимитных ордеров
Поле | Обязательно | Тип | Описание |
timeInForce | False | num | Диапазон: [5, 20160]. По умолчанию: 5.
Время действия лимитного ордера в минутах (обязательно для "limit" ордеров). |
price | False | num | Диапазон: (0; +Inf). Фиксированное значение цены. Обязательно для "limit" ордеров, если priceDeviation не задан. |
priceDeviation | False | object | Настройки отклонения цены Обязательно для "limit" ордеров, если "price" не задан. |
deviation | True | num | Диапазон:
Значение отклонения цены |
deviationType | False | string | Возможное значение: "percents". |
priceType | False | string | Возможные значения: "bid", "ask", "last". По умолчанию: "last".
Значение типа цены, от которого следует отклоняться. |
Параметры Take Profit
Поле | Обязательно | Тип | Описание |
takeProfits | False | array | Массив объектов с параметрами Take Profit. |
price | False | num | Диапазон: (0; +Inf).
Фиксированное значение цены (только для ботов с одной торговой парой). |
priceDeviation | False | num | Диапазон:
Отклонение цены в процентах (например, 10% → 0.1). |
portfolio | False | num | null | Диапазон: (0; 1]. |
Параметры Stop Loss
Поле | Обязательно | Тип | Описание |
stopLoss | False | object | Возможные значения: "price" или "priceDeviation". |
price | True | num | Диапазон: (0; +Inf).
Фиксированное значение цены (для ботов с одной торговой парой). |
priceDeviation | True | num | Диапазон:
Отклонение цены в процентах (например, 10% → 0.1). |
Перенос Stop Loss в безубыток
Поле | Обязательно | Тип | Описание |
activationPrice | True | num | Диапазон: (0; +Inf)
Фиксированное значение цены |
executePrice | False | num|null | Диапазон: (0; +Inf) |
activationPriceDeviation | True | num | Диапазон:
Отклонение цены в процентах (например, 10% → 0.1). |
executePriceDeviation | True | num | Диапазон: (-1; activationPriceDeviation) |
Trailing Stop
Поле | Обязательно | Тип | Описание |
activation | True | num | Диапазон:
Отклонение цены в процентах (например, 10% → 0.1). |
execute | True | num | Диапазон:
Отклонение цены в процентах (например, 10% → 0.1). |
Дополнительные параметры
Поле | Обязательно | Тип | Описание |
keepPositionOpen | False | bool | По умолчанию: true.
Оставлять позицию открытой (влияет только на спотовые стратегии без Take Profit, Stop Loss, Move to Breakeven, Trailing Stop). |
reduceOnly | False | bool | По умолчанию: true.
Уменьшать позиции только при выходе. |
placeConditionalOrdersOnExchange | False | bool | По умолчанию: false.
Размещение условных ордеров на бирже (частично поддерживается, игнорируется, если включен DCA). |
Параметры DCA
Поле | Обязательно | Тип | Описание |
dca | False | object | Параметры усреднения (DCA). |
extraOrderCount | True | num | Диапазон: [1; 30].
Сумма ордеров входа, включая первоначальный ордер и дополнительные DCA-ордера (например, 5 означает 1 вход + 4 DCA ордера). |
extraOrderDeviation | True | num | Диапазон: [0.001; 0.2].
Отклонение цены для DCA ордеров. |
extraOrderVolumeMultiplier | True | num | Диапазон: [1; 10].
Множитель объема для дополнительных DCA ордеров. |
extraOrderDeviationMultiplier | False | num | Диапазон: [1; 10].
По умолчанию: null. Множитель отклонения цены для DCA ордеров. |
takeProfitsBasedOn | False | string | Возможные значения: "average_price", "entry_order". По умолчанию: "average_price".
Основа для расчета Take Profit. |
stopLossBasedOn | False | string | Возможные значения: "average_price", "entry_order". По умолчанию: "entry_order".
Основа для расчета Stop Loss. |
Как создать алерт в TradingView
Сначала обновите стратегию, нажав кнопку "Update on chart", затем создайте алерт, нажав кнопку "Alert".
Теперь настроим алерт:
Выбор стратегии – В выпадающем списке Condition выберите свою стратегию.
Включение вызовов функций алертов – Выберите "alert() function calls only", чтобы алерты срабатывали на основе условий скрипта.
Переход во вкладку "Notifications" – Откройте раздел "Notifications".
Вставка Webhook URL – Вставьте Webhook URL из WunderTrading.
Создание алерта – Нажмите "Create", чтобы завершить настройку и автоматизировать исполнение сделок.
Вот и все! Теперь остается дождаться входного сигнала и проверить, все ли работает корректно. Для этого перейдите в список сигнальных ботов и нажмите кнопку "Logs" у нужного бота. Здесь вы сможете увидеть, был ли успешно выполнен алерт без ошибок. Затем откройте вкладку "Positions", чтобы просмотреть открытую позицию.
Подтверждение настройки бота
После настройки алертов вы увидите экран подтверждения, указывающий на то, что ваш бот успешно настроен. На этом этапе бот будет ожидать поступления сигнала для автоматического открытия позиции.
Если вы предпочитаете войти в позицию немедленно, нажмите "Enter Position Now", где вы можете выбрать между длинной или короткой сделкой, связанной с этим ботом.
Вы можете в любой момент изменить настройки бота или проверить сообщения алертов в личном кабинете.













