English Deutsch 日本語
preview
Переосмысливаем классические стратегии (Часть 16): Стратегия пробоя двойных полос Боллинджера

Переосмысливаем классические стратегии (Часть 16): Стратегия пробоя двойных полос Боллинджера

MetaTrader 5Примеры |
79 0
Gamuchirai Zororo Ndawana
Gamuchirai Zororo Ndawana

Финансовые рынки - это не просто статичные, неподвижные механизмы, существующие в дискретных состояниях. Скорее, финансовые рынки — это живые, динамичные и интеллектуальные системы, реагирующие на информацию. Они постоянно меняются и никогда не фиксируются на каком-либо состоянии навсегда, однако большинство торговых стратегий устроены так, будто рынки могут длительно оставаться в одном и том же состоянии.

Большинство торговых стратегий обычно классифицируют рынок либо как трендовый, либо как флэтовый рынок, а затем предлагают дальнейшие шаги в зависимости от выявленного состояния рынка. Цель этой статьи - проиллюстрировать читателю, что такой взгляд на рынок слишком прост, чтобы быть практичным. Если нам нужны стратегии, которые действительно могут идти в ногу с постоянно меняющимися рынками, рынками, которые порой могут даже вести себя враждебно, тогда нам необходимы инструменты, которые принимают финансовые рынки такими, какие они есть: как постоянно развивающуюся и лишь частично наблюдаемую систему.

Вот тут-то и пригодятся такие торговые стратегии, как стратегия двойных полос Боллинджера. Это продолжение классической системы "Полос Боллинджера", и считается, что она пришла из практики институциональных трейдеров. Она адаптирована так, чтобы плавно подстраиваться к меняющимся рыночным условиям. Результаты бэктеста, которые мы вскоре продемонстрируем, подтвердят наши замечания. Большинство торговых стратегий с полосами Боллинджера ограничены правилами из учебника и, как правило, предполагают, что вы будете работать при благоприятных рыночных условиях. Они предлагают либо торговать пробои, либо работать против импульса на возврат к среднему, но не отражают запутанную реальность того, как на самом деле ведут себя рынки, когда благоприятные и неблагоприятные состояния постоянно чередуются.

В нашей методологии мы реализовали хорошо известную вариацию классической стратегии Полос Боллинджера, которая широко известна большинству трейдеров в нашем сообществе. В этой версии стратегии установлены ориентиры прибыльности, которые должна превзойти стратегия двойных полос Боллинджера. Как мы вскоре обсудим, при тестировании стандартного пробоя индикатора полосы Боллинджера, мы фактически потеряли деньги.

Обе стратегии были протестированы в течение одного и того же пятилетнего исторического периода, с января 2020 по 2025 год. Мы старались изо всех сил, чтобы обе стратегии основывались на идентичных параметрах везде, где это было возможно. Классическая стратегия постоянно приносила убытки, в то время как стратегия двойных полос Боллинджера значительно превосходила ее по своим показателям с фиксированными параметрами, такими как период полос Боллинджера и размер используемого лота. Мы рассмотрим эти результаты более подробно. Но сейчас я кратко подытожу наши основные результаты.

Классическая стратегия принесла валовой убыток в размере -169 долларов за пять лет, в то время как стратегия двойных полос Боллинджера принесла валовую прибыль в размере 228 долларов при тех же условиях и по возможности с использованием фиксированных параметров. Справедливости ради, все сделки были открыты с минимальным размером лота, и каждая стратегия была ограничена одной открытой сделкой за раз. Кроме того, классическая стратегия также давала отрицательный коэффициент Шарпа, равный -0,53, в то время как улучшенная версия достигла положительного коэффициента Шарпа 0,5. Это свидетельствует о явном повышении прибыльности и стабильности.

Что касается точности, то классическая стратегия принесла 46% прибыльных сделок за пять лет, что не впечатляет. Однако стратегия двойных полос Боллинджера позволила заключить 56% прибыльных сделок, что на 21% повысило точность. Еще более поразительным является асимметричный способ, которым мы изменили распределение прибылей и убытков. Решение, которое мы представляем читателю, увеличило валовую прибыль бэктестирования на 70%, но увеличило валовые убытки только на 17%. Этот асимметричный эффект — прибыль растет быстрее, чем убытки — показывает, насколько адекватно стратегия двойных полос Боллинджера перестраивает распределение результатов сделок в более благоприятную форму.

Наконец, если смотреть на профит-фактор, исходная стратегия показала значение 0,82, что означает потерю капитала с течением времени. Стратегия двойных полос Боллинджера дала коэффициент в 1,2, что является ключевым показателем роста капитала, который представляет собой 50%-ное улучшение коэффициента прибыли. 

Если объединить эти результаты, они свидетельствуют о том, что стратегия двойных полос Боллинджера является не просто усовершенствованием оригинала, но сменой парадигмы. Она представляет собой новое семейство стратегий, имеющих общие корни с классическим подходом, но коренным образом меняющих его результаты. Система превратила убыточную стратегию в выигрышную, значительно повысила прибыльность, сохранив при этом замечательный контроль над рисками.

Самое главное, что эти улучшения достигнуты без добавления ненужной сложности. Стратегия двойных полос Боллинджера по-прежнему проста в освоении, реализации и интерпретации результатов, но при этом предлагает гораздо большие преимущества. Это радует меня больше всего, потому что в будущем, если мы решим добавить сложности — с помощью моделей машинного обучения для оптимизации входов и выходов или даже контроллеров с обратной связью для адаптации к доминирующим паттернам, — мы можем быть уверены, что игра стоит свеч, а лежащая в их основе стратегия будет прибыльной.

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


Обзор классической торговой стратегии

Начнем с применения классического индикатора полосы Боллинджера на нашем графике, как мы это обычно делаем. Для этого обсуждения мы выбрали пару EURUSD и будем анализировать ее на дневном таймфрейме. Поэтому на рисунке 1 ниже мы настроили полосы Боллинджера на период в 20 дневных свечей. Обозначим наши верхнюю и нижнюю полосы на 2 стандартных отклонения от средней полосы, так как это классическая настройка.

Рисунок 1: Применение нашего индикатора полосы Боллинджера к паре EURUSD с классическими настройками входных параметров

Классическая версия торговой стратегии проста в использовании. Всякий раз, когда ценовые уровни пробиваются выше самой верхней полосы, мы открываем короткие позиции. И наоборот, когда ценовые уровни пробиваются ниже самой низкой полосы, мы открываем длинные позиции. Логика, лежащая в основе классической стратегии полосы Боллинджера, заключается в том, что рынки движутся по циклам возврата к среднему значению. Таким образом, ожидается, что за пробоями за пределы любой из экстремальных полос последует движение цены, которое вернет ценовые уровни к средней полосе. 

Рисунок 2: Визуализация классической версии стратегии Полосы Боллинджера

Как и в случае с любой торговой стратегией, существуют неотъемлемые ограничения, связанные с торговыми правилами, которые мы определили для классической настройки. Широко известно, что такие торговые стратегии подвержены ложным пробоям. Проще говоря, рыночные условия могут находиться в состоянии летаргического дрейфа, достаточного для того, чтобы вызвать наши сигналы на вход, прежде чем резко изменить курс и вернуться к своей первоначальной траектории. Такие торговые условия приведут к постоянному истощению капитала любого инвестора.

Рисунок 3 ниже, может помочь читателю наглядно представить слабые стороны стратегии, которую мы рассматриваем. На изображении мы видим 2 сигнала на продажу, которые были правильно определены с использованием правил, которые мы установили ранее. Однако, как мы видим, только одна из сделок принесла ожидаемый результат. В первой сделке, ограниченной зеленой рамкой, ценовые уровни вернулись к средней полосе после того, как в моменте пробили верхнюю полосу. Однако затем, по-видимому, повторился тот же паттерн за время, ограниченное свечами в красной рамке, но это был ложный пробой. Уровни цен продолжали расти и не вернулись к среднему уровню, как это предполагалось в классической стратегии.

Рисунок 3: Визуализация ограничений классической версии стратегии Полосы Боллинджера



Начинаем на MQL5

Как и в большинстве наших торговых приложений, начнем с определения системных констант. Эти определения являются краеугольным камнем наших тестов, поскольку они позволяют зафиксировать как можно больше параметров в обоих экспериментах. Важные параметры, такие как период полос Боллинджера, сдвиги, периоды ретроспективного анализа индикатора, таймфреймы и стандартные отклонения, используемые для полос, должны оставаться фиксированными, поскольку они сильно меняют поведение стратегии.

//+------------------------------------------------------------------+
//|                                                DBB Benchmark.mq5 |
//|                                               Gamuchirai Ndawana |
//|                    https://www.mql5.com/ru/users/gamuchiraindawa |
//+------------------------------------------------------------------+
#property copyright "Gamuchirai Ndawana"
#property link      "https://www.mql5.com/ru/users/gamuchiraindawa"
#property version   "1.00"

//+------------------------------------------------------------------+
//| System definitions                                               |
//+------------------------------------------------------------------+
#define BB_PERIOD   20
#define BB_SHIFT    0
#define ATR_PERIOD  14
#define ATR_PADDING 2
#define BB_SD_1     2
#define BB_SD_2     1
#define TF_1        PERIOD_D1
После констант определим глобальные переменные. Большинство глобальных переменных связаны с техническими индикаторами, на которые мы полагаемся, и определением размера стоп-лосса, который мы будем использовать.
//+------------------------------------------------------------------+
//| Global variables                                                 |
//+------------------------------------------------------------------+
int    bb_handler,bb_handler_2,atr_handler;
double bb_reading_u[],bb_reading_m[],bb_reading_l[],bb_reading_u_2[],bb_reading_m_2[],bb_reading_l_2[],atr_reading[];
double padding,close;

После этого мы импортируем библиотеки, необходимые для торговли и для записи торговой информации, такой как цены Bid и Ask.  Библиотеки играют важную роль практически в любом процессе разработки приложений, потому что мы редко пишем весь код с нуля. 

//+------------------------------------------------------------------+
//| Library                                                          |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
#include <VolatilityDoctor\Trade\TradeInfo.mqh>

CTrade    Trade;
TradeInfo *TradeInfoHandler;

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

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Setup our technical indicators
   bb_handler       = iBands(Symbol(),TF_1,BB_PERIOD,BB_SHIFT,BB_SD_1,PRICE_CLOSE);
   bb_handler_2     = iBands(Symbol(),TF_1,BB_PERIOD,BB_SHIFT,BB_SD_2,PRICE_CLOSE);
   atr_handler      = iATR(Symbol(),TF_1,ATR_PERIOD);
   TradeInfoHandler = new TradeInfo(Symbol(),TF_1);
//---
   return(INIT_SUCCEEDED);
  }

Если приложение больше не должно использоваться, необходимо освободить ресурсы памяти, которые были ранее выделены для определенных нами ранее обработчиков.

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- Release the indicators we are no longer using
   IndicatorRelease(bb_handler);
   IndicatorRelease(bb_handler_2);
   IndicatorRelease(atr_handler);
  }

В классической конфигурации стратегии логика входа проста и легко интерпретируется. Если цена закрытия пробьет максимум полос Боллинджера, мы продаем; если цена закрытия пробьет минимум полос Боллинджера и у нас нет открытых позиций, мы покупаем. 

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- Keep track of time
   static datetime timestamp;
   datetime current_time = iTime(Symbol(),TF_1,0);

   if(timestamp != current_time)
     {
      //--- Update indicator readings
      CopyBuffer(bb_handler,0,0,1,bb_reading_m);
      CopyBuffer(bb_handler,1,0,1,bb_reading_u);
      CopyBuffer(bb_handler,2,0,1,bb_reading_l);
      CopyBuffer(bb_handler_2,0,0,1,bb_reading_m_2);
      CopyBuffer(bb_handler_2,1,0,1,bb_reading_u_2);
      CopyBuffer(bb_handler_2,2,0,1,bb_reading_l_2);
      CopyBuffer(atr_handler,0,0,1,atr_reading);

      //--- Get updated market readings
      close = iClose(Symbol(),TF_1,0);
      padding = atr_reading[0] * 2;

      //--- If we have no open positions
      if(PositionsTotal() == 0)
        {
         if(close > bb_reading_u[0])
            Trade.Sell(TradeInfoHandler.MinVolume(),Symbol(),TradeInfoHandler.GetBid(),TradeInfoHandler.GetAsk()+padding,TradeInfoHandler.GetAsk()-padding);

         else
            if(close < bb_reading_l[0])
               Trade.Buy(TradeInfoHandler.MinVolume(),Symbol(),TradeInfoHandler.GetAsk(),TradeInfoHandler.GetBid()-padding,TradeInfoHandler.GetBid()+padding);
        }
     }
  }
//+------------------------------------------------------------------+

После завершения работы приложения удалим определение системных констант, созданных в начале — опять же, это рекомендуемая практика для кода MQL5. 

//+------------------------------------------------------------------+
//| Undefine system definitions                                      |
//+------------------------------------------------------------------+
#undef BB_PERIOD
#undef BB_SD_1
#undef BB_SD_2
#undef BB_SHIFT
#undef ATR_PADDING
#undef ATR_PERIOD
#undef TF_1
//+------------------------------------------------------------------+

Когда все детали объединены, это и есть эталонная конфигурация для нашего классического приложения.

//+------------------------------------------------------------------+
//|                                                DBB Benchmark.mq5 |
//|                                               Gamuchirai Ndawana |
//|                    https://www.mql5.com/ru/users/gamuchiraindawa |
//+------------------------------------------------------------------+
#property copyright "Gamuchirai Ndawana"
#property link      "https://www.mql5.com/ru/users/gamuchiraindawa"
#property version   "1.00"

//+------------------------------------------------------------------+
//| System definitions                                               |
//+------------------------------------------------------------------+
#define BB_PERIOD   20
#define BB_SHIFT    0
#define ATR_PERIOD  14
#define ATR_PADDING 2
#define BB_SD_1     2
#define BB_SD_2     1
#define TF_1        PERIOD_D1

//+------------------------------------------------------------------+
//| Global variables                                                 |
//+------------------------------------------------------------------+
int    bb_handler,bb_handler_2,atr_handler;
double bb_reading_u[],bb_reading_m[],bb_reading_l[],bb_reading_u_2[],bb_reading_m_2[],bb_reading_l_2[],atr_reading[];
double padding,close;

//+------------------------------------------------------------------+
//| Library                                                          |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
#include <VolatilityDoctor\Trade\TradeInfo.mqh>

CTrade    Trade;
TradeInfo *TradeInfoHandler;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Setup our technical indicators
   bb_handler       = iBands(Symbol(),TF_1,BB_PERIOD,BB_SHIFT,BB_SD_1,PRICE_CLOSE);
   bb_handler_2     = iBands(Symbol(),TF_1,BB_PERIOD,BB_SHIFT,BB_SD_2,PRICE_CLOSE);
   atr_handler      = iATR(Symbol(),TF_1,ATR_PERIOD);
   TradeInfoHandler = new TradeInfo(Symbol(),TF_1);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- Release the indicators we are no longer using
   IndicatorRelease(bb_handler);
   IndicatorRelease(bb_handler_2);
   IndicatorRelease(atr_handler);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- Keep track of time
   static datetime timestamp;
   datetime current_time = iTime(Symbol(),TF_1,0);

   if(timestamp != current_time)
     {
      //--- Update indicator readings
      CopyBuffer(bb_handler,0,0,1,bb_reading_m);
      CopyBuffer(bb_handler,1,0,1,bb_reading_u);
      CopyBuffer(bb_handler,2,0,1,bb_reading_l);
      CopyBuffer(bb_handler_2,0,0,1,bb_reading_m_2);
      CopyBuffer(bb_handler_2,1,0,1,bb_reading_u_2);
      CopyBuffer(bb_handler_2,2,0,1,bb_reading_l_2);
      CopyBuffer(atr_handler,0,0,1,atr_reading);

      //--- Get updated market readings
      close = iClose(Symbol(),TF_1,0);
      padding = atr_reading[0] * 2;

      //--- If we have no open positions
      if(PositionsTotal() == 0)
        {
               if(close > bb_reading_u[0])
                  Trade.Sell(TradeInfoHandler.MinVolume(),Symbol(),TradeInfoHandler.GetBid(),TradeInfoHandler.GetAsk()+padding,TradeInfoHandler.GetAsk()-padding);

               else
                  if(close < bb_reading_l[0])
                     Trade.Buy(TradeInfoHandler.MinVolume(),Symbol(),TradeInfoHandler.GetAsk(),TradeInfoHandler.GetBid()-padding,TradeInfoHandler.GetBid()+padding);
        }
     }
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Undefine system definitions                                      |
//+------------------------------------------------------------------+
#undef BB_PERIOD
#undef BB_SD_1
#undef BB_SD_2
#undef BB_SHIFT
#undef ATR_PADDING
#undef ATR_PERIOD
#undef TF_1
//+------------------------------------------------------------------+

Теперь давайте проанализируем результаты работы приложения за пятилетний период тестирования на истории. Общая чистая прибыль составляет −169, что не впечатляет. Коэффициент Шарпа составляет −0.53, а процент прибыльных сделок находится ниже 50%, на уровне 46%. Короче говоря, это приложение показывает результаты хуже случайного выбора и неизменно оказывается убыточным.

Рисунок 4: Визуализация подробной статистики, полученной с помощью классической торговой стратегии

 Кривая эквити для классической стратегии показывает устойчивый нисходящий тренд, который со временем усиливается.

Рисунок 5: Классическая версия торговой стратегии со временем приводит к отрицательному тренду



Обзор измененной торговой стратегии

Усовершенствование простое: вместо одной системы полос Боллинджера мы используем два набора полос. С внутренней полосой используется меньшее стандартное отклонение, а с внешней - большее. При пробое внутренней полосы мы интерпретируем это как сигнал следования за трендом. При пробое внешней полосы (с двумя стандартными отклонениями) мы интерпретируем это как сигнал возврата к среднему значению. Иными словами, если цена пробивает верхнюю внутреннюю полосу, мы покупаем (следование за трендом); если цена на максимуме пробивает внешнюю полосу, мы продаем (возврат к среднему значению). Для нижних полос справедливо обратное утверждение.

Для реализации этой стратегии нам нужно лишь изменить правила входа; большая часть кода остаётся без изменений.

Рисунок 6: Мы добавим второй фильтр, более жесткий уровень стандартного отклонения полосы Боллинджера, но оставим период фиксированным

Мы можем визуализировать пересмотренную версию стратегии с помощью нашего терминала MetaTrader 5. Обратите внимание, что вам не нужно удалять первый индикатор, который мы применили, или переходить на новый график. Просто примените второй экземпляр индикатора полосы Боллинджера на том же графике, который вы выбрали, если вы внимательно следили за ним.

Рисунок 7: Визуализация переосмысленной версии классической стратегии Полосы Боллинджера



Реализуем наши усовершенствования

Теперь мы готовы к реализации усовершенствований стратегии двойных полос Боллинджера. 
//--- If we have no open positions
if(PositionsTotal() == 0)
      {
         //--- Is the close price above the highest band? Buy
         if(close > bb_reading_u[0])
            Trade.Buy(TradeInfoHandler.MinVolume(),Symbol(),TradeInfoHandler.GetAsk(),TradeInfoHandler.GetBid()-padding,TradeInfoHandler.GetBid()+padding);

         //--- Is the close price below the lowest band? Sell
         else
            if(close < bb_reading_l[0])
               Trade.Sell(TradeInfoHandler.MinVolume(),Symbol(),TradeInfoHandler.GetBid(),TradeInfoHandler.GetAsk()+padding,TradeInfoHandler.GetAsk()-padding);

            //--- Is the close price above the mid-high band? Sell
            else
               if((close < bb_reading_u[0]) && (close > bb_reading_l[0]) && (close > bb_reading_u_2[0]))
                  Trade.Sell(TradeInfoHandler.MinVolume(),Symbol(),TradeInfoHandler.GetBid(),TradeInfoHandler.GetAsk()+padding,TradeInfoHandler.GetAsk()-padding);

               //--- Is the close price below the mid-low band? Buy
               else
                  if((close < bb_reading_u[0]) && (close > bb_reading_l[0]) && (close < bb_reading_l_2[0]))
                     Trade.Buy(TradeInfoHandler.MinVolume(),Symbol(),TradeInfoHandler.GetAsk(),TradeInfoHandler.GetBid()-padding,TradeInfoHandler.GetBid()+padding);
      }

Мы проведем бэктест в течение одного и того же пятилетнего периода, охватывающего промежуток с января 2020 года по март 2025 года. 

Рисунок 8: Тестирование усовершенствованной версии торговой стратегии двойных полос Боллинджера

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

Рисунок 9: Выберем настройки случайной задержки для надежной имитации реальных рыночных условий

Изучив подробную статистику по улучшенной стратегии, мы видим явные изменения по всем направлениям. Общая чистая прибыль становится положительной и почти удваивается в абсолютном выражении по сравнению с классической системой. Ожидаемая прибыль на сделку растет, коэффициент прибыли улучшается, а процент прибыльных сделок увеличивается до более привлекательных 56%. Зачастую улучшение стратегии приводит к сокращению количества сделок при одновременном увеличении прибыльности. Однако в этом случае увеличилось как общее количество сделок, так и чистая прибыль. Это говорит о том, что усовершенствованная версия обнаруживает дополнительные сигналы, которые исходная система не распознавала.

Рисунок 10: Пересмотренная торговая стратегия существенно улучшила статистические показатели эффективности нашего торгового приложения

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

Рисунок 11: Кривая эквити, полученная в результате нашей пересмотренной торговой стратегии, наконец стала прибыльной



Заключение

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

API MQL5 позволяет нам переосмыслить эти стратегии. С помощью четко определенных методов и других утилит он может охватывать широкий спектр торговых приложений, даже несмотря на фиксированный размер API. Да, API MQL5 еженедельно пополняется новыми обновлениями. Они постоянно добавляются на платформу MQL5.

Но даже используя только основные утилиты, мы можем последовательно создавать новые приложения, способные устранять слепые зоны, присущие классическим стратегиям. API MQL5 предоставляет нам методы, обладающие широким и динамичным спектром применения — именно то, что нам нужно для создания приложений, которые лучше осведомлены об изменениях состояний рынка, в отличие от своих классических предшественников, рассматривавших рынки только в статическом, бинарном виде.

Название файла Описание файла
DBB.mq5 Пересмотренная торговая стратегия двойных полос Боллинджера, которую мы внедрили для улучшения результатов. 
DBB_Benchmark.mq5 Классическая реализация стратегии полос Боллинджера.

Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/19418

Прикрепленные файлы |
DBB.mq5 (5.29 KB)
DBB_Benchmark.mq5 (4.47 KB)
Разработка инструментария для анализа Price Action (Часть 48): Индекс гармонии нескольких таймфреймов с панелью взвешенного смещения Разработка инструментария для анализа Price Action (Часть 48): Индекс гармонии нескольких таймфреймов с панелью взвешенного смещения
В этой статье представлен инструмент "Multi-Timeframe Harmony Index" – продвинутый советник для MetaTrader 5, который рассчитывает взвешенное смещение рынка по нескольким таймфреймам, сглаживает значения с помощью EMA и выводит результат на аккуратной панели на графике. Он поддерживает настраиваемые алерты и автоматически наносит сигналы покупки и продажи на график, когда значение смещения пересекает значимые пороги. Подходит трейдерам, которые используют анализ нескольких таймфреймов, чтобы соотносить точки входа с общей структурой рынка.
Опубликуйте код статьи в MQL5 Algo Forge за 10 минут: пошаговый гайд Опубликуйте код статьи в MQL5 Algo Forge за 10 минут: пошаговый гайд
Статья — пошаговое руководство по переносу кода из публикации в полноценный проект MQL5 Algo Forge. Вы настроите окружение и авторизацию в MetaEditor, создадите проект в Shared Projects, выберете тип, разложите файлы, добавите README.md, проверите кодировку и сборку, зафиксируете изменения в Git и откроете репозиторий публично. Материал помогает выстроить рабочую структуру и сохранить историю версий для удобства читателей.
Инжиниринг признаков для машинного обучения (Часть 1): дробное дифференцирование — стационарность без потери памяти Инжиниринг признаков для машинного обучения (Часть 1): дробное дифференцирование — стационарность без потери памяти
Целочисленное дифференцирование заставляет выбирать между стационарностью и памятью: доходности (d = 1) стационарны, но отбрасывают всю информацию об уровне цены; исходные цены (d = 0) сохраняют память, но нарушают предпосылку стационарности, важную для моделей машинного обучения. В статье реализован метод дробного дифференцирования с окном фиксированной ширины (FFD) из главы 5 AFML: get_weights_ffd — итеративная рекурсия с отсечением по порогу, frac_diff_ffd — ограниченное скалярное произведение для каждого бара, fracdiff_optimal — бинарный поиск минимального стационарного d*.
Неопределённость как модель (Часть 6): Множественная регрессия и диагностика Неопределённость как модель (Часть 6): Множественная регрессия и диагностика
Практическое введение в множественную регрессию с детерминированными факторами для финансовых рядов. Рассматриваются постановка и матричная форма МНК, диагностика остатков, EDA/CDA, R-квадрат и скорректированный R-квадрат, F-тест, RESET, тест Бройша–Пагана, VIF и расстояние Кука. Показаны приёмы работы с регрессорами: фиктивные переменные, нелинейные трансформации и взаимодействия. Примеры с трендом, днями недели и новостями помогают отбирать факторы и строить пригодные для прогноза модели.