How can I retain a variable in a buffer until a new condition is met? - page 2

 
rrsch #:

Haha, that is exactly what I'm doing, just with the K line from the Stochastic RSI.

I believe I have mine working exactly how I need now, but I'd be curious to take a look at yours.

//+------------------------------------------------------------------+
//|                                                  Colored RSI.mq4 |
//|                                           Copyright 2021, Alex M |
//|                                            https://www.mql5.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, Alex M"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_separate_window
//---
#property indicator_buffers 3
#property indicator_color1 clrWhite
#property indicator_color2 clrGreen
#property indicator_color3 clrRed
#property indicator_maximum 100.0
#property indicator_minimum 0.0
#property indicator_level1 70.0
#property indicator_level2 30.0
//---
extern uint InpRSILookback                = 14;           // RSI Lookback
input ENUM_APPLIED_PRICE InpAppliedPrice  = PRICE_CLOSE;  // Applied Price
//---
double ExtBuy[];
double ExtSell[];
double ExtNeutral[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit() {
  const bool isParamError = int(InpRSILookback) > Bars - 1;
  
  if (isParamError)
    InpRSILookback  = 14;
  
  SetIndexBuffer(0, ExtNeutral);
  SetIndexBuffer(1, ExtBuy);
  SetIndexBuffer(2, ExtSell);  
  
  const string lookback = (string) InpRSILookback;
  const string price    = StringSubstr(EnumToString(InpAppliedPrice), 6);
  const string indiName = "Colored RSI (" 
                          + lookback + ", "
                          + price + ")";
  
  IndicatorSetString(INDICATOR_SHORTNAME, indiName);
  
  return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[]) {
  const bool firstRun   = prev_calculated == 0;
  const bool newCandle  = rates_total - prev_calculated == 1;
  
  if (firstRun) {
    Scan(Bars - (InpRSILookback + 1));
  } else if (newCandle) {
    Scan(1);
  }
  
  return rates_total;
}

void Scan(const int lookback) {
  static double crossoverValue  = 0.0;

  for (int i = lookback; i >= 1; i--) {
    const double rsi  = iRSI(_Symbol, _Period, InpRSILookback, InpAppliedPrice, i);
    
    if (rsi < 30.0 || rsi > 70.0) {
      ExtNeutral[i]   = rsi;
      crossoverValue  = rsi;
      continue;
    }
    
    if (crossoverValue == 0.0)
      continue;
    
    //--- Neutral is always painted, but Buy / Sell will paint over it
    //--- if they have at least two consecutive values    
    ExtNeutral[i]     = rsi;
    const bool isBuy  = rsi > crossoverValue;
    
    if (isBuy) {
      ExtBuy[i]   = rsi;
    } else {
      ExtSell[i]  = rsi;
    }
  }
}
rrsch #:

I'm also not sure where to put the ArrayInitialize functions. If I put them within the for loop, my values are always 0. If I put them just before the for loop (after int limit=...) I get the same result. They also don't do anything from within my OnInit() function.

I want to correct / clarify something.

* Indicator Buffers are always initialized to EMPTY_VALUE. If you want to initialize them to a different value, you cannot do it from OnInit(). Instead, initialize them in firstRun (prev_calculated == 0).

* Arrays of type double are always initialized to 0.0 (unless explicitly defined) and can be initialized to a different value at any time after they've been declared.

 
Alexander Martinez #:

I want to correct / clarify something.

* Indicator Buffers are always initialized to EMPTY_VALUE. If you want to initialize them to a different value, you cannot do it from OnInit(). Instead, initialize them in firstRun (prev_calculated == 0).

* Arrays of type double are always initialized to 0.0 (unless explicitly defined) and can be initialized to a different value at any time after they've been declared.

Nothing is always initialized.
 
Mohammad Hossein Sadeghi #: Nothing is always initialized.

I totally agree!

Alexander Martinez #:

I want to correct / clarify something.

* Indicator Buffers are always initialized to EMPTY_VALUE. If you want to initialize them to a different value, you cannot do it from OnInit(). Instead, initialize them in firstRun (prev_calculated == 0).

* Arrays of type double are always initialized to 0.0 (unless explicitly defined) and can be initialized to a different value at any time after they've been declared.

Variables need to be explicitly initialised, otherwise they will take on the previous value of the RAM they are allocated from. One may get lucky and get the previous values there that you expect, but there is no guarantee. So one should never assume and always set the values explicitly.