Фиксированный стоп-лосс на основе ценового действия и RSI ("умный" стоп-лосс)
Введение
На это исследование меня натолкнули попытки найти грааль в трейдинге. Стоп-лосс – самый важный инструмент в трейдинге по части управления капиталом. В свою очередь, управление капиталом – один из способов зработать на рынке, оставаясь при этом последовательным в долгосрочной перспективе. Как указывалось ранее, управление капиталом тесно связано со стоп-лоссом и соотношением риска и вознаграждения. Соотношение 1:1,5R(риск:вознаграждение), как правило, имеет более высокий коэффициент выигрыша по сравнению с другими, однако соотношение 1:>1.9R(риск:вознаграждение) в большинстве случаев более прибыльно, при этом прибыльность сохраняется длительное время (грааль). Однако у этого грааля есть и недостаток. В идеальной ситуации торговля с соотношением 1:>1,9R(риск:вознаграждение) остается прибыльной, если из 10 сделок (по 1 пипсу каждая) 6 сделок были убыточными (6 пипсов) и 4 сделки прибыльными (8 пипсов). Мы остаемся в прибыли в 2 пипса. В реальности же обычно всё бывает по-другому. Одна из основных причин заключается в таком явлении как охота на стоп-лоссы, когда цена достигает стоп-лосса, а затем идет в предсказанном направлении. Охота на стоп-лоссы – это серьезная проблема в торговле и управлении капиталом. Она также имеет и психологический эффект на трейдеров (в основном начинающих).
Рис. 1.1. Охота на стоп-лоссы
Охота на стоп-лоссы в основном затрагивает фиксированные или трейлинг-стопы на свечном графике или графике ценового действия. Если на графике ценового действия нет стоп-лосса, не будет и охоты на него. Однако отсутствие стоп-лосса резко повышает вероятность полного уничтожения депозита (вероятность равна единице (1)).
Стоп-лосс на основе RSI
Осциллятор RSI является копией линейного графика ценового действия, строящегося в пределах от 0 до 100
Рис. 1.2. RSI и линейный график
Если RSI и линейный график очень похожи, использование индикатора RSI в качестве "умного" стоп-лосса может уменьшить риск охоты на стоп-лосс.
Цель:
Моя цель здесь состоит в том, чтобы проверить, поможет ли использование стоп-лосса на основе RSI уменьшить эффект охоты на стоп-лоссы и при этом добиться долгосрочной прибыльности.
Метод:
Сравнение двух стратегий: использование стоп-лосса на графике ценового действия и стоп-лосса на основе индикатора RSI.
Стратегия и код
Классический стоп-лосс на графике ценового действия
Первый советник будет основан на фиксированном стоп-лоссе, установленном на графике ценового действия. Ниже приведены требования к стратегии.
Параметры | Описание |
---|---|
Используемый индикатор | MACD (12,26,9) |
Используемый индикатор | Moving Average (200) |
Используемый индикатор | Moving Average (50) |
Используемый индикатор | ATR (5) |
Таймфрейм | M1 |
Покупка | Если Moving Average (50) выше Moving Average (200), а линия MACD выше сигнальной, при этом обе они ниже нуля |
Продажа | Если Moving Average (50) ниже Moving Average (200), а линия MACD ниже сигнальной, при этом обе они выше нуля |
Выход | Тейк-профит и стоп-лосс (1:2R). Стоп-лосс на покупку является минимальным за 20 свечей после входа минус значение ATR (5) Стоп-лосс на продажу является максимальным за 20 свечей после входа плюс значение ATR (5)
|
Графическое представление показано ниже.
Рис. 2.1. Покупка
Рис. 2.2. Продажа
Код
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
#include<Trade\Trade.mqh>
CTrade trade;
int MATrend;
int MADirection;
int MACD;
int ATR;
input int afi;// ----------RiskAmount------------
input double risk = 0.02; //% Amount to risk
input int atrValue = 20; // ATR VAlue
input int ai;// ----------Moving Average inputs------------
input int movAvgTrend = 200;// Moving Average Trend
input int movAvgDirection = 50;//moving Average for trend Direction;
input int i;// -----------MACD inputs-----------------------
input int fast = 12;// Macd Fast
input int slow = 26; //Macd Slow
input int signal = 9; //Signal Line
Также объявлены другие переменные
double pipValue = 0.0;// double Balance; // For the Current Balance
Переменные были присвоены каждому обработчику в функции init()
int OnInit() { //--- //Moving Averages Indicators'' MATrend = iMA(_Symbol,_Period,movAvgTrend,0,MODE_SMA,PRICE_CLOSE); //Moving Average 200 MADirection = iMA(_Symbol,_Period,movAvgDirection,0,MODE_EMA,PRICE_CLOSE); //Moving Average 50 //MACD MACD = iMACD(_Symbol,_Period,fast,slow,signal,PRICE_CLOSE);//MACD //ATR ATR = iATR(_Symbol,_Period,atrValue); //--- point=_Point; double Digits=_Digits; if((_Digits==3) || (_Digits==5)) { point*=10; } return(INIT_SUCCEEDED); }
Ниже показан код работы стратегии
void Strategy() { MqlRates priceAction[]; ArraySetAsSeries(priceAction,true); int priceData = CopyRates(_Symbol,_Period,0,200,priceAction); double maTrend[]; ArraySetAsSeries(maTrend,true); CopyBuffer(MATrend,0,0,200,maTrend); //200 MA double madirection[]; ArraySetAsSeries(madirection,true); CopyBuffer(MADirection,0,0,200,madirection); //50 MA double macd[]; ArraySetAsSeries(macd,true); CopyBuffer(MACD,0,0,200,macd); //MACD double macds[]; ArraySetAsSeries(macds,true); CopyBuffer(MACD,1,0,200,macds); //MACD_Signal Line double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); if (madirection[1]>maTrend[1]) { //Buy ; Uptrend bool macd_bZero = macds[1]<0&&macd[1]<0; //MacD Signal Line is less than Zero bool macd_cross = macd[1]>macds[1];// Macd Crosses the signal line if (macd_bZero && macd_cross) { buyTrade = true; } } else if (madirection[1]<maTrend[1]) { //Sell; DownTrend bool macd_bZero = macds[1]>0&&macd[1]>0;; //MacD Signal Line is less than Zero bool macd_cross = macd[1]<macds[1];// Macd Crosses the signal line if (macd_bZero && macd_cross) { sellTrade = true; } } if (buyTrade && sellTrade) { buyTrade = false; sellTrade = false; return; } if (buyTrade) { buyTrade = false; sellTrade = false; Buy(Ask); } else if (sellTrade) { buyTrade = false; sellTrade = false; Sell(Bid); } }
Вход (покупка и продажа)
void Buy(double Ask) { double atr[]; ArraySetAsSeries(atr,true); //This array is use to store all ATR value to the last closed bar CopyBuffer(ATR,0,0,200,atr); // This method copy the buffer value of the ATR indicator into the array (200 buffered data) theLotsize = NormalizeDouble((Balance*risk)/((MathAbs(Ask-((stoplossforBuy(20)-atr[1])))*100)*pipValue),2); // This Calculate the lotsize using the % to risk trade.Buy(theLotsize,_Symbol,Ask,(stoplossforBuy(20)-atr[1]),Ask+(2*MathAbs(Ask-((stoplossforBuy(20)-atr[1])))),NULL); //Buy Entry with zero stoploss && take profit is twice the distance between the entry and the lowest candle } void Sell(double Bid) { double atr[]; ArraySetAsSeries(atr,true); //This array is use to store all ATR value to the last closed bar CopyBuffer(ATR,0,0,200,atr); // This method copy the buffer value of the ATR indicator into the array (200 buffered data) theLotsize = NormalizeDouble((Balance*risk)/((MathAbs(Bid-((stoplossforSell(20)+atr[1])))*100)*pipValue),2); // This Calculate the lotsize using the % to risk trade.Sell(theLotsize,_Symbol,Bid,(stoplossforSell(20)+atr[1]),Bid-(2*MathAbs(((stoplossforSell(20)+atr[1]))-Bid)),NULL); //Sell Entry with zero stoploss && take profit is twice the distance between the entry and the highest candle }
Из приведенных выше кодов мы вызываем два метода – stoplossforSell(int num) и stoplossforBuy(int num). Эти два метода предназначены для определения максимальной и минимальной свечи с присвоенным номером после срабатывания сигнала на вход в сделку. Например, stoplossforSell(20) возвращает максимальную свечу из 20 предыдущих перед входом.
double stoplossforBuy(int numcandle) { int LowestCandle; //Create array for candle lows double low[]; //Sort Candle from current downward ArraySetAsSeries(low,true); //Copy all lows for 100 candle CopyLow(_Symbol,_Period,0,numcandle,low); //Calculate the lowest candle LowestCandle = ArrayMinimum(low,0,numcandle); //Create array of price MqlRates PriceInfo[]; ArraySetAsSeries(PriceInfo,true); //Copy price data to array int Data = CopyRates(Symbol(),Period(),0,Bars(Symbol(),Period()),PriceInfo); return PriceInfo[LowestCandle].low; } double stoplossforSell(int numcandle) { int HighestCandle; double High[]; //Sort array downward from current candle ArraySetAsSeries(High,true); //Fill array with data for 100 candle CopyHigh(_Symbol,_Period,0,numcandle,High); //calculate highest candle HighestCandle = ArrayMaximum(High,0,numcandle); //Create array for price MqlRates PriceInformation[]; ArraySetAsSeries(PriceInformation,true); //Copy price data to array int Data = CopyRates(Symbol(),Period(),0,Bars(Symbol(),Period()),PriceInformation); return PriceInformation[HighestCandle].high; }
Советник проверяет, имеется ли в данный момент открытая сделка. Если нет, вызывается метод стратегии.
void OnTick() { //--- pipValue = ((((SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_VALUE))*point)/(SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_SIZE)))); Balance = AccountInfoDouble(ACCOUNT_BALANCE); if (PositionsTotal()==0) { Strategy(); } }
Стоп-лосс на основе индикатора RSI
Второй советник будет использовать фиксированный стоп-лосс на индикаторе RSI. Ниже приведены требования к стратегии.
Параметры | Описание |
Используемый индикатор | MACD (12,26,9) |
Используемый индикатор | Moving Average (200) |
Используемый индикатор | Moving Average (50) |
Используемый индикатор | ATR (5) |
Таймфрейм | M1 |
Покупка | Если Moving Average (50) выше Moving Average (200), а линия MACD выше сигнальной, при этом обе они ниже нуля |
Продажа | Если Moving Average (50) ниже Moving Average (200), а линия MACD ниже сигнальной, при этом обе они выше нуля |
Выход | Тейк-профит. Стоп-лосс на покупку является минимальным за десять значений RSI после входа А стоп-лосс на продажу является максимальным за десять значений RSI после входа
Если RSI пересекает максимальный или минимальный RSI, сделка закрывается.
|
Для удобства восприятия стоп-лосс отображен в виде линии
Рис. 2.3. Покупка со стоп-лоссом на основе RSI
Сделка закрывается, когда текущее значение RSI становится ниже линии стоп-лосса в окне RSI.
Рис. 2.4. Продажа со стоп-лоссом на основе RSI
Сделка закрывается, когда текущее значение RSI становится выше линии стоп-лосса в окне RSI.
Код
Первая часть кода в основном предназначена для объявления переменных и ввода данных. Некоторые дополнения, отличающие этот советник от предыдущего, указаны ниже
int RSI; input int rsi = 5; // RSI VAlue double lowestrsiValue = 100; double highestrsiValue = 0.0;
Метод onint() также был дополнен
int OnInit() { //RSI RSI = iRSI(_Symbol,_Period,rsi,PRICE_CLOSE); }
Код стратегии не изменился. Однако покупка и продажа не имеют стоп-лосса, так как его роль выполняет уровень RSI. Ниже приведен код входа в рынок
void Buy(double Ask) { double atr[]; ArraySetAsSeries(atr,true); //This array is use to store all ATR value to the last closed bar CopyBuffer(ATR,0,0,200,atr); // This method copy the buffer value of the ATR indicator into the array (200 buffered data) theLotsize = NormalizeDouble((Balance*risk)/((MathAbs(Ask-((stoplossforBuy(20)-atr[1])))*100)*pipValue),2); // This Calculate the lotsize using the % to risk ObjectCreate(0,"sl",OBJ_HLINE,3,0,lowestRSI(10)); // Since our stoploss is zero we assign a smart stoploss on the rsi by drawing a line on the rsi window trade.Buy(theLotsize,_Symbol,Ask,0,Ask+(2*MathAbs(Ask-((stoplossforBuy(20)-atr[1])))),NULL);//Buy Entry with zero stoploss && take profit is twice the distance between the entry and the lowest candle Print("SL",lowestRSI(10)); } void Sell(double Bid) { double atr[]; ArraySetAsSeries(atr,true); //This array is use to store all ATR value to the last closed bar CopyBuffer(ATR,0,0,200,atr); // This method copy the buffer value of the ATR indicator into the array (200 buffered data) theLotsize = NormalizeDouble((Balance*risk)/((MathAbs(Bid-((stoplossforSell(20)+atr[1])))*100)*pipValue),2); // This Calculate the lotsize using the % to risk ObjectCreate(0,"sl",OBJ_HLINE,3,0,highestRSI(10)); // Since our stoploss is zero we assign a smart stoploss on the rsi by drawing a line on the rsi window trade.Sell(theLotsize,_Symbol,Bid,0,Bid-(2*MathAbs(((stoplossforSell(20)+atr[1]))-Bid)),NULL);//Sell Entry with zero stoploss && take profit is twice the distance between the entry and the highest candle Print("SL",highestRSI(10)); }
Последняя часть кода содержит методы, получающие максимальные и минимальные значения RSI. Вызов происходит из метода входа, показанного выше, и использует данные для проведения линии в точке максимального или минимального RSI.
Примечание: Нарисованная линия удаляется в методе стратегии при отсутствии открытой позиции.
double lowestRSI(int count) { double thersi[]; ArraySetAsSeries(thersi,true); CopyBuffer(RSI,0,0,200,thersi); for (int i = 0; i<count;i++) { if (thersi[i]<lowestrsiValue) { lowestrsiValue = thersi[i]; } } return lowestrsiValue; } //This method get the Highest RSI afer ENtry to set the smart Stoploss double highestRSI(int count) { double thersi[]; ArraySetAsSeries(thersi,true); CopyBuffer(RSI,0,0,200,thersi); for (int i = 0; i<count;i++) { if (thersi[i]>highestrsiValue) { highestrsiValue = thersi[i]; } } return highestrsiValue; }
####
Советники готовы и скомпилированы. Пора их протестировать.
Тест и результат
Тестирование охоты на стоп-лосс
В этом разделе будут представлены тестирование и результаты, полученные в результате моделирования. Первое, что нужно сделать, это определить, способен ли советник со стоп-лоссом на основе RSI (RSI STOP-LOSS) уменьшить эффект охоты на стоп-лоссы во время торговли и сравнить его результаты с показателями советника с классическим стоп-лоссом (CLASSIC STOP-LOSS).
Тесты проводятся на таймфрейме M1.
RSI STOP-LOSS
Советник: | MACD_Smart_Stoploss | |||||||||||
Символ: | Volatility 10 Index | |||||||||||
Период: | M1 (2021.07.01 - 2021.07.15) | |||||||||||
Входные параметры: | afi=0 | |||||||||||
risk=0.05 | ||||||||||||
atrValue=20 | ||||||||||||
rsi=14 | ||||||||||||
ai=0 | ||||||||||||
movAvgTrend=200 | ||||||||||||
movAvgDirection=50 | ||||||||||||
i=0 | ||||||||||||
fast=12 | ||||||||||||
slow=26 | ||||||||||||
signal=9 | ||||||||||||
Брокер: | Deriv Limited | |||||||||||
Валюта: | USD | |||||||||||
Начальный депозит: | 500.00 | |||||||||||
Плечо: | 1:500 |
CLASSIC STOP-LOSS
Советник: | MACD_Cross_Stoploss | |||||||||||
Символ: | Volatility 10 Index | |||||||||||
Период: | M1 (2021.07.01 - 2021.07.15) | |||||||||||
Входные параметры: | afi=0 | |||||||||||
risk=0.05 | ||||||||||||
atrValue=5 | ||||||||||||
ai=0 | ||||||||||||
movAvgTrend=200 | ||||||||||||
movAvgDirection=50 | ||||||||||||
i=0 | ||||||||||||
fast=12 | ||||||||||||
slow=26 | ||||||||||||
signal=9 risk reward=1:2 | ||||||||||||
Брокер: | Deriv Limited | |||||||||||
Валюта: | USD | |||||||||||
Начальный депозит: | 500.00 | |||||||||||
Плечо: | 1:50 |
Результаты
Ниже показано графическое представление сделок, совершенных обоими советниками. Всего было рассмотрено три торговых отрезка у каждого советника.
Рис. 3.1. Отрезок 1 (RSI STOP-LOSS)
Рис. 3.1a. Отрезок 1 (CLASSIC STOP-LOSS)
Рис. 3.2. Отрезок 2 (RSI STOP-LOSS)
Рис. 3.2a. Отрезок 2 (CLASSIC STOP-LOSS)
Рис. 3.3. Отрезок 3 (RSI STOP-LOSS)
Рис. 3.3a. Отрезок 3 (CLASSIC STOP-LOSS)
Сравнение показало, что советник RSI STOP-LOSS лучше справился с уменьшением эффекта от охоты на стоп-лоссы, чем советник с классическим стоп-лоссом на графике ценового действия.
Тест на прибыльность
Теперь настала пора заняться самым важным вопросом – определением прибыльности. Так как советник RSI STOP-LOSS лучше справился с охотой на стоп-лоссы, он должен быть прибыльным и иметь более высокий коэффициент выигрыша, поскольку при его работе срабатывает меньше стоп-лоссов по сравнению с классическим стоп-лоссом. Чтобы это подтвердить, нужно провести тест.
Для проведения обоих тестов будут использованы данные, указанные выше. Оба советника будут тестироваться на истории, состоящей из более чем 100 сделок на таймфрейме M1. Результаты приведены ниже.
RSI STOP-LOSS
Результаты | ||||||||||||
Качество истории: | 100% | |||||||||||
Бары: | 20160 | Тики: | 603385 | Символы: | 1 | |||||||
Чистая прибыль: | 327.71 | Абсолютная просадка по балансу: | 288.96 | Абсолютная просадка по средствам: | 367.85 | |||||||
Общая прибыль: | 3 525.74 | Максимальная просадка по балансу: | 483.90 (69.63%) | Максимальная просадка по средствам: | 523.24 (71.95%) | |||||||
Общий убыток: | -3 198.03 | Относительная просадка по балансу: | 69.63% (483.90) | Относительная просадка по средствам: | 73.65% (369.45) | |||||||
Прибыльность: | 1.10 | Матожидание выигрыша: | 1.76 | Уровень маржи: | 317.21% | |||||||
Фактор восстановления: | 0.63 | Коэффициент Шарпа: | 0.08 | Z-Счет: | 1.68 (90.70%) | |||||||
AHPR: | 1.0070 (0.70%) | LR Correlation: | 0.51 | Результат OnTester: | 0 | |||||||
GHPR: | 1.0027 (0.27%) | LR Standard Error: | 134.83 | |||||||||
Всего трейдов: | 186 | Короткие трейды (% выигравших): | 94 (42.55%) | Длинные трейды (% выигравших): | 92 (38.04%) | |||||||
Всего сделок: | 372 | Прибыльные трейды (% от всех): | 75 (40.32%) | Убыточные трейды (% от всех): | 111 (59.68%) | |||||||
Самый большой прибыльный трейд: | 85.26 | Самый большой убыточный трейд: | -264.99 | |||||||||
Средняя прибыльная сделка: | 47.01 | Средний убыточный трейд: | -28.81 | |||||||||
Максимальное количество непрерывных выигрышей (прибыль): | 5 (350.60) | Максимальное количество непрерывных проигрышей (убыток): | 6 (-255.81) | |||||||||
Максимальная непрерывная прибыль (число выигрышей): | 350.60 (5) | Максимальная непрерывный убыток (число проигрышей): | -413.34 (5) | |||||||||
Средний непрерывный выигрыш: | 2 | Средний непрерывный проигрыш: | 2 | |||||||||
Рис. 3.4. Кривая эквити для RSI Stop loss
CLASSIC STOP-LOSS
Результаты | ||||||||||||
Качество истории: | 100% | |||||||||||
Бары: | 20160 | Тики: | 603385 | Символы: | 1 | |||||||
Чистая прибыль: | 3 672.06 | Абсолютная просадка по балансу: | 215.45 | Абсолютная просадка по средствам: | 217.30 | |||||||
Общая прибыль: | 10 635.21 | Максимальная просадка по балансу: | 829.54 (19.27%) | Максимальная просадка по средствам: | 1 159.20 (25.59%) | |||||||
Общий убыток: | -6 963.15 | Относительная просадка по балансу: | 48.76% (270.82) | Относительная просадка по средствам: | 51.81% (303.90) | |||||||
Прибыльность: | 1.53 | Матожидание выигрыша: | 15.97 | Уровень маржи: | 274.21% | |||||||
Фактор восстановления: | 3.17 | Коэффициент Шарпа: | 0.16 | Z-Счет: | -0.14 (11.13%) | |||||||
AHPR: | 1.0120 (1.20%) | LR Correlation: | 0.80 | Результат OnTester: | 0 | |||||||
GHPR: | 1.0093 (0.93%) | LR Standard Error: | 545.00 | |||||||||
Всего трейдов: | 230 | Короткие трейды (% выигравших): | 107 (44.86%) | Длинные трейды (% выигравших): | 123 (38.21%) | |||||||
Всего сделок: | 460 | Прибыльные трейды (% от всех): | 95 (41.30%) | Убыточные трейды (% от всех): | 135 (58.70%) | |||||||
Самый большой прибыльный трейд: | 392.11 | Самый большой убыточный трейд: | -219.95 | |||||||||
Средняя прибыльная сделка: | 111.95 | Средний убыточный трейд: | -51.58 | |||||||||
Максимальное количество непрерывных выигрышей (прибыль): | 6 (1 134.53) | Максимальное количество непрерывных проигрышей (убыток): | 9 (-211.43) | |||||||||
Максимальная непрерывная прибыль (число выигрышей): | 1 134.53 (6) | Максимальная непрерывный убыток (число проигрышей): | -809.21 (4) | |||||||||
Средний непрерывный выигрыш: | 2 | Средний непрерывный проигрыш: | 2 |
Рис. 3.5. Кривая эквити для Classic Stop loss
Результаты
Хотя оба советника оказались прибыльными к концу торгового периода, у первого советника (RSI Stop-Loss) оказалось меньше убытков, при этом некоторые из них оказались довольно большими.Рис. 3.6. Убытки на кривой эквити
Эти убытки могут повлиять на общую прибыльность советника, а также на правильное управление капиталом. С другой стороны, советник на основе классического стоп-лосса понес больше убытков, но при этом заработал больше денег к концу торгового периода.
Заключение
Управление капиталом действительно является граалем трейдинга. Проведенный эксперимент показал, что полностью реализованное управление капиталом принесло больше прибыли при больших убытках, благодаря более последовательной торговле. Однако зависимость стоп-лосса от RSI не дает такой же последовательности для советника RSI STOP-LOSS, поскольку объем риска варьируется.
Рекомендации
Одним из способов уменьшить убытки при использовании советника RSI STOP-LOSS может быть хеджирование. Оно позволяет сделать объем риска более постоянным и повысить прибыль в долгосрочной перспективе.Благодарю за внимание!
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/9827
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
То что Тейк и Стоп должны быть динамичными - это логично для тех, кто хочет улучшить свою торговлю.
Волатильность меняется, ставить физические тейки и стопы - неправильно, они должны быть обоснованы.
Могу лишь добавить, что надо разбить осциллятор для выхода на два, один строится по хай, другой по лоу.