English Español Deutsch 日本語 Português
preview
Возможности Мастера MQL5, которые вам нужно знать (Часть 25): Тестирование и торговля на нескольких таймфреймах

Возможности Мастера MQL5, которые вам нужно знать (Часть 25): Тестирование и торговля на нескольких таймфреймах

MetaTrader 5Торговые системы | 19 декабря 2024, 12:38
135 2
Stephen Njuki
Stephen Njuki

Введение

В предыдущей статье мы рассмотрели пифагоровы средние, которые представляют собой группу скользящих средних. Некоторые из них являются довольно новыми и недостаточно распространенными, несмотря на их потенциальную пользу для трейдеров, доказанную отчетами о тестировании. Эти пифагоровы средние были представлены в виде полукруговой диаграммы, которая суммировала каждое среднее значение при использовании двух неравных значений, сумма которых составляла диаметр полукруга. Среди значений хорды в полукруге было значение, не рассмотренное в статье. Это значение Q, представляющее среднее квадратическое двух значений - a и b.

Среднее квадратическое (quadratic mean, QM) стремится к большим значениям в множестве, среднее значение которого ищется, что отличает его от среднего геометрического и гармонического, которые мы рассматривали в предыдущей статье. Подобно тому, как среднее геометрическое возвращает только положительные значения, выборка, для которой ищется среднее значение, должна иметь только положительные значения. Наша цель в статье - реализация мультитаймфреймовых стратегий в советниках, собранных с помощью Мастера, поэтому QM будет просто инструментом, который мы используем, чтобы показать, как можно тестировать мультитаймфреймовые стратегии в советнике, собранном с помощью Мастера.

Так почему же тестирование на нескольких таймфреймах с помощью советников, созданных с помощью Мастера, является сложным? По моему мнению, это связано с тем, что настройка должна выполняться для каждого добавленного сигнала в пространстве сборки Мастера, что часто упускается из виду. Настройку символов и таймфреймов для советника, собранного с помощью Мастера, можно выполнить на этапах выбора сигнала, но большинство пользователей полагают, что при выборе сигнала, необходимо выбрать символ и таймфрейм, но при сборке с помощью Мастера это не так. В одной из предыдущих статей я показал различные способы реализации торговли несколькими символами в советниках, собранных с помощью Мастера, путем модификации исходного кода. Один очевидный и основной подход, которым я не поделился, — это присоединение множества сигналов, где каждое присоединение относится к определенному символу. Эти множественные присоединения происходят, несмотря на присоединение одного и того же сигнала. Настройка сигнала при назначении символа должна выполняться в соответствии с шагами, указанными ниже:

n1


n2

Аналогично, для каждого советника в сигнале в качестве входного параметра можно настроить несколько таймфреймов (пример кода прилагается). Однако предпочтительным подходом может быть присвоение каждого требуемого таймфрейма сигналу и независимое присоединение этого сигнала к сборке Мастера. Шаги по настройке таймфреймов для каждого сигнала очень похожи на те, о которых мы рассказывали выше при торговле несколькими символами.

f1


f2

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

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

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

В частности, на этапе настройки параметров экземпляру класса сигналов Expert назначаются торговый символ и таймфрейм. Тем не менее, согласно документации, это может произойти и на этапе проверки параметров. Я думаю, что этап установки параметров называется этапом настройки, но мне не удалось найти документацию по этому поводу. Таким образом, поскольку торговый символ определяет множество параметров, на которые будет опираться класс сигнала, например, какие цены OHLC загружать, размер пункта и так далее, по умолчанию торговый символ и таймфрейм устанавливаются один раз при инициализации. Аналогично, таймфрейм для извлечения ценовых буферов OHLC должен быть определен заранее. Это также происходит во время инициализации, но не после нее.

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

Однако есть одно нюанс, когда дело доходит до торговли несколькими символами в этом режиме предварительного назначения в Мастере. Как мы видели в уже упомянутой статье, нам по-прежнему необходимо создать экземпляр массива класса CExpert и переназначить наши необходимые торговые символы каждому экземпляру класса советника в этом массиве. Похоже, назначение символов Мастером заключается лишь в определении того, какой символ будет использоваться при извлечении данных о ценах OHLC в перечислениях USED_SERIES. Однако фактический символ, который торгуется после инициализации в классе данных о символе m_symbol, — это символ, назначенный на самом первом шаге сборки Мастером, до выбора какого-либо сигнала.

s1

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


Сложности этапа настройки при инициализации

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


Квадратические скользящие средние

Средние квадратические (Quadratic Averages, QA) представляют собой просто квадратный корень из среднего значения всех квадратов значений в множестве. Как и большинство неарифметических средних значений, они имеют смещение или весовое предпочтение, и оно, в отличие от среднего геометрического и среднего гармонического, направлено в сторону больших значений в множестве. На полукруглой диаграмме, показанной в предыдущей статье, где различные типы средних значений для двух равных значений a и b были представлены в масштабе внутри полукруга, также было указано среднее квадратическое, и оно было эквивалентно длине хорды, обозначенной Q.

где

  • n - количество значений в множестве
  • x - значения в множестве по соответствующему индекс

Мы используем QM для разработки и тестирования пользовательского сигнала, который торгует на нескольких таймфреймах, и еще одного пользовательского сигнала, который также торгует на нескольких символах. В предыдущей статье из-за смещения или весового предпочтения в сторону меньших значений в множестве для среднего геометрического и гармонического мы разработали зеркальные средние, которые имели смещения в сторону больших значений. Реализация QM в MQL5:

//+------------------------------------------------------------------+
//| Quadratic Mean                                                   |
//+------------------------------------------------------------------+
double CSignalQM::QM(int Index, int Mask = 8)
{  vector _f;
   _f.CopyRates(m_symbol.Name(), m_period, Mask, Index, m_length);
   vector _p = _f*_f;
   double _m = _p.Mean();
   return(sqrt(_m));
}

Прежде чем углубиться в изучение возможных применений, было бы разумно сделать что-то подобное для QM, поскольку оно склоняется к большим значениям. Зеркальное среднее QM' будет больше ориентировано на меньшие значения. Опять же, эта дихотомия меньшего веса стоимости против большего веса стоимости может позволить нам вывести низкие ценовые буферы и высокие ценовые буферы соответственно.

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

QM' можно задать формулой, похожей на ту, которую мы приводили в предыдущей статье:

//+------------------------------------------------------------------+
//| Inverse Quadratic Mean                                           |
//+------------------------------------------------------------------+
double CSignalQM::QM_(int Index, int Mask = 8)
{  double _am = AM(Index, Mask);
   double _qm = QM(Index, Mask);
   return(_am + (_am - _qm));
}

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

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

Как мы уже отмечали выше, собранные с помощью Мастера MQL5 советники были разработаны для обеспечения возможности тестирования (и торговли) на нескольких таймфреймах и нескольких символах на основе каждого сигнала. Каждый используемый советником сигнал получает свой собственный символ и/или таймфрейм, прежде чем он добавляется в Мастер. Это означает, что мы могли бы провести тестирование на наличие нескольких символов и нескольких временных интервалов для любого сигнала, однако, поскольку в предыдущей статье мы рассматривали только новые средние значения, мы продолжим в том же духе, охватив квадратические средние значения.


Разработка пользовательских классов сигналов с помощью QMA

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

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

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

//+------------------------------------------------------------------+
//| "Voting" that price will grow.                                   |
//+------------------------------------------------------------------+
int CSignalQM::LongCondition(void)
{  int result = 0;
   m_close.Refresh(-1);
   if(m_close.GetData(StartIndex()) > m_close.GetData(StartIndex() + 1) && m_close.GetData(StartIndex()) > BandsDn(StartIndex()) && m_close.GetData(StartIndex() + 1) < BandsDn(StartIndex() + 1))
   {  result = int(round(100.0 * ((m_close.GetData(StartIndex()) - m_close.GetData(StartIndex()+1))/(fabs(m_close.GetData(StartIndex()) - m_close.GetData(StartIndex()+1)) + fabs(BandsUp(StartIndex()) - BandsDn(StartIndex()))))));
   }
   return(result);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall.                                   |
//+------------------------------------------------------------------+
int CSignalQM::ShortCondition(void)
{  int result = 0;
   m_close.Refresh(-1);
   if(m_close.GetData(StartIndex()) < m_close.GetData(StartIndex() + 1) && m_close.GetData(StartIndex()) < BandsUp(StartIndex()) && m_close.GetData(StartIndex() + 1) > BandsUp(StartIndex() + 1))
   {  result = int(round(100.0 * ((m_close.GetData(StartIndex()+1) - m_close.GetData(StartIndex()))/(fabs(m_close.GetData(StartIndex()) - m_close.GetData(StartIndex()+1)) + fabs(BandsUp(StartIndex()) - BandsDn(StartIndex()))))));
   }
   return(result);
}


Практическая реализация и тестирование

После того, как советник, использующий наш сигнал выше, собран в Мастере, если мы используем несколько таймфреймов, то заголовочная часть файла *MQ5 будет выглядеть следующим образом:

//+------------------------------------------------------------------+
//|                                                           qm.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include                                                          |
//+------------------------------------------------------------------+
#include <Expert\Expert.mqh>
//--- available signals
#include <Expert\Signal\My\SignalWZ_25.mqh>
//--- available trailing
#include <Expert\Trailing\TrailingNone.mqh>
//--- available money management
#include <Expert\Money\MoneyFixedMargin.mqh>
//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
//--- inputs for expert
input string Expert_Title           = "qm_frame"; // Document name
ulong        Expert_MagicNumber     = 2028; //
bool         Expert_EveryTick       = false; //
//--- inputs for main signal
input int    Signal_ThresholdOpen   = 10;   // Signal threshold value to open [0...100]
input int    Signal_ThresholdClose  = 10;   // Signal threshold value to close [0...100]
input double Signal_PriceLevel      = 0.0;  // Price level to execute a deal
input double Signal_StopLevel       = 50.0; // Stop Loss level (in points)
input double Signal_TakeLevel       = 50.0; // Take Profit level (in points)
input int    Signal_Expiration      = 4;    // Expiration of pending orders (in bars)
input int    Signal_0_QM_Length     = 50;   // QM(50) H1 Averaging Length
input double Signal_0_QM_Weight     = 1.0;  // QM(50) H1 Weight [0...1.0]
input int    Signal_1_QM_Length     = 50;   // QM(50) H4 Averaging Length
input double Signal_1_QM_Weight     = 1.0;  // QM(50) H4 Weight [0...1.0]
input int    Signal_2_QM_Length     = 50;   // QM(50) D1 Averaging Length
input double Signal_2_QM_Weight     = 1.0;  // QM(50) D1 Weight [0...1.0]
//--- inputs for money
input double Money_FixMargin_Percent = 10.0; // Percentage of margin

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


Отчеты и анализ тестера стратегий

Если мы проведем тестовые прогоны для 2023 года на часовом таймфрейме для пары EURJPY, одновременно стремясь получить сбалансированный сигнал от 1-часового, 4-часового и дневного таймфреймов, то получим следующие результаты:

r2

c2

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

r1

c1


Заключение

В заключение мы показали, как можно использовать несколько таймфреймов в советниках, собранных с помощью Мастера. Основной момент, который мы рассмотрели, заключается в том, что процесс сборки в Мастере позволяет каждому сигналу иметь не только свой собственный таймфрейм, но и свой собственный торговый символ. Настройка сигнала путем назначения ему определенного таймфрейма подразумевает, что буферы OHLC для этого сигнала будут привязаны к этому таймфрейму, и это относительно простой процесс, в отличие от настройки сигнала для торговли конкретным символом. Это связано с тем, что когда сигналы назначаются для торговли определенным символом, необходимо внести дополнительные изменения в экземпляр класса CExpert, который должен быть представлен в формате массива для размещения каждого торгуемого символа. При демонстрации торговли с несколькими таймфреймами мы использовали квадратические средние в качестве сигнала, где, как и в предыдущей статье, мы вывели его зеркальную версию, которая имеет больший вес в сторону меньших значений в усредненном наборе, учитывая, что среднее квадратическое по умолчанию имеет больший вес в сторону больших значений. Мы протестировали это в двух условиях, где в одном случае всегда оценивались вероятности, а в другом — искались определенные сигналы для входа, и при каждом подходе мы получили существенно разные результаты.

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

Читатели могут провести необходимую тесты и реализовать вышесказанное. Оба экземпляра этих классов сигналов прикреплены ниже, и, кроме того, существуют альтернативные реализации с несколькими таймфреймами, которые могут принимать в качестве входных данных таймфрейм индикатора, причем этот таймфрейм будет отличаться от таймфрейма графика, к которому прикреплен советник. Такой подход позволяет обойти проблему невозможности выбора оптимального таймфрейма, которая возникает, когда таймфреймы назначаются сигналу во время сборки в Мастере. Используя необходимый входной параметр сигнала, такой подход можно оптимизировать для наилучшего соответствия стратегии. Интересно, что этот подход можно использовать даже для назначения таймфреймов пользовательскому буферу OHLC. Его главный недостаток заключается в мультисимвольной торговле, где, несмотря на то, что значения цен и индикаторов можно получить из имени символа, являющегося параметром, размещение сделок возможно только в том случае, если в собранный файл Expert внесены упомянутые выше изменения.


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

Последние комментарии | Перейти к обсуждению на форуме трейдеров (2)
Marcel Fitzner
Marcel Fitzner | 5 окт. 2024 в 13:22
Кроме того, что в статье показано, как в мастер советника добавляются различные таймфреймы, в коде не показано, как именно происходит тестирование на нескольких таймфреймах - или я что-то упустил?
Khaled Ali E Msmly
Khaled Ali E Msmly | 8 окт. 2024 в 19:44

Привет,Стивен

Ваша статья очень замечательная, спасибо вам за нее. Можете ли вы прикрепить файлы, чтобы мы могли попробовать, или код в статье - это весь код, используемый в эксперименте?

Многомодульный торговый робот на Python и MQL5 (Часть I): Создание базовой архитектуры и первых модулей Многомодульный торговый робот на Python и MQL5 (Часть I): Создание базовой архитектуры и первых модулей
Разрабатываем модульную торговую систему, объединяющую Python для анализа данных с MQL5 для исполнения сделок. Четыре независимых модуля параллельно следят за разными аспектами рынка: объемами, арбитражем, экономикой и рисками, а для анализа используют RandomForest с 400 деревьями. Особый упор сделан на риск-менеджмент, ведь без грамотного управления рисками даже самые продвинутые торговые алгоритмы бесполезны.
Построение модели для ограничения диапазона сигналов по тренду (Часть 5): Система уведомлений (Часть III) Построение модели для ограничения диапазона сигналов по тренду (Часть 5): Система уведомлений (Часть III)
Эта часть серии посвящена интеграции WhatsApp с MetaTrader 5 для получения уведомлений. Мы рассмотрим блок-схему для упрощения понимания и обсудим важность мер безопасности при интеграции. Основная цель индикаторов — упростить анализ за счет автоматизации. Они должны включать методы уведомления для оповещения пользователей при выполнении определенных условий.
Алгоритм черной дыры — Black Hole Algorithm (BHA) Алгоритм черной дыры — Black Hole Algorithm (BHA)
Алгоритм черной дыры (Black Hole Algorithm, BHA) использует принципы гравитации черных дыр для оптимизации решений. В статье мы рассмотрим, как BHA притягивает лучшие решения, избегая локальных экстремумов, и почему этот алгоритм стал мощным инструментом для решения сложных задач. Узнайте, как простые идеи могут привести к впечатляющим результатам в мире оптимизации.
Критерии тренда в трейдинге Критерии тренда в трейдинге
Тренды являются важной частью многих торговых стратегий. В этой статье мы рассмотрим некоторые инструменты, используемые для определения трендов и их характеристик. Понимание и правильная интерпретация трендов могут значительно повысить эффективность трейдинга и минимизировать риски.