Разработка самоадаптирующегося алгоритма (Часть II): Повышение эффективности

14 декабря 2020, 09:40
Maxim Romanov
62
2 099

Введение

Перед началом изучения данной статьи рекомендую ознакомиться с первой статьей "Разработка самоадаптирующегося алгоритма (Часть I): Поиск базовой закономерности". Это не обязательно, основная суть будет понятна, но так будет интереснее.

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

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

Анализ недостатков

Начать разработку нового алгоритма нужно с анализа недостатков предыдущей версии. Я выделил следующие недостатки:

  • Сигналы на открытие серии генерируются слишком редко. Повышение качества сигнала сильно снижает количество сигналов на вход и общую прибыль;
  • Для анализа берется фиксированное окно выборки. Пусть выборки и заданы диапазоном, но анализировать одну выборку фиксированного размера не слишком эффективное решение. Рынок не синусоида, и "хвосты" влияют на текущее качество сигнала. Границы выборки должны быть нечеткими и влиять на итоговое решение. Грубо говоря, в предыдущей версии бралось 100 свечей, и анализировался перевес падающих и растущих. Если перевес проходил порог, то генерировался сигнал на вход. Выборка должна быть не фиксированной, а динамической. Нужно проверять не только какая ситуация была в окне для анализа, но и что было за пределами окна для анализа;
  • Проблема фиксированного окна анализа присуща не всем широко известным методам;
  • Пороговый процент имеет фиксированное значение для каждой выборки, независимо от числа свечей в этой выборке. Такое решение неэффективно, потому что вероятность появления 75% перевеса в выборке 30 свечей и в выборке 200 свечей далеко неодинаковая, она снижается нелинейно с увеличением числа свечей в выборке;
  • Открытие позиций на каждой свече слишком затратно и приводит к повышению просадок. Часто открывается слишком много позиций, нужно уменьшить число открываемых позиций в серии. Так повысится эффективность использования капитала;
  • Закрытие позиций с фиксированным числом прибыли на лот снижает стабильность или доходность. Приходится искать компромисс между стабильностью и доходностью на постоянно меняющемся рынке. Без корректировки этого параметра робот в скором времени получит убыток просто потому, что пропустит оптимальную точку закрытия серии позиций;
  • Жесткое ограничение числа инструментов для одновременной торговли снижает общую прибыльность системы. Сигналы открытия серий на разных инструментах немного коррелируют между собой, соответственно, получение убытка по одному инструменту может коррелировать с получением убытка по другому инструменту. Нужно разработать меры, позволяющие уменьшить корреляцию сигналов, чтобы можно было существенно увеличить число одновременно торгуемых инструментов без значительного увеличения величины просадки.

Упрощенный алгоритм работы

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

  • сканируется окно из N свечей; 
  • проверяется каких свечей больше, падающих или растущих;
  • если перевес больше порогового, то сигнал на начало серии позиций; 
  • больше падающих свечей = сигнал Buy, больше растущих = Sell;
  • расcчитывается лот;
  • открывается новая позиция на каждой следующей свече, пока не сработает условие на закрытие серии; 
  • срабатывает условие закрытия серии;
  • закрываются все позиции;
  • поиск нового сигнала.

Модернизация

Робот был разработан в 2016 году и создавался под MetaTrader 4, поэтому прикреплю в конце код для этого терминала.

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

  1. Динамический пороговый процент начала серии

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

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

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

CP,

где

  • С - число сочетаний
  • n - число свечей в выборке
  • k - число растущих свечей
  • P - вероятность наступления события
  • P2 - удвоенная вероятность события

Вероятность события P нужно умножать на 2, потому что P посчитано для случая, когда больше свечей одного направления, падающих или растущих. Нас интересует общая вероятность, неважно какого направления. Умножать вероятность на 2 не нужно только, если число падающих свечей = числу растущих.

Для примера посчитаем вероятность наступления события, когда из 30 свечей 24 свечи одного направления и 6 другого. Для этого я сделал таблицу на рисунке 1 ниже.

probability table

Рисунок 1. Таблица вероятностей

24 свечи одного направления из 30 соответствует 80% перевеса. Вероятность появления такой комбинации 0.11%. Теперь сравню по таблице, какой процент перевеса должен быль для 100 свечей в выборке, чтобы ее вероятность появления была 0,11%. Для 100 свечей такой вероятности появления комбинаций не встречается. Есть вероятность появления 0.172% и 0.091%. Выберу более редкий вариант, и он соответствует соотношению одного типа свечей к другому, как 66/34 или 66% свечей одного направления.

Ясно, что комбинации для 30 свечей с 80% перевесом падающих или растущих свечей будет встречаться так же часто, как комбинация из 100 свечей с 66% перевесом. Зависимость процента перевеса от числа свечей нелинейная, поэтому для корректировки процента с увеличением числа свечей нужно применить нелинейную функцию. Я разработал такую функцию:

Nonliner proc

Где:

  • Nb — число свечей в выборке.
  • Koef_NonLiner_proc — коэффициент из настроек, нужный чтобы корректировать пороговый процент.

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

Chart function

Рисунок 2.

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

Специально сделано так, чтобы на большем числе свечей сигнал появлялся реже и только если процент перевеса действительно высокий для данного числа свечей.

2. Повышение качества сигналов

Чтобы повысить качество сигнала, выборка не должна состоять из жестко фиксированного числа свечей. Мы видим перевес растущих свечей 65% на 30 свечах, но много это или мало? Если на 100 свечах тоже есть какой-то перевес растущих свечей, то этот факт должен делать сигнал сильнее, если же там нет перевеса или, наоборот, есть перевес падающих свечей, то сигнал нужно ослабить. Я разработал 2 механизма усиления или ослабления сигнала.

а) Использование средневзвешенного процента — это первый вариант повышения качества сигнала. Находим средневзвешенный процент для всех выборок из диапазона, заданного в настройках "Min_diap_bar" и "Max_diap_bar". Выборки нужно брать с каким-то шагом, я предпочитаю четный шаг = 2. Средневзвешенный процент будет определяться для того типа свечей, которого больше в первой выборке. Если в первой выборке больше растущих свечей, то во всех остальных выборках нужно считать процент растущих свечей. Первой выборкой можно сделать самую большую выборку или самую маленькую выборку. Для этого в настройки добавлен переключатель "Bigin_pereb_bar". Весовые коэффициенты можно сделать, используя любую функцию, но я сделал, чтобы они были пропорциональны числу свечей в выборке. 

Если первая выборка с самым маленьким числом свечей, то ее весовой коэффициент W1, для второй выборки весовой коэффициент W2 и так далее до Wn.

weighted average

  • W1 - весовой коэффициент первой выборки;
  • W2 - весовой коэффициент второй выборки;
  • Wn - весовой коэффициент n выборки;
  • Nb1 - число свечей первой выборки;
  • Nbn - число свечей n выборки;
  • Pw - средневзвешенный процент перевеса свечей;
  • P1 - процент падающих/растущих свечей первой выборки;
  • Pn - процент падающих/растущих свечей n выборки;
  • Nbm - число свечей в самой большой выборке.

Если первая выборка с самым большим числом свечей, то весовые коэффициенты нужно перевернуть

 inverted weights
Для получения сигнала на начало серии средневзвешенный процент нужно сравнивать с отдельным значением, указанным в настройке "Porog_Weighted_proc".

б) Использование множественной выборки — это второй вариант повышения качества сигнала. Из диапазона нужно набрать несколько выборок, у которых перевес одного типа свечей больше порогового. Тут будем считать, что чем больше число выборок, на которых процент перевеса больше порогового, тем выше качество сигнала. В качестве порогового процента тут будет использоваться нелинейный процент. То есть для каждой выборки со своим числом свечей должен использоваться свой пороговый процент перевеса.
В настройке "Kol_vibor" буду задавать минимальное число выборок, на которых перевес должен быть больше порогового. Тип свечей, для которых будет определяться процент перевеса, будут зависеть от того, какой тип свечей преобладает в первой выборке. Тут за первую выборку берется та, на которой найден перевес выше порогового. Я сделал, чтобы диапазон можно было перебирать от меньшего к большему и наоборот, чтобы сравнить, как будет лучше работать.
Такая методика помогает учитывать сигнал в более широком окне и не привязываться к фиксированному окну анализа. Например, диапазон окна анализа задается от 30 до 300 свечей с шагом 2, и для формирования сигнала нужно набрать не менее 5 выборок из этого диапазона с перевесом больше порогового. Перевес может сформироваться на 30, 52, 100, 101, 200 свечах. Причем каждая выборка сравнивается со своим пороговым процентом по тому, что используется нелинейный процент. Так эффективнее оценивается, что происходило в широком диапазоне числа свечей и отсутствует привязка к фиксированному значению.

Price Chart

Рисунок 3.

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

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

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

Были разработаны 2 меры, уменьшающие число позиций в серии.

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

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

б) Открытие с контролем процента перевеса. Это дополнительный фильтр открытия позиций в серии. Нужно проверять процент перевеса на всей выборке с появлением каждой новой свечи. Размер выборки с появлением новой свечи будет увеличиваться на единицу. Если с появлением новой свечи процент перевеса увеличился относительно предыдущего измерения, то позицию можно открыть, если нет, то нельзя открывать.

Этот пункт работает практически как пункт (а), но немного по-другому. Смысл у него полностью аналогичный режиму из пункта (а): не дать уменьшиться средней цене открытия серии для позиций Sell и не дать увеличиться средней цене открытия серии для позиций Buy.

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

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

open positions befor

open positions after

Рисунок 4. Пример уменьшения числа позиций в серии

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


Прибыль Максимальный убыток Число позиций Profit factor
Открытие на каждой свече (верхний рисунок) +71.99$ -463.96$ 92 1.56
Открытие с контролем процента перевеса (нижний рисунок) +42.26$ -263.86$ 48 1.68

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

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

4. Модернизация закрытия позиций в прибыли

В первой версии алгоритма было введено понятие прибыль на лот. Это значение устанавливалось в валюте депозита для размера лота, равного единице. Далее считалось число лотов по открытым позициям серии, и значение из настроек умножалось на текущий суммарный лот по открытым позициям серии. Например, в настройках установлено закрыть серию позиций, когда прибыль станет больше 15$ на лот. Сейчас открыто 11 позиций по 0.01 лоту, значит, общая позиция 0.01*11=0.11. Далее прибыль на лот умножается на полученное число лотов 15$*0.11=1.65$. Если общая прибыль по открытым позициям достигнет 1.65$, серию позиций нужно завершить.

Задавать фиксированное значение прибыли на лот в валюте депозита — не самое эффективное решение. Когда волатильность по инструменту падает, риск пропустить правильную точку закрытия растет. И наоборот, когда волатильность растет, робот недополучает прибыль. В итоге во время оптимизации получается усредненное значение прибыли на лот, которое работает недостаточно эффективно. 

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

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

Я отказался от контроля прибыли в валюте депозита, потому что цена пункта непостоянна для валютных пар типа USD/XXX и меняется от текущего значения цены. Прибыль будет контролироваться в пунктах. Для этого нужно взять текущее значение индикатора ATR (в пунктах) и умножить на значение из настроек "Koef_multi_ATR". Получилось число пунктов для закрытии в прибыль. Далее для каждой позиции считается, сколько прошло пунктов от цены открытия до текущего значения и находится среднее значение для всех позиций. Полученное среднее значение сравнивается с числом пунктов для закрытия в прибыль. Если среднее число пунктов больше или равно числу пунктов для закрытия, то серия завершается, если нет, то на следующей свече процедура повторяется. 

Текущая прибыль должна контролироваться на каждом тике или через таймер. Чтобы не нагружать лишними вычислениями, для системы подобного рода, проверять прибыль по таймеру 1 раз в секунду или даже 1 раз в 10 секунд, нормально.

  5. Работа с несколькими торговыми инструментами

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

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

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

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

Чтобы корреляция между сигналами открытия серий на разных инструментах была как можно меньше, нужно разбить валютные пары на отдельные валюты, и считать, что открываются позиции по отдельным валютам. Если открыта позиция Sell по EURUSD, то данная позиция делится на позицию Sell по EUR и Buy по USD. Перед началом каждой новой серии нужно проверять, есть позиции по валютам, входящим в пару или нет. Если есть позиция Sell по EUR, то нужно запретить начало любой серии, где будет требоваться продать EUR. Но не нужно запрещать сигналы, в которых нужно купить EUR. 


Рисунок 5

Пример, как делить валюты на пары, показан на рисунке 5. Ниже, на рисунке 6, схематично показано, какие позиции можно открывать, если открыта позиция Buy EURUSD. Для остальных вариантов работает все аналогично. 

Currencies 2

Рисунок 6.

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

6. Коррекция лота от текущей волатильности

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

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

Для расчета текущего лота нужно взять текущее значение ATR и поделить его на "Norm_ATR" из настроек. Затем "Lot" из настроек нужно поделить на полученный коэффициент. Полученное значение округлить до правильного. Так лот будет уменьшаться при росте размера свечей, и график доходности будет максимально стабилен.

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

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

Тесты

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

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

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

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

GBPUSD 2000 tester chart

GBPUSD 2000 Tester report

Рисунок 7. GBPUSD H1 2000.01.01 - 2020.12.08 статичный лот

На рисунке 7 показан тест GBPUSD для таймфрейма H1, за период почти 21 год с 2000.01.01 по 2020.12.08.  Тут используется множественная выборка из диапазона. Диапазон анализа 68-200 свечей и используется 15 выборок.

Если первая версия алгоритма проходила тест только с 2001 года, то вторая версия уже спокойно проходит тест с 2000 года. По сравнению с первой версией алгоритма в 3 раза увеличилось число позиций, и в 1.9 раза увеличилась прибыль. Профит фактор уменьшился с 7.5 до 2.74, но все еще остается на достойном уровне. Сигналы на начало серии генерируются чаще, а среднее число позиций в серии уменьшилось. Наверное, можно подобрать настройки и лучше, но я взял те, что использовал для торговли.

Ранее была разработана функция коррекции лота от текущего значения ATR. На рисунке 8 проведен тот же тест, что и для рисунка 7, но с динамическим лотом, зависящим от волатильности. Так как для 3000$ использовался лот 0.01, то для корректной работы алгоритма коррекции размера лота я увеличил депозит до 30 000$ и, соответственно, поднял лот до 0.1.

GBPUSD 2000 tester chart dyn lot

GBPUSD 2000 Tester report dyn lot

Рисунок 8. GBPUSD H1 2000.01.01 - 2020.12.08 динамический лот, зависящий от ATR 

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

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

GBPUSD M15 tester chart

GBPUSD 2009 m15 Tester report

Рисунок 9. GBPUSD M15 2009.01.01 - 2020.12.08

На рисунке 9 показан тест GBPUSD M15 2009.01.01 - 2020.12.08 с настройками от таймфрейма H1. Тест был пройден стабильно с 2009 года. Результат хороший по тому, что специально тайм фрейм настройки не оптимизировались под таймфрейм M15. Чтобы подобрать оптимальные настройки для таймфрейма M15, достаточно оптимизировать самый сложный участок, за 1.5 года с 2008.01.01 по 2009.06.01. Если оптимизировать параметры под этот участок, то робот будет проходить тест за 21 год без проблем. 

Для первой версии я показывал тесты по EURUSD H1, поэтому сравним результаты. На рисунке 10 показан результат для EURUSD H1 за период с 2000.01.01 по 2020.12.08.

EURUSD 2000 tester Chart

EURUSD 2000 tester report

Рисунок 10. EURUSD H1 2000.01.01 - 2020.12.08

Первая версия проходила бектест только с 2007 года, новая версия проходит тест уже с 2000 года, за 21 год. Стабильность значительно улучшилась. Максимальная просадка при этом уменьшилась в 1.2 раза, и прибыль увеличилась в 3 раза. Увеличилось число сделок 2.3 раза.

Так как я сравниваю, насколько вторая версия стала лучше, то посмотрим тест по GBPJPY на таймфрейме H1. Первая версия проходила тест с 2009 года.

GBPJPY 2000 tester chart

GBPJPY 2000 tester report

Рисунок 11. GBPJPY H1 2000.01.01 - 2020.12.08

Как видно на рисунке 11, алгоритм стал проходить бектесты с 2000 года, при этом просадка снизилась в 1.8 раза, а профит фактор увеличился до 3.3.

Я оптимизировал 28 валютных пар, состоящих из восьми основных валют USD, GBP, EUR, CHF, CAD, AUD, NZD, JPY. Какие-то валютные пары показывают лучший результат, какие-то худший, но все хорошо оптимизируются и проходят тесты, как правило, с 2004 года. Некоторые валютные пары проходят тест с 2007 года, но их не много.

MetaTrader 4 не умеет проводить тесты сразу по нескольким инструментам, поэтому я провел тест по каждому из 28 инструментов в отдельности и воспользовался сторонним софтом, чтобы объединить отчеты. Так как делал я это в 2017 году, то комбинированный отчет будет с 2010 по 2017 год.

Full report

Рисунок 12. Комбинированный бектест по 28 валютным парам с 2010 по 2017 год

На рисунке 12 видно, что график доходности по бектесту на 28 валютных парах достаточно ровный с доходностью около 100% годовых. Результат красивый, но в реальности доходность ниже из-за того, что будет ограничение одновременной торговли по нескольким валютным парам. Я использовал этого робота для торговли на реальных счетах на протяжении двух лет, и реальная доходность была на уровне 56% годовых. 

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

В торговле я использовал максимально консервативные настройки, но алгоритм можно настроить намного агрессивнее. 

Дополнительные функции

Была заложена дополнительная возможность фильтровать сигналы на начало серии по другим таймфреймам. Например, торговля идет на таймфрейме H1, но дополнительно проверяются сигналы на всех стандартных тайм фреймах. Сигнал на начало серии формируется, только если на таймфреймах M1, M5, M15, M30, H1, H4, D1 тоже есть сигнал на начало серии. Сигнал на подтверждение серии с дополнительных таймфреймов генерируется по тем же правилам и в том же режиме, что и на основном таймфрейме. Дополнительные таймфреймы можно включать или выключать независимо друг от друга.

К сожалению, проверить этот режим не удалось, были проблемы с корректной работой этой функции.

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

  • Возможность установки take profit и stop loss. Значения рассчитываются по определенному алгоритму и могут дублировать реальные точки закрытия или работать независимо.
  • Реализована функция контроля текущих средств. Если средства падают ниже установленного порога, робот закрывает позиции и останавливает торговлю
  • Есть возможность ограничивать максимальное число позиций по инструменту и по всем инструментам.
  • Реализован контроль текущего убытка по каждому торговому инструменту, это дополнительный виртуальный stop loss
  • Между двумя соседними сериями можно задать паузу в числе свечей, чтобы серия не открывалась сразу после закрытия предыдущей. Эта функция нужна, чтобы во время паузы могли начинаться серии по другим инструментам.
  • Можно задать минимальное значение ATR, при котором могут начинаться новые серии по инструменту. Если волатильность маленькая, то торговать может быть не выгодно.
  • Для закрытия позиций может использоваться нелинейная прибыль. Чем больше позиций открыто в серии, тем быстрее желательно завершить эту серию. Поэтому пороговая прибыль падает пропорционально корню квадратному из числа открытых позиций.
  • На экран выводится вся необходимая информация по каждому торгуемому инструменту, чтобы можно было следить что происходит в "голове" у робота.
  • Алгоритм отрабатывает перезагрузки компьютера и терминала, подхватывает свои открытые позиции и продолжает торговлю по текущей ситуации, для этого используются глобальные переменные.

В роботе получилось 2337 настроек на 28 торговых инструментов, поэтому каждый для себя сможет найти интересный режим работы.

Выводы и дальнейшее развитие

  • За основу была взята простая, но понятная закономерность, и в процессе разработки удалось существенно улучшить характеристики алгоритма. Такое возможно именно потому, что используемая закономерность предельно понятна и можно изучить, что именно влияет на прибыль и убытки.
  • Алгоритм отлично оптимизируется под разнообразные инструменты и достаточно стабилен на длительных промежутках времени.
  • Параметры работы стали более гибкие и уже немного корректируются в зависимости от текущих характеристик рынка. Именно эта особенность позволила значительно поднять стабильность. Данный алгоритм можно продолжать улучшать, повышая качество его работы.
  • Есть значительный потенциал для улучшения характеристик алгоритма. Логику можно инвертировать как для трендовой, так и для контр трендовой торговли.
  • Под каждый инструмент требуется проводить оптимизацию. Это плохо, потому что не разработана полноценная теоретическая модель, которая будет говорить какие параметры нужны в данный момент времени по данному торговому инструменту и почему.
  • Необходимость проводить оптимизацию под каждый торговый инструмент говорит о том, что мы не знаем, чем отличаются характеристики ценовых рядов разных торговых инструментов. Любая неопределенность — это неучтенные факторы.
  • Если неизвестно, чем отличаются параметры ценового ряда одного инструмента от другого, то нет возможности контролировать наличие закономерности и на текущем инструменте. Мы не можем сказать, какие именно параметры ценового ряда влияют на получение прибыли и стабильность алгоритма.
  • Непонятно, почему оптимизированные настройки стабильны на одном инструменте и нестабильны на другом. Можно подобрать настройки, которые будут стабильны на всех торговых инструментах, но это приведет к значительному падению прибыльности.
  • Проводя оптимизацию параметров на исторических данных, не удается избавиться от неучтенных факторов. Именно количество неучтенных факторов влияет на стабильность.
  • Чтобы добиться настоящей стабильности и надежности, нужно значительно перерабатывать теорию и отказываться от оптимизации в следующих версиях алгоритма.
  • Каждый параметр из настроек должен от чего-то зависеть. Не должно быть ни одного параметра, который установлен просто по тому, что так лучше работает. Нужно детальное объяснение, почему именно сейчас используется данное значение параметра и когда он должен изменить свое значение.

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

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

Автор идеи и ТЗ Maxim Romanov, код писал Vyacheslav Ivanov.

Предыдущие статьи на эту тему:

Разработка самоадаптирующегося алгоритма (Часть I): Поиск базовой закономерности

Прикрепленные файлы |
robot.zip (40.24 KB)
Set.zip (168.94 KB)
technical_task.zip (69.65 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (62)
Maxim Romanov
Maxim Romanov | 21 дек 2020 в 19:10
prostotrader:

Делайте, но не забудьте завещать внукам, что бы продолжили Ваше дело!

Нее, внуков втягивать не буду, это мое увлечение. Да вам интересно же тоже почитать). Много кому интересно, если было бы не интересно, тут бы никто не сидел. Я понимаю скептицизм, но интересно же).
Кстати технологию, которую я дальше покажу, можно использовать в парном трейдинге высоко коррелированными инструментами. Например brent/wti
Evgeniy Ilin
Evgeniy Ilin | 21 дек 2020 в 20:22
Denis Kirichenko:

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

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

Evgeniy Ilin
Evgeniy Ilin | 22 дек 2020 в 11:25
prostotrader:

Не надоело еще, дорогие товарищи, искать зависимости будущего из прошлого,

даже прикручивая сложные математические формулы и приемы?

Price(t) != Грааль!

Никогда, копаясь в истории Вы не найдете Грааль - его просто быть не может!

Заработать можно только тогда, когда свою прибыль Вы можете рассчитать самой простой формулой

Н-р СПОТ против фьючерса 

F = N*S*(1+r1) - N*div*(1+r2), где

 F – цена фьючерса;  

N – объем фьючерсного конт­ракта (количество акций) ;

  S – спот-цена акции;

  r1 – процентная ставка на срок со дня заключения сделки по фьючерсному контракту до его исполнения;

  div – размер дивидендов по базовой акции;

  r2 – процентная ставка на срок со дня закрытия реестра акционеров («отсечки») до исполнения фьючерсного контракта.

А при "гадании" с помощью различных приемов всегда будет следующее:


Вообще если честно надоело )). Но грааль в голове трейдеров ассоциируется больше с какой то беспроигрышной формулой. В нашем же понимании это определенные показатели торговли такие как профит фактор математическое ожидание и прочие величины. Действительно крайне тяжело найти что то рабочее, но вот вам пример рабочего алгоритма, действительно он способен зарабатывать. О большем никто и не говорит собственно. Тут даже не нужно код копировать, вы сами можете это реализовать. Автор все подробно описал. Главное понять как работает алгоритм и свои 50-100 процентов годовых вы получите. Это очень реальные показатели прибыли на самом деле, все что выше процентов 200 уже очень опасно. Алгоритм действительно рабочий.

Oleksandr Myrhorodskyi
Oleksandr Myrhorodskyi | 24 дек 2020 в 16:02
Отличная работа! Жду следующей статьи и реализации на МТ5. 
Maxim Romanov
Maxim Romanov | 24 дек 2020 в 16:05
Oleksandr Myrhorodskyi:
Отличная работа! Жду следующей статьи и реализации на МТ5. 

Уже отправил на модерацию

Градиентный бустинг в задачах трансдуктивного и активного машинного обучения Градиентный бустинг в задачах трансдуктивного и активного машинного обучения

В данной статье вы познакомитесь с методами активного машинного обучения на реальных данных, узнаете какие плюсы и минусы они имеют. Возможно, эти методы займут свое место в вашем арсенале моделей машинного обучения. Термин трансдукции был введен Владимиром Наумовичем Вапником, изобретателем машины опорных векторов или SVM (support vector machine).

Работа с таймсериями в библиотеке DoEasy (Часть 58): Таймсерии данных буферов индикаторов Работа с таймсериями в библиотеке DoEasy (Часть 58): Таймсерии данных буферов индикаторов

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

Работа с ценами в библиотеке DoEasy (Часть 59): Объект для хранения данных одного тика Работа с ценами в библиотеке DoEasy (Часть 59): Объект для хранения данных одного тика

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

Нейросети — это просто (Часть 9): Документируем проделанную работу Нейросети — это просто (Часть 9): Документируем проделанную работу

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