DutchKevv
DutchKevv

Reputation: 1699

Reversed array with MQL4

With MetaTrader Terminal ( MQL4 ), I try to have a reversed array, that I append ( prepend ) items to.

So, on every tick, myArray[0] becomes the 'newest' value, and the previous value shifts to myArray[1] and so on.

But its harder then it sounds.

I tried like this ->

       double myArray        = [];                        // GLOBAL Dynamic array
extern int    maxArrayLength = 50;                        // EXTERN iterable

// -----------------------------------------------------------------------
bool   prependToReversedDoubleArray( double& theArray[], double value, int maxLength ) {

       int size = ArraySize( theArray );                 // LOCAL size
       ArraySetAsSeries(     theArray, false );          // Normalize the array ( left to right )
       ArrayResize(          theArray, size + 1 );       // Extend array length

       Alert( "test = ", size );

       theArray[size] = value;                           // Insert the new value
       ArraySetAsSeries(     theArray, true );           // Reverse the array again
       if ( ArraySize(       theArray ) > maxLength ) {
            ArrayResize(     theArray,    maxLength );
       }
       return( true );
}

prependToReversedDoubleArray( myArray, 0.1234, maxArrayLength );

Upvotes: 2

Views: 2299

Answers (4)

Enivid
Enivid

Reputation: 210

This can be done for optimal performance by creating your own dynamic Array class based on a linked list of pointers. You can define a custom operator [] to access its elements like you do with a normal array. This class can implement a Prepend() method that would be very fast as it would just have to perform a few operations with pointers and just one memory allocation.

However, such a class is not a simple thing to code, so depending on your goals, it might not be the best solution to your case.

Upvotes: 0

DutchKevv
DutchKevv

Reputation: 1699

thanks for all the good intel! I learned a lot from the explanations :)

The problem I had was, how to append values to the 'beginning' of a reversed array ( write to array[0] and shift the rest up ).

It still not non-blocking and probably not the fastest way, but it works for now.

Here is the solution, it also takes a 'maxLength' value, that keeps the array size as desired :) :

int prependToReversedDoubleArray(  double &theArray[],
                                   double  value,
                                   int     maxLength
                                   )
{   int newSize = ArraySize( theArray ) + 1;
    ArraySetAsSeries( theArray, false );     // Normalize the array (left to right)
    ArrayResize(      theArray, newSize );   // Extend array length

    theArray[newSize-1] = value;             // Insert the new value

    ArraySetAsSeries( theArray, true );      // Reverse the array again

    if (  maxLength > 0
       && newSize   > maxLength )            // Check if the max length is reached
    {     newSize   = maxLength;
          ArrayResize( theArray, maxLength );
    }
    return( newSize );
}

Upvotes: 2

user3666197
user3666197

Reputation: 1


Intro:

Fortunately a default MQL4 instrumentation for TimeSeries organisation will not work on this scenario.

Why?

MQL4 TimeSeries ( reversed ) Arrays do get system-driven event-locked cell-index re-shuffling only on a current TimeFrame's aNewBarEVENT, not based on just every anFxQuoteArrivalEVENT ( as was asked in the O/P to shift / update [0] per each tick arrival " ..., on every tick, " ).


How to make it work somehow?

A trivial for(){ shift 'em all / store new} kind of loops, proposed earlier, seems on a first glimpse, as a simple can-do hack.

The danger is a devil is hidden in details.

After some 100.000+ quotes, the array(s) grow to sizes a single memory-page will not hold the whole array + processing times for a dumb cell-shifting grows ( linearly ) in O(1), but to such scales, which start to destroy an ability to be still as fast as being finally able to wait a few ms / us for next FOREX market events' arrival in a non-blocking mode, thus the MetaTrader Terminal inner architecture loses an ability to hold an illusion of a false-synchronicity with external events.

ArrayResize() is another hidden devil out there.

In other words, such code will start "missing" events ( will drop data ( which it will never see on arrival, as still shuffling data in the cell-shifting loop ) ).


How to make it work fast & smart?

0 ) Avoid memory-page swaps - stay In-RAM.

1 ) Avoid any blocking step.

2 ) Avoid a dumb cell-shuffling of any kind - alike value[i] = value[i-1];.

3 ) Avoid any ArrayResize() on the fly.

Solution leads to a proxy in a form of a circular-buffer architecture with a distributed ( the only possible non-blocking help to an MT4 MQL4 code-execution with a rigid, user non-controllable, thread architecture )

This way MQL4 code can contain a lightweight proxy-object ( internally a local, cache-alike managed ring buffer ) which can also seamlessly access literally limitless amounts of cell-data, stored and practically maintained in a remote process / a fast computing grid.

This is both non-blocking (ever) and fast and smart and limitless ( if your algo-trading needs that ) .

Upvotes: 3

user3722096
user3722096

Reputation: 74

for( int i = arraylength - 1; i >= 1; i-- ) {
    value[i] = value[i-1];
    }
value[0] = newValue;

Upvotes: 3

Related Questions