Eventhandler "onQuotesLoaded"

 
Hello,

is there any eventhandler which is triggered when metatrader has finished updating quotes or does someone have any idea how to code this ?
The problem arisis from the way MT is updating quotes/ticks, small example:

Timeframe: Hourly
Let's say you close MT on thursday 22.00 and open up MT again on monday 11.00 the following week.
The first bar/candle which is loaded is not thursday 21.00,22.00,... but monday 10.00, 9.00, 8.00,... .

So one way would be to check when the last data on thu (22.00) would be just before 23.00, but this fails on weekends, when the last data is the last tick of your broker, so there's no directly following bar/candle.

Any ideas?

marc
 
Hello,

is there any eventhandler which is triggered when metatrader has finished updating quotes or does someone have any idea how to code this ?
The problem arisis from the way MT is updating quotes/ticks, small example:

Timeframe: Hourly
Let's say you close MT on thursday 22.00 and open up MT again on monday 11.00 the following week.
The first bar/candle which is loaded is not thursday 21.00,22.00,... but monday 10.00, 9.00, 8.00,... .

So one way would be to check when the last data on thu (22.00) would be just before 23.00, but this fails on weekends, when the last data is the last tick of your broker, so there's no directly following bar/candle.

Any ideas?

marc



i got the same problem and used the following workaround in my code to fix it, not a perfect solution but seems works fine for me.

the full code can be found at
please let me know if anyone got better idea on this. :)


   if (Bars < 2) {
      //the data is not loaded yet.
      if (Debug) Alert("Data not loaded, only ", Bars, " Bars");
      return (0);
   }
 
   static int wait_count = 0;
   if ((Time[0] - Time[1]) != Period() * 60) {
      //this will happen when the client load block of data at startup.
      //return and wait till the data fully loaded in next call
      wait_count++;
      //only wait 3 times, to prevent deadlock when server data missing.
      if (wait_count <= 3) {
         if (Debug) Alert("Data not fully loaded, waiting for update");
         return (0);
      }
   }
   wait_count = 0;
 
Hello wfy05,

thanks for your answer, very nice and precise coding.
But does this actually work? I noticed that depending on the bandwidth several blocks of data are loaded like e.g. 50bars-100bars. So in this case you would have to store on "init" Time[0] and on the first tick check if Time[50] - Time[ storedValue,last Time[0] ] != Period() * 60.
So I suppose in your workaround almost always Time[0] up to Time[50] are loaded together and therefore the condition would always evaluate to true?

marc
 
Hello wfy05,

thanks for your answer, very nice and precise coding.
But does this actually work? I noticed that depending on the bandwidth several blocks of data are loaded like e.g. 50bars-100bars. So in this case you would have to store on "init" Time[0] and on the first tick check if Time[50] - Time[ storedValue,last Time[0] ] != Period() * 60.
So I suppose in your workaround almost always Time[0] up to Time[50] are loaded together and therefore the condition would always evaluate to true?

marc


You are right, the downloading and updating will be several different blocks when there is lots of data(i only tested 100-200 bars block and the workaround only works well for that). in this case, the data updating is in 512 bars each time usually.

i used the following code to do the testing:

int test1()
{
   string str;
   int size;
   
   int FileHandle = FileOpenHistory(Symbol()+Period() +".hst", FILE_BIN|FILE_READ);
   if(FileHandle < 0) {
      size = -1;
   } else {
      size = FileSize(FileHandle);
   }
   str = ServerAddress() + ": " + size + ", " + Bars + ", " + TimeToStr(Time[0]) + ", " + TimeToStr(Time[1]) + ", " + TimeToStr(Time[Bars-1]);
   Alert(str);
   if(FileHandle >= 0) FileClose(FileHandle);   
   return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
//---- 
   test1();
   return (0);
  }
//+------------------------------------------------------------------+



and some result log during a few test is:

I. Changing server
2005.12.03 20:29:02	test EURUSD,M1: Alert: DirectForex-DirectForex: 260936, 5927, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 20:29:02	test EURUSD,M1: Alert: DirectForex-DirectForex: 249012, 5656, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 20:29:01	test EURUSD,M1: Alert: DirectForex-DirectForex: 226484, 5144, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 20:29:00	test EURUSD,M1: Alert: DirectForex-DirectForex: 203956, 4632, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 20:28:59	test EURUSD,M1: Alert: DirectForex-DirectForex: 181428, 4120, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 20:28:57	test EURUSD,M1: Alert: DirectForex-DirectForex: 158900, 3608, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 20:28:55	test EURUSD,M1: Alert: DirectForex-DirectForex: 136372, 3096, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 20:28:52	test EURUSD,M1: Alert: DirectForex-DirectForex: 113844, 2584, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 20:28:49	test EURUSD,M1: Alert: DirectForex-DirectForex: 91316, 2072, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 20:28:48	test EURUSD,M1: Alert: DirectForex-DirectForex: 68788, 1560, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 20:28:45	test EURUSD,M1: Alert: FxProfit-Demo: 46260, 1048, 2005.11.29 05:22, 2005.11.29 05:21, 2005.11.28 11:51
2005.12.03 20:27:16	test EURUSD,M1: Alert: FxProfit-Demo: 22676, 512, 2005.12.02 22:59, 2005.12.02 22:58, 2005.12.02 14:07


II. Startup:
2005.12.03 21:02:35	test EURUSD,M1: Alert: DirectForex-DirectForex: 260936, 5927, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 21:02:34	test EURUSD,M1: Alert: DirectForex-DirectForex: 246108, 5590, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 21:02:33	test EURUSD,M1: Alert: DirectForex-DirectForex: 223580, 5078, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 21:02:32	test EURUSD,M1: Alert: DirectForex-DirectForex: 201052, 4566, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 21:02:31	test EURUSD,M1: Alert: DirectForex-DirectForex: 178524, 4054, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 21:02:30	test EURUSD,M1: Alert: DirectForex-DirectForex: 155996, 3542, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 21:02:26	test EURUSD,M1: Alert: DirectForex-DirectForex: 133468, 3030, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 21:02:26	test EURUSD,M1: Alert: DirectForex-DirectForex: 110940, 2518, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 21:02:23	test EURUSD,M1: Alert: DirectForex-DirectForex: 88412, 2006, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 21:02:20	test EURUSD,M1: Alert: DirectForex-DirectForex: 65884, 1494, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 21:02:16	test EURUSD,M1: Alert: DirectForex-DirectForex: 43356, 982, 2005.12.02 15:59, 2005.12.02 15:58, 2005.11.28 11:51
2005.12.03 21:02:06	test EURUSD,M1: Alert: : 20828, 470, 2005.11.28 19:41, 2005.11.28 19:40, 2005.11.28 11:51



There is a few more problems found during the test and some might be metatrader bug:
1. The server data might miss a lots in short period timeframes, e.g:

2005.12.02,21:41,1.1713,1.1713,1.1713,1.1713,1
2005.12.02,21:43,1.1712,1.1713,1.1712,1.1713,2
2005.12.02,21:44,1.1714,1.1714,1.1714,1.1714,1
2005.12.02,21:45,1.1715,1.1716,1.1715,1.1716,2
2005.12.02,21:46,1.1715,1.1716,1.1715,1.1715,3
2005.12.02,21:47,1.1713,1.1714,1.1713,1.1714,2
2005.12.02,21:48,1.1713,1.1713,1.1713,1.1713,1
2005.12.02,21:51,1.1714,1.1714,1.1713,1.1713,4
2005.12.02,21:52,1.1714,1.1715,1.1714,1.1714,3
2005.12.02,21:54,1.1715,1.1715,1.1714,1.1715,5
2005.12.02,21:55,1.1714,1.1714,1.1714,1.1714,1
2005.12.02,21:56,1.1715,1.1715,1.1715,1.1715,1
2005.12.02,21:57,1.1714,1.1715,1.1714,1.1714,3
2005.12.02,21:59,1.1715,1.1715,1.1715,1.1715,1


so
1): the data generated from the missing data will not be fully correct.
2): Time[50] - Time[0] will not be Period() * 60 * 50, so the idea you said won't always work.

2. when changing server, Metatrader will first update the data from the new server, but with server name is unchanged. then the server name will be updated in next call, also with the Time[0] updated to latest data. this can be considered as a metatrader bug i think.

3. when loading data at startup, the initial Time[0] before loading can be found, but when changing server, due to the bug above, the initial Time[0] should be Time[1].

Looks like we should do some more fix for those metatrader problems, any comments?

 
New workaround code, also support detecting of new initial history loading.

static int LastStartTime = 0;
static int LastEndTime = 0;
static int LastBarCount = 0;

int reinit()
{
   deinit();
   init();
   LastStartTime = Time[Bars-1];
   LastEndTime = Time[0];
   LastBarCount = Bars;
}

bool IsDataChanged()
{
   static int LastBars = 0, LastTime = 0, LastVolume = 0;
   static double LastOpen = 0, LastClose = 0, LastHigh = 0, LastLow = 0;
   
   if (LastVolume != Volume[0] || LastBars != Bars || LastTime != Time[0]|| 
      LastClose != Close[0] || LastHigh != High[0] || LastLow != Low[0] || 
      LastOpen != Open[0]) {

      LastBars = Bars;
      LastVolume = Volume[0];
      LastTime = Time[0];
      LastClose = Close[0];
      LastHigh = High[0];
      LastLow = Low[0];
      LastOpen = Open[0];
      return (true);
   }
   return (false);
}
int CheckNewData()
{
   static string LastServer = "";
   
   if (Bars < 2) {
      //the data is not loaded yet.
      DebugMsg("Data not loaded, only " +  Bars + " Bars");
      return (-1);
   }

   string serv = ServerAddress();
   if (serv == "") {
      //no server yet
      DebugMsg("No server connected");
      return (-1);
   }

   //server changed? check this and reinit to prevent wrong data while changing server.
   if (LastServer != serv) {
      DebugMsg("Server changed from " + LastServer + " to " + serv);
      LastServer = serv;
      reinit();
      return (-1);
   }

   if (!IsDataChanged()) {
      //return if no data changed to save resource
      //DebugMsg("No data changed");
      return (-1);
   }

   if (Time[Bars-1] != LastStartTime) {
      DebugMsg("Start time changed, new history loaded or server changed");
      reinit();
      return (-1);
   }
      
   int i, cnt;
   
   //try to find LastEndTime bar, which should be Time[0] or Time[1] usually,
   //so the operation is fast
   for (i = 0; i < Bars; i++) {
      if (Time[i] <= LastEndTime) {
         break;
      }
   }
   
   if (i >= Bars || Time[i] != LastEndTime) {
      DebugMsg("End time " + TimeToStr(LastEndTime) + " not found");
      reinit();
      return (-1);
   }
   
   cnt = Bars - i;
   if (cnt != LastBarCount) {
      DebugMsg("Data loaded, cnt is " + cnt + " LastBarCount is " + LastBarCount);
      reinit();
      return (-1);
   }

   //no new data loaded, return with last LastEndTime position.
   LastBarCount = Bars;
   LastEndTime = Time[0];
   return (i);
}

//+------------------------------------------------------------------+
//| program start function                                           |
//+------------------------------------------------------------------+
int start()
{
   static int last_time = 0;

   if (!Enabled) return (0);
         
   //always update or update only after certain interval
   if (UpdateInterval !=  0) {
      int cur_time;
      
      cur_time = GetTickCount();
      if (MathAbs(cur_time - last_time) < UpdateInterval) {
         return (0);
      }
      last_time = cur_time;
   }

   //if (Debug) PerfCheck(true);
   int n = CheckNewData();
   //if (Debug) PerfCheck(false);   
   if (n < 0) return (0);

   //update history file with new data
   WriteHistoryFile(n);
   //refresh chart window
   UpdateChartWindow();
   //if (Debug) PerfCheck(false);
   return(0);
}