ArrayResize() question

To add comments, please log in or register
gatornuke
355
gatornuke  

If i resize an array which already contains data, will this erase all data or just add an extra slot?

i.e., is

ArrayResize({1,1,1},4) = {1,1,1,NULL}?

Nikolay Panev
1174
Nikolay Panev  
gatornuke:

If i resize an array which already contains data, will this erase all data or just add an extra slot?

i.e., is

ArrayResize({1,1,1},4) = {1,1,1,NULL}?

It won't erase the existing data.
gatornuke
355
gatornuke  

Ok, Good. Thanks.

Phillip
803
Phillip  

likewise if you resize an existing array to become a smaller array it merely truncates (deletes) the data that existed in the elements that will no longer exist in the new array

ArrayResize({1,1,1},2)={1,1}

gatornuke
355
gatornuke  

i see...

William Roeder
20208
William Roeder  
You can get {3,2,1,null} or {null,1,2,3} Article: Effective usage of Arrays in MQL
    ArraySetAsSeries(mem, true);        // Shift values m[2]=m[1]; m[1]=m[0]
    int firstBar=ArrayResize(mem, size+1)-1;    if (firstBar < 0){      Alert(
        "ArrayResize failed: ",GetLastError());                         return;}
    ArraySetAsSeries(mem, false);     
 mem[0]=...
...
    ArrayResize(mem, maxBar+1); // Drop firstBar..(maxBar+1)
john
213
john  
WHRoeder:
You can get {3,2,1,null} or {null,1,2,3} Article: Effective usage of Arrays in MQL

With ArrayResize() an incremental element/index is added on a recurring basis, it would have to (I presume) select memory from non contiguous locations each time wouldn't it? A 500,000 element array could then have fragmented addresses between virutually all of it's elements, and leads me to a question. Initializing a large Array size would (presumably) select memory with contiguous addresses, so..


Is one way better than the other as far a processing time, when calculations are made from the arrays.

Contiguous addresses versus non-contiguous addresses? Is one slower and less efficient than the other, in performing calculations?

Thanks

William Roeder
20208
William Roeder  

Most implementations will allocate additional space so subsequent allocations will be simple (amortizing the reallocation costs.) When actual memory needs to be allocated usually the data will be copied to the new allocated location and the old released, thus keeping the array contiguous.

Which is better depends on the application. Which mt4 uses is anybodies guess. I believe (based only on my hunch and the measured fact that array reference takes a measured 10x vs variable access,) that mt4 uses a Deque (STL) not a contiguous array.

john
213
john  

Okay Thanks. So far I have 6. Each is pre-set for 500k 1 dim index size.

I see many others that use ArrayResize to "grow" an array. I thought that could be an overuse of ArraySize intention, and that "growing" an array (my term) was actually not an array, but a Vector?

I wanted to use it too, but didn't know if it should be done as the primary method of sizing. Especially if it would burden my calculation times. Sounds like I could try ArrayResize, and incrementally scale them.

Most of my calculations will be done inside Deinit() for data profiling, so I don't care how slow they run. But some, like correlation coefficient will be run live on every bar or two .

thanks


William Roeder
20208
William Roeder  
New in Build 600+ Using the third argument to ArrayResize - MQL4 Documentation allows preallocation of memory.
J.P.Satrio
18
J.P.Satrio  
#property indicator_separate_window

static int     index = 0;

datetime       timestamp [];

// --- Function for truncating out of date array elements --- //

void Truncate ()

   {

      if ( index == 0 )
      
         {

            Alert ( "Truncate function called with index value of 0." );

         }

      else if ( index == 1 )

         {

            if ( ( TimeCurrent () - timestamp [0] ) > 5 )

               {

                  ArrayResize ( timestamp, 0 );

                  index --;

                  Alert ( "Truncate function called with index value of 1." );

               }


         }

      else if ( index > 1 )

         for ( int count = 2; count <= index; count ++ )

            {

               if ( ( TimeCurrent () - timestamp [count] ) > 5 )

                  {

                     ArrayCopy ( timestamp, timestamp, 0, 1, WHOLE_ARRAY );

                     ArrayResize ( timestamp, index - 1 );

                  
                     index --;

                     Alert ( "Truncate function called, arrays shrinked." );

                  }

            }

   }

// --- Function for expanding dynamic array --- //

void ArrayExpansion ()

   {

      ArrayResize ( timestamp, ArraySize ( timestamp ) + 1 );

   }

// --- Initialization --- //

int OnInit ()

   {

      EventSetTimer ( 1 );

      IndicatorDigits ( Digits + 1 );

      return ( INIT_SUCCEEDED );

   }

// --- Timed events --- //

void OnTimer ()

   {

      // --- Truncating out of date array elements ---

      Truncate();

   }

// --- Tick based events --- //

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[]

   )

   {


         // --- Calling of ArrayExpansion function ---

         ArrayExpansion();


         // -------------------------------- //



         timestamp [index] = TimeCurrent (); // Attaching timestamp to the data

         // ---
         index ++; // Increasing index value

         // --- Calling of Truncate function ---

         Truncate();



      return (rates_total);

   }

Hey, this is the project im working on these days. I'd like to use a dynamic array to attach timestamp to other dynamic arrays with the same index and size. I want to be as effiecient as possible, so I only want to use as many array elements as neccessary, no more, no less. I think the problem is with either the if index... section, or with the time comparison section. Logically I think I'm correct. Could some1 pls help me out?


EDIT: missing info: I intended to create a 5s data window, thats why the code was written. The flow of control, as you can see, first creates a new block in the dynamic array, to home a timestamp record, and the index value is increased by 1 afterwards. Then, on every tick and every second, the Truncate function should take care of the out of date blocks, by shifting the data to the left, then shrinking the array by 1. BUT as soon as the index gets the value of 1, the script crashes. I suspect that it's because of the if statement, it's like it would compare TimeCurrent with a non-existing record. But by the time the index is 1, timestamp [0] should already hold a value. So I can't tell why it keeps crashing. I know that there is a logical error with the if statement which comes after this one also ( because it can face a situation when the index is greater than 1, and more if not all the data got out of date at the same time ), but I can take care of that at a later time. And I'm not shure if the statement ArrayResize ( timestamp, 0 ) is valid or not, so it frees the array completely, parenting no elements. Ideas?

To add comments, please log in or register