straregy tester opens multiple positions

 

hi, Im writing a simple EA. this is my code:


//+------------------------------------------------------------------+
//|                                                      ProjectName |
//|                                      Copyright 2020, CompanyName |
//|                                       http://www.companyname.net |
//+------------------------------------------------------------------+

#property link      "https://www.mql5.com"
#property version   "1.00"

#include <Indicators\Trend.mqh>
#include <Indicators\TimeSeries.mqh>
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\SymbolInfo.mqh>


input ENUM_APPLIED_PRICE   MAAppliedPrice         = PRICE_CLOSE;
input ENUM_MA_METHOD       MAMethod                 = MODE_SMA;

input int                  shortMAPeriod                             = 21;
input int                  shortMAShift                                = 0;

input int                  mediumMAPeriod                        = 100;
input int                  mediumMAShift                           = 0;

input int                  longMAPeriod                              = 300;
input int                  longMAShift                                 = 0;



CiMA           shortMA;
CiMA           mediumMA;
CiMA           longMA;
CiClose        closePrice;
CiOpen         openPrice;
CiLow          lowPrice;
CiHigh         highPrice;


CTrade         trade;
CPositionInfo  position;


//-- Bar0
double Bar0_HighPrice;
double Bar0_ClosePrice;
double Bar0_OpenPrice;
double Bar0_LowPrice;
double Bar0_shortMA;
double Bar0_mediumMA;
double Bar0_longMA;

//-- Bar1
double Bar1_HighPrice;
double Bar1_ClosePrice;
double Bar1_OpenPrice;
double Bar1_LowPrice;
double Bar1_shortMA;
double Bar1_mediumMA;
double Bar1_longMA;




int OnInit() {


   shortMA.Create(_Symbol,PERIOD_CURRENT,shortMAPeriod,shortMAShift,MAMethod,MAAppliedPrice);
   shortMA.Refresh();

   mediumMA.Create(_Symbol,PERIOD_CURRENT,mediumMAPeriod,mediumMAShift,MAMethod,MAAppliedPrice);
   mediumMA.Refresh();

   longMA.Create(_Symbol,PERIOD_CURRENT,longMAPeriod,longMAShift,MAMethod,MAAppliedPrice);
   longMA.Refresh();

   closePrice.Create(_Symbol,PERIOD_CURRENT);
   closePrice.Refresh();

   openPrice.Create(_Symbol,PERIOD_CURRENT);
   openPrice.Refresh();

   lowPrice.Create(_Symbol,PERIOD_CURRENT);
   lowPrice.Refresh();

   highPrice.Create(_Symbol,PERIOD_CURRENT);
   highPrice.Refresh();

   return(INIT_SUCCEEDED);
}







void OnDeinit(const int reason) {


}








void OnTick() {


 
   shortMA.Refresh();
   mediumMA.Refresh();
   longMA.Refresh();
   openPrice.Refresh();
   closePrice.Refresh();
   highPrice.Refresh();
   lowPrice.Refresh();




//-- Bar0
   Bar0_HighPrice   = normalizeDouble( highPrice.GetData(0) );
   Bar0_ClosePrice  = normalizeDouble( closePrice.GetData(0) );
   Bar0_OpenPrice   = normalizeDouble( openPrice.GetData(0) );
   Bar0_LowPrice    = normalizeDouble( lowPrice.GetData(0) );
   Bar0_shortMA     = normalizeDouble( shortMA.Main(0) );
   Bar0_mediumMA    = normalizeDouble( mediumMA.Main(0) );
   Bar0_longMA      = normalizeDouble( longMA.Main(0) );

//-- Bar1
   Bar1_HighPrice   = normalizeDouble( highPrice.GetData(1) );
   Bar1_ClosePrice  = normalizeDouble( closePrice.GetData(1) );
   Bar1_OpenPrice   = normalizeDouble( openPrice.GetData(1) );
   Bar1_LowPrice    = normalizeDouble( lowPrice.GetData(1) );
   Bar1_shortMA     = normalizeDouble( shortMA.Main(1) );
   Bar1_mediumMA    = normalizeDouble( mediumMA.Main(1) );
   Bar1_longMA      = normalizeDouble( longMA.Main(1) );




// -- there is no open position, so we can buy
   if (PositionsTotal() == 0 ) {

      if (Bar0_shortMA < Bar0_mediumMA && Bar0_mediumMA < Bar0_longMA) {

         if ( (Bar1_OpenPrice < Bar1_shortMA && Bar1_ClosePrice > Bar1_shortMA) ) {
         
            trade.Buy(0.1);

         }
      }

   }



// there is 1 open position, so we can close it.
   if (PositionsTotal() == 1 ) {

      if (Bar0_ClosePrice > Bar0_mediumMA) {

         bool selectedByIndex = position.SelectByIndex(0); // we always have 1 position open at a time, so index would always be 0

         if (selectedByIndex == true) {
         
            trade.PositionClose(position.Ticket());
            
         }

      }

   }

}





//+------------------------------------------------------------------+
//|  normalizeDouble Function                                        |
//+------------------------------------------------------------------+
double normalizeDouble(double value) {
   return NormalizeDouble(value,5);
}


with the help of PositionsTotal(), Im making sure that there is no already open position ( so I should be able to open a new buy position). so, logically, a new Buy position can not be opened as long as there is one already.


my problem is that, strategy tester opens a new buy position while the previous open position is not closed yet. see screenshot below (for noq forget those multiple positions on a single bar)

image


before writing a new code for me, just explain whats wrong with my code and why it opens a new buy while there is already one?


I use MetaQoutes Dem. and this is strategy tester settings

im

 

As it's coded, it looks like it's going to immediately close every buy you open, because as soon as you open it, now PositionsTotal() == 1.

Start by either putting your close check first, or putting it in an "else if", not just an if, so that it's not checking it instantly.

I don't think that explains the behavior you're seeing, but it's a start.

 
Scott Allen #:

As it's coded, it looks like it's going to immediately close every buy you open, because as soon as you open it, now PositionsTotal() == 1.

Start by either putting your close check first, or putting it in an "else if", not just an if, so that it's not checking it instantly.

I don't think that explains the behavior you're seeing, but it's a start.

thanks for your reply Scott

I switched the place of the two if statements but it didn't make a difference. (as you said, I checked for close condition first but it still opens a buy while there is already one.)


//+------------------------------------------------------------------+
//|                                                      ProjectName |
//|                                      Copyright 2020, CompanyName |
//|                                       http://www.companyname.net |
//+------------------------------------------------------------------+

#property link      "https://www.mql5.com"
#property version   "1.00"

#include <Indicators\Trend.mqh>
#include <Indicators\TimeSeries.mqh>
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\SymbolInfo.mqh>


input ENUM_APPLIED_PRICE   MAAppliedPrice                         = PRICE_CLOSE;
input ENUM_MA_METHOD       MAMethod                                 = MODE_SMA;

input int                                    shortMAPeriod                           = 21;
input int                                    shortMAShift                              = 0;

input int                                    mediumMAPeriod                      = 100;
input int                                    mediumMAShift                         = 0;

input int                                   longMAPeriod                             = 300;
input int                                   longMAShift                                = 0;



CiMA           shortMA;
CiMA           mediumMA;
CiMA           longMA;
CiClose       closePrice;
CiOpen        openPrice;
CiLow          lowPrice;
CiHigh         highPrice;


CTrade             trade;
CPositionInfo  position;


//-- Bar0
double Bar0_HighPrice;
double Bar0_ClosePrice;
double Bar0_OpenPrice;
double Bar0_LowPrice;
double Bar0_shortMA;
double Bar0_mediumMA;
double Bar0_longMA;

//-- Bar1
double Bar1_HighPrice;
double Bar1_ClosePrice;
double Bar1_OpenPrice;
double Bar1_LowPrice;
double Bar1_shortMA;
double Bar1_mediumMA;
double Bar1_longMA;



static int counter = 0;


int OnInit() {


   shortMA.Create(_Symbol,PERIOD_CURRENT,shortMAPeriod,shortMAShift,MAMethod,MAAppliedPrice);
   shortMA.Refresh();

   mediumMA.Create(_Symbol,PERIOD_CURRENT,mediumMAPeriod,mediumMAShift,MAMethod,MAAppliedPrice);
   mediumMA.Refresh();

   longMA.Create(_Symbol,PERIOD_CURRENT,longMAPeriod,longMAShift,MAMethod,MAAppliedPrice);
   longMA.Refresh();

   closePrice.Create(_Symbol,PERIOD_CURRENT);
   closePrice.Refresh();

   openPrice.Create(_Symbol,PERIOD_CURRENT);
   openPrice.Refresh();

   lowPrice.Create(_Symbol,PERIOD_CURRENT);
   lowPrice.Refresh();

   highPrice.Create(_Symbol,PERIOD_CURRENT);
   highPrice.Refresh();

   return(INIT_SUCCEEDED);
}







void OnDeinit(const int reason) {


}




void OnTick() {



   shortMA.Refresh();
   mediumMA.Refresh();
   longMA.Refresh();
   openPrice.Refresh();
   closePrice.Refresh();
   highPrice.Refresh();
   lowPrice.Refresh();




//-- Bar0
   Bar0_HighPrice   = normalizeDouble( highPrice.GetData(0) );
   Bar0_ClosePrice  = normalizeDouble( closePrice.GetData(0) );
   Bar0_OpenPrice   = normalizeDouble( openPrice.GetData(0) );
   Bar0_LowPrice    = normalizeDouble( lowPrice.GetData(0) );
   Bar0_shortMA     = normalizeDouble( shortMA.Main(0) );
   Bar0_mediumMA    = normalizeDouble( mediumMA.Main(0) );
   Bar0_longMA      = normalizeDouble( longMA.Main(0) );

//-- Bar1
   Bar1_HighPrice   = normalizeDouble( highPrice.GetData(1) );
   Bar1_ClosePrice  = normalizeDouble( closePrice.GetData(1) );
   Bar1_OpenPrice   = normalizeDouble( openPrice.GetData(1) );
   Bar1_LowPrice    = normalizeDouble( lowPrice.GetData(1) );
   Bar1_shortMA     = normalizeDouble( shortMA.Main(1) );
   Bar1_mediumMA    = normalizeDouble( mediumMA.Main(1) );
   Bar1_longMA      = normalizeDouble( longMA.Main(1) );


// there is 1 open position, so we can close it here.
   if (PositionsTotal() == 1 ) {

      if (Bar0_ClosePrice > Bar0_mediumMA) {

         bool selectedByIndex = position.SelectByIndex(0); // we always have 1 position open at a time, so index would always be 0

         if (selectedByIndex == true) {

            trade.PositionClose(position.Ticket());

         }

      }

   }

// -- there is no open position, so we can buy
   if (PositionsTotal() == 0 ) {

      if (Bar0_shortMA < Bar0_mediumMA && Bar0_mediumMA < Bar0_longMA) {

         if ( (Bar1_OpenPrice < Bar1_shortMA && Bar1_ClosePrice > Bar1_shortMA) ) {

            trade.Buy(0.1);

         }
      }

   }

}





//+------------------------------------------------------------------+
//|  normalizeDouble Function                                        |
//+------------------------------------------------------------------+
double normalizeDouble(double value) {
   return NormalizeDouble(value,5);
}

//+------------------------------------------------------------------+


one thing is strange for me though, It shows the open and close position on the chart, but it doesn't list them on the table (see screenshot below)

img


Scott, I want to ask you , would you please test my code in your own MetaTrader ?

Reason: