- Основные понятия календаря
- Получение списка и описаний доступных стран
- Запрос видов событий по странам и валютам
- Получение описания вида события по идентификатору
- Получение записей о событиях по странам или валютам
- Получение записей о событиях конкретного вида
- Чтение записи о событии по идентификатору
- Отслеживание изменений событий по стране или валюте
- Отслеживание изменений событий по типу
- Фильтрация событий по множеству условий
- Перенос базы календаря в тестер
- Торговля по календарю
Торговля по календарю
Существует множество новостных торговых стратегий: с рыночными ордерами или отложенными, с анализом финансовых показателей (направление ценового движения) и без (захват волатильности). Кроме того, во многие другие торговые системы полезно вставлять анти-новостной фильтр. Все такие программы затруднительно оптимизировать и отлаживать, поскольку в тестере календарь MQL5 недоступен. Однако с помощью кэша, разработанного в предыдущем разделе, мы можем исправить ситуацию.
Попробуем создать эксперт, который будет входить в рынок по новостям, в соответствии с оценкой их влияния на цену. Файл кэша "xyz.cal" был только что создан с помощью индикатора CalendarMonitorCached.mq5.
Напомним, что образ календаря в кэше всегда соответствует моменту сохранения и требует осторожности при чтении: у более поздних событий актуальные показатели неизвестны, а более отдаленные события могут вообще не существовать. Регулярно обновляейте файл кэша календаря перед очередной оптимизацией или тестированием.
При необходимости также учтите переводы часов на "летнее" и "зимнее" время в течение года: события из периодов с режимом DST, противоположном режиму DST в момент сохранения архива календаря, потребуется сдвинуть на 1 час назад или вперед. Избежать данных сложностей можно за счет выбора брокера без переключения DST или построение стратегии на таймфреймах больше H1.
Эксперт CalendarTrading.mq5 будет торговать только по новостям, которые:
- относятся к рабочему символу графика;
- имеют тип финансового индикатора (то есть количественные);
- высокой важности;
- получили только что актуальное значение индикатора;
Последнее важно, поскольку для показателей, имеющих прогнозное и актуальное значения, система выставляет соответствующим образом значение поля impact_type: именно оно будет служить торговым сигналом (указывать направление входа в рынок).
Точное время выхода новости, как правило, не совпадает с плановым, проставленным в поле MqlCalendarValue::time. Календарь не фиксирует это время, и оно недоступно в кэше. В связи с этим точность тестирования новостных стратегий может страдать. Если требуется приблизить анализ и принятие решений к онлайн-процессу, накапливайте статистику выхода новостей с помощью сервиса типа CalendarChangeSaver.mq5 и встройте её в кэш.
По умолчанию торговля ведется минимальным лотом, с установкой уровней тейк-профит и стоп-лосс на заданном расстоянии в пунктах — все это отражено во входных параметрах.
input double Volume; // Volume (0 = minimal lot)
|
Для счетов с хеджинговым учетом разрешим одновременное существование нескольких позиций, по умолчанию 25. Это рекомендованная среда для тестирования, потому что она позволяет независимо оценить прибыльность параллельной торговли по новостям разных видов (каждая позиция создается независимо и не приводит к закрытию позиций по другим новостям). С другой стороны, ведение только одно позиции автоматически нивелирует противоречивые сигналы разных новостей.
Опционально эксперт поддерживает фильтры на идентификатор вида новости и текст для поиска по названию.
sinput ulong EventID;
|
Это может пригодиться для проведения последующих исследований конкретных новостей.
На глобальном уровне описаны указатели объектов аналитической обработкой новостей и сопровождения позиций.
AutoPtr<CalendarFilter> fptr;
|
Режим работы и пара валют текущего рабочего символа сохраняются в соответствующих переменных. Для упрощения примера предполагается применение на Forex (на других рынках получится торговля одной валютой — валютой котирования тикера).
const bool Hedging =
|
В обработчике OnInit загрузим кэш календаря и настроим фильтры согласно вышеприведенному описанию. Отсутствие кэша допускается на онлайн-графике: тогда эксперт работает в боевом режиме, напрямую с календарем. В тестере отсутствие файла кэша не даст запуститься эксперту.
int OnInit()
|
В обработчике OnTimer запросим изменения новостей по настроенным фильтрам.
void OnTimer()
|
Когда подходящие изменения обнаружены, они выводятся в журнал следующим образом (фрагмент реального журнала ниже), с указанием времени, валюты, страны, названия, актуального и прогнозного значений, предыдущего значения и теоретической трактовки сигнала:
... Filtering 5 records 2021.02.16 13:00 | EUR | EU | Employment Change q/q | HIGH | +0.3 | -0.4 | +1.0 | POSITIVE 2021.02.16 13:00 | EUR | EU | GDP q/q | HIGH | -0.6 | -0.7 | -0.7 | POSITIVE instant buy 0.01 EURUSD at 1.21638 sl: 1.21138 tp: 1.22138 (1.21637 / 1.21638 / 1.21637) deal #64 buy 0.01 EURUSD at 1.21638 done (based on order #64) ... Filtering 3 records 2021.07.06 12:05 | EUR | DE | ZEW Economic Sentiment Indicator | HIGH | +63.3 | +84.1 | +79.8 | NEGATIVE instant sell 0.01 EURUSD at 1.18473 sl: 1.18973 tp: 1.17973 (1.18473 / 1.18474 / 1.18473) deal #265 sell 0.01 EURUSD at 1.18473 done (based on order #265) ... |
На основе оценки в поле impact_type следует вычислить потенциальное влияние новостей на цену. Здесь важно отметить, что у нас две валюты: базовая и котирования. Когда новость имеет положительный эффект для базовой валюты, курс предположительно будет повышаться, а если отрицательный — то понижаться. Для валюты котирования все наоборот: положительный эффект должен удорожать вторую валюту в паре, что означает уменьшение курса, в то время как отрицательный — ведет к его увеличению. Это нормализованное направление движения цены вычисляется в следующем фрагменте с помощью переменной sign.
static const int impacts[3] = {0, +1, -1};
|
Часто несколько новостей выходит одновременно, поэтому требуется аккумулировать оценки для них всех. Это делается в переменной impact. Поскольку в нашей стратегии фильтруются только новости одной, самой высокой важности, все одиночные сигналы от них просто суммируются, без весовых коэффициентов. В строковой переменной about подготавливается текст для комментария готовящейся сделки: там будут упомянуты идентификаторы событий, вызвавших сделку.
В случае, если робот запущен на счете с неттингом или достигнуто максимальное разрешенное количество позиций, закроем одну.
PositionFilter positions;
|
Теперь можно открыть новую позицию по сигналу. В качестве "магического" номера устанавливается идентификатор события, что позволит нам позднее провести анализ финансовых показателей торговли в разрезе разных видов новостей.
MqlTradeRequestSync request;
|
Двигаем стоп-лоссы у всех позиций по приходу тиков.
void OnTick()
|
А теперь самое интересное. Благодаря тестеру появляется возможность проанализировать успешность новостной стратегии не только в целом, но и в разбивке по конкретным новостям. Соответствующий блок реализован у нас в обработчике OnTester. Сбор данных выполняется с помощью фильтра сделок. Получив из него массив кортежей trades, в котором сообщается прибыль, своп, комиссия и "магическое" число каждой сделки, мы аккумулируем результаты в трех объектах MapArray: они подсчитывают раздельно прибыли, убытки и количество трейдов для каждого magic-а.
double OnTester()
|
В результате получим таблицу, в которой построчно выводится статистика для каждого вида события: его идентификатор, страна, валюта, общая прибыль или убыток, количество трейдов (количество новостей), профит-фактор и название события.
for(int i = 0; i < profits.getSize(); ++i)
|
Для проверки идеи запустим эксперт на периоде с начала 2021 года (по середину 2022) на паре EURUSD. Ниже приведен фрагмент журнала с распечаткой из OnTester.
Trade profits by calendar events:
|
Результаты не очень впечатляют. Все же, торговля на новостях полна субъективизма. Во-первых, теоретические оценки влияния актуального значения новости на курс могут расходиться с эмоциональными ожиданиями толпы или дополнительным информационным фоном (остающимся за пределами календаря и не поддающимся количественной оценке). Во-вторых, мы уже упоминали о неточности времени публикации актуального значения. В-третьих, наша стратегия реализована в самом простом виде, без анализа предварительного движения цены (когда, вероятно, была утечка, и новость "отыграна" раньше).
В целом, данный тест выявил, что любимые трейдерами Nonfarm Payrolls или отчеты по GDP не гарантируют успех, по крайней мере, с нашими настройками по умолчанию. Далее требуется, в обычном порядке, анализировать отдельные сделки, выяснять, что пошло не так, подбирать параметры и совершенствовать алгоритм, в частности добавить модуль корректировки времени по переключению DST в таймзоне сервера.
Вместе с тем, сам технический прием работает нормально, и мы можем для начала просто попытаться выбрать наиболее успешные новости. Например, возьмем новость 276030003 (Ifo Business Climate). Установив её в EventID, получим следующий отчет, совпадающим с нашими расчетными показателями.
Отчет торговли в тестере по новостям Ifo Business Climate
Вы можете также попробовать торговлю по группе одноименных событий. В частности, чтобы реагировать только на новости по GDP (разных стран), введите в переменную Text строку "*GDP*". Звездочки добавлены, потому что без них строка длиной 3 символа будет трактоваться классом фильтра как валюта. Строки любой длины, отличной от 2 (код страны) или 3 (код валюты), могут задаваться как есть, например "farm", "Nonfarm", "Sales" — они будут искаться фильтром как подстроки названий, с учетом регистра.