Download MetaTrader 5

FileWrite - OHLC data and barIndicator (reversing numbering) - SOLVED!

To add comments, please log in or register
humblebee9
30
humblebee9  
Hello,

Working on a very simple array data export to CSV. All is working well, except that the bar indicator [barInd] counting is in reverse to what I would prefer it to be.

So the question - would it be possible to reverse the numbering mechanism? Instead of getting:

barInd   |   Date                 |   Open   |   High   |   Low   |   Close
-----------------------------------------------------------------------------------
358       |   Jan 1, 2015      |   35.1   |   35.5     |   35.0   |   35.2
357       |   Jan 2, 2015      |   36.8   |   37.3     |   35.6   |   36.0
356       |   Jan 3, 2015      |   35.8   |   37.0     |   34.9   |   35.2

I would be getting both barInd and Date in ascending order, not opposing each other, as follows (dates still in the same order, just the barInd is reversed in numbering now): 

barInd   |   Date                 |   Open   |   High   |   Low   |   Close
-----------------------------------------------------------------------------------
356       |   Jan 1, 2015      |   35.1   |   35.5     |   35.0   |   35.2
357       |   Jan 2, 2015      |   36.8   |   37.3     |   35.6   |   36.0
358       |   Jan 3, 2015      |   35.8   |   37.0     |   34.9   |   35.2

Code attached:

//+------------------------------------------------------------------+
//|                                                     DataExport   |
//+------------------------------------------------------------------+
#property strict
#property indicator_separate_window

string file_name = "Data.csv";

int fileh =-1;
int lasterror;

//+------------------------------------------------------------------+

int init()
  {
 
   IndicatorShortName("IndiData");

   fileh = FileOpen(file_name,FILE_CSV|FILE_WRITE,',');
   if(fileh<1)
   {
      lasterror = GetLastError();
      Print("Error updating file: ",lasterror);
      return(false);
   }
  
     // writing file headers below
     
   FileWrite(fileh,
   "barInd",
   "O1",              
   "H1",              
   "L1",              
   "C1"               
   );
      
   return(0);
  
  }

//+------------------------------------------------------------------+

int deinit()

  {
      if(fileh>0)
      {
         FileClose(fileh);
      }
 
  return(0); 
  
  }
 
//+------------------------------------------------------------------+
 
int start()
  {
   int barcount = IndicatorCounted();
   if (barcount<0) return(-1);
   if (barcount>0) barcount--;
  
   int barInd=Bars-barcount-1;
   
      while(barInd>1)
      {
         ExportIndiData(barInd);
         barInd--;
      }     

   return(0);
  
  }
//+------------------------------------------------------------------+

void ExportIndiData(int barInd)
{

  // write data

  FileWrite(fileh,
         barInd,
            Open[barInd],
            High[barInd],
            Low[barInd],
            Close[barInd]              
           );    
}


//+------------------------------------------------------------------+
 
Is what I am seeking even possible? Would the whole start() section need to be rewritten to allow this to happen? I kind of get the feeling this might be tricky since the "barcount--" indicates the order (or direction) how the numbering mechanism works and it is indeed "downward/descending", not "upward/ascending"...

Thanks to anyone caring to answer...
Marco vd Heijden
Moderator
6137
Marco vd Heijden  

Yes just reverse the loop.

Count up in stead of down, or down in stead of up depending on the situation, of course.

humblebee9
30
humblebee9  
Marco vd Heijden:

Yes just reverse the loop.

Count up in stead of down, or down in stead of up depending on the situation, of course.

Thanks Marco. Though as a beginner, I am still struggling with this one... any example you could give, please?
Marco vd Heijden
Moderator
6137
Marco vd Heijden  
Marco vd Heijden:
//+------------------------------------------------------------------+
//|                                                     DataExport   |
//+------------------------------------------------------------------+
#property strict
#property indicator_separate_window

string file_name = "Data.csv";

int fileh =-1;
int lasterror;

//+------------------------------------------------------------------+

int init()
  {

   IndicatorShortName("IndiData");

   fileh = FileOpen(file_name,FILE_CSV|FILE_WRITE,',');
   if(fileh<1)
   {
      lasterror = GetLastError();
      Print("Error updating file: ",lasterror);
      return(false);
   }
  
     // writing file headers below
    
   FileWrite(fileh,
   "barInd",
   "O1",              
   "H1",              
   "L1",              
   "C1"              
   );
      
   return(0);
  
  }

//+------------------------------------------------------------------+

int deinit()

  {
      if(fileh>0)
      {
         FileClose(fileh);
      }

  return(0);
  
  }

//+------------------------------------------------------------------+

int start()
  {
   int barcount = IndicatorCounted();
   if (barcount<0) return(-1);
   if (barcount>0) barcount--;
  
   int barInd=1;
  
      while(barInd<Bars-barcount-1)
      {
         ExportIndiData(barInd);
         barInd++;
      }    

   return(0);
  
  }
//+------------------------------------------------------------------+

void ExportIndiData(int barInd)
{

  // write data

  FileWrite(fileh,
         barInd,
            Open[barInd],
            High[barInd],
            Low[barInd],
            Close[barInd]              
           );    
}


//+------------------------------------------------------------------+
Maybe this but it may need some tweaking with the part just above the loop too...
humblebee9
30
humblebee9  
Marco vd Heijden:
Maybe this but it may need some tweaking with the part just above the loop too...
Yap. that did it. Thanks a ton for such quick help, Marco!!
Marco vd Heijden
Moderator
6137
Marco vd Heijden  

Don't forget to make sure that that values are actually correct.

In some cases you might find the numbering is correct but the data can still be wrong.

Always verify.

humblebee9
30
humblebee9  
Marco vd Heijden:

Don't forget to make sure that that values are actually correct.

In some cases you might find the numbering is correct but the data can still be wrong.

Always verify.

Aah.. my bad... meaning I still don't have what I need...  after adding the date column to it I've just realized the current solution gives the barCount digits in ascending order, however, the dates are now in reverse (descending order) . is there a way to have both in ascending order together??
honest_knave
Moderator
2342
honest_knave  
humblebee9:
Thanks Marco. Though as a beginner, I am still struggling with this one... any example you could give, please?

In addition to Marco's great advice, if you are starting out may I suggest you adopt the new event handling functions?

Your general structure would look like this:

#property strict
#property indicator_chart_window

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  
  }

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
  
   return(rates_total);
  }

 

There is also an excellent post by whroeder1 which will show you how to do your lookbacks correctly. It also explains a little bit about ArraySetAsSeries, which may be useful for your problem.

 

Forum on trading, automated trading systems and testing trading strategies

Range not behaving as expected

whroeder1, 2016.05.11 18:55

First define your maximum lookback.
int lookback = ... // iMA(period) has look back of period.
                        // buffer[i+2] has look back of 2 (as TimeSeries)
                        // buffer[i-2] has look back of 2 (not TimeSeries)
                       // use maximum of all.
int lookback = ... // iMA(period) has look back of period.
                   // buffer[i+2] has look back of 2 (as TimeSeries)
                   // buffer[i-2] has look back of 2 (not TimeSeries)
                   // use maximum of all.
Old way, counting down as a TimeSeries
   int counted = IndicatorCounted();
   for(int iBar = Bars - 1 - MathMax(lookback, counted); iBar >= 0; --iBar){
      // Timeseries and Indicators Access uses index=iBar
   }
New way, counting down as a TimeSeries (Bars always equals rates_total so can be substituted.)
   for(int iBar = Bars-1-MathMax(lookback, prev_calculated); iBar >= 0; --iBar){
      // Timeseries and Indicators Access uses index=iBar
      https://docs.mql4.com/series
   }
   return rates_total-1; // Recalculate current bar next tick.

Returning rates_total-1 makes prev_calculated the same as IndicatorCounted().

Alternatively if you return rates_total then must decrement prev_calculated if non-zero at the beginning of On_Calculate to recalculate the current bar.

Always count down so you're not using future values.

New way, counting up, not a TimeSeries.
   set all accessed arrays and buffers to ArraySetAsSeries(false) Not the Predefined Variables

   for(int iBar = MathMax(lookback, prev_calculated; iBar < Bars; ++iBar){
      // To access a Timeseries use index=Bars -1- iBar
      // and convert any results back index=Bars -1- result
   }
   return rates_total-1; // Recalculate current bar next tick.
Always count up so you're not using future values.

Forum on trading, automated trading systems and testing trading strategies

Range not behaving as expected

whroeder1, 2016.07.28 15:25

New way, counting down as a TimeSeries, but not through bar zero.
   #define LAST 1
   for(int iBar = Bars-1-MathMax(lookback, prev_calculated); iBar >= LAST; --iBar){
      :
   }
   return rates_total-MathMax(1,LAST); // Recalculate Bar LAST once on new bar.
This can be used to not cover newest bars, or can be used to update the indicator in steps, e.g. 1000-900, 899-799, ... 99-0, 0...

Event Handling Functions - Functions - Language Basics - MQL4 Reference
Event Handling Functions - Functions - Language Basics - MQL4 Reference
  • docs.mql4.com
Event Handling Functions - Functions - Language Basics - MQL4 Reference
Marco vd Heijden
Moderator
6137
Marco vd Heijden  

And thats why i never really worry about those issues they are not really related to the end target.

Maybe this ?

//+------------------------------------------------------------------+
//|                                                     DataExport   |
//+------------------------------------------------------------------+
#property strict
#property indicator_separate_window

string file_name = "Data.csv";

int fileh =-1;
int lasterror;

//+------------------------------------------------------------------+

int init()
  {

   IndicatorShortName("IndiData");

   fileh = FileOpen(file_name,FILE_CSV|FILE_WRITE,',');
   if(fileh<1)
   {
      lasterror = GetLastError();
      Print("Error updating file: ",lasterror);
      return(false);
   }
  
     // writing file headers below
    
   FileWrite(fileh,
   "barInd",
   "O1",              
   "H1",              
   "L1",              
   "C1"              
   );
      
   return(0);
  
  }

//+------------------------------------------------------------------+

int deinit()

  {
      if(fileh>0)
      {
         FileClose(fileh);
      }

  return(0);
  
  }

//+------------------------------------------------------------------+

int start()
  {
   int barcount = 0;
   if (barcount>IndicatorCounted()) return(-1);
   if (barcount<IndicatorCounted()) barcount++;
  
   int barInd=1;
  
      while(barInd<Bars-barcount-1)
      {
         ExportIndiData(barInd);
         barInd++;
      }    

   return(0);
  
  }
//+------------------------------------------------------------------+

void ExportIndiData(int barInd)
{

  // write data

  FileWrite(fileh,
         barInd,
            Open[barInd],
            High[barInd],
            Low[barInd],
            Close[barInd]              
           );    
}


//+------------------------------------------------------------------+
I didn't try it though.
humblebee9
30
humblebee9  
Thank you very much for your thoughtful answers so far!! However, no luck still. 

I recognize it may be my mistake perhaps I did not do a good job explaining before. So giving it another try:

Current setup I have:
BarInd (Descending! NOT OK!)  |   Date  (Ascending! OK!)        |   Open   |   High   |   Low   |   Close
-----------------------------------------------------------------------------------------------------------------------
                     3                        |             Jan 1, 2015             |   35.1   |   35.5     |   35.0   |   35.2     
                     2                        |             Jan 2, 2015             |   36.8   |   37.3     |   35.6   |   36.0
                     1                        |             Jan 3, 2015             |   35.8   |   37.0     |   34.9   |   35.2


What all solutions offered provide so far:
barInd  (Ascending! OK!)         |   Date (Descending! NOT OK!)  |   Open   |   High   |   Low   |   Close
------------------------------------------------------------------------------------------------------------------------
                   1                         |               Jan 3, 2015                |   35.8   |   37.0     |   34.9   |   35.2
                   2                         |               Jan 2, 2015                |   36.8   |   37.3     |   35.6   |   36.0 
                   3                         |               Jan 1, 2015                |   35.1   |   35.5     |   35.0   |   35.2


What I would like the end result to be:
barInd  (Ascending! OK!)         |   Date (Ascending! OK!)           |   Open   |   High   |   Low   |   Close
------------------------------------------------------------------------------------------------------------------------
                  1                          |             Jan 1, 2015               |   35.1   |   35.5     |   35.0   |   35.2
                  2                          |             Jan 2, 2015               |   36.8   |   37.3     |   35.6   |   36.0 
                  3                          |             Jan 3, 2015               |   35.8   |   37.0     |   34.9   |   35.2

Attaching again the base script, this time also Date column attached to help visualize better.

Very grateful again for further help.



//+------------------------------------------------------------------+
//|                                                     DataExport   |
//+------------------------------------------------------------------+
#property strict
#property indicator_separate_window

string file_name = "Data.csv";

int fileh =-1;
int lasterror;

//+------------------------------------------------------------------+

int init()
  {

   IndicatorShortName("IndiData");

   fileh = FileOpen(file_name,FILE_CSV|FILE_WRITE,',');
   if(fileh<1)
   {
      lasterror = GetLastError();
      Print("Error updating file: ",lasterror);
      return(false);
   }
  
     // writing file headers below
    
   FileWrite(fileh,
   "barId",
   "Date",
   "O1",              
   "H1",              
   "L1",              
   "C1"              
   );
      
   return(0);
  
  }

//+------------------------------------------------------------------+

int deinit()

  {
      if(fileh>0)
      {
         FileClose(fileh);
      }

  return(0);
  
  }

//+------------------------------------------------------------------+

int start()
  {
   int barcount = IndicatorCounted();
   if (barcount<0) return(-1);
   if (barcount>0) barcount--;
  
   int barInd=Bars-barcount-1;
  
      while(barInd>1)
      {
         ExportIndiData(barInd);
         barInd--;
      }    

   return(0);
  
  }
//+------------------------------------------------------------------+

void ExportIndiData(int barInd)
{

   datetime t = Time[barInd];
  
      string bar_datetime =  
      StringConcatenate(TimeYear(t)+"-"+
                        TimeMonth(t)+"-"+
                        TimeDay(t)+" "+
                        TimeHour(t)+":"+
                        TimeMinute(t)+":"+
                        TimeSeconds(t));
  
  
  // write data

  FileWrite(fileh,
            barInd,
                        bar_datetime,
            Open[barInd],
            High[barInd],
            Low[barInd],
            Close[barInd]              
           );    
}


//+------------------------------------------------------------------+

Files:
whroeder1
17050
whroeder1  
humblebee9:
Current setup I have:
BarInd (Descending!)  |   Date  (Ascending!)      |   Open   |   High   |   Low   |   Close

What all solutions offered provide so far:
barInd  (Ascending!)  |   Date (Descending!)  |   Open   |   High   |   Low   |   Close

What I would like the end result to be:
barInd  (Ascending!)  |   Date (Ascending!)  |   Open   |   High   |   Low   |   Close
  1. You original post and last was counting down. That is Descending/ascending.
  2. Post #3 was counting up. That is Ascending/Descending.
  3. Count down and in your FileWrite change your barInd [Bars-1, Bars-2, .. 1] to Bars - barInd [1, 2, .. Bars-1.]
12
To add comments, please log in or register