Function for MACD histogram average

Viewed 443

I want to get an X bars back average value from the MACD histogram but only for positive or negative values respectively. With that I want to be able to search for histogram spikes and compare them with the average values. So for the sake of (my) simplicity Im trying to achieve this with a function aimed either on the positive or the negative values. Here is an example for the histogram positive values where I try to look back over a _lookback amount of bars and if the bar has a positive value I ad that value to the previous average value and divide it by the number of positive values (ie. c_avgGreenCounter) that printed before that:

f_getAvgHistoGreen(_lookback) => 
var avgHistogramGreen = 0.0
var avgGreenCounter = 0
for i = 0 to _lookback by 1
    if hist[i] >= 0
        avgGreenCounter +=  1
        avgHistogramGreen := (avgHistogramGreen + hist[i]) / 2
    else
        avgHistogramGreen := avgHistogramGreen
        avgGreenCounter := avgGreenCounter
[avgGreenCounter, avgHistogramGreen]
 

Only when I call this with this function:

[avgGreenCounter, avgHistogramGreen] = f_getAvgHistoGreen(50)

the avgGreenCounter hits super high numbers which is obviously wrong. Can someone help me at least with the positive values please? Histogram values print correctly, I've checked them. I think that I will be then able to figure it out for the negatives as well.

2 Answers

Your excessive result is from declaring the variables with var, so that as the script executes on each historical bar, those variables are then retaining the result from the function being called on the previous bar(s). You end up with a cumulative result rather than it only being the result from the last n bars only.

Also during the loop, you don't know how many results will end up being returned, so you only need to find the sum of the histogram values while in the loop. Once the loop is finished you can obtain the average by dividing by the number of results.

//@version=5
indicator("macd avg hist", overlay = false)


f_getAvgHistoGreen(_lookback, _hist) => 
    float _sumHistogramGreen = 0.0
    int _avgGreenCounter = 0
    for i = 0 to _lookback by 1
        if _hist[i] >= 0
            _avgGreenCounter +=  1
            _sumHistogramGreen += _hist[i]
    _avgHistogramGreen = _sumHistogramGreen / _avgGreenCounter
    [_avgGreenCounter, _avgHistogramGreen]


[macdLine, signalLine, histLine] = ta.macd(close, 12, 26, 9)

[avgGCount, avgHistG] = f_getAvgHistoGreen(50, histLine)

plot(avgGCount)
plot(avgHistG)

Your script will be executed on each bar. So, you can calculate this along the way instead of using a for loop which will be executed on each bar, so you can save some performance.

//@version=5
indicator("My Script")
[macdLine, signalLine, histLine] = ta.macd(close, 12, 26, 9)

var pos_hist_cnt = 0
var pos_hist_total = 0.0
var pos_hist_avg = 0.0
var neg_hist_cnt = 0
var neg_hist_total = 0.0
var neg_hist_avg = 0.0

if (histLine >= 0)
    pos_hist_total := pos_hist_total + histLine
    pos_hist_cnt := pos_hist_cnt + 1
    pos_hist_avg := pos_hist_total / pos_hist_cnt

if (histLine <0)
    neg_hist_total := neg_hist_total + histLine
    neg_hist_cnt := neg_hist_cnt + 1
    neg_hist_avg := neg_hist_total / neg_hist_cnt

plot(series=histLine)
plot(series=pos_hist_avg, color=color.green)
plot(series=neg_hist_avg, color=color.red)
Related