ea backtesting vs. live testing

 

I'm new to the MQL4 language and was writing a pretty simple EA that enters a position based on when two moving averages cross. When I use the strategy tester to backtest the program it seems to be working correctly (i.e. the results match the paper results that i have been previously tracking). However, once I attach it to a chart and go live it doesn't seem to be entering the positions when it should. Is there a simple explanation and/or fix for this problem? Thanks.

 
NewTrader7 wrote >>

I'm new to the MQL4 language and was writing a pretty simple EA that enters a position based on when two moving averages cross. When I use the strategy tester to backtest the program it seems to be working correctly (i.e. the results match the paper results that i have been previously tracking). However, once I attach it to a chart and go live it doesn't seem to be entering the positions when it should. Is there a simple explanation and/or fix for this problem? Thanks.

There could be a number of reasons. Could you answer the following:

  • Do you use iMA with shift = 0 or any other item with shift=0 in your entry rules?
  • Are you using the open prices only model or the every tick model in the strategy tester?

It would be helpful if you post the EA code.

Paul

http://paulsfxrandomwalk.blogspot.com/

 

Any errors in the Journal?

Any errors in the Experts tab? Are you sending the contents of GetLastError() to the experts log after each trading attempt?

Is this a demo or live account?

Have you got a "smilie" in the top right of the chart (as opposed to a "scowlie" or an x)?


CB

 
Did you use the default history data which is bogus or downloaded more.
 

The expert is currently running (there is a smiley) on a demo account and no errors are found in the expert tab, it is only missing some entry points live (not all of them). I am using the iMa with a zero shift and using the close price.


The code controlling the moving averages is here:


if(CheckTime==iTime(NULL,TimeFrame,0)) return(0); //This gets it to calculate
else CheckTime = iTime(NULL, TimeFrame, 0); //every hour.

FastMACurrent = iMA(NULL,TimeFrame,FastMAPeriod,FastMAShift,FastMAType,FastMAPrice,0);
FastMAPast = iMA(NULL,TimeFrame,FastMAPeriod,FastMAShift,FastMAType,FastMAPrice,1);

SlowMACurrent = iMA(NULL,TimeFrame,SlowMAPeriod,SlowMAShift,SlowMAType,SlowMAPrice,0);
SlowMAPast = iMA(NULL,TimeFrame,SlowMAPeriod,SlowMAShift,SlowMAType,SlowMAPrice,1);


and the code controlling entering the order is this:


int err = 0;
int ticket;

double signal = NormalizeDouble(Signal,4);
double BuyTakeProfit;
double BuyStopLoss;
double SellTakeProfit;
double SellStopLoss;

if(TakeProfit!= 0) // Sets take profit levels
{
BuyTakeProfit = NormalizeDouble(signal + TakeProfit*Point,4);
SellTakeProfit = NormalizeDouble(signal - TakeProfit*Point,4);
}
if(StopLoss!=0) // Sets stop loss levels
{
BuyStopLoss = NormalizeDouble(signal - StopLoss*Point,4);
SellStopLoss = NormalizeDouble(signal + StopLoss*Point,4);
}

if(total == 0)
{
if(CrossDirection=="Buy") //Buy Condition
{
if(Ask < signal && Ask > BuyStopLoss) //Has ask price already passed making the signal invalid?
{
for(int c=0; c<NumberOfTries;c++)
{
ticket = OrderSend(Symbol(),OP_BUYSTOP,1,signal,5,BuyStopLoss,BuyTakeProfit,"My Order",MagicNumber,0,CLR_NONE);
Print(GetLastError());
err=GetLastError();
if(err==0)
{
if(ticket>0) break;
}
else
{
if(err==0 || err==4 || err==136 || err==137 || err==138 || err==146) //Busy errors
{
Sleep(60000);
continue;
}
else //normal error
{
if(ticket>0) break;
}
}
}


and then of course it has similar code for buylimit,selllimit, and sellstop orders.


Thanks for the help.

 
NewTrader7 wrote >>

The expert is currently running (there is a smiley) on a demo account and no errors are found in the expert tab, it is only missing some entry points live (not all of them). I am using the iMa with a zero shift and using the close price.


The code controlling the moving averages is here:

if(CheckTime==iTime(NULL,TimeFrame,0)) return(0); //This gets it to calculate
else CheckTime = iTime(NULL, TimeFrame, 0); //every hour.

FastMACurrent = iMA(NULL,TimeFrame,FastMAPeriod,FastMAShift,FastMAType,FastMAPrice,0);
FastMAPast = iMA(NULL,TimeFrame,FastMAPeriod,FastMAShift,FastMAType,FastMAPrice,1);

SlowMACurrent = iMA(NULL,TimeFrame,SlowMAPeriod,SlowMAShift,SlowMAType,SlowMAPrice,0);
SlowMAPast = iMA(NULL,TimeFrame,SlowMAPeriod,SlowMAShift,SlowMAType,SlowMAPrice,1);

and the code controlling entering the order is this:

int err = 0;
int ticket;

double signal = NormalizeDouble(Signal,4);
double BuyTakeProfit;
double BuyStopLoss;
double SellTakeProfit;
double SellStopLoss;

if(TakeProfit!= 0) // Sets take profit levels
{
BuyTakeProfit = NormalizeDouble(signal + TakeProfit*Point,4);
SellTakeProfit = NormalizeDouble(signal - TakeProfit*Point,4);
}
if(StopLoss!=0) // Sets stop loss levels
{
BuyStopLoss = NormalizeDouble(signal - StopLoss*Point,4);
SellStopLoss = NormalizeDouble(signal + StopLoss*Point,4);
}

if(total == 0)
{
if(CrossDirection=="Buy") //Buy Condition
{
if(Ask < signal && Ask > BuyStopLoss) //Has ask price already passed making the signal invalid?
{
for(int c=0; c<NumberOfTries;c++)
{
ticket = OrderSend(Symbol(),OP_BUYSTOP,1,signal,5,BuyStopLoss,BuyTakeProfit,"My Order",MagicNumber,0,CLR_NONE);
Print(GetLastError());
err=GetLastError();
if(err==0)
{
if(ticket>0) break;
}
else
{
if(err==0 || err==4 || err==136 || err==137 || err==138 || err==146) //Busy errors
{
Sleep(60000);
continue;
}
else //normal error
{
if(ticket>0) break;
}
}
}

and then of course it has similar code for buylimit,selllimit, and sellstop orders.

Thanks for the help.

Code is much, much easier to read if you use the SRC feature in the forum editor.

I assume you are using a 4 digit broker?

You didn't answer my question of whether you are using the every tick model or open prices only model in the strategy tester. Because your code uses shift=0, then you must use the every tick model. Assuming you are, even this will not give exactly the same results as forward testing because it manufactures ticks using a fractal algorithm. This inaccuracy gets worse with shorter timeframe charts and tighter stops.

Paul

http://paulsfxrandomwalk.blogspot.com/

 
I am using the every tick model and a 4 digit broker. So is there a simple way to correct the code to make sure that it gets the results i want. My timeframe is an hour chart and my stoploss isnt really that tight (50). Thanks
 
NewTrader7:
I am using the every tick model and a 4 digit broker. So is there a simple way to correct the code to make sure that it gets the results i want. My timeframe is an hour chart and my stoploss isnt really that tight (50). Thanks

You're right - a 1H chart with stoploss 50 should backtest quite accurately. The only times it wouldn't is when there is very high volatility with the very short term range more than 50 pips. There are also small differences between demo and live prices, but again on a 1H chart these would not often have an impact.


I can't quite get my head around your strategy - it's possible you're making things difficult for yourself by using pending orders. To really find out why it's not working as it should, you now need to move from the general "some orders aren't being taken" to focus on analysing the reason in each individual occurrence.


Paul

http://paulsfxrandomwalk.blogspot.com/

 

It's a fairly simple trade strategy, I do believe. It looks for the moving averages crosses and then enters a position at the actual intersection of the cross (as opposed to just entering at whatever price once a cross has occurred). That's the reason that I have used pending orders because the strategy must wait for the current price to reach the actual cross intersection price. It looks like some orders are being rejected with an invalid stoploss error while other pending orders are not being set (still working on the why for that one). I don't think the strategy is difficult, but more so the lack of my programming skills in general and with MQL4 specifically. Thanks for the help!

 
NewTrader7 wrote >>

It's a fairly simple trade strategy, I do believe. It looks for the moving averages crosses and then enters a position at the actual intersection of the cross (as opposed to just entering at whatever price once a cross has occurred). That's the reason that I have used pending orders because the strategy must wait for the current price to reach the actual cross intersection price. It looks like some orders are being rejected with an invalid stoploss error while other pending orders are not being set (still working on the why for that one). I don't think the strategy is difficult, but more so the lack of my programming skills in general and with MQL4 specifically. Thanks for the help!

OK. Your pending order approach should work, and like I said you'll need to look ar specific examples of when it doesn't to find out why.

Off topic a little, but I rarely use pending orders - below is how I would code a simple cross strategy using market orders. It incidentally has the benefit of retrying every tick if an order fails to open for some reason. I've used variations of this countless times.

bool bCrossUp=FastMACurrent>SlowMACurrent && FastMAPast<=SlowMAPast;
bool bCrossDown=FastMACurrent<SlowMACurrent && FastMAPast>=SlowMAPast;

if (OpenOrders(MagicNumber)==0 && !LastOrderCloseInCurrentBar(MagicNumber))
{
  if (bCrossUp)
  {
    // market order enter long
  }
  if (bCrossDown)
  {
    // market order enter short
  }
}


int OpenOrders(int nMagic)
{
  nOpenOrders=0;
  for ( int nPosition=0 ; nPosition<OrdersTotal() ; nPosition++ )
  {
    OrderSelect(nPosition, SELECT_BY_POS, MODE_TRADES);
    if (OrderMagicNumber()==nMagic) 
      if (OrderSymbol()==Symbol())
      {
        OpenOrders++
      }
  }
}

bool LastOrderCloseInCurrentBar(int nMagic)
{
  // Only look though most recent 100 trades for last order closed by this system
  int nMaxLookback = MathMax(0,OrdersHistoryTotal()-100);
  for ( int nPosition=OrdersHistoryTotal()-1 ; nPosition>=nMaxLookback ; nPosition-- )
  {
    OrderSelect(nPosition, SELECT_BY_POS, MODE_HISTORY);
    if (OrderMagicNumber() == nMagic)
      if (OrderSymbol()==Symbol())
      {
        return(OrderCloseTime()>=Time[0]);
      }
  }
  return(false);
}

Paul

http://paulsfxrandomwalk.blogspot.com/

Reason: