// Licensed under the Apache License, Version 2.0 // © mihakralj //@version=6 indicator("Bollinger Band Width Percentile (BBWP)", "BBWP", overlay=false, format=format.percent) //@function Calculates Bollinger Band Width Percentile relative to historical range //@param source Series to calculate Bollinger Bands from //@param period Lookback period for BB calculations //@param multiplier Standard deviation multiplier for band width //@param lookback Historical lookback period for percentile calculation //@returns BBWP value representing current BBW percentile in historical range //@optimized for performance and dirty data bbwp(series float source, simple int period, simple float multiplier, simple int lookback) => var int p = math.max(1, period), var int head = 0, var int count = 0 var array buffer = array.new_float(p, na) var float sum = 0.0, var float sumSq = 0.0 float oldest = array.get(buffer, head) if not na(oldest) sum -= oldest sumSq -= oldest * oldest count -= 1 float current_val = nz(source) sum += current_val sumSq += current_val * current_val count += 1 array.set(buffer, head, current_val) head := (head + 1) % p float basis = nz(sum / count, source) float dev = count > 1 ? multiplier * math.sqrt(math.max(0.0, sumSq / count - basis * basis)) : 0.0 float bbw = basis != 0.0 ? 2 * dev / basis : 0.0 var int l = math.max(1, lookback), var int hist_head = 0, var int hist_count = 0 var array hist_buffer = array.new_float(l, na) float hist_oldest = array.get(hist_buffer, hist_head) if not na(hist_oldest) hist_count -= 1 if not na(bbw) hist_count += 1 array.set(hist_buffer, hist_head, bbw) hist_head := (hist_head + 1) % l if hist_count < 2 0.5 else int below_count = 0 for i = 0 to hist_count - 1 float val = array.get(hist_buffer, i) if not na(val) and val < bbw below_count += 1 below_count / hist_count // ---------- Main loop ---------- // Inputs i_period = input.int(20, "Period", minval=1) i_source = input.source(close, "Source") i_multiplier = input.float(2.0, "StdDev Multiplier", minval=0.001) i_lookback = input.int(252, "Lookback Period", minval=1) // Calculation bbwp_value = bbwp(i_source, i_period, i_multiplier, i_lookback) // Plot plot(bbwp_value, "BBWP", color=color.yellow, linewidth=2)