Переосмысливаем классические стратегии (Часть 15): Стратегия пробоя диапазона предыдущего дня
В этой серии статей мы часто пытаемся использовать модели машинного обучения, чтобы помочь повысить эффективность наших торговых стратегий. Однако мы часто упускаем из виду тот факт, что эти модели делают много слепых предположений относительно имеющихся данных. Более того, классическое статистическое обучение не дает нам каких-либо указаний для доказательства того, действительно ли в реальности существуют взаимосвязи, которые мы пытаемся смоделировать.
С другой стороны, трейдеры-люди за долгие годы взаимодействия с рынками усвоили определенную фундаментальную суть того, что можно назвать рыночной логикой. Это понимание, которое мы будем называть рыночной логикой, можно получить только на основе опыта. Надеемся, что мы сможем использовать наработки, накопленные трейдерами-практиками, в наших алгоритмических торговых системах. Трейдеры, осуществляющие дискреционную торговлю, активно работали на финансовых рынках задолго до появления компьютеров. Следовательно, в выработанных ими эмпирических правилах, возможно, есть рациональное зерно, которое стоит использовать.
Как уже отмечалось, мы обычно используем алгоритмы машинного обучения, чтобы помочь нам изучить взаимосвязи, которые проецируют прошлое на будущее. Однако мы почти всегда предполагаем, что такая взаимосвязь существует и её можно изучить на основе данных. Мы редко тратим время на то, чтобы доказать, что эти взаимосвязи вообще существуют. Дискреционные трейдеры в силу необходимости, по сути, были вынуждены искать надежные взаимосвязи, которые могли бы поддержать их карьеру. С этой точки зрения мы могли бы утверждать, что люди-трейдеры были вынуждены выполнять ручной труд, который может заложить основу для разработки наших моделей машинного обучения.
Поэтому мы стремимся преодолеть разрыв между машинным обучением и финансовой торговлей, используя эвристику и эмпирические правила, выработанные людьми за многие годы взаимодействия с рынками. Эти правила, которые трейдеры, как правило, научились соблюдать, могут служить основой, позволяющей нашим моделям изучать финансовые рынки более структурированным образом. Вместо того, чтобы наши модели доказывали взаимосвязи с нуля, мы можем опереться на принципы, чья состоятельность уже подтверждена временем. Это дает нашим моделям преимущество, а не требует, чтобы они начинали с нуля.
Самая важная часть нашего теста - доказать состоятельность стратегии, с которой мы начинаем. По этой причине наша торговая стратегия была основана на хорошо известном методе пробоя, основанном на связи между последовательными торговыми днями. Стратегия, по сути, довольно проста.
Обзор нашей торговой стратегии
В начале каждого торгового дня мы отмечаем максимумы и минимумы предыдущего дня.

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

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

Рисунок 3: Стратегия закрывает позиции при пробое противоположного экстремального ценового уровня, но, как видно на приведенной выше иллюстрации, стратегия содержит определенную погрешность
Мы также заметили, что стратегия была чрезмерно агрессивной и нестабильной. Правила выхода, определенные стратегией, не всегда выполняются полностью, как показано на рисунке 3. Поэтому были необходимы изменения, чтобы обеспечить определенный уровень контроля над волатильностью. Под волатильностью здесь подразумевается колебание прибыли на счете во время тестирования на истории.
Как мы увидим в последующих разделах, сначала мы реализовали исходную торговую стратегию в ее простейшей форме — в соответствии с описанием, принятым большинством трейдеров, — чтобы установить базовый уровень эффективности. Впоследствии мы внесли изменения в стратегию и сравнили улучшения с первоначальной версией, чтобы убедиться, что наши изменения двигают нас в желаемом направлении. Внесенные нами изменения повлияли на стратегию по трем важным направлениям:
ПрибыльностьНаша первоначальная стратегия принесла прибыль всего в 40 долларов за пятилетний период бэктестирования. Это не впечатляет ни в какой мере. Однако впечатляет тот факт, что 68% всех совершенных сделок оказались прибыльными, что примечательно для вневыборочного теста длиной в пять лет, — особенно учитывая, что стратегия не имела параметров настройки и полагалась исключительно на логику и интуицию. К сожалению, средний размер убыточной сделки, как правило, превышал средний размер прибыльной, что и привело к этой жалкой прибыли в 40 долларов.
После нескольких итераций наша улучшенная версия стратегии принесла прибыль в размере 162 долларов за тот же период — увеличение на 300%. Кроме того, нам удалось улучшить коэффициент Шарпа для данной стратегии с 0,13 до 0,40, что на 207% выше, чем в исходном случае. Читателю следует отметить, что все сделки были заключены в рамках минимально допустимого размера лота, чтобы испытать нашу системы для демонстрации эффективности.
Торговая эффективностьПервоначальная стратегия требовала в общей сложности 886 сделок, чтобы получить жалкую прибыль в размере 40 долларов, в то время как наша улучшенная версия требовала всего 246 сделок, чтобы получить прибыль в размере 162 долларов. Это означает, что улучшенная стратегия позволила снизить торговую активность и ненужный риск на рынке на 72% и, кроме того, получить бОльшую прибыль. Это желанная функция любой торговой системы: больше прибыли при меньшем риске.
В первоначальной стратегии средняя прибыль составляла 3,64 долларов, а средний убыток - 7,87 долларов. Нам удалось исправить это поведение. В нашей улучшенной версии мы достигли средней прибыли в размере 14,82 доллара, при этом средний убыток остался практически на том же уровне — 7,95 долларов.
Точность торговлиК сожалению, хотя эти изменения и повысили прибыльность и эффективность, они негативно сказались на точности. Доля прибыльных сделок снизилась с 68% в первоначальной стратегии до 37% в улучшенной версии — снижение точности на 45%. Одной из самых привлекательных особенностей первоначальной стратегии была высокая точность, а попытки ручной доработки без ущерба для точности оказались сложными.
Поэтому мы можем рассмотреть возможность поручить эту задачу контроллеру с обратной связью, как показано в нашем предыдущем обсуждении (ссылка приведена здесь). Мы также считаем, что было бы полезно продолжить тестирование большего количества дискреционных торговых правил, на которые трейдеры-люди полагаются в течение многих лет, избирательно отфильтровывая те, которые естественным образом обеспечивают высокий уровень точности, как, например, результаты, с которых мы начали. Таким образом, эти стратегии могут предложить структурированную основу для того, чтобы наши модели машинного обучения могли изучить как сильные, так и слабые стороны человеческой интуиции. Давайте приступим!
Начинаем на MQL5
Как и в большинстве наших стратегий, начнем с определения необходимых глобальных переменных для следования выбранной стратегии. Нам понадобятся идентификаторы для двух отслеживаемых нами ценовых уровней: максимума и минимума предыдущего дня. Мы также отметим эти ценовые уровни горизонтальными линиями, проходящими через график, поэтому нам понадобятся строки для хранения названий наших ценовых уровней.
//+------------------------------------------------------------------+ //| UB 2.mq5 | //| Gamuchirai Ndawana | //| https://www.mql5.com/ru/users/gamuchiraindawa | //+------------------------------------------------------------------+ #property copyright "Gamuchirai Ndawana" #property link "https://www.mql5.com/ru/users/gamuchiraindawa" #property version "1.00" //+------------------------------------------------------------------+ //| Global Variables | //+------------------------------------------------------------------+ double last_high,last_low; string h,l; bool rest; int atr_handler; double atr[];
Аналогичным образом мы импортируем торговую библиотеку, которая поможет нам управлять нашими позициями во время бэктестинга стратегии.
//+------------------------------------------------------------------+ //| Libraries | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> CTrade Trade;
При первой загрузке нашей системы мы сохраним названия двух отслеживаемых нами ценовых уровней, настроим индикатор среднего истинного диапазона (ATR) для управления рисками и, наконец, сбросим системный флаг с именем «rest». Как следует из названия, наша система будет искать сделки до тех пор, пока параметр rest не будет установлен в значение true. В этот момент система прекратит поиск торговых сетапов и вместо этого начнет управлять открытыми позициями.
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- h="high"; l="low"; rest = false; atr_handler = iATR(Symbol(),PERIOD_H8,4*14); //--- return(INIT_SUCCEEDED); }
Когда наша система не будет использоваться, мы освободим индикатор ATR, освободим ресурсы, чтобы вернуть память системе.
//+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- IndicatorRelease(atr_handler); }
В начале каждого дня мы сохраняем максимум и минимум предыдущего торгового дня.
//--- datetime cd = iTime(Symbol(),PERIOD_D1,0); static datetime ds; if(cd != ds) { ds = cd; last_high = iHigh(Symbol(),PERIOD_D1,1); last_low = iLow(Symbol(),PERIOD_D1,1); if((rest==true) && (PositionsTotal() == 0)) rest = false; Comment("Last High: ",last_high,"\nLast Low: ",last_low); ObjectDelete(0,l); ObjectDelete(0,h); ObjectCreate(0,h,OBJ_HLINE,0,0,last_high); ObjectCreate(0,l,OBJ_HLINE,0,0,last_low); CopyBuffer(atr_handler,0,0,1,atr); }
В течение дня мы будем открывать контртрендовые позиции, когда будет пробит первый экстремальный ценовой уровень. Считается, что этот первый пробой является истинным трендом на этот день.
datetime ch = iTime(Symbol(),PERIOD_H1,0); static datetime hs; if(ch != hs) { hs = ch; double bid,ask,close,padding; close = iClose(Symbol(),PERIOD_H1,0); ask = SymbolInfoDouble(Symbol(),SYMBOL_ASK); bid = SymbolInfoDouble(Symbol(),SYMBOL_BID); padding = atr[0] * 2; if(rest == false) { if(PositionsTotal() == 0) { if(close<last_low) Trade.Buy(0.01,Symbol(),ask,(bid-(padding)),last_high); else if(close>last_high) Trade.Sell(0.01,Symbol(),bid,(ask+(padding)),last_low); rest = true; } } } } //+------------------------------------------------------------------+
В основном, стратегия основана на интуиции, поэтому довольно проста по конструкции. Мы завершили настройку, необходимую для нашей стратегии. Теперь можно приступить к тестированию торговой системы на исторических данных.
Начнем с выбора исторических данных по паре EUR/USD за пять лет и посмотрим как будет работать наша система.

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

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

Рисунок 6: Кривая эквити, построенная в соответствии с первоначальной версией нашей торговой стратегии, отличается недостаточной последовательностью и кажется слишком волатильной
Тем не менее, общая прибыль, полученная с помощью стратегии в ее первоначальном виде, составила всего сорок долларов за пять лет тестирования на истории. Однако, что впечатляет, так это удивительно высокий уровень точности: 68% всех сделок, совершенных с помощью этой стратегии, были прибыльными. Проблема, однако, заключалась в том, что наша средняя прибыльная сделка была меньше, чем средняя убыточная — убытки были почти в два раза больше.

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

Рисунок 8: Визуализация улучшений, которые мы можем внести в первоначальную версию своей торговой стратегии
Реализация этого усовершенствования увеличила нашу общую чистую прибыль от первоначальных сорока долларов. Это позволило нам предвидеть движение в течение каждого дня, не дожидаясь соблюдения традиционных правил стратегии. В наши правила входа потребовалось внести лишь незначительные изменения: теперь мы учитывали абсолютное значение разрыва между текущей ценой закрытия и предыдущими максимумом и минимумом. Если разрыв до максимума был больше, мы открывали длинные позиции. В противном случае мы открывали короткие позиции. После открытия каждой позиции был установлен параметр сброса. И после этого мы будем искать новые сделки только в том случае, если сделка была завершена.
if(rest == false) { if(PositionsTotal() == 0) { //High Gap Is Bigger if(MathAbs(close - last_high) > MathAbs(close - last_low)) Trade.Buy(0.01,Symbol(),ask,(bid-(padding)),last_high); rest = true; //Low Gap Is Bigger else if(MathAbs(close - last_high) < MathAbs(close - last_low)) Trade.Sell(0.01,Symbol(),bid,(ask+(padding)),last_low); rest = true; } }
После объединения наша новая система стала выглядеть так:
//+------------------------------------------------------------------+ //| UB 2.mq5 | //| Gamuchirai Ndawana | //| https://www.mql5.com/ru/users/gamuchiraindawa | //+------------------------------------------------------------------+ #property copyright "Gamuchirai Ndawana" #property link "https://www.mql5.com/ru/users/gamuchiraindawa" #property version "1.00" //+------------------------------------------------------------------+ //| Global Variables | //+------------------------------------------------------------------+ double last_high,last_low; string h,l; bool rest; int atr_handler; double atr[]; //+------------------------------------------------------------------+ //| Libraries | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> CTrade Trade; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- h="high"; l="low"; rest = false; atr_handler = iATR(Symbol(),PERIOD_H8,4*14); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- IndicatorRelease(atr_handler); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- datetime cd = iTime(Symbol(),PERIOD_D1,0); static datetime ds; if(cd != ds) { ds = cd; last_high = iHigh(Symbol(),PERIOD_D1,1); last_low = iLow(Symbol(),PERIOD_D1,1); if((rest==true) && (PositionsTotal() == 0)) rest = false; Comment("Last High: ",last_high,"\nLast Low: ",last_low); ObjectDelete(0,l); ObjectDelete(0,h); ObjectCreate(0,h,OBJ_HLINE,0,0,last_high); ObjectCreate(0,l,OBJ_HLINE,0,0,last_low); CopyBuffer(atr_handler,0,0,1,atr); } datetime ch = iTime(Symbol(),PERIOD_H1,0); static datetime hs; if(ch != hs) { hs = ch; last_high = iHigh(Symbol(),PERIOD_D1,1); last_low = iLow(Symbol(),PERIOD_D1,1); double bid,ask,close,padding; close = iClose(Symbol(),PERIOD_H1,0); ask = SymbolInfoDouble(Symbol(),SYMBOL_ASK); bid = SymbolInfoDouble(Symbol(),SYMBOL_BID); padding = atr[0] * 2; if(rest == false) { if(PositionsTotal() == 0) { if(MathAbs(close - last_high) > MathAbs(close - last_low)) Trade.Buy(0.01,Symbol(),ask,(bid-(padding)),last_high); else if(MathAbs(close - last_high) < MathAbs(close - last_low)) Trade.Sell(0.01,Symbol(),bid,(ask+(padding)),last_low); rest = true; } } } } //+------------------------------------------------------------------+
Кривая эквити, полученная благодаря нашей усовершенствованной стратегии, достигла новых максимумов, недостижимых при использовании исходной версии. Наша общая чистая прибыль выросла до 148 долларов от первоначальных сорока долларов. Однако уже можно заметить, что доля прибыльных сделок начала снижаться.

Рисунок 9: Визуализация кривой эквити, полученной с помощью нашей новой и улучшенной версии исходной торговой стратегии
С одной стороны, наша эффективность повысилась, потому что мы получили прибыль на 108 долларов больше. Однако в то время, как исходной стратегии потребовалось 886 сделок, чтобы получить прибыль в размере 40 долларов, нашей новой версии потребовалось всего 469 сделок, чтобы получить прибыль в размере 148 долларов. Стратегия явно движется в правильном направлении, но дальнейшие усовершенствования все еще возможны.

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

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

Рисунок 12: Условия выхода из исходной стратегии не всегда выполняются при всех возможных рыночных условиях
Поэтому можно предположить, что вместо того, чтобы размещать наши тейк—профиты выше предыдущего экстремума, нам следует разместить их чуть ниже него - возможно, на долю ATR ниже предыдущего максимума. Таким образом, пока цена достаточно близка, мы по-прежнему получаем прибыль.
Кроме того, мы хотим ужесточить стоп-лоссы по мере того, как сделки развиваются в нашу пользу, чтобы получить максимальную прибыль. Для реализации этого мы изменили свои правила: вместо добавления одинакового отступа к стоп-лоссу и тейк-профиту, теперь мы добавляем меньшую долю к тейк-профиту, чем к стоп-лоссу. Это делает стоп-лосс более щадящим, сохраняя при этом тейк-профит более жестким для фиксации импульса.
Пока позиции открыты, мы также условно проверяем, является ли новое предложение по стоп-лоссу более выгодным, чем текущее. В идеале мы всегда хотим, чтобы наш стоп-лосс по возможности был привязан к последней экстремальной цене.
if(ch != hs) { hs = ch; last_high = iHigh(Symbol(),PERIOD_D1,1); last_low = iLow(Symbol(),PERIOD_D1,1); double bid,ask,close,padding; close = iClose(Symbol(),PERIOD_H1,0); ask = SymbolInfoDouble(Symbol(),SYMBOL_ASK); bid = SymbolInfoDouble(Symbol(),SYMBOL_BID); padding = atr[0] * 2; if(rest == false) { if(PositionsTotal() == 0) { if((MathAbs(close - last_high) > MathAbs(close - last_low))) Trade.Buy(0.01,Symbol(),ask,(bid-(padding)),last_high+(padding*0.9)); else if((MathAbs(close - last_high) < MathAbs(close - last_low))) Trade.Sell(0.01,Symbol(),bid,(ask+(padding)),last_low-(padding*0.9)); rest = true; } } if(rest == true) { if(PositionsTotal() > 0) { if(PositionSelectByTicket(PositionGetTicket(0))) { double sl,tp; sl = PositionGetDouble(POSITION_SL); tp = PositionGetDouble(POSITION_TP); //--- Buy if(sl < tp) { if(last_low > sl) Trade.PositionModify(Symbol(),last_low,tp); } if(tp < sl) { if(last_high < sl) Trade.PositionModify(Symbol(),last_high,tp); } } } } }
В совокупности это дало нам окончательную версию системы на данный момент:
//+------------------------------------------------------------------+ //| UB 2.mq5 | //| Gamuchirai Ndawana | //| https://www.mql5.com/ru/users/gamuchiraindawa | //+------------------------------------------------------------------+ #property copyright "Gamuchirai Ndawana" #property link "https://www.mql5.com/ru/users/gamuchiraindawa" #property version "1.00" //+------------------------------------------------------------------+ //| Global Variables | //+------------------------------------------------------------------+ double last_high,last_low; string h,l; bool rest; int atr_handler; double atr[]; //+------------------------------------------------------------------+ //| Libraries | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> CTrade Trade; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- h="high"; l="low"; rest = false; atr_handler = iATR(Symbol(),PERIOD_H8,4*14); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- IndicatorRelease(atr_handler); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- datetime cd = iTime(Symbol(),PERIOD_D1,0); static datetime ds; if(cd != ds) { ds = cd; last_high = iHigh(Symbol(),PERIOD_D1,1); last_low = iLow(Symbol(),PERIOD_D1,1); if((rest==true) && (PositionsTotal() == 0)) rest = false; Comment("Last High: ",last_high,"\nLast Low: ",last_low); ObjectDelete(0,l); ObjectDelete(0,h); ObjectCreate(0,h,OBJ_HLINE,0,0,last_high); ObjectCreate(0,l,OBJ_HLINE,0,0,last_low); CopyBuffer(atr_handler,0,0,1,atr); } datetime ch = iTime(Symbol(),PERIOD_H1,0); static datetime hs; if(ch != hs) { hs = ch; last_high = iHigh(Symbol(),PERIOD_D1,1); last_low = iLow(Symbol(),PERIOD_D1,1); double bid,ask,close,padding; close = iClose(Symbol(),PERIOD_H1,0); ask = SymbolInfoDouble(Symbol(),SYMBOL_ASK); bid = SymbolInfoDouble(Symbol(),SYMBOL_BID); padding = atr[0] * 2; if(rest == false) { if(PositionsTotal() == 0) { if((MathAbs(close - last_high) > MathAbs(close - last_low))) Trade.Buy(0.01,Symbol(),ask,(bid-(padding)),last_high+(padding*0.9)); else if((MathAbs(close - last_high) < MathAbs(close - last_low))) Trade.Sell(0.01,Symbol(),bid,(ask+(padding)),last_low-(padding*0.9)); rest = true; } } if(rest == true) { if(PositionsTotal() > 0) { if(PositionSelectByTicket(PositionGetTicket(0))) { double sl,tp; sl = PositionGetDouble(POSITION_SL); tp = PositionGetDouble(POSITION_TP); //--- Buy if(sl < tp) { if(last_low > sl) Trade.PositionModify(Symbol(),last_low,tp); } if(tp < sl) { if(last_high < sl) Trade.PositionModify(Symbol(),last_high,tp); } } } } } }
Кривая эквити теперь поднимается до более высоких уровней, чем в любой из предыдущих стратегий. Волатильность — диапазон между прибыльными и убыточными сделками — также более контролируема.

Рисунок 13: В окончательной версии нашей торговой стратегии получена кривая эквити с желаемой структурой, которой у нас изначально не было
Просматривая подробную статистику, мы видим, что общая чистая прибыль снова увеличилась - со 148 долларов в предыдущей версии до 162 долларов в этой. Однако доля прибыльных сделок снова меньше, чем раньше, а также меньше, чем в исходной стратегии. Это показывает, что наши улучшения влияют не только на прибыльные сделки, но и на убыточные так, как мы бы не хотели.
Это подчеркивает более глубокую проблему: совершенствование торговых стратегий, созданных только на человеческой интуиции, нелегко решить с помощью дополнительной интуиции. Чтобы действительно двигаться вперед, мы должны рассмотреть другие пути совершенствования, независящие от человеческого суждения.

Рисунок 14: При ближайшем рассмотрении мы поняли, что наши изменения также негативно сказались на эффективности системы с точки зрения точности
Заключение
Трейдеры-люди выживали на финансовых рынках не случайно и не пробивали себе путь наугад, от сделки к сделке. Необходимость и страх понести убытки заставили их искать настоящие и надежные взаимосвязи. Сегодня эта дисциплина часто упускается из виду, поскольку специалисты по машинному обучению стремятся к более объемным данным и более сложным моделям, не задаваясь вопросом, действительно ли их показатели отражают значимый прогресс.
Наша работа предполагает другой путь. Основывая стратегии на дискреционной рыночной логике, мы исходим из доказанной валидности, а не из слепого предположения. Остаточные ошибки этих стратегий — погрешности в наших стратегиях — становятся благодатной почвой для моделей машинного обучения. Таким образом, мы больше не требуем от наших алгоритмов доказывать взаимосвязи с нуля. Вместо этого мы даем им структуру, в которой входы и выходы уже связаны.
Этот сдвиг также приближает нас к выполнению статистических предположений, от которых незаметно зависят наши модели. Фиксированная стратегия в условиях меняющегося рынка формирует результаты, которые напоминают независимые, тождественно распределенные условия, необходимые для устойчивого обучения. В реальном мире, возможно, никогда не будет идеальной системы независимых и одинаково распределенных случайных величин, но этот подход приближает нас к идеалу, делая наши модели менее уязвимыми и более надежными. Мы считаем, что, начав с рыночной логики, усвоенной людьми, и затем обучая модели на ошибках в этой логике, мы сможем дать возможность нашим моделям машинного обучения начать обучение с более высокого уровня.
| Название файла | Информация о файле |
|---|---|
| Daily Breakout Strategy V1.mq5 | Первоначальная и агрессивная версия нашей торговой стратегии, показавшая высокую точность на начальном этапе. |
| Daily Breakout Strategy V2.mq5 | Вторая версия нашей торговой системы показала несколько меньшие уровни точности, но значительно более высокую прибыльность. |
| Daily Breakout Strategy V3.mq5 | Окончательная версия нашей торговой стратегии, показавшая самый высокий уровень прибыльности, но самый низкий уровень точности. |
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/19130
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Автоматизация торговых стратегий в MQL5 (Часть 28): Создание гармонического паттерна "Летучая мышь" на основе Price Action с визуальной обратной связью
Тестер стратегий для Python и MetaTrader 5 (Часть 04): Основы работы тестера
Тестер стратегий для Python и MetaTrader 5 (Часть 05): Тестер стратегий для нескольких символов и таймфреймов
Тестер стратегий для Python и MetaTrader 5 (Часть 03): Обработка и управление торговыми операциями по образцу MetaTrader 5
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования