Почему мой советник продолжает давать отрицательную прибыль при обратном тестировании?

 

Я имитировал и написал такой же советник, как в примере здесь https://www.mql5.com/en/articles/1510, за исключением условий для покупки/продажи.

Условие для открытия позиции на покупку : RSI ниже 5 И цена Ask выше 200 дневной скользящей средней, выход, когда цена Ask выше 5 дневной скользящей средней.

Условие для открытия позиции на продажу : RSI выше 95 И цена Bid ниже 200 дневной скользящей средней, выход, когда цена Bid ниже 5 дневной скользящей средней.g

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

Кстати, могу я узнать, что такое shift и ma_shift и как их заполнять? Это параметр, необходимый для индикатора iRSI(), я не знал, что написать, поэтому просто присвоил ему 0.

вот код

//+------------------------------------------------------------------+
//|                                              My RSI strategy.mq4 |
//|                        Copyright 2013, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright 2013, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"
#include <stderror.mqh> 
#include <stdlib.mqh>  
//All Variables here

extern double UpperBound    =  90;      //set upper bound value for RSI
extern double LowerBound    =  5;      //set lower bound value for RSI
extern double VarPeriod     =  2;      //number of periods
extern double BuyVolume     = 0.1;       //set buying volume(lots)
extern double SellVolume    = 0.1;       //set selling volume(lots)
extern double StopLoss      = 25;       //Set the stop loss level
extern double TakeProfit    = 25;       //Set the take profit level
extern double TrailingStop = 30;


//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   Alert ("The minimum stoploss and take profit is " + MarketInfo(Symbol(),MODE_STOPLEVEL));
   double CurrentRSI;                  //Finds out the RSI for now
   double MA200;                       //200 day Moving Average           
   double MA5;                         //5 day Moving Average
   double CurrentAsk;                  //Finds out the Ask price now
   double CurrentBid;                  //Finds out the Bid price now
  
   
   CurrentAsk = MarketInfo(Symbol(), MODE_ASK);
   CurrentBid = MarketInfo(Symbol(), MODE_BID);
   MA200 = iMA(NULL, 0, 200, 8,MODE_SMA,PRICE_CLOSE, 0);
   MA5 = iMA(NULL, 0, 5, 8,MODE_SMA,PRICE_CLOSE, 0);
   CurrentRSI = iRSI (NULL, 0, VarPeriod,PRICE_CLOSE ,0);
   
   Alert("Bid is " + CurrentBid);
   Alert("Ask is " + CurrentAsk);
   Alert("200 Day Moving Average is " + MA200); 
   Alert("5 Day Moving Average is " + MA5); 
   Alert("RSI Index is " + CurrentRSI);
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//----
   
   double CurrentRSI;                  //Finds out the RSI for now
   double MA200;                       //200 day Moving Average           
   double MA5;                         //5 day Moving Average
   double CurrentAsk;                  //Finds out the Ask price now
   double CurrentBid;                  //Finds out the Bid price now
   int Ticket;
   int cnt;
   int Ticket2;
   int Total;
   
   CurrentAsk = MarketInfo(Symbol(), MODE_ASK);
   CurrentBid = MarketInfo(Symbol(), MODE_BID);
   MA200 = iMA(NULL, 0, 200, 8,MODE_SMA,PRICE_CLOSE, 0);
   MA5 = iMA(NULL, 0, 5, 8,MODE_SMA,PRICE_CLOSE, 0);
   CurrentRSI = iRSI (NULL, 0, VarPeriod,PRICE_CLOSE ,0);
   
   
    if(Bars<100)
     {
      Print("bars less than 100");
      return(0);  
     }
   
   if(AccountFreeMargin()<(1000*BuyVolume))
        {
         Print("We have no money. Free Margin = ", AccountFreeMargin());
         return(0);  
        }
   
    if (CurrentRSI < LowerBound && MarketInfo(Symbol(), MODE_ASK) > MA200 ) {    //Condition to execute buy entry
  
        Ticket = OrderSend(Symbol(), OP_BUY, BuyVolume, Ask, 3, Bid - ( StopLoss * Point ), Ask + ( TakeProfit * Point ), "Buy.", 111,0,Yellow)   ;       //execute buy order
   
    if(Ticket>0)
           {
            if(OrderSelect(Ticket,SELECT_BY_TICKET,MODE_TRADES)) 
               Print("BUY order opened : ",OrderOpenPrice());
           }
         if (Ticket < 0) {
         Print("Error opening BUY order : ",GetLastError()); 
         return(0); 
   }
   return(0);
  }
  
 
  if (CurrentRSI > UpperBound && MarketInfo(Symbol(), MODE_BID) > MA200) {     //Condition to execute sell entry
  
       Ticket2 = OrderSend(Symbol(), OP_SELL, SellVolume, Bid, 3, Ask + ( StopLoss * Point ), Bid - ( TakeProfit * Point ), "Sell.",000, 0, Yellow)  ;     //execute sell order
       if(Ticket2>0)
           {
            if(OrderSelect(Ticket2,SELECT_BY_TICKET,MODE_TRADES)) 
               Print("SELL order opened : ",OrderOpenPrice());
           }
         if (Ticket2<0) {
          Print("Error opening SELL order : ",GetLastError()); 
         return(0); 
        }
       return(0);
   
   } 
   
   Total=OrdersTotal();
    for(cnt=0;cnt<Total;cnt++)
  {
   OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
   if(OrderType()<=OP_SELL && OrderSymbol()==Symbol())  // check for symbol and check for opened position 
     {
if(OrderType()==OP_BUY)   // long position is opened
{
   
   if (CurrentAsk > MA5){      //condition to close long position
    OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close long position
   return(0); // exit
   
   if(TrailingStop>0)  
              {                 
               if(Bid-OrderOpenPrice()>Point*TrailingStop)
                 {
                  if(OrderStopLoss()<Bid-Point*TrailingStop)
                    {
                     OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green);
                     return(0);
                    }
                 }
              }
   
   }
   }
   
   if(OrderType()==OP_SELL)   // long position is opened
{
   if(CurrentBid < MA5){       //condition to close short position
   OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // close short position
   return(0); // exit
   }
   
  if(TrailingStop>0)  
              {                 
               if((OrderOpenPrice()-Ask)>(Point*TrailingStop))
                 {
                  if((OrderStopLoss()>(Ask+Point*TrailingStop)) || (OrderStopLoss()==0))
                    {
                     OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,OrderTakeProfit(),0,Red);
                     return(0);
                    }
                 }
              }
   }
   }
   }
   
    
   
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
 

Параметр RSI установлен на 0, результата нет, так как ... Ничего

RSI 0

Не менее 2

rsi 2

 

Не каждый советник и не каждая стратегия является прибыльной

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

   MA200 = iMA(NULL, 0, 200, 8,MODE_SMA,PRICE_CLOSE, 0);
   MA5 = iMA(NULL, 0, 5, 8,MODE_SMA,PRICE_CLOSE, 0);
   CurrentRSI = iRSI (NULL, 0, VarPeriod,PRICE_CLOSE ,0);

Каждый тик вы вычисляете значения выше, и они могут меняться с каждым тиком, потому что вы выбрали "....,PRICE_CLOSE, 0);".

Значения, которые вы видите на графике при тестировании, это не те значения, которые вы имели при открытии сделки...

   if(AccountFreeMargin()<(1000*BuyVolume))
        {
         Print("We have no money. Free Margin = ", AccountFreeMargin());
         return(0);  
        }
   
    if (CurrentRSI < LowerBound && MarketInfo(Symbol(), MODE_ASK) > MA200 ) {    //Condition to execute buy entry
  
        Ticket = OrderSend(Symbol(), OP_BUY, BuyVolume, Ask, 3, Bid - ( StopLoss * Point ), Ask + ( TakeProfit * Point ), "Buy.", 111,0,Yellow)   ;       //execute buy order
   
    if(Ticket>0)
           {
            if(OrderSelect(Ticket,SELECT_BY_TICKET,MODE_TRADES)) 
               Print("BUY order opened : ",OrderOpenPrice());
           }
         if (Ticket < 0) {
         Print("Error opening BUY order : ",GetLastError()); 
         return(0); 
   }
   return(0);
  }
  

Когда условия для открытия покупки выполнены, и тестер открывает покупку, то не проверяется, была ли уже открыта покупка с тем же условием.

После открытия покупки на следующем тике вы можете снова иметь условие для открытия сделки.

Это открытие сделок может работать в StrategyTester, но в реальном времени на демо на реальном счете,

Например, при выборе "3" Slippage слишком мал для торговли на "пятизначном" счете.

Отправка OrderSend со значением для OrderStopLoss() и OrdertakeProfit() > 0 будет неудачной для ECN счетов

   Total=OrdersTotal();
    for(cnt=0;cnt<Total;cnt++)
  {
   OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
   if(OrderType()<=OP_SELL && OrderSymbol()==Symbol())  // check for symbol and check for opened position 
     {
В OrderSend и в этом цикле для проверки сделок я упускаю, что вы используете OrderMagicNumber().

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

OrderModify может происходить с каждым пунктом, что может привести к ошибкам от брокера, например, tradecontext слишком занят.

 
FXEWEN:

Параметр RSI установлен на 0, результата нет, так как ... Ничего

Не менее 2

Я установил период iRSI на 2.....

 
cyxstudio:


Кстати, могу я узнать, что такое shift и ma_shift и как их заполнять? Это параметр, необходимый для индикатора iRSI(), я не знал, что написать, поэтому просто присвоил ему 0.


Не уверен, откуда вы взяли эту информацию, но она неверна...

iRSI() double iRSI(string symbol,int timeframe,int period,int applied_price,int shift)

Возможно, вы имели в виду iMA()? shift - это номер бара, для которого вы хотите получить MA, ma_shift позволяет вам перемещать значение MA относительно номера бара, так что если вы дадите ему shift 5 и ma_shift -2, это даст вам MA для бара 7, вам нужно будет немного поэкспериментировать с этим, чтобы проверить, прав ли я, в принципе, да.


 
deVries:


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

Каждый тик вы вычисляете значения выше и они могут меняться с каждым тиком, потому что вы выбрали "....,PRICE_CLOSE, 0);".


что я должен выбрать для значения сдвига" ....,PRICE_CLOSE, 0);"?

 
cyxstudio:

что я должен выбрать для значения сдвига" ....,PRICE_CLOSE,0);"?

Что требует ваша стратегия? Используйте это. Используйте бар 0, если хотите, но он будет "перерисовываться", даже если вы используете PRICE_CLOSE, Close[0](цена закрытия бара 0) == Bid. Когда бар 0 наконец закроется, это уже не бар 0, а бар 1.
 
deVries:

Не каждый советник и не каждая стратегия является прибыльной

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

Каждый тик вы рассчитываете значения выше, и они могут меняться с каждым тиком, потому что вы выбрали "....,PRICE_CLOSE, 0);".

Значения, которые вы видите на графике при тестировании, не являются значениями, которые вы имели при открытии сделки...

Когда условия для открытия покупки выполнены, и тестер открывает покупку, то не проверяется, была ли уже открыта покупка с тем же условием.

После открытия покупки на следующем тике вы можете снова иметь условие для открытия сделки.

Это открытие сделок может работать в StrategyTester, но в реальном времени на демо на реальном счете,

Например, при выборе "3" Slippage слишком мал для торговли на "пятизначном" счете.

Отправка OrderSend со значением для OrderStopLoss() и OrdertakeProfit() > 0 будет неудачной для ECN счетов

В OrderSend и в этом цикле для проверки сделок я упускаю, что вы используете свой OrderMagicNumber().

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

OrderModify может произойти с каждым пунктом, что может привести к ошибкам от брокера, например, tradecontext слишком занят.

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

//+------------------------------------------------------------------+
//|                                                My Strategy 4.mq4 |
//|                        Copyright 2013, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright 2013, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"

extern double StopLoss = 40;
extern double TakeProfit = 40;
extern double Lots = 0.1;
extern double Slippage = 10;
extern double RSINow;
extern double MA200;
extern double MA5;
extern bool A1 = false;
extern bool A2 = false;
extern int Ticket;
extern int Ticket2;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+ 
int init()
  {
//----
   Alert("Minimum Stop Level is " + MarketInfo(Symbol(), MODE_STOPLEVEL)); //find out minimum stop loss
   
   RSINow = iRSI(NULL, 1440, 2, PRICE_CLOSE, 0);			//calculates the RSI value for 2 days
   MA200 = iMA(NULL, 1440, 200, 0, MODE_SMA, PRICE_CLOSE,0);		//calculates the moving average for 200 days
   MA5 = iMA(NULL, 1440, 5, 0, MODE_SMA, PRICE_CLOSE,0);     		//calculates the moving average for 5 days
   Alert(RSINow);
   Alert(MA200);
   Alert(MA5);
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//----

   
   
   //check if a long position is possible, A is false means no buy trade is open , execute buy when RSI drops below 5 and when Ask price rises above 200 day moving average
   if (A1 == false && RSINow < 5 && Ask > MA200) {
   
   Ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, Bid - ( StopLoss * Point ), Ask + ( TakeProfit * Point ));
   
   if(Ticket>0) {
            if(OrderSelect(Ticket,SELECT_BY_TICKET,MODE_TRADES)) {
               Print("BUY order opened : ",OrderOpenPrice());
               A1 = true;
           }
         if (Ticket < 0) {
         Print("Error opening BUY order : ",GetLastError()); 
         return(0); 
   }
   }
   } 
   
   
   
     //check if a short position is possible, A2 is false means no sell trade is open , execute sell when RSI rises above 95 and when Bid price drops below 200 day moving average

   if (A2 == false && RSINow > 95 && Bid < MA200) {
   
   Ticket2 = OrderSend(Symbol(), OP_BUY, Lots, Bid, Slippage, Ask + ( StopLoss * Point ), Bid - ( TakeProfit * Point ));
   if(Ticket2>0) {
            if(OrderSelect(Ticket2,SELECT_BY_TICKET,MODE_TRADES)) {
               Print("SELL order opened : ",OrderOpenPrice());
               A2 = true;
           }
         if (Ticket2 < 0) {
         Print("Error opening SELL order : ",GetLastError()); 
         return(0); 
         }
   }
   
   } 
   
   
   //check if buy position can be closed, once Ask price rises above 5 day moving average, its time to close the position.
   
   if ((A1 == true) && (Ask > MA5)) {
   OrderClose(Ticket, Lots, Bid, Slippage, Violet);
   A1 = false;
   return(0);
   }
   
   
   
   
   //check if sell position can be closed, if Bid price drops below 5 day moving average, close sell position.
   
   if ((A2 == true) && (Bid < MA5)) {
   OrderClose(Ticket2, Lots, Bid, Slippage, Violet);
   A2 = false;
   return(0);
   }
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
 
cyxstudio:

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


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

Вы используете A1 и A2, которые получают значение true в момент открытия сделки.

Но что произойдет, если питание вашего компьютера отключится, и вам придется перезагрузить компьютер и metatrader.

Вы должны проверить в этот момент, открыты ли сделки от вашего советника.

Как вы собираетесь это сделать ????.

Чтобы сделать это проще, используйте определенный OrderMagicNumber для открытия и проверки сделок.

.

скользящая средняя сейчас не перемещается на несколько баров в будущее ок.

но вы рассчитываете его только в секции init(), это будет выполняться только при запуске вашего эксперта.

Мне не хватает этого в Start() .... Почему вы удалили его там???

.

 

Я переписал ваш код и попробовал тест, смотрите также настройки.

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

Отчет тестера стратегии
RSI_strategy_cyxstudio
AlpariUK-Demo - Micro+Classic (Build 451)

СимволEURUSD (евро против доллара США)
ПериодЕжедневно (D1) 2010.10.01 00:00 - 2013.01.29 00:00 (2010.10.01 - 2013.01.30)
МодельКаждый тик (наиболее точный метод, основанный на всех доступных наименьших таймфреймах)
ПараметрыRSIPeriod=3; UpperBound=90; LowerBound=5; MASlowPeriod=200; MAFastPeriod=5; Lots=0.1; StopLoss=60; TakeProfit=120; TrailingStop=40; MagicNumber=54333; CommentEA="RSI стратегия"; Slippage.Pips=3;
Бары в тесте1603Тики смоделированы40187739Качество моделированиян/а
Ошибки несовпадающих графиков2062601
Первоначальный депозит3000.00
Итого чистая прибыль967.18Валовая прибыль2226.34Валовый убыток-1259.16
Коэффициент прибыли1.77Ожидаемая прибыль13.62
Абсолютная просадка107.10Максимальная просадка327.47 (7.99%)Относительная просадка7.99% (327.47)
Всего сделок71Короткие позиции (выигранные %)66 (69.70%)Длинные позиции (выиграно %)5 (80.00%)
Прибыльные сделки (% от общего количества)50 (70.42%)Убыточные сделки (% от общего количества)21 (29.58%)
Крупнейшийприбыльная сделка120.07убыточная сделка-60.00
Среднееприбыльная сделка44.53убыточная торговля-59.96
Максимумпоследовательных побед (прибыль в деньгах)8 (424.26)последовательные проигрыши (убыток в деньгах)3 (-179.93)
Максимальныйпоследовательная прибыль (количество выигрышей)424.26 (8)последовательный убыток (количество проигрышей)-179.93 (3)
Среднеепоследовательные выигрыши4последовательные проигрыши2

 
deVries:

Я переписал ваш код и попробовал тест, смотрите также настройки.

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


Общее количество сделок71Короткие позиции (выигранные %)66 (69.70%)Длинные позиции (выигранные %)5 (80.00%)





Это заставляет меня думать, что здесь что-то не так.
Причина обращения: