Price Extrapolator with Std Deviation
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © peacefulLizard50262

//@version=5
indicator('Price Extrapolator with Log Normal Deviation', shorttitle='PE', overlay=true)

// Input for the length of historical data to calculate the average log return
length = input.int(14, 'Length', 1)

// Input for the number of future price points to extrapolate
num_future_points = input.int(5,'Number of Future Price Points', 1)

// Input for the deviation multiplier
factor = input.float(0.25, "Multiplier", 0, 2, 0.05) // Adjust this value between 0 and 1 to control the tightness of the cone

// Calculate the average log return over the specified length
log_returns = math.log(close / close[1])
avg_log_return = ta.sma(log_returns, length)

// Calculate the variance of log returns
log_returns_variance = ta.variance(log_returns, length)

// Calculate the log-normal deviation
log_normal_deviation = math.exp(math.sqrt(log_returns_variance)) - 1

// Initialize arrays to store the future price points and their standard deviations
var float[] future_prices = array.new_float(num_future_points)
var float[] upper_std_dev_prices = array.new_float(num_future_points)
var float[] lower_std_dev_prices = array.new_float(num_future_points)

// Fill the arrays with extrapolated price points and their standard deviations
for i = 0 to num_future_points - 1
    if barstate.islast
        array.set(future_prices, i, open * math.exp((i + 1) * avg_log_return))
    array.set(upper_std_dev_prices, i, open * math.exp((i + 1) * (avg_log_return + factor * log_normal_deviation)))
    array.set(lower_std_dev_prices, i, open * math.exp((i + 1) * (avg_log_return - factor * log_normal_deviation)))

// Modified draw_lines function to handle array input correctly
draw_lines(values, line_color) =>
    lines = array.new<line>(array.size(values) - 1)
    if barstate.islast
        for i = 0 to array.size(values) - 2
            array.push(lines, line.new(bar_index + i, array.get(values, i), bar_index + i + 1, array.get(values, i + 1), width = 2, color=line_color))

    if barstate.isconfirmed
        for i = 0 to array.size(lines) - 1
            line.delete(array.get(lines, i))

draw_lines(future_prices, color.green)
draw_lines(upper_std_dev_prices, color.red)
draw_lines(lower_std_dev_prices, color.red)
