iClose returning wrong value

 

Hi! I'm having a very strange problem when trying to access the close price of the candle in another timeframe. Sometimes the value comes right, but sometimes it comes wrong. Any idea what might be happening?


Code:


input ENUM_TIMEFRAMES     UseTimeFrame  = PERIOD_D1;

Print(iClose(Symbol(),UseTimeFrame,1));


P.S.: This does not happen only when I call the function inside Print and not only on D1 timeframe. The Print function is called inside OnTick.

 
Douglas Eiras:

Hi! I'm having a very strange problem when trying to access the close price of the candle in another timeframe. Sometimes the value comes right, but sometimes it comes wrong. Any idea what might be happening?

It is common with using another timeframe or symbol. First you have to cause synchronization the other timeframe (symbol) data before calling timeseries functions (iClose).

 
Douglas Eiras:

Hi! I'm having a very strange problem when trying to access the close price of the candle in another timeframe. Sometimes the value comes right, but sometimes it comes wrong. Any idea what might be happening?


Code:



P.S.: This does not happen only when I call the function inside Print and not only on D1 timeframe. The Print function is called inside OnTick.

Its most likely that when you are using the Print() , it usually print a string value, but iClose() return a double value..

Also you haven't Normalize the double so I think, MT4 tries to round off to some near value...(This is my opinion only, I might be wrong)

try

   Print(NormalizeDouble(iClose(Symbol(),1440,1),Digits));
   
   //OR
   
   double DailyClose = iClose(Symbol(),1440,1);
   Print(DailyClose);
 
Lakshan Perera:

Its most likely that when you are using the Print() , it usually print a string value, but iClose() return a double value..

Also you haven't Normalize the double so I think, MT4 tries to round off to some near value...(This is my opinion only, I might be wrong)

try

You are wrong. The problem is in incomplete data from another timeframe.
 
Petr Nosek:

It is common with using another timeframe or symbol. First you have to cause synchronization the other timeframe (symbol) data before calling timeseries functions (iClose).

Hi! Thanks for your answer. How do i do this synchronization by code? I tried using RefresRates() and Sleep before calling the function, but it didn't work.

 
  1. RefreshRates updates:
    Predefined variables: Ask, Bars, Bid, Close[], High[], Low[], Open[], Point, Time[], Volume[]
              RefreshRates - Timeseries and Indicators Access - MQL4 Reference
              Predefined Variables - MQL4 Reference
    Also updates: Hour, Minute, and Seconds
              Minute() returns wrong values - or am I wrong? - MQL4 and MetaTrader 4 - MQL4 programming forum
    And updates: OrderClosePrice() on the next order select call.
    You aren't using any of them.

  2. On MT4: Unless the current chart is that specific pair/TF referenced, you must handle 4066/4073 errors.
              Download history in MQL4 EA - MQL4 and MetaTrader 4 - MQL4 programming forum
 
Douglas Eiras:

Hi! Thanks for your answer. How do i do this synchronization by code? I tried using RefresRates() and Sleep before calling the function, but it didn't work.

You can use something like this:

#property script_show_inputs

input string inpSym="EURUSD";          // Symbol
input ENUM_TIMEFRAMES inpTF=PERIOD_M5; // Timeframe
input uint inpTimeOut=1000;            // TimeOut in millisedonds

void OnStart()
  {
   string priceFormat=StringFormat("%%.%df",SymbolInfoInteger(inpSym,SYMBOL_DIGITS));
   if(!Refresh(inpSym,inpTF,inpTimeOut)) printf("Refreshing the symbol: %s , period: %s has failed",inpSym,EnumToString(inpTF));
   else 
      printf("Symbol (period): %s (%s) => iHigh[0]="+priceFormat+" ; iLow[0]="+priceFormat+" ; iTime[0]=%s",inpSym,EnumToString(inpTF),
         iHigh(inpSym,inpTF,0),iLow(inpSym,inpTF,0),TimeToString(iTime(inpSym,inpTF,0)));
  }

bool Refresh(string symbol=NULL,ENUM_TIMEFRAMES tf=PERIOD_CURRENT,const uint timeOut=1000)
  {
   if(symbol==NULL || symbol=="") symbol=_Symbol;
   if(tf==PERIOD_CURRENT) tf=(ENUM_TIMEFRAMES)_Period;
   datetime lastBarTime[1];
   uint startCount=GetTickCount();
   while((CopyTime(symbol,tf,0,1,lastBarTime)!=1 || lastBarTime[0]<TimeCurrent()-TimeCurrent()%PeriodSeconds(tf)) && GetTickCount()-startCount<timeOut && !IsStopped());
   return(lastBarTime[0]>=TimeCurrent()-TimeCurrent()%PeriodSeconds(tf));
  }

This code doesn't catch all possible errors but for study purpose it is enough (I hope).

EDIT: see https://www.mql5.com/en/forum/231717/page2#comment_6809758

 
Petr Nosek:

You can use something like this:

This code doesn't catch all possible errors but for study purpose it is enough (I hope).

I tried to use your code but it did'nt work unfortunately :(

It keeps waiting forever.


Code:

#property strict
input ENUM_TIMEFRAMES     UseTimeFrame  = PERIOD_W1;

void OnTick()
{
   while (true)
   {
      if (Refresh(Symbol(),UseTimeFrame,1000))
      {
         Print(iClose(Symbol(),UseTimeFrame,1));
         break;
      }
      Print("Waiting...");
   }  
}

bool Refresh(string symbol=NULL,ENUM_TIMEFRAMES tf=PERIOD_CURRENT,const uint timeOut=1000)
  {
   if(symbol==NULL || symbol=="") symbol=_Symbol;
   if(tf==PERIOD_CURRENT) tf=(ENUM_TIMEFRAMES)_Period;
   datetime lastBarTime[1];
   uint startCount=GetTickCount();
   while((CopyTime(symbol,tf,0,1,lastBarTime)!=1 || lastBarTime[0]!=TimeCurrent()-TimeCurrent()%PeriodSeconds(tf)) && GetTickCount()-startCount<timeOut && !IsStopped());
   return(lastBarTime[0]==TimeCurrent()-TimeCurrent()%PeriodSeconds(tf));
  }
Files:
waiting.png  25 kb
 
whroeder1:
  1. RefreshRates updates: You aren't using any of them.

  2. On MT4: Unless the current chart is that specific pair/TF referenced, you must handle 4066/4073 errors.
              Download history in MQL4 EA - MQL4 and MetaTrader 4 - MQL4 programming forum

The link you sent has a piece of code. I tried to use it and the message kept returning error 0 forever (see image 1).


Code used:


#property strict
input ENUM_TIMEFRAMES     UseTimeFrame  = PERIOD_W1;

#define HR2400 PERIOD_D1 * 60    // 86400 = 24 * 3600
int      TimeOfDay(datetime when=0){      if(when == 0)  when = TimeCurrent();
                                          return( when % HR2400 );            }
datetime DateOfDay(datetime when=0){      if(when == 0)  when = TimeCurrent();
                                          return( when - TimeOfDay(when) );   }
#define SYMBOL string
#define THIS_SYMBOL ""
bool  download_history(ENUM_TIMEFRAMES period=PERIOD_CURRENT){
   return download_history(_Symbol, period); 
}

void OnTick()
{
   
   while(!download_history(UseTimeFrame) ){ Sleep(1000); RefreshRates(); }
   
   Print(iClose(Symbol(),UseTimeFrame,1));
   
   
}

bool  download_history(
      SYMBOL            symbol=THIS_SYMBOL,     ///< The symbol required.
      ENUM_TIMEFRAMES   period=PERIOD_CURRENT   /**< The standard timeframe.*/){
   if(symbol == THIS_SYMBOL)     symbol = _Symbol;
   if(period == PERIOD_CURRENT)  period = _Period;
   datetime today = DateOfDay();
   ResetLastError();
   datetime other = iTime(symbol, period, 0);
   if(_LastError == 0 
   && today == DateOfDay(other)) return true;   
   if(_LastError != ERR_HISTORY_WILL_UPDATED
   && _LastError != ERR_NO_HISTORY_DATA)
      Print(StringFormat("iTime(%s,%i) Failed: %i", symbol, period,_LastError));
   return false;
}
Files:
img1.png  30 kb
 
Any other idea guys? :(
 
Douglas Eiras: returning error 0 forever (see image 1).
input ENUM_TIMEFRAMES     UseTimeFrame  = PERIOD_W1;
:
   datetime today = DateOfDay();
   datetime other = iTime(symbol, period, 0);
:
   && today == DateOfDay(other)) return true; 

Error zero mean NO error! Obviously the start of the week is not equal to the start of the day. Try removing that second condition.

Reason: