Beginner - Moving data between arrays and using ArraySetAsSeries

 

Please be gentle. I have been through the documentation, and adding or moving data between arrays is not straight forward.


I'm trying to take the open and place all of the values into another array, so I can use ArraySetAsSeries for another function.

void OnStart()
  {
//---
   MqlRates rates[];
   ArraySetAsSeries(rates,true);
   int copied=CopyRates(Symbol(),0,0,100,rates);
   if(copied>0)
     {
      Print("Bars copied: "+copied);
      string format="open = %G, high = %G, low = %G, close = %G, volume = %d";
      string out;
      int size=fmin(copied,10);
      for(int i=0;i<size;i++)
        {
         out=i+":"+TimeToString(rates[i].time);
         out=out+" "+StringFormat(format,
                                  rates[i].open,
                                  rates[i].high,
                                  rates[i].low,
                                  rates[i].close,
                                  rates[i].tick_volume);
         Print(out);
        }
     }
   else Print("Failed to get history data for the symbol ",Symbol());
  }


My code, works if I ArrayPrint, but I cannot add to ArraySetAsSeries:


void OnTick()
{
   MqlRates rates[];
   ArraySetAsSeries(rates,true);
   int copied=CopyRates(Symbol(),0,0,100,rates);
   int newArrSize = ArraySize(rates);
   
   if(copied>0)
   {
      Print("Bars copied: "+copied);

      double OpenArray[], CloseArray[];
      int size=fmin(copied,10);
     
      ArrayResize(OpenArray, newArrSize);
      ArrayResize(CloseArray, newArrSize);
               
      for(int i=0; i<newArrSize; i++)
      {
         OpenArray[i] = rates[i].open;
      }
                 
      for(int i=0; i<newArrSize; i++)
      {
         CloseArray[i] = rates[i].close;
      }

       ArrayPrint(OpenArray);
       ArrayPrint(CloseArray);
        
   }
   else Print("Failed to get history data for the symbol ",Symbol());
}


It's a bit confusing why I cannot just :

ArraySetAsSeries(rates[i].open,true);


I get the error:

'OpenArray' - undeclared identifier


I am trying to move the onCalculate to a EA using onTick instead of using an indicator

https://www.mql5.com/en/docs/array/arraysetasseries




Documentation on MQL5: Array Functions / ArraySetAsSeries
Documentation on MQL5: Array Functions / ArraySetAsSeries
  • www.mql5.com
The function sets the AS_SERIES flag to a selected object of a dynamic array , and elements will be indexed like in timeseries . Parameters array[]...
 
blackbic:


It's a bit confusing why I cannot just :

ArraySetAsSeries(rates[i].open,true);


because ArraySetAsSeries needs to be applied to the whole array not a single element....

 


ArraySetAsSeries(rates,true);
bool  ArraySetAsSeries(     const void&  array[],    // array by reference     bool         flag        // true denotes reverse order of indexing    );
 
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlRates rates[];
   ArraySetAsSeries(rates, true);
   int copied = CopyRates(Symbol(), 0, 0, 5, rates);   // 5 bars are easier for now
   int newArrSize = ArraySize(rates);

   if(copied > 0)
     {
      Print("Bars copied: " + string(copied));

     }
   else
      Print("Failed to get history data for the symbol ", Symbol());

   PrintRatesForwardsAndBackwards(rates);  // calling of the custom function
  }

//+------------------------------------------------------------------+
//| custom function to pass rates[] to                               |
//+------------------------------------------------------------------+
void PrintRatesForwardsAndBackwards(MqlRates &rates_array[]) //passing the rates[] array with reference to the custom function
  {
   Print("\nSeries==true: ");
   for(int i = 0; i < ArraySize(rates_array); i++)
     {
      Print(rates_array[i].close);
     }

   ArraySetAsSeries(rates_array, false);
   Print("\nSeries==false: ");
   for(int i = 0; i < ArraySize(rates_array); i++)
     {
      Print(rates_array[i].close);
     }

   
   Print("\nPrint Rates Array directly: ");  
   ArrayPrint(rates_array);
  }
//+------------------------------------------------------------------+

You can always pass an array by reference to a function and do something with it, MqlRates is no exception. Unfortunately you have to do the ArrayPrint yourself if you can't pass a single array but it is possible to ArrayPrint rates directly.

 
Tobias Johannes Zimmer #:

You can always pass an array by reference to a function and do something with it, MqlRates is no exception. Unfortunately you have to do the ArrayPrint yourself if you can't pass a single array but it is possible to ArrayPrint rates directly.


Thank you for your time and effort! I was able to modify your example and the rest of the code with these changes and get the results I was looking for. Your amazing!
 
blackbic #:

Thank you for your time and effort! I was able to modify your example and the rest of the code with these changes and get the results I was looking for. Your amazing!
You're welcome.
 
blackbic:
void OnTick()
{
   MqlRates rates[];
   ArraySetAsSeries(rates,true);
   int copied=CopyRates(Symbol(),0,0,100,rates);
   int newArrSize = ArraySize(rates);
   
   if(copied>0)
   {
      Print("Bars copied: "+copied);

      double OpenArray[], CloseArray[];
      int size=fmin(copied,10);
     
      ArrayResize(OpenArray, newArrSize);
      ArrayResize(CloseArray, newArrSize);
               
      for(int i=0; i<newArrSize; i++)
      {
         OpenArray[i] = rates[i].open;
      }
                 
      for(int i=0; i<newArrSize; i++)
      {
         CloseArray[i] = rates[i].close;
      }

       ArrayPrint(OpenArray);
       ArrayPrint(CloseArray);
        
   }
   else Print("Failed to get history data for the symbol ",Symbol());
}

You can copy synchronized timeseries to separate arrays with a single CopySeries function call

Forum on trading, automated trading systems and testing trading strategies

New MetaTrader 5 build 3620: Web Terminal improvements, ONNX support and fast matrix multiplications in MQL5

MetaQuotes, 2023.03.03 11:14

  1. MQL5: Added new CopySeries function for copying synchronized timeseries from MqlRates into separate arrays.

    The CopySeries function allows obtaining only the necessary timeseries into different specified arrays during one call, while all of timeseries data will be synchronized. This means that all values in the resulting arrays at a certain index N will belong to the same bar on the specified Symbol/Timeframe pair. Therefore, there is no need for the programmer to additionally synchronize the received timeseries by the bar opening time.

    Unlike CopyRates, which returns the full set of timeseries as an MqlRates array, the CopySeries function allows obtaining specific required timeseries into separate arrays. This can be done by specifying a combination of flags to select the type of timeseries. The order of the arrays passed to the function must match the order of the fields in the MqlRates structure:

    struct MqlRates
      {
       datetime time;         // period beginning time
       double   open;         // open price
       double   high;         // high price for the period
       double   low;          // low price for the period
       double   close;        // close price
       long     tick_volume;  // tick volume
       int      spread;       // spread
       long     real_volume;  // exchange volume
      }

    Thus, if you need to get the values of the 'time', 'close' and 'real_volume' timeseries for the last 100 bars of the current Symbol/Timeframe, you should use the following call:

    datetime  time[];
    double    close[];
    long      volume[];
    CopySeries(NULL,0,0,100,COPY_RATES_TIME|COPY_RATES_CLOSE|COPY_RATES_VOLUME_REAL,time,close,volume);
    

    The order of the arrays "time, close, volume" must match the order of the fields in the MqlRates structure. The order of values in the rates_mask is ignored. The mask could be as follows:

    COPY_RATES_VOLUME_REAL|COPY_RATES_TIME|COPY_RATES_CLOSE

    Example

    //--- input parameters
    input datetime InpDateFrom=D'2022.01.01 00:00:00';
    input datetime InpDateTo  =D'2023.01.01 00:00:00';
    input uint     InpCount   =20;
    //+------------------------------------------------------------------+
    //| Script program start function                                    |
    //+------------------------------------------------------------------+
    void OnStart(void)
      {
    //--- arrays to get timeseries from the Rates structure
       double   open[];
       double   close[];
       float    closef[];
       datetime time1[], time2[];
    //---request close prices to a double array
       ResetLastError();
       int res1=CopySeries(NULL, PERIOD_CURRENT, 0, InpCount,
                           COPY_RATES_TIME|COPY_RATES_CLOSE, time1, close);
       PrintFormat("1. CopySeries  returns %d values. Error code=%d", res1, GetLastError());
       ArrayPrint(close);
       
    
    //--- now also request open prices; use float array for close prices
       ResetLastError();
       int res2=CopySeries(NULL, PERIOD_CURRENT, 0, InpCount,
                           COPY_RATES_TIME|COPY_RATES_CLOSE|COPY_RATES_OPEN, time2, open, closef);
       PrintFormat("2. CopySeries  returns %d values. Error code=%d", res2, GetLastError());
       ArrayPrint(closef);
    //--- compare the received data
       if((res1==res2) && (time1[0]==time2[0]))
         {
          Print("  | Time             |    Open      | Close double | Close float |");
          for(int i=0; i<10; i++)
            {
             PrintFormat("%d | %s |   %.5f    |   %.5f    |   %.5f   |",
                         i, TimeToString(time1[i]), open[i], close[i], closef[i]);
            }
         }
    /*  Result
            1. CopySeries  returns 0 values. Error code=0
            [ 0] 1.06722 1.06733 1.06653 1.06520 1.06573 1.06649 1.06694 1.06675 1.06684 1.06604
            [10] 1.06514 1.06557 1.06456 1.06481 1.06414 1.06394 1.06364 1.06386 1.06239 1.06247
            2. CopySeries  returns 0 values. Error code=0
            [ 0] 1.06722 1.06733 1.06653 1.06520 1.06573 1.06649 1.06694 1.06675 1.06684 1.06604
            [10] 1.06514 1.06557 1.06456 1.06481 1.06414 1.06394 1.06364 1.06386 1.06239 1.06247
              | Time             |    Open      | Close double | Close float |
            0 | 2023.03.01 17:00 |   1.06660    |   1.06722    |   1.06722   |
            1 | 2023.03.01 18:00 |   1.06722    |   1.06733    |   1.06733   |
            2 | 2023.03.01 19:00 |   1.06734    |   1.06653    |   1.06653   |
            3 | 2023.03.01 20:00 |   1.06654    |   1.06520    |   1.06520   |
            4 | 2023.03.01 21:00 |   1.06520    |   1.06573    |   1.06573   |
            5 | 2023.03.01 22:00 |   1.06572    |   1.06649    |   1.06649   |
            6 | 2023.03.01 23:00 |   1.06649    |   1.06694    |   1.06694   |
            7 | 2023.03.02 00:00 |   1.06683    |   1.06675    |   1.06675   |
            8 | 2023.03.02 01:00 |   1.06675    |   1.06684    |   1.06684   |
            9 | 2023.03.02 02:00 |   1.06687    |   1.06604    |   1.06604   |
    */
      }
 
when you set one buffer as series, you will likely want to set the other corresponding buffers as series as well if they have something to do with a plot (or if the data needs to be synchronized with the other buffers)