"

New bar event in EA

by Dr.Hamdi Boukamcha
Name:
New bar event in EA
Author: symr (2011.07.01 16:45)
Rating: 5
Downloaded: 2839
Download:
New bar event in EA   ea_symr_newBar.mq4 (2.6 Kb) View
So many people wants:

How to detect new bar present.

It is so simple especially if u want detect new bar in current timeframe,

void start(){
  static datetime tmp;
  if (tmp!= Time[0]) {
    tmp =  Time[0];
    //do ur code here
  }
}

but what about the other timeframe event? It is not too hard but it has some restriction:

MT4 is not support onBar event, but u can put the upward times into array and check the array times every tick, if it reached the right time, execute the new bar event.
That means if u run eg.: backtest on M5 timeframe u can catch the M6 M7…D1 events.
Why u can detect only upward trends? The answer is a question: how to generate tick data by metatrader? A1, A2, A3,…

Until the D1 timeframe its more difficult because the week starting at eg.: Sunday 20:45 (Broker specific) and the start of the month can start in the middle of the week… etc.
I think this info isnt too relevant, so i dont publish it…

So there is a topic for this Q, but i think so many people dont read the articles and forums, so i published this code.

Some explanation:

in the init function u fill the time array with the starter times :

  curIndex = utils.periodToPeriodIndex(Period());
  times[curIndex] = Time[0];
  for(int i=curIndex+1; i<MAX; i++)
    times[i] = times[curIndex]- MathMod(times[curIndex],utils.periodIndexToPeriod(i)*60);

and in the start function u checked is there enough time elapsed now, then execute the event

  if (times[curIndex] != Time[0]) {
    times[curIndex] = Time[0];
    onBar(Period());
    for(int i=curIndex+1; i<MAX; i++) {
      int period  = utils.periodIndexToPeriod(i),
          seconds = period*60,
          time0   = times[curIndex] - MathMod(times[curIndex],seconds);
      if (times[i] != time0) {
        times[i] = time0;
        onBar(period);
      }
    }
  }

 

Write ur code in

void onTick() { 
}

and

void onBar(int period) {
}

That’s all folks.

 

Update 1.1: Thx to WHRoeder for clear code

5 comments  To post a new comment, please log in or register

Why don’t you just use the iTime function?

http://docs.mql4.com/series/itime

27.11.2012 10:48 Master.Aurora

Why not use iTime(“EURUSD”,PERIOD_M1,0)

e.g.

if(New_Time_M1 != iTime(“EURUSD”,PERIOD_M1,0)) // Compare time –> new bar is born
{
New_Time_M1=iTime(“EURUSD”,PERIOD_M1,0); // New time set
New_Bar_M1=true; // A new bar detected

}

 

 

 

07.07.2011 22:44 alexander_zde

WHRoeder:

  1. times[curIndex]-(MathMod(times[curIndex]/60,utils.periodIndexToPeriod(i)))*60

    for efficiency and readability, simplify

    times[curIndex]- MathMod(times[curIndex],utils.periodIndexToPeriod(i)*60);

  2. for efficiency and readability and to avoid unnecessary function calls, I’d replace the functions with an array and save results
    int utils.periodIndexToPeriod   = {
        PERIOD_M1,  PERIOD_M5,  PERIOD_M15, PERIOD_M30, PERIOD_H1,  PERIOD_H4,
        PERIOD_D1,  PERIOD_W1,  PERIOD_MN1, 20,         50  };
    
    for(int i=curIndex+1; i<MAX; i++)
        int period  = utils.periodIndexToPeriod[i];
            seconds = period*60,
            time0   = times[curIndex] - MathMod(times[curIndex],seconds);
        if (times[i] != time0) {
            times[i] = time0;
            onBar(period);
    }   }

  3. And avoid unnecessary function calls with the simpler
    times[curIndex] = Time[0]; // = iTime(NULL,0,0);

Thanks for this I am trying with custom timerames, if I set it up for a 3 hour candle for example eg 180 minutes. When does this time start to count? eg form midnight every 3 hours or does it depend when the indicatoe is placed on the chart?

 

thanks again

05.07.2011 17:04 manuel_fx

Hi.

thx for this ideas, ur right.

1. Accessing the arrays is more faster than use switch – case element. (in this example 4 times), some test:

  start = GetTickCount();

  for(test=0; test<10000000; test++)
   for(i=0; i<MAX; i++)
    int value1 = utils.periodIndexToPeriod[i];

  log("Elapsed : " + (GetTickCount()-start)); // 2100 ms

  start = GetTickCount();

  for(test=0; test<10000000; test++)
   for(i=0; i<MAX; i++)
    int value2 = utils2.periodIndexToPeriod(i);

  log("Elapsed : " + (GetTickCount()-start)); // 8000 ms

but how accsess this 10.000.000*MAX in a row? 😀 and i think much more readble switch – case options beacuse it is more similar the other rutins. Easily readable by someone who not a coder.

2. use local variable in loop save some times but not so much i think so test it: in half year backtest, where do some loop in onBar event, ur code done in 6006ms, my 5990ms on ~ 72Kbar event so its same

3. Time[0] / iTime(NULL,0,0) does not affect the result.

So i change the loop code for ur versions (more readable), but not change the array access rutin. btw thx a lot, i swear i will not publish a code, after 2 am, when i am too tired 😛

01.07.2011 20:27 symr

  1. times[curIndex]-(MathMod(times[curIndex]/60,utils.periodIndexToPeriod(i)))*60

    for efficiency and readability, simplify

    times[curIndex]- MathMod(times[curIndex],utils.periodIndexToPeriod(i)*60);

  2. for efficiency and readability and to avoid unnecessary function calls, I’d replace the functions with an array and save results
    int utils.periodIndexToPeriod   = {
        PERIOD_M1,  PERIOD_M5,  PERIOD_M15, PERIOD_M30, PERIOD_H1,  PERIOD_H4,
        PERIOD_D1,  PERIOD_W1,  PERIOD_MN1, 20,         50  };
    
    for(int i=curIndex+1; i<MAX; i++)
        int period  = utils.periodIndexToPeriod[i];
            seconds = period*60,
            time0   = times[curIndex] - MathMod(times[curIndex],seconds);
        if (times[i] != time0) {
            times[i] = time0;
            onBar(period);
    }   }

  3. And avoid unnecessary function calls with the simpler
    times[curIndex] = Time[0]; // = iTime(NULL,0,0);

Share this article

Leave a comment