Отвечаю на критику: бэктест линейной регрессии (из S&C 2007 года) на фьючерсах MOEX в 2025. Код и результаты!

Последние две недели я публиковал подборки из рубрики Traders’ Tips журнала Technical Analysis of STOCKS & COMMODITIES за 2001-2005 и 2006-2010 годы. Спасибо за ваши комментарии — от ироничных “опять комиксы?” до вполне серьёзных вопросов о практическом применении и бэктестах. Именно они побудили меня подойти к делу иначе. Подборка систем и индикаторов за 2006-2010 одного старейшего журнала по техническому анализу Вместо очередного обзора я решил сосредоточиться на одной идее: реализовать её на Pine Script для TradingView и протестировать на фьючерсах с Московской Биржи. Кстати, Traders’ Tips — это не отдельное приложение, а рубрика в журнале. Но суть не в этом: её практическая ценность по-прежнему велика. Лучшие системы и индикаторы 2001–2005: подборка из архива классического издания по теханализу В центре внимания — случайно выбранная статья Барбары Стар “Confirming Price Trend” (S&C, декабрь 2007). Почему именно она? Подтверждение тренда остаётся актуальной задачей, а методы вроде линейной регрессии и R² доступны для понимания и применимы на дневных и часовых графиках. В статье — теория этой стратегии, код на Pine Script, результаты тестирования и выводы. Маленький кусок статьи. Легально тут Что такое линейная регрессия и R-squared: простыми словамиПредставьте, что вы едете по дороге. Линейная регрессия — это как прямая трасса, проведённая по данным: она показывает общий курс, игнорируя кочки и повороты. Цена движется вокруг этой «дороги», а наклон линии подсказывает, в какую сторону едем — вверх или вниз.Теперь про R-squared: это как индикатор сигнала Wi-Fi. Если он близок к 1 — цена чётко держится вдоль регрессии, тренд сильный. Если ближе к нулю — «связь» теряется, рынок шумный, направление неясное.Маленький кусок статьи. Легально тут Почему это круче скользящих средних? У регрессии меньше запаздываний и она точнее «схватывает» развороты. А R-squared помогает не гадать — есть тренд или просто случайное движение. Вместе они дают простую, но мощную систему фильтрации шума и подтверждения тренда.Как использовать это в трейдингеНачнём с периода: 10 баров — для поиска коротких импульсов и ранних сигналов, 20 баров — сбалансированный вариант для дневных графиков, 50 баров — для фильтрации шума и работы по тренду. Выбор зависит от стиля торговли и таймфрейма.R-squared помогает определить фазу тренда:его рост с низких уровней (например, с 0.1 до 0.3) часто указывает на начало движения;падение с высоких (например, с 0.6 до 0.3) — признак ослабления и возможного флэта.Ориентиры:для 20 баров значим уровень 0.20;для 10: 0.40;для 50: достаточно 0.08.Наклон линии регрессии (slope) показывает направление:выше нуля — тренд вверх;ниже — вниз.Вместе с R² он позволяет отличить уверенное движение от случайного шума и избегать ложных входов. Бэктест: проверим идею на практикеИнструмент: TradingView и Pine ScriptДля реализации стратегии я выбрал TradingView. Это один из самых доступных инструментов для быстрого прототипирования торговых идей: открыл браузер, вставил код — и сразу увидел результат на графике. Особенно важно, что платформа не требует установки дополнительных библиотек, терминалов и настроек, как это часто бывает с Python или AmiBroker. Всё работает «из коробки», а язык Pine Script — простой и интуитивный, особенно если вы уже знакомы с техническим анализом.К тому же, код можно легко адаптировать и поделиться ссылкой на него, чтобы каждый мог протестировать его самостоятельно — даже без подписки на платные функции. У меня есть реферальная ссылка TradingView: если вы зарегистрируетесь по ней, это немного поддержит меня, а вам будет всё то же самое.Таймфреймы: дневной и часовойЯ протестировал стратегию на двух таймфреймах: дневном и часовом. Почему именно они?Дневной — наиболее стабилен и подходит для анализа крупных движений. Его удобно использовать и тем, кто торгует вручную и не хочет реагировать на каждое движение внутри дня.Часовой — даёт больше сигналов и позволяет точнее отследить динамику внутри тренда.Мне кажется что для частного трейдера эти два масштаба — оптимальный компромисс между частотой сигналов и управляемостью стратегии.Тестируемая логикаВ стратегии используются два ключевых фильтра: наклон линии линейной регрессии и значение R². Условия простые: входим в позицию, если цена «прорывает» линию регрессии, а R² превышает заданный порог и растёт. Выход из позиции осуществляется по трейлинг-стопу, значение которого задаётся в процентах от экстремума.Представленный код — моя интерпретация идеи из статьи Барбары Стар. Он может отличаться от оригинального примера из журнала, но отражает основную логику и добавляет реалистичные параметры торговли, включая комиссии и проскальзывание.Результаты: деньДля дневного графика я включил настройку «Корректировать с учётом изменений контрактов» — такая корректировка убирает ценовые разрывы между контрактами (гэпы), возникающие при переходе от одного фьючерса к другому.Торговля тремя контрактами фьючерсом на доллар/рубль (Si) на Мосбирже с ко

Май 13, 2025 - 10:05
 0
Отвечаю на критику: бэктест линейной регрессии (из S&C 2007 года) на фьючерсах MOEX в 2025. Код и результаты!

Отвечаю на критику: бэктест линейной регрессии (из S&C 2007 года) на фьючерсах MOEX в 2025. Код и результаты!


Последние две недели я публиковал подборки из рубрики Traders’ Tips журнала Technical Analysis of STOCKS & COMMODITIES за 2001-2005 и 2006-2010 годы. Спасибо за ваши комментарии — от ироничных “опять комиксы?” до вполне серьёзных вопросов о практическом применении и бэктестах. Именно они побудили меня подойти к делу иначе.

Подборка систем и индикаторов за 2006-2010 одного старейшего журнала по техническому анализу

Вместо очередного обзора я решил сосредоточиться на одной идее: реализовать её на Pine Script для TradingView и протестировать на фьючерсах с Московской Биржи. Кстати, Traders’ Tips — это не отдельное приложение, а рубрика в журнале. Но суть не в этом: её практическая ценность по-прежнему велика.

Лучшие системы и индикаторы 2001–2005: подборка из архива классического издания по теханализу

В центре внимания — случайно выбранная статья Барбары Стар “Confirming Price Trend” (S&C, декабрь 2007). Почему именно она? Подтверждение тренда остаётся актуальной задачей, а методы вроде линейной регрессии и R² доступны для понимания и применимы на дневных и часовых графиках.

В статье — теория этой стратегии, код на Pine Script, результаты тестирования и выводы.Отвечаю на критику: бэктест линейной регрессии (из S&C 2007 года) на фьючерсах MOEX в 2025. Код и результаты!
Маленький кусок статьи. Легально тут

Что такое линейная регрессия и R-squared: простыми словами

Представьте, что вы едете по дороге. Линейная регрессия — это как прямая трасса, проведённая по данным: она показывает общий курс, игнорируя кочки и повороты. Цена движется вокруг этой «дороги», а наклон линии подсказывает, в какую сторону едем — вверх или вниз.

Теперь про R-squared: это как индикатор сигнала Wi-Fi. Если он близок к 1 — цена чётко держится вдоль регрессии, тренд сильный. Если ближе к нулю — «связь» теряется, рынок шумный, направление неясное.Маленький кусок статьи. Легально тутМаленький кусок статьи. Легально тут


Почему это круче скользящих средних? У регрессии меньше запаздываний и она точнее «схватывает» развороты. А R-squared помогает не гадать — есть тренд или просто случайное движение. Вместе они дают простую, но мощную систему фильтрации шума и подтверждения тренда.

Как использовать это в трейдинге

Начнём с периода: 10 баров — для поиска коротких импульсов и ранних сигналов, 20 баров — сбалансированный вариант для дневных графиков, 50 баров — для фильтрации шума и работы по тренду. Выбор зависит от стиля торговли и таймфрейма.

R-squared помогает определить фазу тренда:

  • его рост с низких уровней (например, с 0.1 до 0.3) часто указывает на начало движения;

  • падение с высоких (например, с 0.6 до 0.3) — признак ослабления и возможного флэта.

Ориентиры:

  • для 20 баров значим уровень 0.20;

  • для 10: 0.40;

  • для 50: достаточно 0.08.

Наклон линии регрессии (slope) показывает направление:

  • выше нуля — тренд вверх;

  • ниже — вниз.

Вместе с R² он позволяет отличить уверенное движение от случайного шума и избегать ложных входов.


Бэктест: проверим идею на практике

Инструмент: TradingView и Pine Script

Для реализации стратегии я выбрал TradingView. Это один из самых доступных инструментов для быстрого прототипирования торговых идей: открыл браузер, вставил код — и сразу увидел результат на графике. Особенно важно, что платформа не требует установки дополнительных библиотек, терминалов и настроек, как это часто бывает с Python или AmiBroker. Всё работает «из коробки», а язык Pine Script — простой и интуитивный, особенно если вы уже знакомы с техническим анализом.

К тому же, код можно легко адаптировать и поделиться ссылкой на него, чтобы каждый мог протестировать его самостоятельно — даже без подписки на платные функции. У меня есть реферальная ссылка TradingView: если вы зарегистрируетесь по ней, это немного поддержит меня, а вам будет всё то же самое.

Таймфреймы: дневной и часовой

Я протестировал стратегию на двух таймфреймах: дневном и часовом. Почему именно они?

  • Дневной — наиболее стабилен и подходит для анализа крупных движений. Его удобно использовать и тем, кто торгует вручную и не хочет реагировать на каждое движение внутри дня.

  • Часовой — даёт больше сигналов и позволяет точнее отследить динамику внутри тренда.

Мне кажется что для частного трейдера эти два масштаба — оптимальный компромисс между частотой сигналов и управляемостью стратегии.

Тестируемая логика

В стратегии используются два ключевых фильтра: наклон линии линейной регрессии и значение R². Условия простые: входим в позицию, если цена «прорывает» линию регрессии, а R² превышает заданный порог и растёт. Выход из позиции осуществляется по трейлинг-стопу, значение которого задаётся в процентах от экстремума.

Представленный код — моя интерпретация идеи из статьи Барбары Стар. Он может отличаться от оригинального примера из журнала, но отражает основную логику и добавляет реалистичные параметры торговли, включая комиссии и проскальзывание.

Результаты: день

Для дневного графика я включил настройку «Корректировать с учётом изменений контрактов» — такая корректировка убирает ценовые разрывы между контрактами (гэпы), возникающие при переходе от одного фьючерса к другому.

Торговля тремя контрактами фьючерсом на доллар/рубль (Si) на Мосбирже с комиссией 0.04% и проскальзыванием:Отвечаю на критику: бэктест линейной регрессии (из S&C 2007 года) на фьючерсах MOEX в 2025. Код и результаты! Результаты: день

Подробности:Отвечаю на критику: бэктест линейной регрессии (из S&C 2007 года) на фьючерсах MOEX в 2025. Код и результаты! Результаты: день

Результаты: час

На часовом таймфрейме стратегия охватила примерно полтора года котировок. Это позволяет увидеть, как система работает в разных фазах рынка: трендовых и боковых.

Торговля тремя контрактами фьючерсом на доллар/рубль (Si) на Мосбирже с комиссией 0.04% и проскальзыванием:Отвечаю на критику: бэктест линейной регрессии (из S&C 2007 года) на фьючерсах MOEX в 2025. Код и результаты! Результаты: час

Подробности:Отвечаю на критику: бэктест линейной регрессии (из S&C 2007 года) на фьючерсах MOEX в 2025. Код и результаты! Результаты: час


Код стратеги на Pine Script для TradingView

Отвечаю на критику: бэктест линейной регрессии (из S&C 2007 года) на фьючерсах MOEX в 2025. Код и результаты!

Верхняя панель — код стратегии:

//07.05.2025
// Стратегия на основе линейной регрессии и коэффициента детерминации R-squared
// На основе https://traders.com/documentation/feedbk_docs/2007/12/Abstracts_new/Star/star.html

// Михаил Шардин, https://shardin.name/?utm_source=tradingview

//@version=6
strategy("Линейная регрессия + R² стратегия",
     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=3,
     initial_capital=500000)                        // Начальный капитал

// === Входные параметры ===
// Параметры линейной регрессии
src = input.source(hlcc4, title="Источник данных")
len = input.int(defval=20, minval=1, title="Длина периода линейной регрессии")
r_squared_threshold = input.float(0.2, title="Порог R-squared", step=0.01, minval=0)
trailingStopOffset = input.float(3.9, "Отступ трейлинг-стопа (%)", step=0.1, minval=0.1)

// Выбор таймфрейма для расчетов
targetTimeframe = input.timeframe("", title="Таймфрейм для расчетов",
     tooltip="Укажите таймфрейм, на котором должны производиться расчеты")

// === Расчеты линейной регрессии и R-squared ===
// Получаем данные с выбранного таймфрейма
targetClose = request.security(syminfo.tickerid, targetTimeframe, src)

// Расчет линии линейной регрессии
lrc = ta.linreg(targetClose, len, 0)

// Расчет коэффициента детерминации R-squared
correlation_coeff = ta.correlation(targetClose, lrc, len)
r_squared = math.pow(correlation_coeff, 2)

// Обработка случая, когда стандартное отклонение источника равно нулю (все значения одинаковы)
is_constant_src = ta.stdev(targetClose, len) == 0
r_squared_adjusted = is_constant_src ? 1.0 : r_squared

// === Условия входа ===
// Условие для лонг: линия регрессии ниже цены закрытия и R² растет и выше порога
long_condition = lrc < close and r_squared_adjusted > r_squared_adjusted[1] and r_squared_adjusted > r_squared_threshold

// Условие для шорт: линия регрессии выше цены закрытия и R² растет и выше порога
short_condition = lrc > close and r_squared_adjusted > r_squared_adjusted[1] and r_squared_adjusted > r_squared_threshold

// === Трейлинг-стоп на основе процентного отступа ===
var float highestLongPrice = na
var float lowestShortPrice = na
var float trailingStopLong = na
var float trailingStopShort = na

// Флаг для блокировки новых сигналов при активной позиции
var bool blockNewSignals = false

// Обновляем трейлинг-стопы
if (strategy.position_size > 0)  // Если открыта длинная позиция
    highestLongPrice := na(highestLongPrice) ? close : math.max(highestLongPrice, close)
    trailingStopLong := highestLongPrice * (1 - trailingStopOffset / 100)
    blockNewSignals := true

if (strategy.position_size < 0)  // Если открыта короткая позиция
    lowestShortPrice := na(lowestShortPrice) ? close : math.min(lowestShortPrice, close)
    trailingStopShort := lowestShortPrice * (1 + trailingStopOffset / 100)
    blockNewSignals := true

// Проверяем условия выхода
if (strategy.position_size > 0 and close <= trailingStopLong)
    strategy.close("Лонг")
    highestLongPrice := na
    trailingStopLong := na
    blockNewSignals := false

if (strategy.position_size < 0 and close >= trailingStopShort)
    strategy.close("Шорт")
    lowestShortPrice := na
    trailingStopShort := na
    blockNewSignals := false

// === Открытие позиций (только если нет активной позиции) ===
if (long_condition and not blockNewSignals and strategy.position_size == 0)
    strategy.entry("Лонг", strategy.long)
    highestLongPrice := close
    trailingStopLong := close * (1 - trailingStopOffset / 100)
    blockNewSignals := true

if (short_condition and not blockNewSignals and strategy.position_size == 0)
    strategy.entry("Шорт", strategy.short)
    lowestShortPrice := close
    trailingStopShort := close * (1 + trailingStopOffset / 100)
    blockNewSignals := true

// === Отображение ===
// Отображение линии линейной регрессии
plot(lrc, color = color.blue, title = "Линия линейной регрессии",
     style = plot.style_line, linewidth = 2)

// Отображение трейлинг-стопов
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)

// Дополнительные информационные панели
var table info = table.new(position.top_right, 3, 4, border_width=1)
table.cell(info, 0, 0, "Linear Regression", bgcolor=color.new(color.blue, 90), text_color=color.white)
table.cell(info, 0, 1, "Значение:", text_color=color.white)
table.cell(info, 1, 1, str.tostring(lrc, "#.##"), text_color=color.white)
table.cell(info, 0, 2, "R-squared:", text_color=color.white)
table.cell(info, 1, 2, str.tostring(r_squared_adjusted, "#.####"), text_color=r_squared_adjusted > r_squared_threshold ? color.green : color.red)
table.cell(info, 0, 3, "Сигнал:", text_color=color.white)
table.cell(info, 1, 3, blockNewSignals ? "Заблокирован" : long_condition ? "ЛОНГ" : short_condition ? "ШОРТ" : "Нет сигнала",
           text_color=blockNewSignals ? color.yellow :
                     long_condition ? color.green :
                     short_condition ? color.red :
                     color.white)

Нижняя панель — код индикатора:

// 07.05.2025
// Михаил Шардин, https://shardin.name/?utm_source=tradingview

// На основе https://traders.com/documentation/feedbk_docs/2007/12/Abstracts_new/Star/star.html

//@version=6
indicator(title="Коэффициент детерминации (R-squared)", shorttitle="R²", overlay=false, precision=4)

// Настройки индикатора
src = input.source(close, title="Источник данных")
len = input.int(20, minval=2, title="Длина периода") // Для корреляции нужно минимум 2 точки

// Выбор таймфрейма для расчетов
targetTimeframe = input.timeframe("", title="Таймфрейм для расчетов",
     tooltip="Укажите таймфрейм, на котором должны производиться расчеты регрессии и R²")

targetSrc = request.security(syminfo.tickerid, targetTimeframe, src, lookahead=barmerge.lookahead_on)

// Расчет линии линейной регрессии (Ŷ - предсказанные значения)
lrc = ta.linreg(targetSrc, len, 0)

// Расчет коэффициента детерминации R-squared
// R² = (Correlation(Y, Ŷ))²
// Y - это targetSrc (фактические значения)
// Ŷ - это lrc (предсказанные значения)
correlation_coeff = ta.correlation(targetSrc, lrc, len)
r_squared = math.pow(correlation_coeff, 2)

// Обработка случая, когда стандартное отклонение источника равно нулю (все значения одинаковы)
is_constant_src = ta.stdev(targetSrc, len) == 0
r_squared_adjusted = is_constant_src ? 1.0 : r_squared

// Отображение R-squared на графике
plot(r_squared_adjusted, color=color.new(color.blue, 0), title="R-squared", style=plot.style_line, linewidth=2)

// Уровни для R-squared для лучшей визуальной интерпретации
hline(1, "Идеальное соответствие", color.gray, linestyle=hline.style_dashed)
hline(0.8, "Очень сильное", color.new(color.green, 50), linestyle=hline.style_dotted)
hline(0.5, "Среднее", color.new(color.orange, 50), linestyle=hline.style_dotted)
hline(0.2, "Слабое", color.new(color.red, 50), linestyle=hline.style_dotted)
hline(0, "Нет соответствия", color.gray, linestyle=hline.style_dashed)

Выводы и личное мнение

Тест показал: линейная регрессия с R² действительно может стать эффективным фильтром и подтверждением тренда — особенно на умеренных и длинных периодах.

Важно понимать, что простота кода не гарантирует прибыль — параметры требуют подстройки под инструмент, а условия рынка — постоянного внимания.

Тем не менее, эта стратегия может служить хорошей основой или фильтром внутри более сложной торговой системы.

Автор: Михаил Шардин