В трейдинге акцент часто смещён в сторону поиска идеальных входов, тогда как стратегии выхода остаются в тени. Между тем именно выходы определяют соотношение прибыли и убытков. Раздельное тестирование помогает изолировать входы и оценить, как разные методы управления позицией влияют на результат. В этой статье входы будут выполняться с 50% вероятностью — это устраняет фактор предсказуемости и позволяет объективно сравнивать эффективность различных стратегий выхода.
В статье тестирую две стратегии трейлинг-стопов для Московской биржи на фьючерсном контракте USD/RUB (Si) на часовом таймфрейме, используя язык Pine Script в TradingView.
Цель исследования и описание общего подхода
Главный вопрос исследования — какой метод трейлинг-стопа показывает лучшие результаты при одинаковых входах: фиксированный процентный или адаптивный ATR? Простой трейлинг-стоп строго ограничивает риск, но полностью игнорирует рыночную волатильность. В отличие от него, ATR-трейлинг, основанный на значении среднего истинного диапазона, автоматически подстраивается под текущие колебания рынка и способен удерживать прибыль в затяжных трендах.
Цель тестирования — проверить, действительно ли адаптивный подход оказывается эффективнее на волатильном рынке фьючерса Si, благодаря способности гибко реагировать на изменчивую динамику цены.
Для сравнения двух методов применяются одни и те же условия: используется фьючерсный контракт Si (USD/RUB) с часовым таймфреймом, комиссия составляет 0,04% на сделку, учитывается проскальзывание в размере 10 тиков, а торговля ведётся одним контрактом.
Обзор первой стратегии: простой трейлинг-стоп
Стратегия использует фиксированный процентный трейлинг-стоп. После случайного входа (лонг или шорт с 50% вероятностью каждые 24 часа) стоп-уровень постоянно пересчитывается для лонга: от максимальной достигнутой цены, для шорта: от минимальной достигнутой цены.
Основная идея в коде:
// Установка начального стопа при входе trailingStopLong := close * (1 - trailingStopOffset / 100) // Обновление стопа для лонга highestLongPrice := math.max(highestLongPrice, close) trailingStopLong := highestLongPrice * (1 - trailingStopOffset / 100)

Преимущества:
-
Простота реализации и понимания
-
Предсказуемый фиксированный риск
-
Хорошо работает в трендах
Недостатки:
-
Не адаптируется к волатильности рынка
-
Может преждевременно закрывать позиции при повышенной волатильности
-
Требует ручной настройки параметра под каждый инструмент
Полный код ниже (вся коллекция на GitHub):
// === Описание стратегии === // Эта стратегия основана на случайных входах в рынок с использованием простого трейлинг-стопа для управления рисками. // Основные особенности: // 1. Случайные входы: Стратегия совершает входы в длинные (Long) или короткие (Short) позиции с заданной вероятностью // каждые N баров. Частота входов регулируется параметром "Частота входов (каждые N баров)". // 2. Генерация направлений: Для определения направления входа используется генератор случайных чисел. // Если случайное значение меньше установленной вероятности входа в Long, открывается длинная позиция, иначе — короткая. // 3. Простой трейлинг-стоп: После входа в позицию устанавливается трейлинг-стоп на заданном расстоянии в процентах от цены. // Трейлинг-стоп обновляется при движении цены в благоприятную сторону, защищая прибыль и минимизируя убытки. // 4. Гибкость настроек: Пользователь может задать вероятность входа в Long, частоту входов и размер трейлинг-стопа. // 5. Отображение трейлинг-стопа: На графике отображаются уровни трейлинг-стопов для активных позиций, что позволяет // визуально контролировать ход торговли. // Михаил Шардин, https://shardin.name/?utm_source=tradingview //@version=6 strategy("Случайные входы + простой трейлинг стоп", overlay=true, commission_type=strategy.commission.percent, // Тип комиссии: процент commission_value=0.04, // Значение комиссии: 0.04% slippage=10, // Проскальзывание в тиках process_orders_on_close=true, default_qty_type=strategy.fixed, // Фиксированный размер позиции default_qty_value=1, // 1 контракт/лот initial_capital=500000) // Начальный капитал // === Параметры === entryFrequency = input.int(24, "Частота входов (каждые N баров)", minval=1) longProbability = input.int(50, "Вероятность входа в Long (%)", minval=0, maxval=100) trailingStopOffset = input.float(1.5, "Отступ трейлинг-стопа (%)", step=0.1, minval=0.1) // === Сигнал на вход === entrySignal = bar_index % entryFrequency == 0 and bar_index > 0 // Игнорируем первый бар // === Гарантированный рандом === randValue = math.random(0, 100) // Генерация случайного числа от 0 до 100 randDirection = randValue < longProbability ? 1 : -1 // 1 = Long, -1 = Short // === Переменные для трейлинг-стопов === var float highestLongPrice = na var float lowestShortPrice = na var float trailingStopLong = na var float trailingStopShort = na // === Условие входа === longCondition = entrySignal and randDirection == 1 and strategy.position_size == 0 shortCondition = entrySignal and randDirection == -1 and strategy.position_size == 0 // === Вход в позиции === if (longCondition) strategy.entry("Long", strategy.long) highestLongPrice := close trailingStopLong := close * (1 - trailingStopOffset / 100) if (shortCondition) strategy.entry("Short", strategy.short) lowestShortPrice := close trailingStopShort := close * (1 + trailingStopOffset / 100) // === Обновление трейлинг-стопа === if (strategy.position_size > 0) // Если открыта длинная позиция highestLongPrice := math.max(highestLongPrice, close) trailingStopLong := highestLongPrice * (1 - trailingStopOffset / 100) if (close <= trailingStopLong) // Закрытие по трейлинг-стопу strategy.close("Long") if (strategy.position_size < 0) // Если открыта короткая позиция lowestShortPrice := math.min(lowestShortPrice, close) trailingStopShort := lowestShortPrice * (1 + trailingStopOffset / 100) if (close >= trailingStopShort) // Закрытие по трейлинг-стопу strategy.close("Short") // === Отображение трейлинг-стопов === plot(strategy.position_size > 0 ? trailingStopLong : na, title="Лонг трейлинг-стоп", color=color.green, linewidth=2, style=plot.style_linebr) plot(strategy.position_size < 0 ? trailingStopShort : na, title="Шорт трейлинг-стоп", color=color.red, linewidth=2, style=plot.style_linebr) // === Информация для отладки === if (barstate.islast) label.new(bar_index, high, "Текущий индекс бара: " + str.tostring(bar_index) + "\nСледующая сделка через: " + str.tostring(entryFrequency - (bar_index % entryFrequency)) + " баров" + "\nНаправление следующей: " + (randDirection == 1 ? "LONG" : "SHORT") + "\nТекущая позиция: " + (strategy.position_size > 0 ? "LONG" : strategy.position_size < 0 ? "SHORT" : "НЕТ"), color=color.blue, style=label.style_label_down)
Обзор второй стратегии: ATR трейлинг-стоп
ATR-трейлинг динамически адаптируется к рыночной волатильности. При каждом входе (лонг/шорт с 50% вероятностью) стоп рассчитывается для лонга: цена закрытия - (ATR(14) × 4) для шорта: цена закрытия + (ATR(14) × 4).
Адаптивный метод выхода: трейлинг-стоп на основе ATR учитывает волатильность инструмента. При росте колебаний стоп отодвигается дальше, при затухании — приближается. Это помогает держать тренд и снижать количество ложных выходов на «шуме».
Основная идея в коде:
// Расчет ATR atr = ta.atr(atrPeriod) // Установка ATR-стопа trailingStopLong := close - atr * atrMultiplier trailingStopShort := close + atr * atrMultiplier // Адаптивное обновление trailingStopLong := math.max(trailingStopLong, close - atr * atrMultiplier)

Преимущества:
-
Автоматическая подстройка под текущую волатильность
-
Шире стопы при высокой волатильности (меньше ложных выходов)
-
Уже стопы при спокойном рынке (лучше защищает прибыль)
Недостатки:
-
Сложнее в настройке (нужно подбирать период и множитель)
-
Может давать слишком широкие стопы в периоды экстремальной волатильности
Полный код ниже (вся коллекция на GitHub):
// === Описание стратегии === // Эта стратегия основана на случайных входах в рынок с использованием трейлинг-стопов для управления рисками. // Основные особенности: // 1. Случайные входы: Стратегия генерирует случайные сигналы для входа в длинные (Long) или короткие (Short) позиции // с заданной вероятностью. Частота входов регулируется параметром "Частота входов (каждые N баров)". // 2. Трейлинг-стоп: Для управления рисками используется трейлинг-стоп, который рассчитывается на основе ATR (Average True Range) // и заданного множителя. Трейлинг-стоп автоматически обновляется при движении цены в пользу позиции. // 3. Гибкость настроек: Пользователь может настроить вероятность входа в длинную позицию, период ATR и множитель для трейлинг-стопа. // Михаил Шардин, https://shardin.name/?utm_source=tradingview //@version=6 strategy("Случайные входы + ATR трейлинг стоп", overlay=true, commission_type=strategy.commission.percent, // Тип комиссии: процент commission_value=0.04, // Значение комиссии: 0.04% slippage=10, // Проскальзывание в тиках process_orders_on_close=true, default_qty_type=strategy.fixed, // Фиксированный размер позиции default_qty_value=1, // 1 контракт/лот initial_capital=500000) // Начальный капитал // === Параметры === entryFrequency = input.int(24, "Частота входов (каждые N баров)", minval=1) longProbability = input.int(50, "Вероятность входа в Long (%)", minval=0, maxval=100) atrPeriod = input.int(14, "Период ATR") atrMultiplier = input.float(4.0, "Множитель ATR", step=0.1, minval=0.1) // === ATR для трейлинг-стопов === atr = ta.atr(atrPeriod) // === Сигнал на вход === entrySignal = bar_index % entryFrequency == 0 and bar_index > 0 // Игнорируем первый бар // === Гарантированный рандом === randValue = math.random(0, 100) // Генерация случайного числа от 0 до 100 randDirection = randValue < longProbability ? 1 : -1 // 1 = Long, -1 = Short // === Условие входа === longCondition = entrySignal and randDirection == 1 and strategy.position_size == 0 shortCondition = entrySignal and randDirection == -1 and strategy.position_size == 0 // === Переменные для трейлинг-стопов === var float trailingStopLong = na var float trailingStopShort = na // === Вход в позиции === if (longCondition) strategy.entry("Long", strategy.long) trailingStopLong := close - atr * atrMultiplier // label.new(bar_index, high, "Открыт LONG", color=color.green, style=label.style_label_down, textcolor=color.white) if (shortCondition) strategy.entry("Short", strategy.short) trailingStopShort := close + atr * atrMultiplier // label.new(bar_index, low, "Открыт SHORT", color=color.red, style=label.style_label_up, textcolor=color.white) // === Обновление трейлинг-стопа === if (strategy.position_size > 0) // Если открыта длинная позиция trailingStopLong := math.max(trailingStopLong, close - atr * atrMultiplier) if (close <= trailingStopLong) // Закрытие по трейлинг-стопу strategy.close("Long") // label.new(bar_index, high, "Закрыт LONG", color=color.green, style=label.style_label_down, textcolor=color.white) if (strategy.position_size < 0) // Если открыта короткая позиция trailingStopShort := math.min(trailingStopShort, close + atr * atrMultiplier) if (close >= trailingStopShort) // Закрытие по трейлинг-стопу strategy.close("Short") // label.new(bar_index, low, "Закрыт SHORT", color=color.red, style=label.style_label_up, textcolor=color.white) // === Отображение трейлинг-стопов === plot(strategy.position_size > 0 ? trailingStopLong : na, title="Лонг трейлинг-стоп", color=color.green, linewidth=2, style=plot.style_linebr) plot(strategy.position_size < 0 ? trailingStopShort : na, title="Шорт трейлинг-стоп", color=color.red, linewidth=2, style=plot.style_linebr) // === Информация для отладки === if (barstate.islast) label.new(bar_index, high, "Текущий индекс бара: " + str.tostring(bar_index) + "\nСледующая сделка через: " + str.tostring(entryFrequency - (bar_index % entryFrequency)) + " баров" + "\nНаправление следующей: " + (randDirection == 1 ? "LONG" : "SHORT") + "\nТекущая позиция: " + (strategy.position_size > 0 ? "LONG" : strategy.position_size < 0 ? "SHORT" : "НЕТ"), color=color.blue, style=label.style_label_down)
Методика тестирования
Тестирование проводилось на часовом таймфрейме фьючерса Si (USD/RUB) за период с 29.12.2023 по 21.04.2025. Это 480 дней или 11 520 часовых баров. Оценивались ключевые метрики:
-
Общие ПР/УБ: Итоговый финансовый результат стратегии выхода.
-
Макс. просадка средств: Максимальное падение эквити от пика, показатель риска.
-
Всего сделок: Общее количество для статистической значимости.
-
Прибыльные сделки, %: Доля выигрышных выходов.
-
Фактор прибыли: Отношение валовой прибыли к валовому убытку (эффективность).
Поскольку входы случайны (50/50), различия в этих показателях напрямую демонстрируют эффективность именно стратегии выхода. Это позволяет объективно сравнить, какой подход — жесткий процентный стоп или адаптивный ATR — лучше управляет позицией в заданных условиях.
Результаты и сравнение
Сравним ключевые показатели обеих стратегий выхода при идентичных случайных входах на фьючерсе Si за период ~16 месяцев:
|
Метрика |
Простой трейлинг (1.5%) |
ATR трейлинг (4xATR) |
|---|---|---|
|
Общие ПР/УБ |
-2.79% |
+6.43% |
|
Макс. просадка средств |
5.00% |
1.03% |
|
Всего сделок |
62 |
71 |
|
Прибыльные сделки, % |
30.65% |
50.70% |
|
Фактор прибыли |
0.705 |
2.305 |
Результаты однозначно показывают преимущество адаптивного ATR-трейлинга на волатильном фьючерсе Si.
-
Где ATR-выход был лучше: практически по всем параметрам. ATR-стоп не только принёс прибыль (+6.43%) против убытка простого стопа (-2.79%), но и показал в 5 раз меньшую максимальную просадку (1.03% vs 5.00%). Значительно выше процент прибыльных сделок (50.70% vs 30.65%) и фактор прибыли (2.305 vs 0.705), что говорит о лучшем удержании прибыльных позиций и контроле убытков.
-
Где выигрывает простой трейлинг: в данном тесте – нигде. Его единственное преимущество простота – не компенсировало неспособность адаптироваться.
-
Реакция на волатильность: фиксированный стоп в 1.5%, вероятно, был слишком узким для волатильности Si, приводя к частым преждевременным выходам. ATR-стоп, динамически расширяясь и сужаясь вместе с рынком, позволил эффективнее «пересиживать» локальные коррекции и удерживать трендовые движения, что и отразилось на итоговой прибыли и просадке.
Выводы
Раздельное тестирование выходов — ценный метод анализа, так как изолирует влияние стратегии управления позицией от качества входов, позволяя объективно оценить её эффективность.
Как показали результаты для волатильного фьючерса Si, ATR-трейлинг предпочтительнее в условиях высокой изменчивости рынка. Его способность адаптивно расширять и сужать стоп помогает удерживать тренды и фильтровать рыночный шум, что критично для улучшения итогового ПР/УБ.
Однако простота фиксированного стопа может быть привлекательной. Это наводит на мысль о потенциале гибридных подходов, сочетающих преимущества обоих методов, что заслуживает отдельного исследования.
Автор: Михаил Шардин
🔗 Моя онлайн-визитка
📢 Telegram «Умный Дом Инвестора»
22 апреля 2025 г.
ссылка на оригинал статьи https://habr.com/ru/articles/902334/
Добавить комментарий