improve

//@version=5
strategy("Machine Learning Adaptive SuperTrend [AlgoAlpha]", "AlgoAlpha - 🤖 Adaptive SuperTrend", overlay = true, max_labels_count = 500)

import TradingView/ta/7

atr_len = input.int(10, "ATR Length", group = "SuperTrend Settings")
fact = input.float(3, "SuperTrend Factor", group = "SuperTrend Settings")
training_data_period = input.int(100, "Training Data Length", group = "K-Means Settings")
highvol = input.float(0.75, "Initial High volatility Percentile Guess", maxval = 1, group = "K-Means Settings", tooltip = "The initial guess of where the potential 'high volatility' area is, a value of 0.75 will take the 75th percentile of the range of ATR values over the training data period")
midvol = input.float(0.5, "Initial Medium volatility Percentile Guess", maxval = 1, group = "K-Means Settings", tooltip = "The initial guess of where the potential 'medium volatility' area is, a value of 0.5 will take the 50th percentile of the range of ATR values over the training data period")
lowvol = input.float(0.25, "Initial Low volatility Percentile Guess", maxval = 1, group = "K-Means Settings", tooltip = "The initial guess of where the potential 'low volatility' area is, a value of 0.25 will take the 25th percentile of the range of ATR values over the training data period")
green = input.color(#00ffbb, "Bullish Color", group = "Appearance")
red = input.color(#ff1100, "Bearish Color", group = "Appearance")

pine_supertrend(factor, atr) =>
    src = hl2
    upperBand = src + factor * atr
    lowerBand = src - factor * atr
    prevLowerBand = nz(lowerBand[1])
    prevUpperBand = nz(upperBand[1])

    lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
    upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand
    int _direction = na
    float superTrend = na
    prevSuperTrend = superTrend[1]
    if na(atr[1])
        _direction := 1
    else if prevSuperTrend == prevUpperBand
        _direction := close > upperBand ? -1 : 1
    else
        _direction := close < lowerBand ? 1 : -1
    superTrend := _direction == -1 ? lowerBand : upperBand
    [superTrend, _direction]

volatility = ta.atr(atr_len)

upper = ta.highest(volatility, training_data_period)
lower = ta.lowest(volatility, training_data_period)

high_volatility = lower + (upper-lower) * highvol
medium_volatility = lower + (upper-lower) * midvol
low_volatility = lower + (upper-lower) * lowvol

iterations = 0

size_a = 0
size_b = 0
size_c = 0

hv = array.new_float()
mv = array.new_float()
lv = array.new_float()
amean = array.new_float(1,high_volatility)
bmean = array.new_float(1,medium_volatility)
cmean = array.new_float(1,low_volatility)

if nz(volatility) > 0 and bar_index >= training_data_period-1

    while ((amean.size() == 1 ? true : (amean.first() != amean.get(1))) or (bmean.size() == 1 ? true : (bmean.first() != bmean.get(1))) or (cmean.size() == 1 ? true : (cmean.first() != cmean.get(1)))):
        hv.clear()
        mv.clear()
        lv.clear()
        for i = training_data_period-1 to 0
            if math.abs(volatility[i] - amean.first()) < math.abs(volatility[i] - bmean.first()) and math.abs(volatility[i] - amean.first()) < math.abs(volatility[i] - cmean.first())
                hv.unshift(volatility[i])

            if math.abs(volatility[i] - bmean.first()) < math.abs(volatility[i] - amean.first()) and math.abs(volatility[i] - bmean.first()) < math.abs(volatility[i] - cmean.first())
                mv.unshift(volatility[i])

            if math.abs(volatility[i] - cmean.first()) < math.abs(volatility[i] - amean.first()) and math.abs(volatility[i] - cmean.first()) < math.abs(volatility[i] - bmean.first())
                lv.unshift(volatility[i])
        
        amean.unshift(hv.avg())
        bmean.unshift(mv.avg())
        cmean.unshift(lv.avg())
        size_a := hv.size()
        size_b := mv.size()
        size_c := lv.size()
        iterations := iterations + 1

hv_new = amean.first()
mv_new = bmean.first()
lv_new = cmean.first()
vdist_a = math.abs(volatility - hv_new)
vdist_b = math.abs(volatility - mv_new)
vdist_c = math.abs(volatility - lv_new)

distances = array.new_float()
centroids = array.new_float()

distances.push(vdist_a)
distances.push(vdist_b)
distances.push(vdist_c)

centroids.push(hv_new)
centroids.push(mv_new)
centroids.push(lv_new)

cluster = distances.indexof(distances.min()) // 0 for high, 1 for medium, 2 for low
assigned_centroid = cluster == -1 ? na : centroids.get(cluster)

[ST, dir] = pine_supertrend(fact, assigned_centroid)

// Define buy and sell conditions
longCondition = ta.crossunder(dir, 0)
shortCondition = ta.crossover(dir, 0)

// Execute buy and sell orders
if (longCondition)
    strategy.entry("Long", strategy.long)

if (shortCondition)
    strategy.entry("Short", strategy.short)

// Stop Loss and Take Profit based on ATR
atrVal = ta.atr(14)
strategy.exit("Exit Long", from_entry = "Long", stop = close - 1.5 * atrVal, limit = close + 2 * atrVal)
strategy.exit("Exit Short", from_entry = "Short", stop = close + 1.5 * atrVal, limit = close - 2 * atrVal)

t1 = 70
t2 = 95

upTrend = plot(close > ST ? ST : na, color = color.new(green, t1), style = plot.style_linebr)
downTrend = plot(close < ST ? ST : na, color = color.new(red, t1), style = plot.style_linebr, force_overlay = false)
bodyMiddle = plot(barstate.isfirst ? na : (open + close) / 2, "Body Middle", display = display.none)

fill(bodyMiddle, upTrend, (open + close) / 2, ST, color.new(green, t2), color.new(green, t1))
fill(bodyMiddle, downTrend, ST, (open + close) / 2, color.new(red, t1), color.new(red, t2))

plotshape(ta.crossunder(dir, 0) ? ST : na, "Bullish Trend", shape.labelup, location.absolute, green, text = "▲", textcolor = chart.fg_color, size = size.small)
plotshape(ta.crossover(dir, 0) ? ST : na, "Bearish Trend", shape.labeldown, location.absolute, red, text = "▼", textcolor = chart.fg_color, size = size.small)