problem with passing struct arrays - page 2

 
Dominik Egert #:
To solve your problem: Define the struct on global space, outside the function. Then declare the array also outside the function.

thank you very much for the good advice. definitely worth it.

Finally, I would like to ask that if the struct array[] is still somewhere inside the function, how can it be accessed or not?

 
titaanlabidas #:

thank you very much for the good advice. definitely worth it.

Finally, I would like to ask that if the struct array[] is still somewhere inside the function, how can it be accessed or not?

There is something called "scope-operator", {}.

This determines the "scope" or visibility of a language "statement", like a variable or function.

You cannot move a declaration outside this scope by another operator, but you can gain access to a different scope using "::" as a scope naming operator.

Scopes are organized in a tree like manor, you can access scopes higher up in the hierarchy or side by side hierarchy using "::" as scope resolution operator.

I suggest reading about namespaces, and understanding the concept of also nested namespaces, as this gives the best insights to how this all works.

There is more to it than I have covered here, like where in memory is the data stored and such.

In short: if you declare/define a struct in a certain scope, it will be only accessible in this scope. A functions scope is only valid while the function is executing. A namespace is on global scope, so always valid.
 
Dominik Egert #:
nnot move a declaration outside this scope by another operator, but you can gain access to a different scope using "::" as a scope naming operator.

I was in a hurry to quickly delete the question but You was faster. this was a quickly written and very stupid question on my part. sorry. I already got works and get access nicely. data can be accessed same way as usual. Here it wasn´t about accessing data from another class, but a normal scope problem indeed, this recent learning of OOP has turned my brain into ultimate mess. Just a little while ago o tried to do the same thing with a  class that´s why it crashed in my head. I initially decided to simply put the data in a structure so that they would be in a separate room and better arranged. If I already wrote in the topic here I will show how I solved this situation, so if that something is very wrongly made you can hang me :D   Anyway thanks again !

struct TS_Struct_Data
{
    datetime t[];
    double   c[];
    double   h[];
    double   l[];
};

void fill_ts_struct(int bars, int &count, const ENUM_TIMEFRAMES cycle, TS_Struct_Data &ts) 
{
    
    TS_Struct_Data TS_Struct_arr[]; 
     
    if (ArraySize(TS_Struct_arr) < bars)
    {
        ArrayResize(TS_Struct_arr, bars);
        ArrayResize(ts.t, bars);
        ArrayResize(ts.c, bars);
        ArrayResize(ts.h, bars);
        ArrayResize(ts.l, bars);
        for (int i = bars - 1; i >= 0; i--) { ts.t[i] = iTime (NULL, cycle, bars - i); }        
        for (int i = bars - 1; i >= 0; i--) { ts.c[i] = iClose(NULL, cycle, bars - i); }
        for (int i = bars - 1; i >= 0; i--) { ts.h[i] = iHigh (NULL, cycle, bars - i); }
        for (int i = bars - 1; i >= 0; i--) { ts.l[i] = iLow  (NULL, cycle, bars - i); } 
        count = bars;
    }
    else
    {
        ArrayResize(TS_Struct_arr, count);
        ArrayResize(ts.t, count);
        ArrayResize(ts.c, count);
        ArrayResize(ts.h, count);
        ArrayResize(ts.l, count);
        ts.t[count - 1] = iTime (NULL, cycle, 1);        
        ts.c[count - 1] = iClose(NULL, cycle, 1);
        ts.h[count - 1] = iHigh (NULL, cycle, 1);
        ts.l[count - 1] = iLow  (NULL, cycle, 1);
    }
}
TS_Struct_Data tsa;
void OnTick(){

if (process_M1.G_Execute_now()){
        fill_ts_struct(lookback,ts_count,execution_cycle_1,tsa);
        ts_count++;
        for(int i=0;i<ArraySize(tsa.c);i++){Print("array index [",i, "] value is: ",tsa.c[i]);}
        for(int i=0;i<ArraySize(tsa.t);i++){Print("array index [",i, "] value is: ",tsa.t[i]);}
}
 
titaanlabidas #:

I was in a hurry to quickly delete the question but You was faster. this was a quickly written and very stupid question on my part. sorry. I already got works and get access nicely. data can be accessed same way as usual. Here it wasn´t about accessing data from another class, but a normal scope problem indeed, this recent learning of OOP has turned my brain into ultimate mess. Just a little while ago o tried to do the same thing with a  class that´s why it crashed in my head. I initially decided to simply put the data in a structure so that they would be in a separate room and better arranged. If I already wrote in the topic here I will show how I solved this situation, so if that something is very wrongly made you can hang me :D   Anyway thanks again !

don´t hang me yet, went wrong in a hurry again....now it should be written in proper handwriting, often used arrays are not directly global ,but are accessible from everywhere. : I couldn´t do better :D 

struct TS_Struct_Data
{
    datetime t[];
    double   c[];
    double   h[];
    double   l[];
};

void fill_ts_struct(int bars, int &count, const ENUM_TIMEFRAMES cycle, TS_Struct_Data &ts) 
{
     
    if (ArraySize(ts.t) < bars)
    {
        ArrayResize(ts.t, bars);
        ArrayResize(ts.c, bars);
        ArrayResize(ts.h, bars);
        ArrayResize(ts.l, bars);
        for (int i = bars - 1; i >= 0; i--) { ts.t[i] = iTime (NULL, cycle, bars - i); }        
        for (int i = bars - 1; i >= 0; i--) { ts.c[i] = iClose(NULL, cycle, bars - i); }
        for (int i = bars - 1; i >= 0; i--) { ts.h[i] = iHigh (NULL, cycle, bars - i); }
        for (int i = bars - 1; i >= 0; i--) { ts.l[i] = iLow  (NULL, cycle, bars - i); } 
        count = bars;
    }
    else
    {
        ArrayResize(ts.t, count);
        ArrayResize(ts.c, count);
        ArrayResize(ts.h, count);
        ArrayResize(ts.l, count);
        ts.t[count - 1] = iTime (NULL, cycle, 1);        
        ts.c[count - 1] = iClose(NULL, cycle, 1);
        ts.h[count - 1] = iHigh (NULL, cycle, 1);
        ts.l[count - 1] = iLow  (NULL, cycle, 1);
    }
}

now it is the case that my data can be accessed like this ts.c[0] but mqlrates data are accessible like this ts[0].c  

I understand that the mqlrates data is in inside the additional array that holds the index, but the elements must still exist inside separate arrays ? Or am i wrong? would it be better if i try to put the data as they are after mqlrates and copyrates ? It would require making an additional array, does it make any sense ? I just want to do things 100% properly....

 
titaanlabidas #:

don´t hang me yet, went wrong in a hurry again....now it should be written in proper handwriting, often used arrays are not directly global ,but are accessible from everywhere. : I couldn´t do better :D 

now it is the case that my data can be accessed like this ts.c[0] but mqlrates data are accessible like this ts[0].c  

I understand that the mqlrates data is in inside the additional array that holds the index, but the elements must still exist inside separate arrays ? Or am i wrong? would it be better if i try to put the data as they are after mqlrates and copyrates ? It would require making an additional array, does it make any sense ? I just want to do things 100% properly....

There is no propper way to do it, because it depends on the situation.

MqlRates places data in order of the struct into memory:

struct MqlRates
  {
   datetime time;         // Period start time
   double   open;         // Open price
   double   high;         // The highest price of the period
   double   low;          // The lowest price of the period
   double   close;        // Close price
   long     tick_volume;  // Tick volume
   int      spread;       // Spread
   long     real_volume;  // Trade volume
  };

Improperly formatted code edited by moderator.

Depending on your access pattern to the data, it can be more efficient to have the data organized like that. In case you access open high low close and then move on to the next "set" of data.

Contrary to that, if you pan through all close values, and then all high values in separate loops, you might want to have your data organized as arrays of close values and separate from that array of open values.... - This will make data be most compact in memory, in terms of processing order, and therefore support your CPU caching to be more efficient.

There is no "one fits all" solution, as it depends on the usage of the data.
 
Dominik Egert #:

There is no propper way to do it, because it depends on the situation.

MqlRates places data in order of the struct into memory:

Improperly formatted code edited by moderator.

Depending on your access pattern to the data, it can be more efficient to have the data organized like that. In case you access open high low close and then move on to the next "set" of data.

Contrary to that, if you pan through all close values, and then all high values in separate loops, you might want to have your data organized as arrays of close values and separate from that array of open values.... - This will make data be most compact in memory, in terms of processing order, and therefore support your CPU caching to be more efficient.

There is no "one fits all" solution, as it depends on the usage of the data.

thanks for referral. After this information, i thought that i would start measuring the difference in performance speed but then i luckily decided to read more about this topic first. It was all new to me and i guess i couldn´t read it with that look before as i had no direct contact with this subject and to me seemed everything like one big struct :D.  Now with surprise it turned out that there is a lot of talk about it and there is a lot of information available about this topic and the results of the performance measurements also. Depending on the cases that confirm until 2-3 times differences in speed and the main speed advantage is related to the cache. Without going into deep i´ll share a quick summary about the topic. Since i didn´t know it myself, maybe someone else is also interested.

 this topic was discussed two primary types of structures.  SoA(Struct of Array) and AoS(Array of Struct). There is more like AoSoA, SoP, Padded AoS and maybe more but they are not discussed at the moment.

AoS is better choice : less load data pet time. process one or few struct  at a time. May lead to better cache utilization if data is accessed randomly.

SoA is better choice : heavy load data per time. If you have you process a bunch of structs at a time. especially vectorized processes. Keep memory access contiguous if access over structure instances. 

struct {
    uint8_t r, g, b;
} AoS[N];

struct {
    uint8_t r[N];
    uint8_t g[N];
    uint8_t b[N];
} SoA;

I guess it went well this time and SoA was right choice. because in my case the close, high, low and time arrays receive quite a lot loads in parallel all the time until ea works. 

and again... if I explained something very wrong, you can shoot me :D
 

 
titaanlabidas #:

thanks for referral. After this information, i thought that i would start measuring the difference in performance speed but then i luckily decided to read more about this topic first. It was all new to me and i guess i couldn´t read it with that look before as i had no direct contact with this subject and to me seemed everything like one big struct :D.  Now with surprise it turned out that there is a lot of talk about it and there is a lot of information available about this topic and the results of the performance measurements also. Depending on the cases that confirm until 2-3 times differences in speed and the main speed advantage is related to the cache. Without going into deep i´ll share a quick summary about the topic. Since i didn´t know it myself, maybe someone else is also interested.

 this topic was discussed two primary types of structures.  SoA(Struct of Array) and AoS(Array of Struct). There is more like AoSoA, SoP, Padded AoS and maybe more but they are not discussed at the moment.

AoS is better choice : less load data pet time. process one or few struct  at a time. May lead to better cache utilization if data is accessed randomly.

SoA is better choice : heavy load data per time. If you have you process a bunch of structs at a time. especially vectorized processes. Keep memory access contiguous if access over structure instances. 

I guess it went well this time and SoA was right choice. because in my case the close, high, low and time arrays receive quite a lot loads in parallel all the time until ea works. 

and again... if I explained something very wrong, you can shoot me :D
 

Brief, but accurate.

There is a keyword you might want to look into. "pack".

You can apply it to objects.
Reason: