
Возможности Мастера MQL5, которые вам нужно знать (Часть 38): Полосы Боллинджера
Введение
Полосы Боллинджера — популярный технический индикатор, разработанный Джоном Боллинджером в 1987 году и состоящий из 3 линий (или буферов данных). Его основная функция — поиск способа количественной оценки волатильности рынка путем определения точек перекупленности и перепроданности торгуемых ценных бумаг. Полосы Боллинджера расширяются и сужаются из-за волатильности рынка: если волатильность увеличивается, две внешние полосы расходятся еще больше, а если волатильность сокращается, две внешние полосы сближаются.
Трейдеры используют эти расширения и сокращения для прогнозирования периодов ценовых прорывов или ценовых консолидаций соответственно. Верхняя и нижняя полосы Боллинджера также действуют как динамические уровни поддержки и сопротивления, поскольку цены имеют тенденцию отскакивать от этих уровней, предлагая потенциальные подсказки для разворотов или продолжений. Полосы Боллинджера часто поддерживают стратегии возврата к среднему значению, при которых ожидается, что цены вернутся к среднему значению (средней полосе) после касания верхней или нижней полосы. Условия перекупленности и перепроданности также определяются, когда цена выходит за пределы внешних полос, сигнализируя о потенциальных точках разворота.
Кроме того, когда цены постоянно находятся вблизи верхней полосы, это указывает на приближение бычьего тренда, тогда как преимущественное расположение в нижней полосе часто указывает на сохранение медвежьего тренда. Таким образом, прорывы или отбои от этих полос могут указывать на начало нового тренда или поворотный момент. Наконец, сжатие полос Боллинджера происходит, когда верхняя и нижняя полосы находятся очень близко друг к другу в течение определенного периода времени, так что волатильность низкая, а потенциальные возможности прорыва неизбежны. Трейдеры внимательно следят за этим, часто используя направление прорыва как сигнал для направления. Формула для трех буферов данных проста и может быть записана следующими уравнениями:
где:
- MB — буфер средней полосы
- SMA — функция простой скользящей средней.
- P - история цен закрытия
- n — период расчета простой скользящей средней
где:
- UB — буфер верхней полосы
- k — настраиваемый коэффициент, которому по умолчанию часто присваивается значение 2
- Sigma — стандартное отклонение за усредненный период.
где:
- LB — буфер нижней полосы
Цель статьи — не только перечислить различные сигналы, которые могут генерировать полосы Боллинджера, но и, как всегда, показать, как их можно интегрировать в единый файл класса пользовательских сигналов. Обычно такие статьи структурированы таким образом, что сначала идет теоретическое обоснование идеи, а затем в конце представляются тестирование стратегии и результаты. Однако в этой статье, как и в некоторых предыдущих, мы поделимся результатами тестов для каждой представленной настройки сигнала вместе с кодом настройки сигнала. То есть мы представим результаты нескольких тестов на протяжении всей статьи. Мы рассмотрим до 8 возможных сигналов полос Боллинджера, которые могут быть использованы трейдерами.
Пользовательские классы сигналов играют ключевую роль не только в разработке универсальных и надежных сигналов, поскольку они позволяют комбинировать различные стратегии, но и в минималистском подходе к кодированию, который позволяет быстро тестировать и перепроверять идеи за короткий промежуток времени. Код, прикрепленный в конце этой статьи, предназначен для использования в Мастере MQL5. Новички могут подробнее узнать о нем здесь и здесь. После перекрестной проверки идей трейдеры могут либо запустить собранный советник, либо перекодировать его, настроив исполнение сделок, сохранив при этом базовую стратегию.
Прежде чем мы рассмотрим сигналы, было бы полезно продемонстрировать, как мы подготавливаем пользовательский класс сигналов для обработки всех этих 8 альтернативных сигналов. Ниже представлен интерфейс класса пользовательского сигнала:
//+------------------------------------------------------------------+ //| Class CSignalBollingerBands. | //| Purpose: Class of generator of trade signals based on | //| the 'BollingerBands' indicator. | //| Is derived from the CExpertSignal class. | //+------------------------------------------------------------------+ class CSignalBollingerBands : public CExpertSignal { protected: CiBands m_bands; // object-indicator .... //--- "weights" of market models (0-100) int m_pattern_0; // model 0 "Price Crossing the Upper Band or the Lower Band" int m_pattern_1; // model 1 "Price Bouncing Off Lower Band or Upper Band " int m_pattern_2; // model 2 "Price Squeeze Followed by a Breakout Above Upper Band or Below Lower Band " int m_pattern_3; // model 3 "Price Double Bottoms Near Lower Band or Double Top Near Upper Band " int m_pattern_4; // model 4 "Price Bounces Off the Middle Band from Above & Bounce Off from Below " int m_pattern_5; // model 5 "Volume Divergence at Lower Band or Upper Band " int m_pattern_6; // model 6 "Bands Widening After Downtrend or After Uptrend " int m_pattern_7; // model 7 "Bands Orientation and Angle Changes " uchar m_patterns_used; // bit-map integer for used pattens public: CSignalBollingerBands(void); ~CSignalBollingerBands(void); .... protected: ... //--- methods to check for patterns bool IsPattern_0(ENUM_POSITION_TYPE T); bool IsPattern_1(ENUM_POSITION_TYPE T); bool IsPattern_2(ENUM_POSITION_TYPE T); bool IsPattern_3(ENUM_POSITION_TYPE T); bool IsPattern_4(ENUM_POSITION_TYPE T); bool IsPattern_5(ENUM_POSITION_TYPE T); bool IsPattern_6(ENUM_POSITION_TYPE T); bool IsPattern_7(ENUM_POSITION_TYPE T); };
Он следует стандартному подходу к большинству пользовательских сигналов, а основным дополнением для этой статьи являются перечисленные переменные m_pattern_XX, которые выделены в коде. Эти переменные, представляющие вес (значение в диапазоне от 0 до 100), часто встречаются в пользовательских классах сигналов, которые собираются с помощью Мастера. Яркими примерами являются класс сигналов конвертов и класс сигналов RSI. Оба эти класса используют переменные шаблона (или паттерна), имеющие предустановленный постоянный вес, который часто не достигает 100. Назначение им постоянного веса само по себе не является проблемой, поскольку в принципе каждый класс предназначен для использования с другими классами сигналов, так что оптимизируется или корректируется соответствующий вес каждого класса по отношению к общему сигналу советника.
Поэтому идея их оптимизации выглядит немного странной, учитывая, что существует огромный риск переобучения для тестируемого символа или торговой ценной бумаги, а использование этих паттернов часто предполагает, что трейдер хорошо знаком с относительной важностью и весом каждого паттерна. Оптимизатор в данном случае не нужен. Кроме того, в случае использования нескольких классов сигналов, каждый из которых имеет свой собственный паттерн, требования к оптимизации будут заоблачными. Вот почему всегда лучше иметь их в качестве "основанных на знаниях" (knowledge-based) констант, а не весовых коэффициентов, которые нужно обучать.
Однако в этой статье мы рассмотрим возможность оптимизации этих паттернов. Мы сделаем это в первую очередь по той причине, что данный класс собирается исключительно внутри Мастера. Он не будет сравниваться с другим сигналом. Таким образом, наш весовой параметр для этого сигнала останется равным 1,0, как и для большинства классов сигналов, которые мы тестировали в этих сериях. Кроме того, обычно при назначении постоянных значений паттернов используется только один из них. Обычно это означает, что поскольку класс сигнала собирается вместе с другими сигналами, а его вес оптимизируется, выбранный паттерн оптимизируется для работы с другими сигналами, в то время как другие, невыбранные паттерны, простаивают.
В этой статье мы хотим использовать все паттерны, где бы они ни присутствовали. Паттерны по своей природе парные, то есть для условий на покупку и продажу. Маловероятно, что любые два разных типа паттерна могут быть отображены одновременно. (Под этим мы подразумеваем, что, скажем, модель 1 и модель 2 могут появиться одновременно, а не то, что условия на покупку и продажу для одной модели могут быть отображены одновременно). Таким образом, одновременное использование подразумевает, что один паттерн может указывать на длинную позицию, в то время как другой паттерн в другое время указывает на короткую позицию или закрытие позиции, которую мы открыли ранее. Эти пользовательские классы сигналов имеют пороговые значения закрытия и открытия, поэтому при наличии определенного паттерна, в зависимости от его оптимизированного значения, он может либо просто закрыть уже открытую позицию, либо развернуться. Поэтому наш советник оптимизирует веса этих паттернов в течение короткого периода времени для одного символа и смотрит, даст ли это нам что-нибудь интересное.
Наш пользовательский класс сигналов наследуется от класса CExpertSignal, который имеет функцию PatternsUsage, принимающую в качестве входных данных целое число битовой маски для шаблонов, используемых в пользовательском классе сигналов. Поскольку мы можем использовать до 8 паттернов сигналов, размер нашей битовой карты будет варьироваться от 0 до 2 в степени 8 минус один, что составляет 255. Это означает, что помимо определения пороговых значений индивидуальных паттернов (где эти пороговые значения устанавливают закрытие и открытие позиций), мы выберем те паттерны из 8, которые лучше всего подойдут в качестве стратегии, использующей полосы Боллинджера. Этот выбор комбинации паттернов для одновременного использования показан в окончательном отчете тестера (из-за большого объема отчет будет представлен в следующей статье). Для каждого из доступных паттернов результаты тестирования, представленные ниже, получены при использовании советником одного паттерна.
Однако в ходе тестирования выяснилось, что назначение количества используемых паттернов не позволяет должным образом использовать функцию определения IS_PATTERN_USAGE(), как можно было бы ожидать. Похоже, что по умолчанию всегда применяется назначение -1 в качестве количества используемых шаблонов, что подразумевает возможность использования всех шаблонов, независимо от предоставленных нами входных данных. Чтобы обойти эту проблему, мы используем нашу собственную побитовую реализацию, которая позволяет преобразовывать входное целое число хэш-карты в нули и единицы, из которых можно прочитать, какие паттерны были выбраны. Приведенная ниже таблица может служить руководством по основным 8 индивидуальным картам паттернов и тому, как мы их интерпретируем в нашем коде:
входная карта (m_patterns_used) | подразумеваемые биты | byte-checker |
1 | 00000001 | 0x01 |
2 | 00000010 | 0x02 |
4 | 00000100 | 0x04 |
8 | 00001000 | 0x08 |
16 | 00010000 | 0x10 |
32 | 00100000 | 0x20 |
64 | 01000000 | 0x40 |
128 | 10000000 | 0x80 |
Как видно, каждая из перечисленных 8 карт подразумевает использование одного паттерна. Это лучше всего видно на примере подразумеваемых битов, где в строке из 8 символов все символы, кроме одного, являются нулями. Входным данным фактически может быть присвоено любое значение от 0 до 255, поэтому это беззнаковый символ (тип данных uchar).
Пересечение ценой верхней или нижней полосы
Итак, наш первый сигнал — это когда цена пересекает либо верхнюю, либо нижнюю полосу. Когда цена пересекает верхнюю полосу сверху вниз и опускается ниже нее, мы интерпретируем это как медвежий сигнал. И наоборот, когда цена пересекает нижнюю полосу снизу и закрывается выше нее, мы потенциально интерпретируем это как бычий сигнал. Мы реализуем эту логику в функции, которая проверяет наличие шаблона 0 следующим образом:
//+------------------------------------------------------------------+ //| Check for Pattern 0. | //+------------------------------------------------------------------+ bool CSignalBollingerBands::IsPattern_0(ENUM_POSITION_TYPE T) { m_bands.Refresh(-1); m_close.Refresh(-1); if(T == POSITION_TYPE_BUY && Close(StartIndex() + 1) < Lower(StartIndex() + 1) && Close(StartIndex()) > Lower(StartIndex())) { return(true); } else if(T == POSITION_TYPE_SELL && Close(StartIndex() + 1) > Upper(StartIndex() + 1) && Close(StartIndex()) < Upper(StartIndex())) { return(true); } return(false); }
Наш код довольно прост, отчасти благодаря стандартному библиотечному коду MQL5, где кодирование для индикатора Bollinger Bands сведено к минимуму, так что после объявления экземпляра класса для индикатора следующим образом:
//+------------------------------------------------------------------+ //| Class CSignalBollingerBands. | //| Purpose: Class of generator of trade signals based on | //| the 'BollingerBands' indicator. | //| Is derived from the CExpertSignal class. | //+------------------------------------------------------------------+ class CSignalBollingerBands : public CExpertSignal { protected: CiBands m_bands; // object-indicator ... ... };
инициализация происходит так:
//+------------------------------------------------------------------+ //| Create indicators. | //+------------------------------------------------------------------+ bool CSignalBollingerBands::InitIndicators(CIndicators *indicators) { //--- check pointer if(indicators == NULL) return(false); //--- initialization of indicators and timeseries of additional filters if(!CExpertSignal::InitIndicators(indicators)) return(false); //--- create and initialize MA indicator if(!InitMA(indicators)) return(false); //--- ok return(true); }
Все, что нам нужно сделать, это обновить его, как указано в функции выше. Нас не волнует количество буферов, поскольку функции, обслуживающие верхнюю, нижнюю и основную (или среднюю) полосы, встроены в класс. Кроме того, основные цены открытия, максимума, минимума и закрытия символа инициализируются в ссылочных классах при условии, что они объявлены в конструкторе класса следующим образом:
//+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CSignalBollingerBands::CSignalBollingerBands(void) ... { //--- initialization of protected data m_used_series = USE_SERIES_OPEN + USE_SERIES_HIGH + USE_SERIES_LOW + USE_SERIES_CLOSE; ... }
Это снова оставляет необходимость только обновлять соответствующий ценовой хэндл на каждом баре перед получением текущей цены. В нашем случае мы используем цену закрытия, поэтому это все, что нам нужно обновить. Мы запускаем тесты на собранном с помощью Мастера советнике, где мы присваиваем используемой входной битовой карте паттерна значение 1, поскольку мы используем только первый паттерн. Результаты частично оптимизированного теста при использовании только паттерна 0 дают нам следующие результаты:
Приведенные выше результаты получены в ходе тестовых прогонов пары USDCHF на дневном графике за 2023 год. Поскольку мы используем только паттерн 0, входное целое число хэш-таблицы для используемых паттернов равно 1. Мы проверяем наличие этого шаблона в условиях на покупку и продажу, которые приведены в коде в конце этой статьи, вместе с результатами тестирования по всем шаблонам.
Отскок цены от нижней или верхней полосы
Нашим следующим сигналом является отскок цен от любой из внешних полос. Если цена касается верхней полосы, а затем отступает от нее, это считается медвежьим сигналом. И наоборот, если цена опустилась до нижней полосы Боллинджера, а затем восстановилась, это считается бычьим сигналом. Такая интерпретация вытекает из того, что верхние и нижние полосы являются ключевыми зонами разворота. Это, в свою очередь, можно объяснить психологией рынка, когда трейдеры чувствуют, что если цена чрезмерно растет в каком-либо направлении, то настала пора коррекции. Напомним, полосы Боллинджера не только отслеживают тренды благодаря базовому (или среднему) буферу, но и волатильность. Таким образом, когда цена приближается к любой из внешних полос или когда они расширяются, подразумевается волатильность.
Инструменты подтверждения, которые могут быть альтернативными индикаторами, в идеале следует использовать вместе с полосами Боллинджера. Для реализации проверки на отскок от внешних полос в MQL5 мы используем следующий источник:
//+------------------------------------------------------------------+ //| Check for Pattern 1. | //+------------------------------------------------------------------+ bool CSignalBollingerBands::IsPattern_1(ENUM_POSITION_TYPE T) { m_bands.Refresh(-1); m_close.Refresh(-1); if(T == POSITION_TYPE_BUY && Close(StartIndex() + 2) > Lower(StartIndex() + 2) && Close(StartIndex() + 1) <= Lower(StartIndex() + 1) && Close(StartIndex()) > Lower(StartIndex())) { return(true); } else if(T == POSITION_TYPE_SELL && Close(StartIndex() + 2) < Upper(StartIndex() + 2) && Close(StartIndex() + 1) >= Upper(StartIndex() + 1) && Close(StartIndex()) < Upper(StartIndex())) { return(true); } return(false); }
Мы используем до 8 шаблонов, и, как видно из приведенной выше таблицы, входная карта (используемый входной шаблон) для второго шаблона равна 2. Это гарантирует, что при проверке условий на покупку и продажу мы используем только эту модель — отскок от верхней и нижней полос. Тестовые прогоны по паре USDCHF на дневном таймфрейме за 2023 год дают следующие результаты:
Сжатие цен, сопровождаемое прорывом выше верхней полосы или ниже нижней полосы
Паттерн 2 представляет собой сжатие цены с последующим прорывом. Ценовое сжатие обычно представляет собой длительный период низкой волатильности, который в случае полос Боллинджера характеризуется узким разрывом между верхними и нижними полосами. Насколько долгим должен быть этот разрыв — вопрос субъективный. Для наших целей мы немного упрощаем ситуацию, поскольку интерпретируем сжатие как любое одновременное сжатие по направлению к основанию полосы Боллинджера как для верхней, так и для нижней полосы. Это означает, что если это сжатие имеет длину всего в один бар, мы будем использовать его. Реализация на языке MQL5 представлена ниже.
//+------------------------------------------------------------------+ //| Check for Pattern 2. | //+------------------------------------------------------------------+ bool CSignalBollingerBands::IsPattern_2(ENUM_POSITION_TYPE T) { m_bands.Refresh(-1); m_close.Refresh(-1); if(Upper(StartIndex()) > Upper(StartIndex() + 1) && Upper(StartIndex() + 1) < Upper(StartIndex() + 2) && Lower(StartIndex()) < Lower(StartIndex() + 1) && Lower(StartIndex() + 1) > Lower(StartIndex() + 2)) { if(T == POSITION_TYPE_BUY && Close(StartIndex()) >= Upper(StartIndex())) { return(true); } else if(T == POSITION_TYPE_SELL && Close(StartIndex()) <= Lower(StartIndex())) { return(true); } } return(false); }
Фактически, согласно нашему коду, длительность сжатия составляет строго один бар. Наш код даже не учитывает, насколько велик разрыв между верхней и нижней полосами, а ведь это еще один ключевой фактор. Из нашего исходного кода выше следует, что любое падение верхней полосы, происходящее одновременно с подъемом нижней полосы, равносильно сжатию. Если после этого сжатия цена находится на уровне верхней полосы или ближе к ней, это свидетельствует о бычьем сигнале. Если же, с другой стороны, после этого сжатия цена находится на нижней границе диапазона, то мы воспринимаем это как медвежий сигнал. Тестовые запуски только с этим паттерном дали нам следующие результаты:
Приведенные выше результаты краткого оптимизационного прогона за 2023 год на дневном таймфрейме для символа USDCHF не прошли перекрестную проверку и служат лишь для указания на потенциал паттерна 2.
Двойное дно около нижней полосы или двойная вершина около верхней полосы
Этот паттерн немного похож на паттерн 1. Главное отличие в том, что здесь мы имеем более одного отскока от внешних полос. Этот паттерн, обозначенный как паттерн 3, можно рассматривать как паттерн 1 с подтверждением. По этой причине он не требует большого количества торговых настроек. Реализация в MQL5:
//+------------------------------------------------------------------+ //| Check for Pattern 3. | //+------------------------------------------------------------------+ bool CSignalBollingerBands::IsPattern_3(ENUM_POSITION_TYPE T) { m_bands.Refresh(-1); m_close.Refresh(-1); m_high.Refresh(-1); m_low.Refresh(-1); if ( T == POSITION_TYPE_BUY && Close(StartIndex() + 4) < Close(StartIndex() + 3) && Close(StartIndex() + 3) > Close(StartIndex() + 2) && Close(StartIndex() + 2) < Close(StartIndex() + 1) && Close(StartIndex() + 1) > Close(StartIndex()) && Close(m_close.MinIndex(StartIndex(), 5)) - Upper(StartIndex()) >= -1.0 * Range(StartIndex()) ) { return(true); } else if ( T == POSITION_TYPE_SELL && Close(StartIndex() + 4) > Close(StartIndex() + 3) && Close(StartIndex() + 3) < Close(StartIndex() + 2) && Close(StartIndex() + 2) > Close(StartIndex() + 1) && Close(StartIndex() + 1) < Close(StartIndex()) && Lower(StartIndex()) - Close(m_close.MaxIndex(StartIndex(), 5)) >= -1.0 * Range(StartIndex()) ) { return(true); } return(false); }
Входная карта, которая ограничивает нас торговлей только с помощью этого шаблона, — это битовая карта 4. Как видно из таблицы выше, рассмотрение подразумеваемых битов показывает, что при счете справа налево все биты равны нулю, за исключением 4-го символа, представляющего наш паттерн 3. Тесты на дневном таймфрейме USDCHF за 2023 дают нам следующие результаты:
Как совершенно очевидно, сделок совершается не так много, поскольку двойное дно на любой из верхних или нижних полос — нечастое явление. Это, возможно, означает, что этот паттерн можно использовать независимо, без связки с другим индикатором, в отличие от некоторых паттернов, которые мы только что рассмотрели выше.
Отскок от средней полосы сверху и отскок снизу
Паттерн 4 развивается вокруг моделей продолжения тренда. Когда цена движется в каком-либо направлении, довольно часто на этом пути случаются некоторые паузы. Во время этих перерывов наблюдается больше резких движений, чем четких трендов, однако довольно часто (но не всегда) перед возобновлением тренда цена может протестировать уровень сопротивления (если тренд нисходящий) или уровень поддержки (если тренд восходящий). Тестирование этих уровней можно охарактеризовать как базовый буфер полос Боллинджера, поскольку он, как и верхняя и нижняя полосы, имеет тенденцию действовать как динамический уровень поддержки/сопротивления.
С помощью этого паттерна мы интерпретируем бычий паттерн, если цена тестирует базу (средний буфер) сверху, а затем отскакивает от нее вверх, и медвежий паттерн, если то же самое происходит в обратном порядке. Отскок снизу. Реализация в MQL5:
//+------------------------------------------------------------------+ //| Check for Pattern 4. | //+------------------------------------------------------------------+ bool CSignalBollingerBands::IsPattern_4(ENUM_POSITION_TYPE T) { m_bands.Refresh(-1); m_close.Refresh(-1); if(T == POSITION_TYPE_BUY && Close(StartIndex() + 2) > Base(StartIndex() + 2) && Close(StartIndex() + 1) <= Base(StartIndex() + 1) && Close(StartIndex()) > Base(StartIndex())) { return(true); } else if(T == POSITION_TYPE_SELL && Close(StartIndex() + 2) < Base(StartIndex() + 2) && Close(StartIndex() + 1) >= Base(StartIndex() + 1) && Close(StartIndex()) < Base(StartIndex())) { return(true); } return(false); }
Тестирование с настройками среды, аналогичными указанным выше, дало нам следующие результаты:
Наш индикатор полос Боллинджера использует одни и те же настройки во всех тестовых прогонах в этой статье, где период индикатора равен 20, а отклонение равно 2.
Дивергенция (расхождение объема) на нижней или верхней полосе
Шестой паттерн, который отслеживает расхождения между объемом и волатильностью. Многие валютные трейдеры, особенно на этой платформе, редко имеют надежные данные об объемах из-за сложностей в интеграции этой информации разными брокерскими компаниями. Таким образом, при отслеживании или измерении объема мы используем, возможно, второго по эффективности посредника. Диапазон ценового бара. Аргументы в пользу использования этого метода заключаются в том, что когда на определенную пару делают ставки многие покупатели, эта пара обязательно сильно изменится в направлении ставки. Это, конечно, не совсем верно, поскольку такое же большое количество коротких контрактов на другом конце может сдержать движение цены, и все же общий задействованный объем не будет отражен в результирующем ценовом диапазоне бара.
Так что это просто компромисс. Мы интерпретируем бычий сигнал, когда диапазон ценового бара систематически уменьшается в течение трех последовательных ценовых баров, и в то же время цена закрытия находится на уровне или ниже нижней полосы полос Боллинджера. Аналогично, у нас будет медвежий сигнал, когда диапазон ценовых баров снизится на 3 бара, а цена закрытия окажется на уровне или выше верхнего буфера полос. Причиной этого может быть истощение предыдущих трендов, когда падение "объема" на крайнем конце ценового диапазона указывает либо на разворот, либо, по крайней мере, на откат. В MQL5 это реализовано следующим образом:
//+------------------------------------------------------------------+ //| Check for Pattern 5. | //+------------------------------------------------------------------+ bool CSignalBollingerBands::IsPattern_5(ENUM_POSITION_TYPE T) { m_bands.Refresh(-1); m_close.Refresh(-1); m_high.Refresh(-1); m_low.Refresh(-1); if(Range(StartIndex()) < Range(StartIndex() + 1) && Range(StartIndex() + 1) < Range(StartIndex() + 2)) { if(T == POSITION_TYPE_BUY && fabs(m_close.GetData(StartIndex()) - Lower(StartIndex())) < fabs(m_close.GetData(StartIndex()) - Base(StartIndex()))) { return(true); } else if(T == POSITION_TYPE_SELL && fabs(m_close.GetData(StartIndex()) - Upper(StartIndex())) < fabs(m_close.GetData(StartIndex()) - Base(StartIndex()))) { return(true); } } return(false); }
Тесты только с этим шаблоном и с использованием тех же настроек среды, что и в предыдущих прогонах, дали нам следующие результаты:
Заключение
Я намеревался охватить все 8 паттернов полос Боллинджера, как указано в прилагаемом коде, но тогда статья получилась бы слишком длинной. Поэтому остальные паттерны я рассмотрю в следующей статье.
Мы рассмотрели 5 из как минимум 8 сигнальных моделей, которые можно использовать при торговле с использованием полос Боллинджера. Этот индикатор не только фиксирует общий тренд цены, но и отслеживает волатильность благодаря двум внешним буферам полос. Как мы видели, если объединить эту информацию с психологией рынка, то на основе одного этого индикатора можно сгенерировать целый ряд сигналов. Хотя каждый из этих паттернов можно использовать по отдельности, как мы и сделали в этой статье для краткости, входной параметр используемых паттернов на самом деле может позволить множественный выбор паттернов, чтобы их можно было комбинировать и оптимизировать для более динамичной настройки, которая лучше подойдет для различных типов рынков. Надеемся, мы рассмотрим это и многое другое в следующей статье.
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/15803





- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Отличная работа!!! Можете поделиться файлом набора для этих результатов?
Нет, я их не храню. Они слишком специфичны.
Спасибо Стивену за эту хорошую статью.