English 中文 Español Deutsch 日本語 Português
Универсальный торговый эксперт: Торговые режимы стратегий (Часть 1)

Универсальный торговый эксперт: Торговые режимы стратегий (Часть 1)

MetaTrader 5Примеры | 7 января 2016, 08:19
15 331 8
Vasiliy Sokolov
Vasiliy Sokolov

Содержание

 

Введение

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

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

Данная статья открывает серию статей, описывающих работу одного такого движка, который условно можно назвать "Универсальный эксперт". Это название объединяет набор классов, позволяющих писать торговые алгоритмы простым способом: обычным перечислением условий на вход и выход из позиции. При этом обеспечивать свой эксперт необходимыми данными и торговой логикой вроде перебора позиций не нужно — все это сделает за вас торговый движок.

Предложенный материал обширен, поэтому разделен на четыре части. Опишем эти части более подробно.

Часть 1. Торговые режимы стратегии. Описывается в данной статье. Первая часть посвящена оригинальной концепции управления позициями на основе торговых режимов. Благодаря торговым режимам можно легко и просто сформулировать торговую логику эксперта. Эксперт, написанный в этом стиле, легко отлаживать. Логика таких экспертов становится универсальной и похожей, что также облегчает управление этими стратегиями. Идеи, изложенные в данном материале, универсальны и не требуют написания объектно-ориентированного кода. Это значит, что не зависимо от того, будете Вы использовать предлагаемый набор библиотек или нет, данный материал может быть Вам полезен.

Часть 2. Событийная модель и прототип торговой стратегии. В данном разделе описывается оригинальная событийная модель на основе централизованной обработки событий. Это значит, что все события "собираются" в одном месте торговой логики эксперта, которая их обрабатывает. Кроме того, события являются мультиинструментальными, например, если эксперт запущен на валютной паре EURUSD, можно получить событие о приходе нового тика на инструменте GBPUSD. Данная событийная модель может быть крайне полезной при написании экспертов, торгующих на нескольких инструментах. В данной части также описывается базовый класс торгового движка CStrategy и класс, представляющий позицию в MetaTrader 5 — CPositionMT5.

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

Часть 4. Торговля в группе и управление портфелем стратегий. В данной части описываются специальные алгоритмы, с помощью которых можно интегрировать несколько торговых логик в один исполняющий модуль ex5. Также описываются механизмы, с помощью которых можно формировать набор пользовательских стратегий с использованием XML-файла.

 

Методы открытия новой и сопровождения существующей позиции

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

Рис. 1. График торговой системы на двух скользящих средних

Красной линией показана быстрая простая скользящая средняя с периодом 50. Синей линией показана медленная скользящая средняя с периодом 120. В моменты их пересечения (они указаны синими пунктирными линиями) направление позиции эксперта меняется на противоположное. С неалгоритмической точки зрения данного описания достаточно, чтобы каждый трейдер смог понять, как торговать по данной стратегии. Однако, если мы собрались создать эксперта, основанного на этой стратегии, данного описания будет явно недостаточно.

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

  1. Если в момент пересечения средних у эксперта существует открытая короткая позиция — ее необходимо закрыть.
  2. Убедиться в отсутствии ранее открытой длинной позиции. Если длиной позиции нет — открыть ее, если есть — ничего не делать.

Действия в момент пересечения быстрой скользящей средней медленной сверху вниз будут противоположными по направлению:

  1. Если в момент пересечения средних у эксперта существует открытая длинная позиция — ее необходимо закрыть.
  2. Убедиться в отсутствии ранее открытой короткой позиции. Если короткой позиции нет — открыть ее, если есть — ничего не делать.

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

Сделаем так, что для покупки и продажи будут использоваться разные наборы средних. Например, в длинную позицию мы будем входить, когда быстрая скользящая средняя с периодом 50 пересекла медленную скользящую среднюю с периодом 120. А вот продавать мы начнем, когда быстрая скользящая средняя с периодом 20 пересекла медленную скользящую среднюю с периодом 70. Согласно новым правилам, сигналы на покупку перестанут совпадать с сигналами на продажу — они начнут возникать в разные моменты времени, при различных рыночных ситуациях.

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

Рассмотри наши действия под другим углом. Приведем таблицу, в которой по горизонтали будет указан тип торговой операции (Buy или Sell), а по вертикали — тип торгового действия (открыть или закрыть). В самих ячейках таблицы будет указан конкретный набор действий:

Buy Sell
Открыть 1. Если длинных позиций нет и быстрая скользящая средняя с периодом 50 выше медленной скользящей средней с периодом 120 — открыть длинную позицию 2. Если коротких позиций нет и быстрая скользящая средняя с периодом 20 ниже медленной скользящей средней с периодом 70 — открыть короткую позицию
Закрыть 3. Если быстрая скользящая средняя с периодом 50 ниже медленной скользящей средней с периодом 120 — закрыть длинную позицию 4. Если быстрая скользящая средняя с периодом 20 выше медленной скользящей средней с периодом 70 — закрыть короткую позицию

 

Таблица 1. Наборы торговых действий

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

  • BuyInit — метод, открывающий новую длинную позицию, если согласно перечисленным в нем условиям наступил момент для открытия длинной позиции;
  • SellInit — метод, открывающий новую короткую позицию, если согласно перечисленным в нем условиям наступил момент для открытия короткой позиции;
  • SupportBuy — метод, получающий в качестве параметра длинную позицию. Если переданную позицию требуется закрыть, данный метод должен выполнить соответствующее торговое действие.
  • SupportSell — метод, получающий в качестве параметра короткую позицию. Если переданную позицию требуется закрыть, данный метод должен выполнить соответствующее торговое действие.

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

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

 

Торговые режимы стратегии

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

Рис. 2. Режимы торговли в MetaTrader 4

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

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

Торговый режим Описание Методы, которые вызываются Методы, чьи вызовы пропускаются
Покупки и продажи Разрешены сделки как на покупку, так и на продажу. Ограничений в торговле нет. BuyInit
SellInit
BuySupport
SellSupport
Только покупки Разрешены только покупки. Продажи не производятся. Ранее открытые короткие позиции сопровождаются в штатном режиме до момента закрытия. BuyInit
BuySupport
SellSupport
SellInit
Только продажи Разрешены только продажи. Покупки не производятся. Ранее открытые длинные позиции сопровождаются в штатном режиме до момента закрытия. SellInit
BuySupport
SellSupport
BuyInit
Отсутствие новых входов Запрещено открывать новые сделки на продажу и покупку. Ранее открытые длинные и короткие позиции сопровождаются в штатном режиме до момента их закрытия по сигналам выхода. BuySupport
SellSupport
BuyInit
SellInit
Ожидание Контроль над сопровождением ранее открытых позиций останавливается. Инициализация новых сделок на продажу и покупку приостанавливается. Данный режим, как правило, используется в моменты, когда рынок закрыт и совершать торговые действия нельзя. BuyInit
SellInit
BuySupport
SellSupport
Стоп Все ранее открытые позиции принудительно закрываются. Новые позиции, как на покупку, так и на продажу, не инициируются. Закрытие всех открытых позиций с помощью специального метода BuyInit
SellInit
BuySupport
SellSupport

 

Таблица 2. Режимы торговли эксперта

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

//+------------------------------------------------------------------+
//| Определяет торговое состояние эксперта.                          |
//+------------------------------------------------------------------+
enum ENUM_TRADE_STATE
{
   TRADE_BUY_AND_SELL,              // Разрешены покупки и продажи.
   TRADE_BUY_ONLY,                  // Разрешены только покупки. Продажи запрещены.
   TRADE_SELL_ONLY,                 // Разрешены только продажи. Покупки запрещены.
   TRADE_STOP,                      // Торговля запрещена. Немедленно закрыть все позиции. Новые сигналы на вход не принимать.
   TRADE_WAIT,                      // Контроль над открытыми позициями теряется. Новые сигналы игнорируются. Полезен в моменты выхода новостей.
   TRADE_NO_NEW_ENTRY               // Сигналы на вход игнорируются. Однако уже открытые позиции сопровождаются согласно торговой логике. 
};

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

 

Переключатель торговых режимов CTradeState

Используя торговые режимы, эксперт всегда сможет понять, в какой момент времени выполнять те или иные действия. Однако сам этот момент времени необходимо задать индивидуально, для каждого эксперта в отдельности. Управление режимами особенно необходимо при торговле в секции FORTS Московской биржи. У биржевой торговли в этой секции есть несколько особенностей, главная из которых — проведение клиринга дважды в день, с 14:00 до 14:03 (промежуточный клиринг) и с 18:45 до 19:00 (основной клиринг). Крайне желательно не давать возможности эксперту в эти моменты времени совершать торговые действия.

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

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

//+------------------------------------------------------------------+
//|                                                  TimeControl.mqh |
//|                                 Copyright 2015, Vasiliy Sokolov. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Vasiliy Sokolov."
#property link      "http://www.mql5.com"
#include "Strategy.mqh"
#define ALL_DAYS_OF_WEEK 7
//+------------------------------------------------------------------+
//| Модуль торговых состояний TradeState                             |
//+------------------------------------------------------------------+
class CTradeState
{
private:
   ENUM_TRADE_STATE  m_state[60*24*7];  // Маска торговых состояний
public:
                     CTradeState(void);
                     CTradeState(ENUM_TRADE_STATE default_state);
   ENUM_TRADE_STATE  GetTradeState(void);
   ENUM_TRADE_STATE  GetTradeState(datetime time_current);
   void              SetTradeState(datetime time_begin, datetime time_end, int day_of_week, ENUM_TRADE_STATE state);
};

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

Алгоритм работы модуля напоминает вкладку "Расписание" агента тестирования в MetaTrader 5:

Рис. 3. Вкладка "Расписание" в агенте тестирования MetaTrader 5

Данное окно позволяет установить рабочие диапазоны по дням недели, в течение которых можно выполнять задания из MQL5 Cloud Network. Класс CTradeState работает схожим образом, однако позволяет для каждого диапазона устанавливать одно из пяти значений перечисления ENUM_TRADE_STATE.

Чтобы лучше понять, как использовать CTradeState, сконфигурируем модуль торговых состояний. В повседневной работе на рынке FORTS автор данной статьи использует следующую конфигурацию, представленную в виде таблицы:

Время Режим Описание
10:00-10:01 TRADE_WAIT Время открытия рынка. Момент открытия характеризуется высокой волатильностью и резкими скачками цен. Торговые действия в эти моменты сопряжены с высоким риском, поэтому в первую минуту торгов лучше воздержаться от торговли, для чего перевести эксперт в режим ожидания.
14:00 - 14:03 TRADE_WAIT Время проведения промежуточного клиринга. В этот промежуток времени рынок не работает, поэтому торговый эксперт также необходимо установить в режим TRADE_WAIT.
18:45 - 18:49 TRADE_WAIT Время проведения основного клиринга. В этот момент рынок также закрыт и торговля запрещена. Действует режим TRADE_WAIT.
23:50 - 9:59 TRADE_WAIT Рынок закрыт, торговля запрещена. Режим советника TRADE_WAIT.
Пятница, с 15:00 TRADE_NO_NEW_ENTRY Пятница — последний торговый день недели. Чтобы не оставлять открытые позиции на выходные дни, требуется их закрывать в последний день торгов. Поэтому открывать новые позиции в последний день торгов, чтобы через несколько часов их закрыть, не имеет смысла. Именно для этих целей используется режим NO_NEW_ENTRY. Каждую пятницу, начиная с 15:00, новые сигналы на вход игнорируются. Существующие позиции могут только закрываться.
Пятница, 23:40-23:50 TRADE_STOP Время, предшествующее закрытию рынка. В это время все позиции должны быть закрыты. Торговый эксперт, перейдя в 23:40 в режим TRADE_STOP, закроет свою открытую позицию и перейдет в режим ожидания.
Суббота, Воскресенье TRADE_WAIT В выходные дни торговля не ведется. Из-за переноса праздников некоторые субботние дни могут быть рабочими. В такие дни биржа работает. Это очень редкое явление, и таких "рабочих" дней необходимо избегать из-за низкой волатильности и статистической неопределенности. Торговля в эти дни должна быть запрещена независимо от того, рабочий это день или нет.

 

Таблица 3. Торговые режимы в зависимости от времени

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

//+------------------------------------------------------------------+
//|                                               TestTradeState.mq5 |
//|                                 Copyright 2015, Vasiliy Sokolov. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Vasiliy Sokolov."
#property link      "http://www.mql5.com"
#property version   "1.00"
#include <Strategy\TradeState.mqh>

CTradeState TradeState(TRADE_BUY_AND_SELL);  // Устанавливаем режим по умолчанию Buy And Sell
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
   TradeState.SetTradeState(D'15:00', D'23:39', FRIDAY, TRADE_NO_NEW_ENTRY);
   TradeState.SetTradeState(D'10:00', D'10:01', ALL_DAYS_OF_WEEK, TRADE_WAIT);
   TradeState.SetTradeState(D'14:00', D'14:03', ALL_DAYS_OF_WEEK, TRADE_WAIT);
   TradeState.SetTradeState(D'18:45', D'18:59', ALL_DAYS_OF_WEEK, TRADE_WAIT);
   TradeState.SetTradeState(D'23:50', D'23:59', ALL_DAYS_OF_WEEK, TRADE_WAIT);
   TradeState.SetTradeState(D'0:00',  D'9:59',  ALL_DAYS_OF_WEEK, TRADE_WAIT);
   TradeState.SetTradeState(D'23:40', D'23:49', FRIDAY, TRADE_STOP);
   TradeState.SetTradeState(D'00:00', D'23:59', SATURDAY, TRADE_WAIT);
   TradeState.SetTradeState(D'00:00', D'23:59', SUNDAY, TRADE_WAIT);
   
   printf("10:00 - " + EnumToString(TradeState.GetTradeState(D'10:00')));
   printf("14:01 - " + EnumToString(TradeState.GetTradeState(D'14:01')));
   printf("18:50 - " + EnumToString(TradeState.GetTradeState(D'18:50')));
   printf("23:50 - " + EnumToString(TradeState.GetTradeState(D'23:51')));
   printf("Friday, > 15:00 - " + EnumToString(TradeState.GetTradeState(D'2015.11.27 15:00')));
   printf("Saturday - " + EnumToString(TradeState.GetTradeState(D'2015.11.28')));
   printf("Sunday - " + EnumToString(TradeState.GetTradeState(D'2015.11.29')));
   printf("Default State - " + EnumToString(TradeState.GetTradeState(D'11:40')));
}
//+------------------------------------------------------------------+

Вывод этого скрипта будет следующий:

Default State - TRADE_BUY_AND_SELL
Sunday - TRADE_WAIT
Saturday - TRADE_WAIT
Friday, > 15:00 - TRADE_NO_NEW_ENTRY
23:50 - TRADE_STOP
18:50 - TRADE_WAIT
14:01 - TRADE_WAIT
10:00 - TRADE_WAIT

Обратите внимание, в каком формате задаются режимы торговли. В них не используется компонента даты, а только часы и минуты (D'15:00' или D'18:40'), Если методу передать полную дату, например так:

TradeState.SetTradeState(D'2015.11.27 15:00', D'2015.11.27 23:39', FRIDAY, TRADE_NO_NEW_ENTRY);

Компонента даты все равно будет проигнорирована.

Второй момент, на который необходимо обратить внимание, это последовательность вызовов SetTradeState. Последовательность имеет значение! Дело в том, что модуль CTradeState хранит маску торговых состояний в виде массива ENUM_TRADE_STATE, количество элементов которого равно количеству минут в неделе (10 080 элементов). Метод SetTradeState на основе переданных дат рассчитывает диапазон элементов этого массива, после чего заполняет их соответствующим состоянием. Это значит, что предыдущее состояние заменяется на новое. Таким образом, последнее изменение становится окончательным. Полный код этого метода представлен ниже:

//+------------------------------------------------------------------+
//| Устанавливает торговое состояние TradeState                      |
//| INPUT:                                                           |
//| time_begin  - Время, начиная с которого действует торговое       |
//|               состояние.                                         |
//| time_end    - Время, до которого действует торговое состояние    |
//| day_of_week - День недели, на который распространяется установка |
//|               торгового состояния. Соответствует модификаторам   |
//|               ENUM_DAY_OF_WEEK или модификатору ALL_DAYS_OF_WEEK |
//| state       - Торговое состояние.                                |
//| Внимание, компонента даты в time_begin и time_end игнорируется.  |
//+------------------------------------------------------------------+
void CTradeState::SetTradeState(datetime time_begin,datetime time_end, int day_of_week, ENUM_TRADE_STATE state)
{
   if(time_begin > time_end)
   {
      string sb = TimeToString(time_begin, TIME_MINUTES);
      string se = TimeToString(time_end, TIME_MINUTES);
      printf("Time " + sb + " must be more time " + se);
      return;
   }
   MqlDateTime btime, etime;
   TimeToStruct(time_begin, btime);
   TimeToStruct(time_end,  etime);
   for(int day = 0; day < ALL_DAYS_OF_WEEK; day++)
   {
      if(day != day_of_week && day_of_week != ALL_DAYS_OF_WEEK)
         continue;
      int i_day = day*60*24;
      int i_begin = i_day + (btime.hour*60) + btime.min;
      int i_end = i_day + (etime.hour*60) + etime.min;
      for(int i = i_begin; i <= i_end; i++)
         m_state[i] = state;
   }
}

Метод GetTradeState работает проще. Он рассчитывает индекс элемента массива, который соответствует запрашиваемому времени, после чего возвращает значение этого элемента:

//+------------------------------------------------------------------+
//| Возвращает ранее заданное торговое состояние для переданного     |
//| времени.                                                         |
//+------------------------------------------------------------------+
ENUM_TRADE_STATE CTradeState::GetTradeState(datetime time_current)
{
   MqlDateTime dt;
   TimeToStruct(time_current, dt);
   int i_day = dt.day_of_week*60*24;
   int index = i_day + (dt.hour*60) + dt.min;
   return m_state[index];
}

Полный исходный код класса CTradeState приведен в файле TradeState.mqh и доступен в составе исходных кодов описываемого торгового движка. О том, как работает данный класс в его составе, будет написано в следующих частях статьи.

 

Заключение

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

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

Вы можете скачать и установить полные коды библиотеки "Универсальный эксперт" себе на компьютер. Исходный код библиотеки включен в качестве приложения к данному материалу. Описание большей части классов этой библиотеки будет дано в следующих статьях серии.

Прикрепленные файлы |
strategyarticle.zip (85.76 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (8)
Vasiliy Sokolov
Vasiliy Sokolov | 7 янв. 2016 в 15:29
Maxim Kuznetsov:
То что торговые режимы появляются это бесспорно. Только задавать эти режимы лучше снаружи, вообще внешними средствами. Так из советника "уходит" лишний код, как ни крути, а он ест ресурсы (и вычислительные, и на разработку, и на поддержку и проч.). Зато вместо советника получается эдакий "торговый комплекс", где можно с одного пульта рулить несколькими совами.

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

Alexander Fedosov
Alexander Fedosov | 17 февр. 2016 в 21:11
Идея мне показалась достаточно интересное, буду читать далее. Спасибо за статью.
Dmitry Fedoseev
Dmitry Fedoseev | 18 февр. 2016 в 10:58
Maxim Kuznetsov:
То что торговые режимы появляются это бесспорно. Только задавать эти режимы лучше снаружи, вообще внешними средствами. Так из советника "уходит" лишний код, как ни крути, а он ест ресурсы (и вычислительные, и на разработку, и на поддержку и проч.). Зато вместо советника получается эдакий "торговый комплекс", где можно с одного пульта рулить несколькими совами.

С чего вы взяли что лучше? Ваш подход отвратителен! Еще расскажите о том. какой вы реалист, и что тестером не пользуетесь.

Получается куча функций от которых зависит результат работы советника, но которые невозможно проверять в тестере.

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

Yuriy Asaulenko
Yuriy Asaulenko | 11 авг. 2016 в 22:36

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

Спасибо. 

Vasiliy Sokolov
Vasiliy Sokolov | 12 авг. 2016 в 13:43
Yuriy Asaulenko:

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

Спасибо. 

Пример XML-сериализации стратегий:

<Global>
        <Strategies>
                <Strategy Name="MovingAverage" Magic="100" Timeframe="PERIOD_M1" Symbol="Si">
                        <TradeStateStart>Stop</TradeStateStart>
                        <Params>
                                <FastMA>1</FastMA>
                                <SlowMA>3</SlowMA>
                                <Shift>0</Shift>
                                <Method>MODE_SMA</Method>
                                <AppliedPrice>PRICE_CLOSE</AppliedPrice>
                        </Params>
                </Strategy>
                <Strategy Name="MovingAverage" Magic="101" Timeframe="PERIOD_M5" Symbol="SBRF">
                        <TradeStateStart>BuyOnly</TradeStateStart>
                        <Params>
                                <FastMA>15</FastMA>
                                <SlowMA>21</SlowMA>
                                <Shift>0</Shift>
                                <Method>MODE_SMA</Method>
                                <AppliedPrice>PRICE_CLOSE</AppliedPrice>
                        </Params>
                </Strategy>
                <Strategy Name="BollingerBands" Magic="102" Timeframe="PERIOD_M15" Symbol="GAZR">
                        <TradeStateStart>BuyAndSell</TradeStateStart>
                        <Params>
                                <Period>30</Period>
                                <StdDev>1.5</StdDev>
                        </Params>
                </Strategy>
                <Strategy Name="BollingerBands" Magic="103" Timeframe="PERIOD_M30" Symbol="ED">
                        <TradeStateStart>BuyAndSell</TradeStateStart>
                        <Params>
                                <Period>20</Period>
                                <StdDev>2.0</StdDev>
                        </Params>
                </Strategy>
        </Strategies>
</Global>

Вопрос серриализации стратегий разбирается в следующих частях. Там присутствует этот пример.

Графические интерфейсы I: Функции для кнопок формы и удаление элементов интерфейса (Глава 4) Графические интерфейсы I: Функции для кнопок формы и удаление элементов интерфейса (Глава 4)
В этой главе продолжим развивать класс CWindow, дополняя его методами, которые позволят управлять формой посредством нажатия на ее элементах. Сделаем так, чтобы программу можно было закрыть через кнопку на форме, а также реализуем возможность сворачивания и разворачивания формы при необходимости.
Графические интерфейсы I: "Оживление" графического интерфейса (Глава 3) Графические интерфейсы I: "Оживление" графического интерфейса (Глава 3)
В предыдущей статье серии был начат процесс разработки класса формы для элементов управления. В этой статье продолжим развивать класс, наполняя его методами для перемещения формы в области графика, а также интегрируем этот элемент интерфейса в ядро библиотеки. Кроме этого, настроим всё таким образом, чтобы при наведении курсора на элементы формы изменялся их цвет.
Универсальный торговый эксперт: Событийная модель и прототип торговой стратегии (Часть 2) Универсальный торговый эксперт: Событийная модель и прототип торговой стратегии (Часть 2)
Данная статья продолжает серию заметок, посвященных универсальной модели эксперта. В этой части описывается оригинальная событийная модель на основе централизованной обработки данных, а также рассматривается структура базового класса движка — CStrategy.
Графические интерфейсы I: Форма для элементов управления (Глава 2) Графические интерфейсы I: Форма для элементов управления (Глава 2)
В этой статье создадим первый и самый главный элемент графических интерфейсов — форму для элементов управления. К этой форме можно будет присоединять множество различных элементов управления в любом расположении и в любых комбинациях.