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

//@version=4
study("Delta Barcode", max_lines_count=110)
color c00 = input(#ffaf90)
color c01 = input(#4a148c)
int ammount_bar_lines = 100
int ammount_extra_lines = 3
int total_lines = ammount_bar_lines + ammount_extra_lines
var float[] deltas = array.new_float(ammount_bar_lines)
var line[] lines = array.new_line(total_lines)
var label la = label.new(bar_index, 0.0, '', style=label.style_circle, size=size.tiny) // label for debug
float max = 0.0
float min = 0.0

// color functions:
f_rgb_clamp(_value) => (255.0 + _value) % 255.0
f_lerp(_cola, _colb, _r) => _cola + (_colb - _cola) * _r
f_col(_i)=>color.rgb(f_rgb_clamp(f_lerp(color.r(c00), color.r(c01), _i)), f_rgb_clamp(f_lerp(color.g(c00), color.g(c01), _i)), f_rgb_clamp(f_lerp(color.b(c00), color.b(c01), _i)), 0)
// expects a sample with the deltas(distance) to mean.
f_kurtosis(_sample)=>
    int _size = array.size(_sample)
    float _x2 = 0.0
    float _x4 = 0.0
    for _i = 0 to _size-1
        float _xi = array.get(_sample, _i)
        _x2 += pow(_xi, 2)
        _x4 += pow(_xi, 4)
    (_x4 / _size) / pow(_x2 / _size, 2)

// initialize new lines once:
if barstate.isfirst
    for _i = 0 to total_lines-1
        _line = line.new(bar_index, 0.0, bar_index, 0.0, width=4)
        array.set(lines, _i, _line)
// update new values:
if bar_index > ammount_bar_lines
    // update stats:
    for _i=1 to ammount_bar_lines
        _delta = close-close[_i]
        if _delta > max
            max := _delta
        if _delta < min
            min := _delta
        _col = f_col((_delta-min) / (max-min)) //_delta >= 0.0 ? color.green : color.maroon
        array.set(deltas, _i-1, _delta)
        line _line = array.get(lines, _i-1)
        line.set_xy1(_line, bar_index-_i, 0.0)
        line.set_xy2(_line, bar_index-_i, 1.0)
        line.set_color(_line, _col)
    // update drawings:
    float _mean = array.avg(deltas)
    float _mode = nz(array.mode(deltas), 0.0)
    float _std = array.stdev(deltas)
    float _skew = 0.5 + max(-0.5, min(0.5, 0.20 * ((_mean - _mode) / _std)))
    float _kurt = min(1.0, abs(0.2 * ((99.0 / (98.0 * 97.0)) * (101.0 * (f_kurtosis(deltas) - 3.0) + 6.0)) ))//excess sample kurtosis
    
    line _sline = array.get(lines, ammount_bar_lines)
    line _kline_u = array.get(lines, ammount_bar_lines+1)
    line _kline_l = array.get(lines, ammount_bar_lines+2)
    color _skew_col = f_col(_skew)
    line.set_xy1(_sline, bar_index, _skew)
    line.set_xy2(_sline, bar_index+10, _skew)
    line.set_width(_sline, 2)
    line.set_color(_sline, _skew_col)

    line.set_xy1(_kline_u, bar_index, 1 - (1.0 - _skew) * _kurt)
    line.set_xy2(_kline_u, bar_index+10, _skew)
    line.set_width(_kline_u, 1)
    line.set_color(_kline_u, f_col(_kurt))
    line.set_xy1(_kline_l, bar_index, _skew * _kurt)
    line.set_xy2(_kline_l, bar_index+10, _skew)
    line.set_width(_kline_l, 1)
    line.set_color(_kline_l, f_col(_kurt))

    label.set_xy(la, bar_index+10, _skew)
    label.set_color(la, _skew_col)
    label.set_tooltip(la, str.format('Skewness: {0}\nKurtosis: {1}', _skew, _kurt))