2

I am trying to create a one standard deviation upper and lower band on an array called ATREx. The first while loop below creates the array ATREx. I believe this section is correctly coded.

However, the second while loop which is used to create the upper and lower band on the ATREx array doesn't seem to give the right result.

Any idea what am I missing?

Counted_bars=IndicatorCounted();
i=Bars-Counted_bars-1;
while(i>0)
{
    Moving_Average_Close=iMA(NULL,0,40,0,MODE_EMA,PRICE_CLOSE,i);
    Moving_Average_Low=iMA(NULL,0,40,0,MODE_EMA,PRICE_LOW,i);
    Moving_Average_High=iMA(NULL,0,40,0,MODE_EMA,PRICE_HIGH,i);
    ATR=iATR(NULL,0,14,i);

    if(close[i]<Moving_Average_Close)
    {
        ATREx[i]=(((low[i]-Moving_Average_Low)/close[i])*100)*((ATR/close[i])*100);
        //ATREx_200[i]=(((low[i]-Moving_Average_Low_200)/close[i])*100)*((ATR/close[i])*100);
    }
    else
        ATREx[i]=(((high[i]-Moving_Average_High)/close[i])*100)*((ATR/close[i])*100);

        i--;
}

j=Bars-Counted_bars-1;

while (j>0)
{
    ATREx_Upper[j]=iMAOnArray(ATREx,0,40,0,MODE_EMA,j)+iStdDevOnArray(ATREx,0,200,0,MODE_EMA,j);
    ATREx_Lower[j]=iMAOnArray(ATREx,0,40,0,MODE_EMA,j)-iStdDevOnArray(ATREx,0,200,0,MODE_EMA,j);
    j--;
}
Jonas
  • 6,915
  • 8
  • 35
  • 53
chweet
  • 35
  • 1
  • 7

1 Answers1

0

Obey the calling-signatures:

The { iMAOnArray | iStdDevOnArray() | ... } indicator is calculated from left to right. To access to the array elements as to a series array (i.e., from right to left), one has to use the ArraySetAsSeries() function.

double  iMAOnArray(     double array[],   // array with data <--------------
                        int    total,     // number of elements <-----------
                        int    ma_period, // MA averaging period
                        int    ma_shift,  // MA shift
                        int    ma_method, // MA averaging method
                        int    shift      // shift
                        )

double  iStdDevOnArray( double array[],   // array with data <--------------
                        int    total,     // number of elements <-----------
                        int    ma_period, // MA averaging period
                        int    ma_shift,  // MA shift
                        int    ma_method, // MA averaging method
                        int    shift      // shift
                        )

The second section was extremely low-performing:

MT4 Terminal is known for having a one central bottleneck. The all-graphs' shared solo-thread for each CustomIndicator instance. So be many times more careful inside the CustomIndicator code:

Counted_bars = IndicatorCounted();
       i     = Bars -   Counted_bars - 1;
while( i >  0 )
{      Moving_Average_Close = iMA(  _Symbol, PERIOD_CURRENT, 40, 0, MODE_EMA, PRICE_CLOSE, i );
       Moving_Average_Low   = iMA(  _Symbol, PERIOD_CURRENT, 40, 0, MODE_EMA, PRICE_LOW,   i );
       Moving_Average_High  = iMA(  _Symbol, PERIOD_CURRENT, 40, 0, MODE_EMA, PRICE_HIGH,  i );
       ATR                  = iATR( _Symbol, PERIOD_CURRENT, 14, i );

       if (  close[i] < Moving_Average_Close )
       {     ATREx[i] = ( ( (  low[i] - Moving_Average_Low     ) / close[i] ) * 100 ) * ( ( ATR / close[i] ) * 100 );
      // ATREx_200[i] = ( ( (  low[i] - Moving_Average_Low_200 ) / close[i] ) * 100 ) * ( ( ATR / close[i] ) * 100 );
       }
       else  ATREx[i] = ( ( ( high[i] - Moving_Average_High    ) / close[i] ) * 100 ) * ( ( ATR / close[i] ) * 100 );
       i--;
       }

       int    nBARs   = 40;  //              //?40  vvv                     // NEVER LEAVE ANY FULL-DEPTH PROCESSING aFeasibleDEPTH WILL SUITE ENOUGH
       double aCPY[];                        // ||
       ArraySetAsSeries();                   // ||
                                             // ||
       j  = Bars - Counted_bars - 1;         // ||
while( j >  0 )                              // ||   ?40                    // OUGHT BE 40?
{      ArrayCopy( aCPY, ATREx, 0, j, nBARs );// vv   vvv
       double aStDev  = iStdDevOnArray( aCPY, nBARs, 200, 0, MODE_EMA, 0 ), // NEVER LEAVE ANY  EXTENSIVE PROCESSING PIECE OF CODE IN INDICATOR (a blocking solo-thread for *ALL* MT4.Graphs !!! )
              aMeanL  = iMAOnArray(     aCPY, nBARs,  40, 0, MODE_EMA, 0 ); // NEVER LEAVE ANY  EXTENSIVE PROCESSING PIECE OF CODE IN INDICATOR ( a blocking solo-thread for *ALL* MT4.Graphs !!! )

       ATREx_Upper[j] = aMean + aStDev;                                     // REUSE VALUEs      NEVER RE-PROCESS THE SAME THING, THAT HAS ALREADY BEEN COMPUTED
       ATREx_Lower[j] = aMean - aStDev;                                     // REUSE VALUEs      NEVER RE-PROCESS THE SAME THING, THAT HAS ALREADY BEEN COMPUTED
    // *******************************************************************************************************************
    //                                                               WAS 4x MORE EXPENSIVE:
    // *******************************************************************************************************************
    // ATREx_Upper[j] = iMAOnArray(     ATREx, 0,  40, 0, MODE_EMA, j ) + iStdDevOnArray( ATREx, 0, 200, 0, MODE_EMA, j );
    // ATREx_Lower[j] = iMAOnArray(     ATREx, 0,  40, 0, MODE_EMA, j ) - iStdDevOnArray( ATREx, 0, 200, 0, MODE_EMA, j ); 
    // *******************************************************************************************************************
       j--;
}

Epilogue and Errata:

double            aCPY[];       // best put MEM .ALLOC in file-scope declarations
ArraySetAsSeries( aCPY, True ); // lock a TimeSeries ordering right there

While nBARs may require some quantitative modeling to meet the best precision / computing_expenses balance, it is warmly recommended not to copy WHOLE_ARRAY, unless any indeed ( mathematically supported ) full-depth reverse-stepped convolution ( where any change in [0] is due to get computationally back-propagated, in a domino manner, deeper-back into aTimeDOMAIN history -- which for obvious reasons is the very opposite sort of behaviour, right on the contrary to the needs that a quantitatively based Technical Analysis is happy to work with. ). So rather copy, as Albert EINSTEIN has so lovely coined for modern physics - "COPY AS-MUCH BARS BACK, AS NEEDED, BUT NOT A SINGLE MORE" - then you have the best performance.

While the repetitive use of iMAOnArray() and iStdDevOnArray(), it is not numerically and computationally as efficient as if using a sliding window computing, that never re-calculates any value, but improves the speed by re-using all already once computed values -- iMAOnArray( ATTREx, WHOLE_ARRAY, 3, 0, MODE_SMA, j); being one of the examples, as being re-looped in [j] by while(){...}.

Matt
  • 74,352
  • 26
  • 153
  • 180
user3666197
  • 1
  • 6
  • 50
  • 92
  • 1
    Thanks! I have some follow up questions but can't put them all in this comment section. I have put in above as "An Answer". Hopefully you can help take a look. Thanks again in advance! – chweet Jun 27 '17 at 14:23