Koalafied Volume Extension Bubbles
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © TJ_667

//@version=5
indicator("Koalafied Volume Extension Bubbles", overlay = true, max_labels_count = 500)

// ---------- FUNCTIONS ---------- //
 
Z_score(_src, _length, MA_sel)=>
    _mean = MA_sel == 'SMA' ? ta.sma(_src, _length) : MA_sel == 'EMA' ? ta.ema(_src, _length) :  MA_sel == 'WMA' ? ta.wma(_src, _length) : na
    _value = (_src - _mean) / (ta.stdev(_src, _length))

timeChange(period) =>
	ta.change(time(period))



// ---------- INPUTS ---------- //

var GRP1 = "INPUTS"
len = input(21, "Z-Score MA Length", group = GRP1)
MA_sel = input.string(title='MA Selection', defval='SMA', options=['SMA', 'EMA', 'WMA'], group = GRP1)
deviation_1 = input(2.0, "Std Dev", group = GRP1)
deviation_2 = input(3.0, "Std Dev", group = GRP1)
size_circles = input.string(title='Bubble Size Selection', defval='Big', options=['Small', 'Big'], group = GRP1)
offset_circles = input(true, "Offset Volume Bubbles to Period Start", group = GRP1)


var GRP2 = "COLOR SELECTION"
_colup_ext2 = input.color(color.lime, "Bull Extension 2", group = GRP2)
_colup_ext1 = input.color(color.blue, "Bull Extension 1", group = GRP2)
_coldown_ext1 = input.color(color.red, "Bear Extension 1", group = GRP2)
_coldown_ext2 = input.color(color.purple, "Bear Extension 2", group = GRP2)
trans_circles = input.int(50, "Volume Bubble Transparency", group = GRP2)



// ---------- CALCS ---------- //
src = volume
vol = Z_score(src, len, MA_sel) 
extension_1 = vol > deviation_1 and vol < deviation_2 
extension_2 = vol > deviation_2 
bull = close > open
bear = close < open

_devUp2 = extension_2 and bull
_devUp1 = extension_1 and bull
_devDown1 = extension_1 and bear
_devDown2 = extension_2 and bear


// Bubble offset calcs

_start = timeChange("D")
var int count = na
count := _start ? 0 : count + 1

circ_size = size_circles == "Small" ? true : false

// ---------- PLOTS ---------- //

if _devUp2
    dn1 = label.new(bar_index[offset_circles ? count : 0], ((open + close) / 2), color = color.new(_colup_ext2, trans_circles), style = label.style_circle, size = circ_size ? size.auto : size.tiny)
if _devUp1
    dn1 = label.new(bar_index[offset_circles ? count : 0], ((open + close) / 2), color = color.new(_colup_ext1, trans_circles), style = label.style_circle, size = circ_size ? size.auto : size.tiny)
if _devDown1
    dn1 = label.new(bar_index[offset_circles ? count : 0], ((open + close) / 2), color = color.new(_coldown_ext1, trans_circles), style = label.style_circle, size = circ_size ? size.auto : size.tiny)
if _devDown2
    dn1 = label.new(bar_index[offset_circles ? count : 0], ((open + close) / 2), color = color.new(_coldown_ext2, trans_circles), style = label.style_circle, size = circ_size ? size.auto : size.tiny)


// ---------- Alerts ---------- //

ext_alert = _devUp2 or _devUp1 or _devDown1 or _devDown2
alertcondition(ext_alert, "Volume Extension Alert",  "VOL EXT")

