Оптимизация и тестирование торговых стратегий (Часть 1): Взгляд на "Red Dragon H4", "BOLT", "YinYang", и "Statistics SAR"
Введение
Добрый день, уважаемые пользователи, сообщества MQL5. Так как я постоянно занимаюсь, разработкой разного рода торговых систем сегодня хочу поделиться с Вами несколькими из них по стратегиям "Red Dragon H4", "BOLT", "YinYang" и "Statistics SAR". Данные стратегии были найдены на просторах интернета. Привлекли мое внимание своей простотой и использованием в терминале MetaTrader 5. Некоторые позиционируются как классические трендовые стратегии, некоторые как разворотные контртрендовые. Сразу хотелось бы сказать, что итоговый результат разработки советников по данным стратегиям мне неизвестен. Данная статья пишется вместе с разработкой, что придает ей некой загадочности. Тем самым я хотел бы начать новую серию своих статей и постоянно делиться с вами своими достижениями.
Стратегия «Red Dragon H4»
Немаловажную роль в рассмотрении данной стратегии сыграл факт использования большого таймфрейма, на котором, как известно меньше шумов и ложных входов, хотя и сигналов тоже меньше. Авторы стратегии утверждают, что на сильном тренде система отлично дает сигналы в моменты завершения коррекций. Однако при присутствии на рынке затяжного разворота, торговая система очень редко генерирует сигналы, что позволяет ей не уходить в просадку.
Также немаловажным фактором мотивации написания торгового робота сыграл факт «свежести» системы. Стратегию начали использовать в 2022-2023 годах. Изначального применения на самых популярных торговых парах EURUSD и GBPUSD, а также тонкий намек на возможность применения на других валютных парах. То есть стратегия позиционируется как мультивалютная и нуждается в проверке этого утверждения. И так начнем.
Здесь я приведу описание самой стратегии, правил входа и выхода из позиций для лучшего понимания работы. Приведу примеры на скриншотах. Возможно, кому-то потребуется видоизменить саму стратегию или советник в дальнейшем. К тому же я думаю, необходимо проверить стратегию и на других более мелких таймфреймах и посмотреть что получится.
Рынок, валютная пара, временной интервал:
- Валютная пара – мультивалютная.
- Временной интервал – Н4.
- Рынок - FOREX
Используемые индикаторы:
- Экспоненциальная скользящая средняя с периодом 120 - EMA120.
- Exponential Moving Average 14 - EMA14, построенная по ценам Low.
- Такая же EMA14, построенная по ценам High.
- Индикатор Parabolic SAR с шагом 0,01 и с максимумом 0,2.
- Индикатор Accelerator Oscillator.
Условия для покупок по стратегии «Red Dragon H4»:
- На закрытии очередной предыдущей свечи индикатор Parabolic SAR перескакивает сверху-вниз и оказывается под текущей свечей.
- Именно эта же предыдущая свеча должна быть закрыта выше EMA14 (High).
- Так же эта свеча должна быть закрыта выше ЕМА120.
- Индикатор Accelerator Oscillator на предыдущей свече находится выше своей нулевой отметки.
- Если все условия выполнены, то на открытии следующей свечи заключается сделка на покупку.
- Stop Loss устанавливается за ЕМА14 (Low). Если минимум сигнальной свечи находится ниже, то Stop Loss следует устанавливать именно под нее. То есть на Low предыдущей свечи.
- После прохождения цены в положительной зоне расстояния равного размеру Stop Loss сделку необходимо перевести в безубыток.
- Take Profit устанавливается в размере, двукратно превышающем размер Stop Loss .
- Новую позицию в ту же сторону можно открывать, если предыдущая позиция уже переведена в безубыток.
Ниже приведу пару скриншотов с входами на покупку:
Условия для продаж по стратегии «Red Dragon H4»:
- На закрытии очередной предыдущей свечи индикатор Parabolic SAR перескакивает снизу-вверх и располагается над текущей свечей.
- Именно эта же предыдущая свеча должна быть закрыта ниже EMA14 (Low).
- Так же эта свеча должна быть закрыта ниже ЕМА120.
- Индикатор Accelerator Oscillator на предыдущей свече находится ниже своей нулевой отметки.
- Если все условия выполнены, то на открытии следующей свечи заключается сделка на продажу.
- Stop Loss устанавливается за ЕМА14 (High). Если максимум сигнальной свечи находится выше, то Stop Loss следует устанавливать именно над ней. То есть на High предыдущей свечи.
- После прохождения цены в положительной зоне расстояния равного размеру Stop Loss сделку необходимо перевести в безубыток.
- Take Profit устанавливается в размере, двукратно превышающем размер Stop Loss, как и в случае с покупками.
- Новую позицию в ту же сторону можно открывать, если предыдущая позиция уже переведена в безубыток, как и в случае с покупками.
Ниже приведу пару скриншотов с входами на продажу:
Пишем код советника по стратегии «Red Dragon H4»:
Для проведения дальнейшей оптимизации выводим параметры индикаторов и множителя Take Profit в переменные:
input group "+++ Indicators +++" input int Big_MA = 120; input int Small_MA = 14; input ENUM_MA_METHOD Method_MA = MODE_EMA; input double Step_SAR = 0.01; input double Maximum_SAR = 0.2; input group "+++ Take profit +++" input double StoplossMultiplierForTakeprofit = 2.0;
Получаем хендлы и значения наших индикаторов:
handle_In1=iMA(symbolS1.Name(),PERIOD_CURRENT,Big_MA,0,Method_MA,PRICE_CLOSE); //--- if the handle is not created if(handle_In1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In2=iMA(symbolS1.Name(),PERIOD_CURRENT,Small_MA,0,Method_MA,PRICE_HIGH); //--- if the handle is not created if(handle_In2==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In3=iMA(symbolS1.Name(),PERIOD_CURRENT,Small_MA,0,Method_MA,PRICE_LOW); //--- if the handle is not created if(handle_In3==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In4=iSAR(symbolS1.Name(),PERIOD_CURRENT,Step_SAR,Maximum_SAR); //--- if the handle is not created if(handle_In4==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In5=iAO(symbolS1.Name(),PERIOD_CURRENT); //--- if the handle is not created if(handle_In5==INVALID_HANDLE) { return(INIT_FAILED); } //--- //--- get data from the three buffers of the MA indicator ArraySetAsSeries(ind_In1S1,true); if(!iGetArray(handle_In1,0,0,5,ind_In1S1)) { return; } //--- //--- get data from the three buffers of the MA indicator ArraySetAsSeries(ind_In2S1,true); if(!iGetArray(handle_In2,0,0,5,ind_In2S1)) { return; } //--- //--- get data from the three buffers of the MA indicator ArraySetAsSeries(ind_In3S1,true); if(!iGetArray(handle_In3,0,0,5,ind_In3S1)) { return; } //--- //--- get data from the three buffers of the SAR indicator ArraySetAsSeries(ind_In4S1,true); if(!iGetArray(handle_In4,0,0,5,ind_In4S1)) { return; } //--- //--- get data from the three buffers of the AO indicator ArraySetAsSeries(ind_In5S1,true); if(!iGetArray(handle_In5,0,0,5,ind_In5S1)) { return; } //---
Основной блок логики советника:
//Sell++++++++++++++++++++++++++++++++++++++++++++++++ if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (SpreadS1<=MaxSpread) && (Triger_Sell!=iClose(symbolS1.Name(),PERIOD_CURRENT,1)) && (ind_In4S1[1]>iClose(symbolS1.Name(),PERIOD_CURRENT,1)) && (ind_In4S1[2]<iClose(symbolS1.Name(),PERIOD_CURRENT,2)) && (iClose(symbolS1.Name(),PERIOD_CURRENT,1)<ind_In1S1[1]) && (iClose(symbolS1.Name(),PERIOD_CURRENT,1)<ind_In3S1[1]) && (ind_In5S1[1]<0)) { double sl = 0; double tp = 0; if(iHigh(symbolS1.Name(),PERIOD_CURRENT,1)>ind_In2S1[1]) { sl = iHigh(symbolS1.Name(),PERIOD_CURRENT,1); } else { sl = ind_In2S1[1]; } tp = BidS1-((sl-AskS1)*StoplossMultiplierForTakeprofit); OpenSell(symbolS1.Name(), LotsXSell, tp, sl, EAComment); Triger_Sell=iClose(symbolS1.Name(),PERIOD_CURRENT,1); } //Buy++++++++++++++++++++++++++++++++++++++++++++++++ if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (SpreadS1<=MaxSpread) && (Triger_Buy!=iClose(symbolS1.Name(),PERIOD_CURRENT,1)) && (ind_In4S1[1]<iClose(symbolS1.Name(),PERIOD_CURRENT,1)) && (ind_In4S1[2]>iClose(symbolS1.Name(),PERIOD_CURRENT,2)) && (iClose(symbolS1.Name(),PERIOD_CURRENT,1)>ind_In1S1[1]) && (iClose(symbolS1.Name(),PERIOD_CURRENT,1)>ind_In2S1[1]) && (ind_In5S1[1]>0)) { double sl = 0; double tp = 0; if(iLow(symbolS1.Name(),PERIOD_CURRENT,1)<ind_In3S1[1]) { sl = iLow(symbolS1.Name(),PERIOD_CURRENT,1); } else { sl = ind_In3S1[1]; } tp = AskS1+((BidS1-sl)*StoplossMultiplierForTakeprofit); OpenBuy(symbolS1.Name(), LotsXBuy, tp, sl, EAComment); Triger_Buy=iClose(symbolS1.Name(),PERIOD_CURRENT,1); }
Следует пояснить некоторые моменты, а именно:
- параметр StoplossMultiplierForTakeprofit отвечает за умножение Take Profit относительно Stop Loss;
- Triger_Sell и Triger_Buy используются для запоминания цены открытия свечи и в дальнейшем проверяются в условии открытия позиции. Это необходимо для предотвращения получения нескольких входов на одном сигнале;
- проверки if(iHigh(symbolS1.Name(),PERIOD_CURRENT,1)>ind_In2S1[1]) и if(iLow(symbolS1.Name(),PERIOD_CURRENT,1)<ind_In3S1[1]) используются для определения расположения Stop Loss описанного в условиях стратегии.
Тестирование и оптимизация советника по стратегии «Red Dragon H4»:
Проведем тестирование с параметрами по умолчанию по валютных парах EURUSD и GBPUSD в период времени с 2020.02.13 по 2023.02.13 на разных таймфреймах:
EURUSD H1 StoplossMultiplierForTakeprofit = 1.0
EURUSD H4 StoplossMultiplierForTakeprofit = 1.0
EURUSD H1 StoplossMultiplierForTakeprofit = 2.0
EURUSD H4 StoplossMultiplierForTakeprofit = 2.0
GBPUSD H1 StoplossMultiplierForTakeprofit = 1.0
GBPUSD H4 StoplossMultiplierForTakeprofit = 1.0
GBPUSD H1 StoplossMultiplierForTakeprofit = 2.0
GBPUSD H4 StoplossMultiplierForTakeprofit = 2.0
Как видно из тестов мы получили неоднозначные результаты. Проведем оптимизацию с параметрами указанными на скриншоте ниже:
Результаты оптимизации:
Результат тестирования лучшего результата оптимизации:
Заключение по стратегии «Red Dragon H4»:
Как видно из проведенной работы стратегия выдает не очень хорошие результаты и обладает низким профит фактором даже при соотношении 1 к 2 или 1 к 3 Stop Loss к Take Profit. Интересной особенностью является получение сигнала именно в момент переворота индикатора Parabolic SAR. Возможно, это влияет на частоту сделок. Также на результаты может влиять постоянно плавающие значения Stop Loss и соответственно Take Profit.
Стратегия «BOLT»
Стратегия также найдена на просторах интернета и немного мной изменена. Причиной изменений стало выявление более подходящих, на мой взгляд, точек разворота рынка. Стратегия и в изначальном виде имела явно выраженный контр трендовый характер, теперь она стала еще более агрессивной. Я со своей стороны не рекомендую к использованию ее новичками. К тому же стратегия работает с сеткой, что рискованно для депозита. И так приступим к рассмотрению.
Рынок, валютная пара, временной интервал:
- Валютная пара – мультивалютная.
- Временной интервал – Н1.
- Рынок - FOREX
Используемые индикаторы:
- Индикатор Bollinger Bands с параметрами Период для расчета средней линии = 30, смещение индикатора по горизонтали = 0, количество стандартных отклонений = 3.
- Индикатор HLC Trend. Данный индикатор не входит в состав стандартных индикаторов поставляемых с терминалом MetaTrader 5 и его необходимо установить отдельно. Параметры High Price Period = 34, Low Price Period = 13, Close Price Period = 5, Moving Average Method = MODE_SMA.
Условия для продаж по стратегии «BOLT»:
- На закрытии очередной предыдущей свечи цена коснулась верхней границы индикатора Bollinger Bands. Таким образом, мы получаем первый сигнал на открытие первого ордера.
- После получения первого сигнала ждем схождения индикатора HLC Trend на предыдущем баре относительно пред предыдущего.
- Зеленая линия индикатора HLC Trend выше красной линии.
- Условием на открытие дополнительного ордера является сохранение условий 1 и 2 а также нахождение цены выше цены открытия предыдущего ордера на продажу. Этот параметр можно менять в настройках советника. Параметр StepOrdersPips.
- Закрытие всех позиций на продажу происходит после пересечения красной и зеленой линии индикатора HLC Trend. Зеленая линия индикатора ниже красной линии.
- Страховочный Stop Loss используется при желании.
Ниже приведу пару скриншотов с входами на продажу:
Условия для покупок по стратегии «BOLT»:
- На закрытии очередной предыдущей свечи цена коснулась нижней границы индикатора Bollinger Bands. Таким образом, мы получаем первый сигнал на открытие первого ордера.
- После получения первого сигнала ждем схождения индикатора HLC Trend на предыдущем баре относительно пред предыдущего.
- Зеленая линия индикатора HLC Trend ниже красной линии.
- Условием на открытие дополнительного ордера является сохранение условий 1 и 2 а также нахождение цены выше цены открытия предыдущего ордера на продажу. Этот параметр можно менять в настройках советника. Параметр StepOrdersPips.
- Закрытие всех позиций на покупку происходит после пересечения красной и зеленой линии индикатора HLC Trend. Зеленая линия индикатора выше красной линии.
- Страховочный Stop Loss используется при желании.
Ниже приведу пару скриншотов с входами на покупку:
Пишем код советника по стратегии «BOLT»:
Для проведения дальнейшей оптимизации выводим параметры индикаторов, шага сетки и Stop Loss в переменные:
input group "+++ Indicators +++" input int BandsPeriod = 30; input double BandsDeviation = 3.0; input int HLCTrend_high_period = 34; input int HLCTrend_low_period = 13; input int HLCTrend_close_period = 5; input group "+++ Grid +++" input int StepOrdersPips = 200; input group "+++ Stop loss +++" input int StopLoss = 9000;
Получаем хендлы и значения наших индикаторов:
handle_In1=iBands(symbolS1.Name(),PERIOD_CURRENT,BandsPeriod,0,BandsDeviation,PRICE_CLOSE); //--- if the handle is not created if(handle_In1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In2=iCustom(symbolS1.Name(),PERIOD_CURRENT,"HLC Trend",HLCTrend_high_period,HLCTrend_low_period,HLCTrend_close_period,MODE_SMA); //--- if the handle is not created if(handle_In2==INVALID_HANDLE) { return(INIT_FAILED); } //--- //--- get data from the three buffers of the BB indicator ArraySetAsSeries(ind_In1S1,true); if(!iGetArray(handle_In1,1,0,5,ind_In1S1)) { return; } //--- //--- get data from the three buffers of the BB indicator ArraySetAsSeries(ind_In2S1,true); if(!iGetArray(handle_In1,2,0,5,ind_In2S1)) { return; } //--- //--- get data from the three buffers of the HLC Trend indicator ArraySetAsSeries(ind_In3S1,true); if(!iGetArray(handle_In2,0,0,5,ind_In3S1)) { return; } //--- //--- get data from the three buffers of the HLC Trend indicator ArraySetAsSeries(ind_In4S1,true); if(!iGetArray(handle_In2,1,0,5,ind_In4S1)) { return; } //---
Основной блок логики советника:
//Sell++++++++++++++++++++++++++++++++++++++++++++++++ if ((iHigh(symbolS1.Name(),PERIOD_CURRENT,1)>ind_In1S1[1]) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0)){Triger_Sell=true;} if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (SpreadS1<=MaxSpread) && (Triger_Sell==true) && (ind_In3S1[1]>ind_In4S1[1]) && (ind_In3S1[1]<ind_In3S1[2]) && (ind_In4S1[1]>ind_In4S1[2])) { OpenSell(symbolS1.Name(), LotsXSell, 0, StopLoss, EAComment); Triger_Sell=false; } if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (SpreadS1<=MaxSpread) && (BidS1>(GetPrice(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(StepOrdersPips*PointS1))) && (ind_In3S1[1]>ind_In4S1[1]) && (ind_In3S1[1]<ind_In3S1[2]) && (ind_In4S1[1]>ind_In4S1[2])) { OpenSell(symbolS1.Name(), LotsXSell, 0, StopLoss, EAComment); } if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (ind_In3S1[1]<ind_In4S1[1])) { ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL); } //Buy++++++++++++++++++++++++++++++++++++++++++++++++ if ((iLow(symbolS1.Name(),PERIOD_CURRENT,1)<ind_In2S1[1]) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0)){Triger_Buy=true;} if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (SpreadS1<=MaxSpread) && (Triger_Buy==true) && (ind_In3S1[1]<ind_In4S1[1]) && (ind_In3S1[1]>ind_In3S1[2]) && (ind_In4S1[1]<ind_In4S1[2])) { OpenBuy(symbolS1.Name(), LotsXBuy, 0, StopLoss, EAComment); Triger_Buy=false; } if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (SpreadS1<=MaxSpread) && (AskS1<(GetPrice(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)-(StepOrdersPips*PointS1))) && (ind_In3S1[1]<ind_In4S1[1]) && (ind_In3S1[1]>ind_In3S1[2]) && (ind_In4S1[1]<ind_In4S1[2])) { OpenBuy(symbolS1.Name(), LotsXBuy, 0, StopLoss, EAComment); } if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (ind_In3S1[1]>ind_In4S1[1])) { ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY); }
Следует пояснить некоторые моменты, а именно:
- Переменные Triger_Sell и Triger_Buy значения True/False отвечают за запоминание касаний верхней и нижней сторон индикатора Bollinger Bands. По условиям стратегии это первый сигнал.
- Отслеживания цены последней позиции для выставления сетки ордеров происходит с помощью функции GetPrice, которая возвращает цену открытия в зависимости от типа позиции.
- В сетке уже не участвуют триггеры касания индикатора Bollinger Bands. Выполняются только условия схождения индикатора HLC Trend.
Тестирование и оптимизация советника по стратегии «BOLT»:
Проведем тестирование с параметрами по умолчанию по валютных парах EURUSD и GBPUSD в период времени с 2020.02.13 по 2023.02.13 на разных таймфреймах. Шаг сетки равен 200 пунктов по пятизнаку:
EURUSD M30
EURUSD H1
EURUSD H4
GBPUSD M30
GBPUSD H1
GBPUSD H4
Как видно из тестов мы получили результаты с большими просадками. Проведем оптимизацию с параметрами указанными на скриншоте ниже:
Результаты оптимизации:
Результаты тестирования лучшего прохода по максимуму комплексного критерия:
Заключение по стратегии «BOLT»:
Как видно из проведенной работы над советником стратегия выдает просадки, иногда закрывая сетку с убытком, а иногда с профитом. Возможно, добавление легкого мартингейла немного бы выровняло график баланса. Но в свою очередь это очень рискованно. Также необходимо проверить получившийся советник на более спокойных валютных парах, предполагаю, что не большая волатильность на них приведет к более устойчивым результатам.
Стратегия «YinYang»
По своей сути стратегия работает как в скальпинговом варианте, так и более классическом виде. Является как трендовой, так и контр трендовой одновременно, получая сигналы на вход в позиции в разных состояниях рынка. Изначально стратегия рекомендована для валютной пары GBPUSD, но мы, как всегда, проверим и на других валютных парах. Так же стратегия интересна тем, что имеет сразу по 2 условия на покупку и продажу. Такой ее вариант мы и реализуем в нашем советнике с помощью комментариев к сделкам, разделив их соответственно для одновременной работы.
Рынок, валютная пара, временной интервал:
- Валютная пара – изначально GBPUSD.
- Временной интервал – M15.
- Рынок - FOREX
Используемые индикаторы:
- Индикатор Envelopes с периодом 21 и с отклонением 0,18%.
- Индикатор Parabolic SAR с шагом 0,02; максимум 0,7.
- Индикатор Awesome Oscillator.
Условия для продаж по стратегии «YinYang»:
Вариант 1
- В прошлом цена касалась верхней линии индикатора Envelopes что является тригером на продажу, но еще не касалась нижней границы.
- Индикатор Parabolic SAR меняет свое положение и окажется выше цены на графике.
- Индикатор Awesome Oscillator находится выше нуля и окрашен в красный цвет. То есть его значения падают относительно предыдущих значений.
- После получения всех сигналов на следующей свече открываем продажу.
Вариант 2
- Текущая цена находится между верхней и нижней линиями индикатора Envelopes.
- Индикатор Parabolic SAR меняет свое положение и окажется выше цены на графике.
- Индикатор Awesome Oscillator находится выше нуля и эго значение растет.
Для обоих вариантов на продажу
- Stop Loss устанавливаем за индикатор Parabolic SAR.
- Рекомендуемый Take Profit 500-600 пунктов по пятизнаку.
- При получении обратного сигнала в обоих вариантах следует закрыть текущую позицию даже с убытком.
Ниже приведу пару скриншотов с входами на продажу варианта 1:
Ниже приведу пару скриншотов с входами на продажу варианта 2:
Условия для покупок по стратегии «YinYang»:
Вариант 1
- В прошлом цена касалась нижней линии индикатора Envelopes что является тригером на покупку по первому варианту стратегии, но еще не касалась нижней границы.
- Индикатор Parabolic SAR меняет свое положение и окажется ниже цены на графике.
- Индикатор Awesome Oscillator находится ниже нуля и окрашен в зеленый цвет. То есть его значения падают относительно предыдущих значений.
- После получения всех сигналов на следующей свече открываем покупку.
Вариант 2
- Текущая цена находится между верхней и нижней линиями индикатора Envelopes.
- Индикатор Parabolic SAR меняет свое положение и окажется ниже цены на графике.
- Индикатор Awesome Oscillator находится выше нуля и эго значение растет.
Для обоих вариантов на покупку
- Stop Loss устанавливаем за индикатор Parabolic SAR.
- Рекомендуемый Take Profit 500-600 пунктов по пятизнаку.
- При получении обратного сигнала в обоих вариантах следует закрыть текущую позицию даже с убытком.
Ниже приведу пару скриншотов с входами на покупку варианта 1:
Ниже приведу пару скриншотов с входами на покупку варианта 2:
Пишем код советника по стратегии «YinYang»:
Для проведения дальнейшей оптимизации выводим параметры индикаторов и Take Profit в переменные. Stop Loss мы выставляем по индикатору Parabolic SAR. Также введем 2 параметра типа bool для отключения или включения соответствующей стратегии для управления ими:
input group "+++ Indicators +++" input int EnvelopesPeriod = 21; input double EnvelopesDeviation = 0.18; input double Step_SAR = 0.01; input double Maximum_SAR = 0.2; input group "+++ Take profit +++" input int TakeProfit = 500; input group "+++ ON/OF Strategies +++" input bool Strategy1 = true; input bool Strategy2 = true;
Получаем хендлы и значения наших индикаторов:
handle_In1=iEnvelopes(symbolS1.Name(),PERIOD_CURRENT,EnvelopesPeriod,0,MODE_SMA,PRICE_CLOSE,EnvelopesDeviation); //--- if the handle is not created if(handle_In1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In2=iSAR(symbolS1.Name(),PERIOD_CURRENT,Step_SAR,Maximum_SAR); //--- if the handle is not created if(handle_In2==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In3=iAO(symbolS1.Name(),PERIOD_CURRENT); //--- if the handle is not created if(handle_In3==INVALID_HANDLE) { return(INIT_FAILED); } //--- //--- get data from the three buffers of the Envelopes indicator ArraySetAsSeries(ind_In1S1,true); if(!iGetArray(handle_In1,0,0,5,ind_In1S1)) { return; } //--- //--- get data from the three buffers of the Envelopes indicator ArraySetAsSeries(ind_In2S1,true); if(!iGetArray(handle_In1,1,0,5,ind_In2S1)) { return; } //--- //--- get data from the three buffers of the SAR indicator ArraySetAsSeries(ind_In3S1,true); if(!iGetArray(handle_In2,0,0,5,ind_In3S1)) { return; } //--- //--- get data from the three buffers of the AO indicator ArraySetAsSeries(ind_In4S1,true); if(!iGetArray(handle_In3,0,0,5,ind_In4S1)) { return; } //---
Основной блок логики советника:
//Variant 1 +++++++++++++++++++++++++++++++++++++++++++++++++++ if (Strategy1==true){ //Sell++++++++++++++++++++++++++++++++++++++++++++++++ if ((iHigh(symbolS1.Name(),PERIOD_CURRENT,1)>ind_In1S1[1]) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment+"ST1")==0)){Triger_Sell=true;} if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment+"ST1")==0) && (SpreadS1<=MaxSpread) && (Triger_Sell==true) && (ind_In3S1[1]>iClose(symbolS1.Name(),PERIOD_CURRENT,1)) && (ind_In4S1[1]<ind_In4S1[2]) && (ind_In4S1[1]>0) && (ind_In4S1[2]>0)) { double sl = ind_In3S1[1]; ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment+"ST1"); OpenSell(symbolS1.Name(), LotsXSell, TakeProfit, sl, EAComment+"ST1"); Triger_Sell=false; } //Buy++++++++++++++++++++++++++++++++++++++++++++++++ if ((iLow(symbolS1.Name(),PERIOD_CURRENT,1)<ind_In2S1[1]) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment+"ST1")==0)){Triger_Buy=true;} if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment+"ST1")==0) && (SpreadS1<=MaxSpread) && (Triger_Buy==true) && (ind_In3S1[1]<iClose(symbolS1.Name(),PERIOD_CURRENT,1)) && (ind_In4S1[1]>ind_In4S1[2]) && (ind_In4S1[1]<0) && (ind_In4S1[2]<0)) { double sl = ind_In3S1[1]; ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment+"ST1"); OpenBuy(symbolS1.Name(), LotsXBuy, TakeProfit, sl, EAComment+"ST1"); Triger_Buy=false; } } //Variant 2 +++++++++++++++++++++++++++++++++++++++++++++++++++ if (Strategy2==true){ //Sell++++++++++++++++++++++++++++++++++++++++++++++++ if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment+"ST2")==0) && (SpreadS1<=MaxSpread) && (ind_In3S1[1]>iClose(symbolS1.Name(),PERIOD_CURRENT,1)) && (iClose(symbolS1.Name(),PERIOD_CURRENT,1)<ind_In1S1[1]) && (iClose(symbolS1.Name(),PERIOD_CURRENT,1)>ind_In2S1[1]) && (ind_In4S1[1]<0) && (ind_In4S1[2]<0) && (ind_In4S1[1]<ind_In4S1[2])) { double sl = ind_In3S1[1]; ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment+"ST2"); OpenSell(symbolS1.Name(), LotsXSell, TakeProfit, sl, EAComment+"ST2"); } //Buy++++++++++++++++++++++++++++++++++++++++++++++++ if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment+"ST2")==0) && (SpreadS1<=MaxSpread) && (ind_In3S1[1]<iClose(symbolS1.Name(),PERIOD_CURRENT,1)) && (iClose(symbolS1.Name(),PERIOD_CURRENT,1)<ind_In1S1[1]) && (iClose(symbolS1.Name(),PERIOD_CURRENT,1)>ind_In2S1[1]) && (ind_In4S1[1]>0) && (ind_In4S1[2]>0) && (ind_In4S1[1]>ind_In4S1[2])) { double sl = ind_In3S1[1]; ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment+"ST2"); OpenBuy(symbolS1.Name(), LotsXBuy, TakeProfit, sl, EAComment+"ST2"); } }
Тестирование и оптимизация советника по стратегии «YinYang»:
Проведем тестирование с параметрами по умолчанию по валютных парах EURUSD и GBPUSD в период времени с 2020.02.13 по 2023.02.13 на таймфрейме M15:
Вариант 1:
EURUSD
GBPUSD
Вариант 2:
EURUSD
GBPUSD
Как видно из тестов мы получили негативный результат по обеим вариантам стратегии. Проведем оптимизацию с параметрами указанными на скриншоте ниже. Для простоты используем только первый вариант входов:
Результаты оптимизации:
Заключение по стратегии «YinYang»:
Как видно из проведенной работы над советником стратегия абсолютно не применима к нашим валютным парам и таймфрейму. Хочу сказать, что проведенные тесты на таймфрейме H1 привели к такому же результату. Что же не расстраиваемся и идем дальше.
Стратегия «Statistics SAR»
Насмотревшись на индикатор Parabolic SAR и его поведение относительно цены, мне пришла в голову, на мой взгляд, неплохая стратегия. Основана она на сборе статистики расхождения цены и самого индикатора Parabolic SAR. Мне показалось, что цена очень интересно с ним взаимодействует. Строго прошу не судить, так как стратегия авторская.
Рынок, валютная пара, временной интервал:
- Валютная пара – мультивалютная, проверять будем на EURUSD и GBPUSD.
- Временной интервал – M15-H1.
- Рынок - FOREX
Используемые индикаторы:
- Индикатор Parabolic SAR с шагом 0,02; максимум 0,2 по умолчанию. В дальнейшем используется оптимизация этих параметров.
- Индикатор Moving Average с периодом 1. Используем как значение цены.
Условия для продаж по стратегии «Statistics SAR»:
- Собираем статистику расхождения индикатора Moving Average с периодом 1 и индикатора Parabolic SAR для нахождения среднего значения. Используется задаваемое в параметрах количество свечей.
- Индикатор Parabolic SAR находится под ценой, в нашем случае Moving Average с периодом 1.
- Расстояние в пунктах между ценой и SAR превышает среднее значение, умноженное на некий коэффициент, определенный в параметрах советника.
- Stop Loss и Take Profit имеют фиксированные значения. Вынесены в параметры советника.
Ниже приведу пару скриншотов с попыткой отследить такие ситуации на продажу:
Условия для покупок по стратегии «Statistics SAR»:
- Собираем статистику расхождения индикатора Moving Average с периодом 1 и индикатора Parabolic SAR для нахождения среднего значения. Используется задаваемое в параметрах количество свечей.
- Индикатор Parabolic SAR находится над ценой, в нашем случае Moving Average с периодом 1.
- Расстояние в пунктах между SAR и ценой превышает среднее значение, умноженное на некий коэффициент, определенный в параметрах советника.
- Stop Loss и Take Profit имеют фиксированные значения. Вынесены в параметры советника.
Ниже приведу пару скриншотов с попыткой отследить такие ситуации на покупку:
Следует отметить, что количество данных для сбора статистики может отличаться в зависимости от используемого таймфрейма. Также следует обратить внимание, что проводить сбор статистики лучше отдельно для покупок и продаж, но сегодня мы проведем общий сбор для выяснения жизнеспособности моей стратегии.
На заметку:
- На таймфрейме H1 30 дней равно 720 свечей.
- На таймфрейме M30 30 дней равно 1440 свечей.
- На таймфрейме M15 30 дней равно 2880 свечей.
Пишем код советника по стратегии «Statistics SAR»:
Для проведения дальнейшей оптимизации выводим параметры индикаторов, параметры Take Profit и Stop Loss в переменные. Также выводим количество свечей для сбора статистики – параметр Canbles:
input group "+++ Indicators +++" input double Step_SAR = 0.02; input double Maximum_SAR = 0.2; input group "+++ Take profit/Stop loss +++" input int TakeProfit = 400; input int StopLoss = 200; input group "+++ Statistics +++" input int Canbles = 720; input double MultiplyingAverage = 2.0;
Получаем хендлы и значения наших индикаторов:
handle_In1=iMA(symbolS1.Name(),PERIOD_CURRENT,1,0,MODE_SMA,PRICE_CLOSE); //--- if the handle is not created if(handle_In1==INVALID_HANDLE) { return(INIT_FAILED); } //--- handle_In2=iSAR(symbolS1.Name(),PERIOD_CURRENT,Step_SAR,Maximum_SAR); //--- if the handle is not created if(handle_In2==INVALID_HANDLE) { return(INIT_FAILED); } //--- //--- get data from the three buffers of the MA 1 indicator ArraySetAsSeries(ind_In1S1,true); if(!iGetArray(handle_In1,0,0,Canbles+5,ind_In1S1)) { return; } //--- //--- get data from the three buffers of the SAR indicator ArraySetAsSeries(ind_In2S1,true); if(!iGetArray(handle_In2,0,0,Canbles+5,ind_In2S1)) { return; } //---
Код получения статистики:
//Statistics++++++++++++++++++++++++++++++++++++++++++++++++ if(isNewBar2()==true) { //--- get data from the three buffers of the MA 1 indicator ArraySetAsSeries(ind_In1S1,true); if(!iGetArray(handle_In1,0,0,Candles+5,ind_In1S1)) { return; } //--- //--- get data from the three buffers of the SAR indicator ArraySetAsSeries(ind_In2S1,true); if(!iGetArray(handle_In2,0,0,Candles+5,ind_In2S1)) { return; } //--- Sr=0; Count=0; for(int i=0; i<=Candles; i++) { if((ind_In1S1[i]!=0) && (ind_In2S1[i]!=0)) { Sr = Sr + int(MathAbs((ind_In1S1[i]-ind_In2S1[i])/PointS1)); Count++; } } Sr = Sr/Count; } //Statistics++++++++++++++++++++++++++++++++++++++++++++++++
Основной блок логики советника:
//Sell++++++++++++++++++++++++++++++++++++++++++++++++ if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (SpreadS1<=MaxSpread) && (ind_In1S1[1]>ind_In2S1[1]) && (((ind_In1S1[1]-ind_In2S1[1])/PointS1)>=(Sr*MultiplyingAverage))) { OpenSell(symbolS1.Name(), LotsXSell, TakeProfit, StopLoss, EAComment); } //Buy+++++++++++++++++++++++++++++++++++++++++++++++ if((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (SpreadS1<=MaxSpread) && (ind_In1S1[1]<ind_In2S1[1]) && (((ind_In2S1[1]-ind_In1S1[1])/PointS1)>=(Sr*MultiplyingAverage))) { OpenBuy(symbolS1.Name(), LotsXBuy, TakeProfit, StopLoss, EAComment); }
Немного объяснений по коду. Дабы ускорить, советник статистику мы собираем один раз в день. Функция isNewBar2() возвращает признак открытия новой свечи на таймфрейме D1. Также обязательно проверяем, не равно ли среднее значение нулю - (Sr!=0). Среднее и текущее значения считаются в пунктах.
Тестирование и оптимизация советника по стратегии «Statistics SAR»:
Проведем тестирование с параметрами по умолчанию по валютных парах EURUSD и GBPUSD в период времени с 2020.02.13 по 2023.02.13 на разных тайм фреймах. Параметр MultiplyingAverage = 2.0 :
EURUSD M15
EURUSD M30
EURUSD H1
GBPUSD M15
GBPUSD M30
GBPUSD H1
Как видно из тестов мы получили негативный результат по обеим валютним парам с параметрами по умолчанию. Проведем оптимизацию на тайм фрейме H1 с параметрами указанными на скриншоте ниже:
Результаты оптимизации:
Результат лучшего прохода по комплексному критерию:
Заключение по стратегии «Statistics SAR»:
Как видно из проведенной оптимизации стратегия вполне пригодна для дальнейшего развития и модернизации. По комплексному критерию результаты не плохие.
Выводы по результатам анализа
- Стратегия "Red Dragon H4" показывает не очень хорошие результаты и обладает низким профит фактором, но интересна моментом получения сигнала при перевороте индикатора Parabolic SAR.
- Стратегия "BOLT" может приводить к просадкам и требует дополнительной оптимизации, возможно, с использованием мартингейла, что увеличивает риски.
- Стратегия "YinYang" абсолютно не применима к выбранным валютным парам и таймфрейму, показывая плохие результаты.
- Стратегия "Statistics SAR" кажется перспективной для дальнейшего развития и модернизации, показывая комплексно не плохие результаты.
Заключение
Сегодня мы с Вами проверили ряд стратегий, написавши по ним торговых роботов. Получили некоторые результаты. В одних случаях неплохие можно сказать средней результативности тесты. В других плохие результаты не применимы к теперешнему рынку. В любом случае сегодня мы провели не малую работу и научились некоторым приемам, таким как:
- Использование триггеров для определения точки входа.
- Выставления Stop Loss по индикаторам.
- Умножение на порядок Take Profit в зависимости от Stop Loss.
- Рассмотрели простенький вариант использования сетки в торговле.
- Использование двух сигналов на открытие позиций в одном советнике.
- Сбор статистических данных для использования в торговле.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования