Please Help

 

I can't see why this function doesn't work.

//Creates strings like these:
// yyyymmdd,hh:mm,o(4dp) ,h(4dp) ,l(4dp) ,c(4dp) ,Volume
// 20130829,20:25,33.2050,33.2060,33.2030,33.2040,20
string MakeInfoString(string symbol, int period, int Bar){

        string Strline = TimeToStr( iTime(symbol,period, Bar) , TIME_DATE|TIME_SECONDS );
        Strline = StringSubstr(Strline,0,4) + StringSubstr(Strline,5,2) + StringSubstr(Strline,8,2) + "," + StringSubstr(Strline,11,5);

        Strline = Strline + "," + DoubleToStr( NormalizeDouble(iOpen(symbol,period, Bar),4) , 4) + "," + DoubleToStr( NormalizeDouble(iHigh(symbol,period, Bar),4) , 4) + "," 
                + DoubleToStr( NormalizeDouble(iLow(symbol,period, Bar),4) , 4) + "," + DoubleToStr( NormalizeDouble(iClose(symbol,period, Bar),4) , 4) + "," + DoubleToStr(iVolume(symbol,period, Bar),0);


        int err = GetLastError();
        static int tries = 0;
        if( tries<100 && err==4066){
                Sleep(10);
                tries++ ;
                Print(symbol,period , ", Bar =", Bar ,", slept  ", 10*tries ,"ms due to  error ",err," in MakeInfoString() -- " ,  ErrorDescription(err));
                Strline = MakeInfoString(symbol,  period,  Bar);  
        }

        if(tries >= 100 ){
                err = GetLastError();
                Print(symbol,period , ", Bar =", Bar, ", Timed out! " ,":  Error ",err," in MakeInfoString() -- " ,  ErrorDescription(err));
        }

        tries = 0;    
        return(Strline);
}


it is always returning "9700101,00:00,0.0000,0.0000,0.0000,0.0000,0"

 
BenLinus:


I can't see why this function doesn't work.

You check for error 4066, don't wait long enough and then don't bother trying to get the correct data when you have found that . . . "Requested history data in updating state."
 
RaptorUK:
... don't bother trying to get the correct data when you have found that . . . "Requested history data in updating state."


but I've called the function again. That should get the data right?

Strline = MakeInfoString(symbol,  period,  Bar); 

If the error still occurs, then it should sleep even more.


My 4066 error handling block is not triggered. I tried for bar 2000 and bar 1.

 
If you get 4066, you MUST wait the full 15 seconds (15000) and then retry once. If you try earlier (like your sleep(10)) you will not get 4066 and will not get any data.
 
BenLinus:


I can't see why this function doesn't work.

it is always returning "9700101,00:00,0.0000,0.0000,0.0000,0.0000,0"

First, as WHRoeder has suggested, when using a "i"-function, you get a 4066 error only the first time if the history is in a state of updating, and no error and no data returned in subsequent calls. So you have to test for a 4066 error and whether data has been returned. Second, as both RaptorUK and WHRoeder have said, you aren't waiting long enough between calls. Your code sleeps for 10 ms and your tries variable is set to 100, so (assuming that part of your code works correctly--I'm not sure if it performs as you intended it to work) you are only pausing for 1000 ms, which is only 1 second. Third, you aren't giving the program calling your function any way of really determining whether the function worked correctly or encountered an error.

Below is some example code. MakeInfoString returns a bool, so the calling program can determine whether the function worked properly or encountered an unexpected error. Additionally, it sleeps for upto 20 seconds in 2 second intervals. And when data is returned by iTime(), it verifies that the time returned by iTime() is the time for the specified bar (using iBarShift()). A potentially negative aspect of the code below is the use of sleep in the function itself. Depending on the situation, it may be better to have the calling program determine what to do upon an error (including a 4066 error), whether to sleep for a specified time or simply return out of start() and wait for next tick.

bool MakeInfoString (string& rString, string symbol, int period, int bar) {
   GetLastError();      // clear error flag
   for (int MaxIterations = 10; MaxIterations > 0; MaxIterations--) {
      datetime bartime = iTime(symbol, period, bar);
      if (GetLastError() == 4066 || bartime <= 0)
         Sleep(2000);
      else {
         if (iBarShift(symbol, period, bartime, true) == bar) { // verify
            // build return string
            string Strline = TimeToStr(bartime, TIME_DATE|TIME_SECONDS);
            Strline = StringSubstr(Strline,0,4) + StringSubstr(Strline,5,2) + StringSubstr(Strline,8,2) + "," + StringSubstr(Strline,11,5);
            Strline = Strline + "," 
                    + DoubleToStr(NormalizeDouble(iOpen(symbol,period, bar),4), 4) + "," 
                    + DoubleToStr(NormalizeDouble(iHigh(symbol,period, bar), 4), 4) + "," 
                    + DoubleToStr(NormalizeDouble(iLow(symbol,period, bar), 4), 4) + "," 
                    + DoubleToStr(NormalizeDouble(iClose(symbol,period, bar), 4), 4) + "," 
                    + DoubleToStr(iVolume(symbol,period, bar), 0);
            rString = Strline;
            return (true);
         }
         else
            continue;
      }
   }
   return (false);
}
 
Thirteen:

First, as WHRoeder has suggested, when using a "i"-function, you get a 4066 error only the first time if the history is in a state of updating, and no error and no data returned in subsequent calls. So you have to test for a 4066 error and whether data has been returned. Second, as both RaptorUK and WHRoeder have said, you aren't waiting long enough between calls. Your code sleeps for 10 ms and your tries variable is set to 100, so (assuming that part of your code works correctly--I'm not sure if it performs as you intended it to work) you are only pausing for 1000 ms, which is only 1 second. Third, you aren't giving the program calling your function any way of really determining whether the function worked correctly or encountered an error.

Below is some example code. MakeInfoString returns a bool, so the calling program can determine whether the function worked properly or encountered an unexpected error. Additionally, it sleeps for upto 20 seconds in 2 second intervals. And when data is returned by iTime(), it verifies that the time returned by iTime() is the time for the specified bar (using iBarShift()). A potentially negative aspect of the code below is the use of sleep in the function itself. Depending on the situation, it may be better to have the calling program determine what to do upon an error (including a 4066 error), whether to sleep for a specified time or simply return out of start() and wait for next tick.



Thanks for the code.

I couldn't get it to work:

int init()
{

                           string line;
                           if( !MakeInfoString(line, "USDJPY" , PERIOD_H1 , 1) ) {
                                int err = GetLastError();
                              Print("MakeInfoString() failed: Error ",err, " -- " ,  ErrorDescription(err) );                      
                        }
                    
                           
                           Print(" line = ", line );



        return(0);
}

OUTPUT:
2013.09.13 20:23:05	testscript USDJPY.,M1: removed
2013.09.13 20:23:05	stdlib USDJPY.,M1: removed
2013.09.13 20:23:05	stdlib USDJPY.,M1: uninit reason 0
2013.09.13 20:23:05	testscript USDJPY.,M1: uninit reason 0
2013.09.13 20:23:05	testscript USDJPY.,M1: deinitialized
2013.09.13 20:23:05	testscript USDJPY.,M1: initialized
2013.09.13 20:23:05	testscript USDJPY.,M1:  line = 
2013.09.13 20:23:05	testscript USDJPY.,M1: MakeInfoString() failed: Error 0 -- no error


 
BenLinus:

I couldn't get it to work:

Works fine for me . . .

int init()
{

   string line;
   if( !MakeInfoString(line, "USDJPY" , PERIOD_H1 , 1) ) {
      int err = GetLastError();
      Print("MakeInfoString() failed: Error ",err, " -- " ,  err );  // removed ErrorDescription() since I don't have the code for it                     
   }
                    
   Print(" line = ", line );



   return(0);
}

MakeInfoTest #1

 
Thirteen:

Works fine for me . . .


did you try bar 2000?
 
BenLinus:

did you try bar 2000?
int init()
{
   string line;
   if( !MakeInfoString(line, "USDJPY" , PERIOD_H1 , 2000) ) {
      int err = GetLastError();
      Print("MakeInfoString() failed: Error ",err, " -- " ,  err );                      
   }
             
   Print(" line = ", line );

   return(0);
}

MakeInfoTest #2

 
Thirteen:


It seems, I forgot to add a period after the symbol name -- my broker has the symbols end with period. After adding periods, it worked for some symbols but not others. So, I tested for all my symbols :

int init()
{
   int Periods[6] = { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_H1, PERIOD_D1, PERIOD_W1}; 
   
   int err;
        string line;
        datetime starttime = TimeCurrent();
        
   int TotalSymbols;
   string SymbolArray[];

        TotalSymbols = StoreSymbols(SymbolArray);

        for(int symbol =0; symbol< TotalSymbols; symbol++) {
           for(int PeriodIndex=0; PeriodIndex<ArraySize(Periods) ; PeriodIndex++ ){
            
               if( IsStopped() ) return(0);
                           
               if( !MakeInfoString(line, SymbolArray[symbol] , Periods[PeriodIndex] , 2000) ){
                     err = GetLastError();
                     Print(SymbolArray[symbol],Periods[PeriodIndex],"MakeInfoString() failed: Error ",err, " -- " ,  ErrorDescription(err) );                     
                }
                    
                           
               Print(SymbolArray[symbol],Periods[PeriodIndex], "bar 2000  = ", line );

           }
        }
   
   Print( "took ", (TimeCurrent()-starttime)/60 , " minutes.");
        return(0);
} 

//Stores the symbols into the givin array and returns the number of symbols
int StoreSymbols(string& SymbolArray[]) 
{
  ...
}

SAMPLE OUTPUT:

2013.09.13 21:51:46     testscript USDJPY.,M1: took 6 minutes.
2013.09.13 21:51:46     testscript USDJPY.,M1: USDRUB.10080bar 2000  = 20050914,00:00,28.3710,28.3810,28.3060,28.3160,234
2013.09.13 21:51:46     testscript USDJPY.,M1: USDRUB.10080MakeInfoString() failed: Error 0 -- no error
2013.09.13 21:51:24     testscript USDJPY.,M1: USDRUB.1440bar 2000  = 20050914,00:00,28.3710,28.3810,28.3060,28.3160,234
2013.09.13 21:51:22     testscript USDJPY.,M1: USDRUB.60bar 2000  = 20130513,00:00,31.3960,31.4210,31.3840,31.4140,83
2013.09.13 21:51:20     testscript USDJPY.,M1: USDRUB.15bar 2000  = 20130808,01:45,33.0020,33.0180,33.0020,33.0180,5
2013.09.13 21:51:17     testscript USDJPY.,M1: USDRUB.5bar 2000  = 20130830,13:45,33.2560,33.2560,33.2460,33.2470,21
2013.09.13 21:51:15     testscript USDJPY.,M1: USDRUB.1bar 2000  = 20130910,20:24,32.9700,32.9710,32.9700,32.9700,3
2013.09.13 21:51:13     testscript USDJPY.,M1: USDJPY.10080bar 2000  = 20060427,00:00,114.8200,115.1000,113.8200,114.1500,9003
2013.09.13 21:51:13     testscript USDJPY.,M1: USDJPY.10080MakeInfoString() failed: Error 0 -- no error
2013.09.13 21:50:51     testscript USDJPY.,M1: USDJPY.1440bar 2000  = 20060427,00:00,114.8200,115.1000,113.8200,114.1500,9003
2013.09.13 21:50:49     testscript USDJPY.,M1: USDJPY.60bar 2000  = 20130520,20:00,102.4400,102.5500,102.2300,102.3400,272
2013.09.13 21:50:47     testscript USDJPY.,M1: USDJPY.15bar 2000  = 20130815,19:00,97.8100,97.8600,97.7400,97.8600,62
2013.09.13 21:50:45     testscript USDJPY.,M1: USDJPY.5bar 2000  = 20130904,13:35,99.5800,99.5800,99.5600,99.5700,10

It always failed for weekly bars. shouldn't the times be same for the same bar 2000 and time frame across different symbols?

took 6 minutes.

Not sure why some symbols didn't work on their own before.


And, when I cut its sleep down to 600 ms, it gave me the same out put but in only 27 seconds. So, does this mean I don't need to sleep full to seconds?

 
BenLinus:

#1: It always failed for weekly bars.

#2 : shouldn't the times be same for the same bar 2000 and time frame across different symbols?

#3: Not sure why some symbols didn't work on their own before.

#4: And, when I cut its sleep down to 600 ms, it gave me the same out put but in only 27 seconds. So, does this mean I don't need to sleep full to seconds?

  1. Yes, I would expect there would be a good possibility that the function would return false for trying to access the 2000th weekly bar. Assuming your broker trades all 52 weeks a year, 2000 divided by 52 is approximately 38.5 years. Does your broker even have weekly history data that goes back 38.5 years for the specified currency pair? There is a very good possibility that it doesn't, so the function returns false.
  2. Not necessarily . . . because some timeframes for a particular currency pair may have missing bars when no ticks were received during that time. If you want to use a synchronized time, then you probably should search for the bar with that time using iBarShift().
  3. Not sure what you mean.
  4. Of course, since the history data has already been downloaded into the Terminal's History Center!! What happens when the data hasn't been downloaded . . . how long will downloading that data take? It can take a several seconds for the data to be downloaded from your broker. Each call to MakeInfoString does not mean that the function will take 20 seconds to retrieve the data; rather, MakeInfoString is designed to take upto 20 seconds in 2 second intervals. If no 4066 error and data is returned from iTime() and the returned data is valid, the function returns immediately after building the return string without sleeping (and probably in less than a second). If the function doesn't need to sleep, it won't.
Also, why are you printing the 'line" variable when MakeInfoString() returns false?

 . . .

if (!MakeInfoString(line, SymbolArray[symbol], Periods[PeriodIndex], 2000)) {
   err = GetLastError();
   Print (SymbolArray[symbol], Periods[PeriodIndex], "MakeInfoString() failed: Error ", err, " -- ",  ErrorDescription(err));                     
}
Print (SymbolArray[symbol], Periods[PeriodIndex], "bar 2000  = ", line);

 . . . 
Reason: