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

 

Hi all,

I'm working with the Stochastic RSI and I want to register specific buy & sell conditions for an EA.

I want it to tell me whether the K line is crossing upward or downward between the 80 & 20 levels. This is determined by whether it last crossed upward from the 20 level, or downward from the 80 level.

I've created BuyBuffer[], which is given a value of 1 when Stochastic K crosses above the 20:

if(KBuffer[i+1]<20 && KBuffer[i]>20)   BuyBuffer[i]=1;

I simply want to "set and forget" this buffer until the K line closes above the 80, and then fill it with a 0 value.


When the K line then dips below the 80 level I want to assign a sell condition:

if(KBuffer[i+1]>80 && KBuffer[i]<80)   SellBuffer[i]=1;


I'm not sure how to make the buffers hold onto their 1 or 0 value until I want to change them at the 80 and 20 crossings.

What do I need to make this work?


See attached image for a visual depiction – green highlights are the buy condition, red highlights are the sell condition.

 
rrsch:


I'm not sure how to make the buffers hold onto their 1 or 0 value until I want to change them at the 80 and 20 crossings.

What do I need to make this work?

double KBuffer[];
double BuyBuffer[];
double SellBuffer[];
double crossoverValue; //--- Keep track of the crossover value

//--- Initialize BuyBuffer and SellBuffer to zeros
ArrayInitialize(BuyBuffer, 0.0);
ArrayInitialize(SellBuffer, 0.0);

//--- when checking stoch
//--- put the stoch value in the KBuffer
//--- IF stoch < 20 or stoch > 80, put the value in the crossoverValue
//--- ELSE IF stoch > crossoverValue, put 1 in the BuyBuffer
//--- ELSE, put 1 in the SellBuffer

EDIT: you might not even need to record the value of stoch in the KBuffer, but you need to record the crossover value only when it's < 20/ > 80 without doing anything to the BuyBuffer/SellBuffer.

But once it's >= 20 / <= 80, just check if the stoch value is greater than the crossoverValue, and put 1 in BuyBuffer if it is. If it's not greater than the crossoverValue, then it must be less, so put a 1 in the SellBuffer, instead.

EDIT 2: make sure to check that crossoverValue != 0.0 before putting in 1 in either BuyBuffer/SellBuffer.

 
Alexander Martinez #:

EDIT: you might not even need to record the value of stoch in the KBuffer, but you need to record the crossover value only when it's < 20/ > 80 without doing anything to the BuyBuffer/SellBuffer.

But once it's >= 20 / <= 80, just check if the stoch value is greater than the crossoverValue, and put 1 in BuyBuffer if it is. If it's not greater than the crossoverValue, then it must be less, so put a 1 in the SellBuffer, instead.

EDIT 2: make sure to check that crossoverValue != 0.0 before putting in 1 in either BuyBuffer/SellBuffer.

This looks awesome, thank you!

It's not working for me right now though, I'm still having basically the same issue as before. I'm starting with ensuring that crossoverValue is working – retaining its value after KBuffer goes above 20 or below 80. Currently it's not, I lose the value when my K line is in the "middle zone".

I'm still getting the hang of MQL4, so I'm not sure if I'm implementing this right...?

{
//---
   int limit=prev_calculated==0?rates_total-(InpRSIPeriod+1):rates_total-prev_calculated+1;

   for(int i=limit; i>=0; i--)
   {
      RSIBuffer[i]=iRSI(_Symbol,_Period,InpRSIPeriod,InpRSIAppliedPrice,i);
      if(i<rates_total-(InpRSIPeriod+2))                 StochBuffer[i]=Stoch(RSIBuffer, RSIBuffer, RSIBuffer, InpStochastikPeriod,i,rates_total);
      if(StochBuffer[i+InpStockKPeriod-1]!=EMPTY_VALUE)  KBuffer[i]=SimpleMA(i,InpStockKPeriod,StochBuffer,rates_total);
      if(KBuffer[i+InpStockDPeriod-1]!=EMPTY_VALUE)      DBuffer[i]=SimpleMA(i,InpStockDPeriod,KBuffer,rates_total);
      
      if(KBuffer[i]>80 || KBuffer[i]<20)   CrossoverValue[i]=KBuffer[i];
   }
//--- return value of prev_calculated for next call
   return(rates_total);
}

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.

 
rrsch #:

This looks awesome, thank you!

It's not working for me right now though, I'm still having basically the same issue as before. I'm starting with ensuring that crossoverValue is working – retaining its value after KBuffer goes above 20 or below 80. Currently it's not, I lose the value when my K line is in the "middle zone".

I'm still getting the hang of MQL4, so I'm not sure if I'm implementing this right...?


It looks like because you declared CrossoverValue as an array, and you might be checking the value of it based on the current index (i). When you do that, there's likely not a value for it at that index.

I forgot to include it, so I apologize, but you want to declare crossoverValue as a static variable. A static variable is initialized only one time and it retains its value throughout the life of the program, regardless of whether if it lost scope.

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

You only need to initialize the arrays one time, so do that in OnInit function, which is an function that runs during the Init event. The Init event only occurs when your program is first loaded and is the very first event in the life of an script/indicator/EA.

Hope this helps. 👍

Client Terminal Events - MQL4 programs - MQL4 Reference
Client Terminal Events - MQL4 programs - MQL4 Reference
  • docs.mql4.com
Client Terminal Events - MQL4 programs - MQL4 Reference
 
Alexander Martinez #:

It looks like because you declared CrossoverValue as an array, and you might be checking the value of it based on the current index (i). When you do that, there's likely not a value for it at that index.

I forgot to include it, so I apologize, but you want to declare crossoverValue as a static variable. A static variable is initialized only one time and it retains its value throughout the life of the program, regardless of whether if it lost scope.

You only need to initialize the arrays one time, so do that in OnInit function, which is an function that runs during the Init event. The Init event only occurs when your program is first loaded and is the very first event in the life of an script/indicator/EA.

Hope this helps. 👍

Yes, amazing, thank you!

"Static variable" is basically the answer to my original question, that was the missing piece for me. Thanks for explaining it in some detail here though, that gave me what I needed to implement it successfully.

Got it working, thank you!

 
rrsch #:

Yes, amazing, thank you!

"Static variable" is basically the answer to my original question, that was the missing piece for me. Thanks for explaining it in some detail here though, that gave me what I needed to implement it successfully.

Got it working, thank you!

Glad to hear you got it figured out! Take care. 👍

 

I'm running into a new issue with this indicator now...

I want this indicator to paint only according to its value at candle close. When I was coding it with historical data it was working right, but now that I'm looking at it on the live feed, if its value momentarily goes above and back below the 80 it paints as a sell signal even though at candle close it should paint as a buy signal.

What do I need to add to have this indicator paint according to its value at bar close?

See attachment for detail. The bottom version is one I just added, and it's giving the signals I want. You can easily see the difference in the top one where price spiked up and back down again (or vice versa) in the middle of a candle.

 
rrsch #:

I'm running into a new issue with this indicator now...

I want this indicator to paint only according to its value at candle close. When I was coding it with historical data it was working right, but now that I'm looking at it on the live feed, if its value momentarily goes above and back below the 80 it paints as a sell signal even though at candle close it should paint as a buy signal.

What do I need to add to have this indicator paint according to its value at bar close?

See attachment for detail. The bottom version is one I just added, and it's giving the signals I want. You can easily see the difference in the top one where price spiked up and back down again (or vice versa) in the middle of a candle.

If it's repainting, it's because your loop reads from the bar that's still open. If you don't want to repaint, you should start / end at bar index 1 instead of 0.

for (int i = 1; i < Bars - 1; i++) {
  // do something
}

or

for (int i = Bars - 1; i > 0; i--) {
  // do something
}
 
rrsch #:

I'm running into a new issue with this indicator now...

I want this indicator to paint only according to its value at candle close. When I was coding it with historical data it was working right, but now that I'm looking at it on the live feed, if its value momentarily goes above and back below the 80 it paints as a sell signal even though at candle close it should paint as a buy signal.

What do I need to add to have this indicator paint according to its value at bar close?

See attachment for detail. The bottom version is one I just added, and it's giving the signals I want. You can easily see the difference in the top one where price spiked up and back down again (or vice versa) in the middle of a candle.

BTW, if you're trying to create something like this, let me know, and I'll share the code here.


I made this because I've seen the effect before and read up on how to do it, but was finally inspired to write it based off of your post.

 
Alexander Martinez #:

If it's repainting, it's because your loop reads from the bar that's still open. If you don't want to repaint, you should start / end at bar index 1 instead of 0.

Ah, that is deceptively simple. Thank you so much for your help! It's really appreciated.

 
Alexander Martinez #:

BTW, if you're trying to create something like this, let me know, and I'll share the code here.


I made this because I've seen the effect before and read up on how to do it, but was finally inspired to write it based off of your post.

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.

Reason: