Most efficient way to access values defined for each timeframe?

 

Hi,

I've got different settings associated with each timeframe in MT5 so I set them up in an array like this:

// timeframe specific settings
double timeframe_vars[][3] = {
        {PERIOD_M1, m1_setting_1, m1_setting_2},
        {PERIOD_M2, m2_setting_1, m2_setting_2},
        ...
        {PERIOD_MN1, mn1_setting_1, mn1_setting_2}
        };

...and then the basic way to reach the settings would be to simply search the array like this:

int tf_index = ArrayBsearch(timeframe_vars, _Period);
double tf_setting_1 = timeframe_vars[tf_index][1];
double tf_setting_2 = timeframe_vars[tf_index][2];

But I'm wondering if there's a more efficient way to achieve the same result or a better way to code this that I didn't think of yet...

I know it works like this but I'm always trying to learn how to improve my coding skills so if you have any tips or advice, thanks for letting me know!

*edit*: after tips from R4tna C and Paul Anscombe, I changed the method I use for this from using an array with an ArrayBsearch function to using a switch operator. The results are the same but I think in the backend this method is more efficient, plus it also gives me the option of combining variables of different types. So unless I find a better way to do this, that's the code I'm using right now:

switch(_Period) {
	case PERIOD_M1: setting1 = "setting 1"; setting2 = "setting 2"; break;
	case PERIOD_M2: setting1 = "setting 1"; setting2 = "setting 2"; break;
	case PERIOD_M3: setting1 = "setting 1"; setting2 = "setting 2"; break;
	// etc for all timeframes in MT5 ...
	case PERIOD_MN1: setting1 = "setting 1"; setting2 = "setting 2"; break;
}
 
Jeepack:

Hi,

I've got different settings associated with each timeframe in MT5 so I set them up in an array like this:

...and then the basic way to reach the settings would be to simply search the array like this:

But I'm wondering if there's a more efficient way to achieve the same result or a better way to code this that I didn't think of yet...

I know it works like this but I'm always trying to learn how to improve my coding skills so if you have any tips or advice, thanks for letting me know!

You may want to look at using structures in arrays, especially if you have different types - as it happens I shared an example yesterday: 

https://www.mql5.com/en/forum/428037#comment_40564541

What data type for of MQL5 is good for this?
What data type for of MQL5 is good for this?
  • 2022.07.03
  • www.mql5.com
Hello, I need to store (add, delete, edit) max profit base on ticket numbers for example as below, what data type or library of mql5 can I use...
 
R4tna C #:

You may want to look at using structures in arrays, especially if you have different types - as it happens I shared an example yesterday: 

https://www.mql5.com/en/forum/428037#comment_40564541

Thanks! Good to know in case I can't store all settings as doubles.

I wish I was able to use structures to pair integer values in such a way that would allow me to get the array index for _Period without having to search through an array of 21 items but I don't think that's possible. To give you an example of what I mean lets say you do:

string Timeframe_settings_array[49154]; // to be able to use the monthly timeframe ENUM value of 49153 as the final index
Timeframe_settings_array[PERIOD_M1] = "1 minute timeframe settings";
Timeframe_settings_array[PERIOD_M2] = "2 minute timeframe settings";
// ...
Timeframe_settings_array[PERIOD_D1] = "1 day timeframe settings";
Timeframe_settings_array[PERIOD_W1] = "1 week timeframe settings";
Timeframe_settings_array[PERIOD_MN1] = "1 month timeframe settings";

Then you could access each settings directly without having to search for the index with:

Print(Timeframe_settings_array[_Period]);

Of course having such a large array would be worse than having to search through a list of 21 items to find the timeframe's array index... I'm only giving this example because I'm having trouble finding a way to explain my question.

I wonder if there's a way to do this without having to create an array larger than 21 (21 different timeframes available in MT5). Maybe with structures, but I honestly don't think so...

 
Jeepack #:

Thanks! Good to know in case I can't store all settings as doubles.

I wish I was able to use structures to pair integer values in such a way that would allow me to get the array index for _Period without having to search through an array of 21 items but I don't think that's possible. To give you an example of what I mean lets say you do:

Then you could access each settings directly without having to search for the index with:

Of course having such a large array would be worse than having to search through a list of 21 items to find the timeframe's array index... I'm only giving this example because I'm having trouble finding a way to explain my question.

I wonder if there's a way to do this without having to create an array larger than 21 (21 different timeframes available in MT5). Maybe with structures, but I honestly don't think so...

You sort of can - I do it by building my own index using #define statements:

//1. Struc Constants (to create an index)
#define def_ArraySize                4                              //Array size
#define def_ArrayM1                  0                              //Array loc of M1
#define def_ArrayM5                  1                              //Array loc of M5
#define def_ArrayM15                 2                              //Array loc of M15
#define def_ArrayM30                 3                              //Array loc of M30


//2. Later define the array like so
   Struc_USDShift      USDShiftArray[def_ArraySize]; //Static array contains [M1, M5, M15, M30] 


//3. Later add the data you want:
      USDShiftArray[def_ArrayM1].compute(PERIOD_M1);
      USDShiftArray[def_ArrayM5].compute(PERIOD_M5);
      USDShiftArray[def_ArrayM15].compute(PERIOD_M15);
      USDShiftArray[def_ArrayM30].compute(PERIOD_M30);

//NOTE: compute() is a method of Struc_USDShift which contains the fields you want (in this example shift and lookback seen below)

//4. Then you can do a direct lookup (as well as use loops if you need to process all records)
                           double shiftM1  =   USDShiftArray[def_ArrayM1].shift,
                           int    lookbackM1 =   USDShiftArray[def_ArrayM1].lookback,
PS - don't sort the array - you have to preserve the sequence for it to work
 

And BTW - you can do it with objects too:

#define def_ArraySize                4                              //Array size
#define def_ArrayM1                  0                              //Array loc of M1
#define def_ArrayM5                  1                              //Array loc of M5
#define def_ArrayM15                 2                              //Array loc of M15
#define def_ArrayM30                 3                              //Array loc of M30


class objContainer
  {
public:
                     objContainer(void)
                     {};
                    ~objContainer(void)
                    {};
       int    lookback;
       double shift;

         void Init(ENUM_TIMEFRAMES) 
         {
         //your code
         }
         ;
  };
  

//Later in the code:
    objContainerArray[def_ArrayM1] = new objContainer;
    objContainerArray[def_ArrayM1].Init(PERIOD_M1);
//And so forth...
 
R4tna C #:

You sort of can - I do it by building my own index using #define statements:

PS - don't sort the array - you have to preserve the sequence for it to work

All of this is really interesting stuff, new for me, so I appreciate the tip.

I don't think I can use this if I'm starting with a value that I'm getting from the current chart like "_Period" but I think that's fine though. Now that I think about it, code runs so fast that finding the index with ArrayBsearch(timeframe_vars, _Period) probably doesn't even take a millisecond so I guess trying to go faster is pointless in this particular case. I think that's also how code runs in the backend anyways so even if I could write a direct pathway in the code, it might still take the same amount of time... sort of like a calculator probably computes 5 + 5 + 5 + 5 + 5 the same way as 5 x 5. Don't take my word on this though because I don't know how calculators are programed. Actually, I just looked it up and that would be correct, 5 x 5 would be done as 5 + 5 + 5 + 5 + 5 on the calculator's backend. So I guess the conclusion is that even if I could write a direct pathway from _Period to a defined index, I don't think it would change anything...

 
Jeepack #:

All of this is really interesting stuff, new for me, so I appreciate the tip.

I don't think I can use this if I'm starting with a value that I'm getting from the current chart like "_Period" but I think that's fine though. Now that I think about it, code runs so fast that finding the index with ArrayBsearch(timeframe_vars, _Period) probably doesn't even take a millisecond so I guess trying to go faster is pointless in this particular case. I think that's also how code runs in the backend anyways so even if I could write a direct pathway in the code, it might still take the same amount of time... sort of like a calculator probably computes 5 + 5 + 5 + 5 + 5 the same way as 5 x 5. Don't take my word on this though because I don't know how calculators are programed. Actually, I just looked it up and that would be correct, 5 x 5 would be done as 5 + 5 + 5 + 5 + 5 on the calculator's backend. So I guess the conclusion is that even if I could write a direct pathway from _Period to a defined index, I don't think it would change anything...

Yes these loops would execute so fast it may not be worth the bother, but if you were reading  _Period from the chart and want to do a direct lookup, you just need a switch statement to fetch the right record:

    double shift = 0;
    switch(_Period)
      {
       case  PERIOD_M1:
       shift =  objContainerArray[def_ArrayM1].shift;
         
         break;
       case  PERIOD_M5:
       shift =  objContainerArray[def_ArrayM5].shift;
       //etc etc
      }
 
R4tna C #:

Yes these loops would execute so fast it may not be worth the bother, but if you were reading  _Period from the chart and want to do a direct lookup, you just need a switch statement to fetch the right record:

Makes sense. It's clean and easy to understand.

 
Jeepack #:

All of this is really interesting stuff, new for me, so I appreciate the tip.

I don't think I can use this if I'm starting with a value that I'm getting from the current chart like "_Period" but I think that's fine though. Now that I think about it, code runs so fast that finding the index with ArrayBsearch(timeframe_vars, _Period) probably doesn't even take a millisecond so I guess trying to go faster is pointless in this particular case. I think that's also how code runs in the backend anyways so even if I could write a direct pathway in the code, it might still take the same amount of time... sort of like a calculator probably computes 5 + 5 + 5 + 5 + 5 the same way as 5 x 5. Don't take my word on this though because I don't know how calculators are programed. Actually, I just looked it up and that would be correct, 5 x 5 would be done as 5 + 5 + 5 + 5 + 5 on the calculator's backend. So I guess the conclusion is that even if I could write a direct pathway from _Period to a defined index, I don't think it would change anything...

Don’t search what is effectively a static index use a cross ref function or switch
 
R4tna C #: You sort of can - I do it by building my own index using #define statements:
//1. Struc Constants (to create an index)
#define def_ArraySize                4                              //Array size
#define def_ArrayM1                  0                              //Array loc of M1
#define def_ArrayM5                  1                              //Array loc of M5
#define def_ArrayM15                 2                              //Array loc of M15
#define def_ArrayM30                 3                              //Array loc of M30

Use proper enumerations over #define.

Because the enumerations are not sequential, you can not increment/decrement them to get the next larger/smaller one.
          Why are MT5 ENUM_TIMEFRAMES strange? - General - MQL5 programming forum - Page 2 #11 (2020)

 
William Roeder #:

Use proper enumerations over #define.

Because the enumerations are not sequential, you can not increment/decrement them to get the next larger/smaller one.
          Why are MT5 ENUM_TIMEFRAMES strange? - General - MQL5 programming forum - Page 2 #11 (2020)

Good point - I use enumerations often but in this case #define was sufficient for what I was developing

Reason: