Using EMAs in a script to filter trends causes #4806 and #4022

 

Hello,

I wanted to make a script which checks the first 100 symbols in the list if they are in an uptrend according to this definition:

EMA50 > EMA200 and no price low should touch the EMA50. And these criteria should be met in the last 10 periods.

In the screenshot you can see what I am looking for. The red line is the EMA200 and the green line the EMA50. And within the last 10 candles all lows are above the EMA50.

Here is my code and I have no idea why it isn't working. Any help is very appreciated!

void OnStart()
  {
//---
   for (int i=0; i<100; i++) {
      string sym=SymbolName(i, true);
      Print(sym);
      int bars=Bars(sym,PERIOD_D1);
      int ema200Handle=iMA(sym,PERIOD_D1,200,0,MODE_EMA,PRICE_CLOSE);
      if (ema200Handle==INVALID_HANDLE) {
         Print(sym+": EMA200 INVALID_HANDLE");
         continue;
      }
      int ema50Handle=iMA(sym,PERIOD_D1,50,0,MODE_EMA,PRICE_CLOSE);
      if (ema50Handle==INVALID_HANDLE) {
         Print(sym+": EMA50 INVALID_HANDLE");
         continue;
      }
      double ema200Buffer[], ema50Buffer[];
      ArraySetAsSeries(ema200Buffer, true);
      ArraySetAsSeries(ema50Buffer, true);
      int copied=CopyBuffer(ema200Handle,0,0,10,ema200Buffer);
      if (copied<10) {
         Print(sym+": EMA200 CopyBuffer() failed. Error #"+(string)GetLastError());
         continue;
      }
      copied=CopyBuffer(ema50Handle,1,0,10,ema50Buffer);
      if (copied<10) {
         Print(sym+": EMA50 CopyBuffer() failed. Error #"+(string)GetLastError());
         continue;
      }
      MqlRates rates[];
      copied=CopyRates(sym,PERIOD_D1,0,10,rates);
      if (copied<0) {
         Print(sym+": CopyRates() failed. Error #"+(string)GetLastError());
         continue;
      }
      bool out=false;
      for (int j=0; j<=10; j++) {
         if (ema50Buffer[j]<=ema200Buffer[j]) {
            out=true;
            break;
         }
         if (rates[j].low<ema50Buffer[j]) {
            out=true;
            break;
         }
      }
      if (!out) {
         long chartID=ChartOpen(sym,PERIOD_D1);
         if (chartID>0) {
            ChartScreenShot(chartID, sym+".png", 1280, 720);
            ChartClose(chartID);
         }
      }
   }
  }
Files:
GBPUSDDaily.png  16 kb
 
copied=CopyBuffer(ema50Handle,0,0,10,ema50Buffer);
ArraySetAsSeries(rates, true);
 
 for (int j=0; j<=10; j++) 

0 to 10 is 11 datas, not 10 ?

 
Nagisa Unada:

Thanks, I changed it.

But the script is still not working. I often (but not always) receive #4806. CopyBuffer() fails.

And the whole script takes very long to complete although I changed the symbols from 100 to 20. It takes around 3 minutes to complete for only 20 symbols.

Something else but be very wrong in my code..

 
ffoorr:

0 to 10 is 11 datas, not 10 ?

I just noticed that and changed it to j<10. But nevertheless the code doesn't really work.

 
Marbo:

I just noticed that and changed it to j<10. But nevertheless the code doesn't really work.

This is the log. Please have a look how long this script works.

I can't believe that it is so complicated to check if EMA50 is above EMA200 during the last 10 periods. :(
Files:
errors.PNG  73 kb
 

It will never work like that as the indicator doesn't (always) have time to calculate before you request data.

You need to use BarsCalculated() to check when the indicator is ready, and Sleep() if it's not.

 
Alain Verleyen:

It will never work like that as the indicator doesn't (always) have time to calculate before you request data.

You need to use BarsCalculated() to check when the indicator is ready, and Sleep() if it's not.

I use a while loop now to wait until the indicator is ready but the script seems stays in the while loop forever. That means that BarsCalculated() only returns -1. But why?

void OnStart()
  {
//---
   for (int i=0; i<20; i++) {
      string sym=SymbolName(i, true);
      Print(sym);
      int ema200Handle=iMA(sym,PERIOD_D1,200,0,MODE_EMA,PRICE_CLOSE);
      if (ema200Handle==INVALID_HANDLE) {
         Print(sym+": EMA200 INVALID_HANDLE");
         continue;
      }
      int ema50Handle=iMA(sym,PERIOD_D1,50,0,MODE_EMA,PRICE_CLOSE);
      if (ema50Handle==INVALID_HANDLE) {
         Print(sym+": EMA50 INVALID_HANDLE");
         continue;
      }
      double ema200Buffer[], ema50Buffer[];
      ArraySetAsSeries(ema200Buffer, true);
      ArraySetAsSeries(ema50Buffer, true);
      while(BarsCalculated(ema200Handle)<0) {
         Print(sym);
         Sleep(500);
      }
      int copied=CopyBuffer(ema200Handle,0,0,10,ema200Buffer);
      if (copied<0) {
         Print(sym+": EMA200 CopyBuffer() failed. Error #"+(string)GetLastError());
         continue;
      }
      while(BarsCalculated(ema50Handle)<0) {
         Print(sym);
         Sleep(500);
      }
      copied=CopyBuffer(ema50Handle,0,0,10,ema50Buffer);
      if (copied<0) {
         Print(sym+": EMA50 CopyBuffer() failed. Error #"+(string)GetLastError());
         continue;
      }
      MqlRates rates[];
      ArraySetAsSeries(rates, true);
      copied=CopyRates(sym,PERIOD_D1,0,10,rates);
      if (copied<0) {
         Print(sym+": CopyRates() failed. Error #"+(string)GetLastError());
         continue;
      }
      bool out=false;
      for (int j=0; j<10; j++) {
         if (ema50Buffer[j]<=ema200Buffer[j]) {
            out=true;
            break;
         }
         if (rates[j].low<ema50Buffer[j]) {
            out=true;
            break;
         }
      }
      if (!out) {
         long chartID=ChartOpen(sym,PERIOD_D1);
         if (chartID>0) {
            ChartScreenShot(chartID, sym+".png", 1280, 720);
            ChartClose(chartID);
         }
      }
   }
  }
 
You are using a 200 MA on a daily timeframe, are you sure you have enough bars for all symbols ?
 
Alain Verleyen:
You are using a 200 MA on a daily timeframe, are you sure you have enough bars for all symbols ?

You are absolutely right. I just checked it, opened (the first time) [DAX30] and noticed that the chart needed some time to load. Now I opened the chart once, I know there are 200 bars.

My problem is that I want to scan symbols which are not opened in a chart. Therefore I use Bars() to initiate the history download but often I just receive a zero and the download has not started.

It's pretty difficult to access the data history with MQL5 compared to MQL4 and I haven't found a good solution yet to load all data which are needed for the indicator calculation.

In some cases Bars() worked, in other cases SeriesInfoInteger() worked but I am still more trying than logically coding... very frustrating because all my problems have to do with the data history mangagement of MT5 and not with my own ideas.

 
Marbo:

You are absolutely right. I just checked it, opened (the first time) [DAX30] and noticed that the chart needed some time to load. Now I opened the chart once, I know there are 200 bars.

My problem is that I want to scan symbols which are not opened in a chart. Therefore I use Bars() to initiate the history download but often I just receive a zero and the download has not started.

It's pretty difficult to access the data history with MQL5 compared to MQL4 and I haven't found a good solution yet to load all data which are needed for the indicator calculation.

In some cases Bars() worked, in other cases SeriesInfoInteger() worked but I am still more trying than logically coding... very frustrating because all my problems have to do with the data history mangagement of MT5 and not with my own ideas.

I just made a test with this script:

void OnStart()
  {
//---
   Alert(Bars("COCOA",PERIOD_D1));
  }

I never opened any COCOA chart before. The first time I ran the script the result was 30. The second time the result was 34. And the third and fourth time the result stayed 34.

Then I opened the daily chart of COCOA and after that the result was 2633.

I always thought that using Bars() start the history download process but that's obviously not the case.

I really searched so much to find a useful idea how to download the needed data history but I haven't found anything yet.

Could you give me an advice or link how I do that in an indicator?

Files:
cocoa.PNG  3 kb
Reason: