vol_box
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © voided

//@version=5
indicator("vol_box", overlay = true)

stdevs  = input.float(title = "stdevs", defval = 1.0)
pp      = input.int(title = "periods to project", defval = 1)
window  = input.int(title = "window", defval = 20)
ppy     = input.int(title = "periods per year", defval = 252)
history = input.bool(title = "show history", defval = false)

var rvs = array.new_float()

squared_returns     = math.pow(math.log(close / close[1]), 2.0)
smoothed_returns    = ta.ema(squared_returns, window)
rv                  = math.sqrt(smoothed_returns * ppy)

array.push(rvs, rv)

upper   = close * (1 + rv * stdevs * math.sqrt(pp / ppy))
lower   = close * (1 - rv * stdevs * math.sqrt(pp / ppy))

var fcst    = array.new_int()

array.push(fcst, close <= upper[pp] and close >= lower[pp] ? 1 : 0)

hist_transp = history ? 0 : 100

hist_upper = close > upper[pp] ? color.new(color.red, hist_transp) : color.new(color.blue, hist_transp)
hist_lower = close < lower[pp] ? color.new(color.red, hist_transp) : color.new(color.blue, hist_transp)

plot(upper[pp], title = "upper bound", color = hist_upper, style = plot.style_stepline)
plot(lower[pp], title = "upper bound", color = hist_lower, style = plot.style_stepline)

if barstate.islast

    bgc = color.new(color.white, 100)
    bc  = color.new(color.blue, 0)
    
    pct_rnk = array.percentrank(rvs, array.indexof(rvs, rv))
    acc     = array.avg(fcst) * 100
    
    b_txt   = str.format("rv: {0,number,#.#}%\nrnk: {1, number, #.#}%\nacc: {2, number, #.#}%", rv * 100, pct_rnk, acc)
    
    b = box.new(left = bar_index + 1, top = upper, bottom = lower, right = bar_index + pp, xloc = xloc.bar_index, bgcolor = bgc, border_color = bc, text = b_txt, text_color = bc, text_halign = text.align_left, text_valign = text.align_top, text_size = size.tiny)
    
    box.delete(b[1])