Price Region Regression
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © dandrideng

//@version=5
indicator(title="Price Region Regression", shorttitle="PRR", overlay=true, max_bars_back=1000, max_lines_count=400, max_labels_count=400)

import dandrideng/least_squares_regression/1 as lsr

//optimized Price Region regression
reg_forward = input.int(defval=20, title="Regression Lookback Forward", group="Price Region Regression")
min_length = input.int(defval=100, title="Min Regression Length", maxval=500, group="Price Region Regression")
max_length = input.int(defval=200, title="Max Regression Length", maxval=500, group="Price Region Regression")
length_step = input.int(defval=50, title="Regression Length Step", maxval=500, group="Price Region Regression")
std_offset = input.float(defval=2.0, title="Multiply Regression Std", group="Price Region Regression")
draw_region = input.bool(defval=true, title="Draw Regression Region", group="Price Region Regression")
extend_lines = input(defval=true, title="Extend Lines", group="Price Region Regression") ? extend.right : extend.none

int x1 = na
int x2 = na
float y1 = na
float y2 = na
float r = 0
float s = 0
float o = na
for length = min_length to max_length by length_step
    tick = array.new_int(length, 0)
    price = array.new_float(length, 0)
    
    for i = 0 to length - 1
        array.set(tick, i, i + reg_forward)
        array.set(price, i, close[i + reg_forward])
    
    [_a, _b, _r, _s] = lsr.basic_lsr(tick, price, length)
    if r < _r
        x2 := array.get(tick, 0)
        x1 := array.get(tick, length - 1)
        y1 := x1 * _a + _b
        y2 := x2 * _a + _b
        r := _r
        s := _s
        o := _s * std_offset

if draw_region
    var line reg_mid_line = na
    line.delete(reg_mid_line)
    reg_mid_line := line.new(x1=bar_index - x1, y1=y1, x2=bar_index - x2, y2=y2)
    line.set_width(reg_mid_line, 2)
    line.set_color(reg_mid_line, color.new(color.purple, 20))
    line.set_extend(reg_mid_line, extend_lines)
    line.set_style(reg_mid_line, line.style_dashed)
    
    var line reg_upp_line = na
    line.delete(reg_upp_line)
    reg_upp_line := line.new(x1=bar_index - x1, y1=y1 + o, x2=bar_index - x2, y2=y2 + o)
    line.set_width(reg_upp_line, 2)
    line.set_color(reg_upp_line, color.new(color.purple, 20))
    line.set_extend(reg_upp_line, extend_lines)
    
    var line reg_low_line = na
    line.delete(reg_low_line)
    reg_low_line := line.new(x1=bar_index - x1, y1=y1 - o, x2=bar_index - x2, y2=y2 - o)
    line.set_width(reg_low_line, 2)
    line.set_color(reg_low_line, color.new(color.purple, 20))
    line.set_extend(reg_low_line, extend_lines)
    
    linefill.new(reg_mid_line, reg_upp_line, color=color.new(color.purple, 90))
    linefill.new(reg_mid_line, reg_low_line, color=color.new(color.purple, 90))

    var label reg_label = na
    label.delete(reg_label)
    reg_label := label.new(x=bar_index - reg_forward, y=y2 + o, textcolor=color.white)
    label.set_color(reg_label, color.new(color.blue, 50))
    label.set_text(reg_label, "LEVEL: " + str.tostring(r, "#.###") + "\nOFFSET: " + str.tostring(o, "#.###") + "\nKLINES: " + str.tostring(x1-x2+1, "#.###"))

// reg_mid_plot = plot(draw_region ? y2 : na, linewidth=1, color=color.new(color.blue, 50), offset=-reg_forward)
// reg_upp_plot = plot(draw_region ? y2 + o : na, linewidth=2, color=color.new(color.blue, 50), offset=-reg_forward)
// reg_low_plot = plot(draw_region ? y2 - o : na, linewidth=2, color=color.new(color.blue, 50), offset=-reg_forward)
// fill(reg_mid_plot, reg_upp_plot, color=color.new(color.blue, 95))
// fill(reg_mid_plot, reg_low_plot, color=color.new(color.blue, 95))
	    
//end of file