The SuperTrend AI Clustering indicator is a sophisticated evolution of the classic SuperTrend. This new approach combines the traditional logic of the SuperTrend with algorithmic evaluation techniques to deliver more precise and adaptive signals.
By computing multiple SuperTrends with varying parameters and using an intelligent clustering system, this indicator automatically selects the most effective configuration for the current market context, dynamically adjusting support and resistance levels. This makes it an especially useful tool for traders seeking a more refined trend analysis.
The traditional SuperTrend is a trend-following indicator based on the average price and the Average True Range (ATR). It signals trend reversals when the price crosses above or below a dynamic support or resistance level calculated from the ATR.
The SuperTrend AI Clustering extends this logic in an innovative way. Instead of relying on a single ATR multiplier, it calculates multiple SuperTrends using different factors. It then evaluates the recent historical performance of each and groups them using a clustering method inspired by the k-means algorithm.
Finally, it automatically selects the most appropriate group based on the user’s preference (best performance, average, or worst), and builds the final SuperTrend using parameters from that group only.
The entire process can be summarized in three stages:
Here are the customizable parameters available in the indicator:
These parameters allow the indicator to adapt its behavior based on the asset’s volatility or the trader’s style.
The signals generated by SuperTrend AI Clustering can be used for trend reversal indications or to confirm entry and exit points:
This adaptive approach represents a significant improvement over the traditional SuperTrend by dynamically adjusting its responsiveness to market conditions. (original code from LuxAlgo).
//---------------------------------------------------------------//
//SuperTrend AI Clustering
//version = 2
//02.06.2025
//Iván González @ www.prorealcode.com
//Sharing ProRealTime knowledge
//---------------------------------------------------------------//
//-----Inputs----------------------------------------------------//
//---------------------------------------------------------------//
//length=10 // ATR length
//minMult=1
//maxMult=5
//step=0.5
//perfAlpha=10 // Performance memory
//fromCluster=1 // 1=best 2=average 3=worst
maxiter=10 // Número máximo de iteraciones de clustering
epsilon=0.0001 // Precisión para simular convergencia
//---------------------------------------------------------------//
//-----Average True Range----------------------------------------//
//---------------------------------------------------------------//
atr=averagetruerange[length](close)
//---------------------------------------------------------------//
//-----Supertrend cálculo múltiple-------------------------------//
//---------------------------------------------------------------//
$holderUpper[0]=(high+low)/2
$holderLower[0]=(high+low)/2
k=0
for factor=0 to floor((maxMult-minMult)/step) do
up=(high+low)/2+atr*factor
dn=(high+low)/2-atr*factor
if close > $holderUpper[k] then
$holderTrend[k]=1
elsif close < $holderUpper[k] then
$holderTrend[k]=0
else
$holderTrend[k]=$holderTrend[k]
endif
if close[1]<$holderUpper[k] then
$holderUpper[k]=min(up,$holderUpper[k])
else
$holderUpper[k]=up
endif
if close[1]>$holderLower[k] then
$holderLower[k]=max(dn,$holderLower[k])
else
$holderLower[k]=dn
endif
if (close[1]-$holderOutput[k])>0 then
diff=1
elsif (close[1]-$holderOutput[k])<0 then
diff=-1
else
diff=0
endif
$holderPerf[k]=$holderPerf[max(0,k-1)]+2/(perfAlpha+1)*((close-close[1])*diff-$holderPerf[max(0,k-1)])
if $holderTrend[k]=1 then
$holderOutput[k]=$holderLower[k]
else
$holderOutput[k]=$holderUpper[k]
endif
$holderFactor[k] = (minMult+k*step)
k=k+1
next
//---------------------------------------------------------------//
//-----K-means con convergencia----------------------------------//
//---------------------------------------------------------------//
centroid1 = 0
centroid2 = 0
centroid3 = 0
count = k
FOR i = 0 TO count - 1 DO
IF i < count / 3 THEN
centroid1 = centroid1 + $holderPerf[i]
ELSIF i < 2 * count / 3 THEN
centroid2 = centroid2 + $holderPerf[i]
ELSE
centroid3 = centroid3 + $holderPerf[i]
ENDIF
NEXT
centroid1 = centroid1 / (count / 3)
centroid2 = centroid2 / (count / 3)
centroid3 = centroid3 / (count / 3)
converged = 0
iter = 0
WHILE iter < maxiter AND converged = 0 DO
old1 = centroid1
old2 = centroid2
old3 = centroid3
$cluster1Perf[0] = 0
$cluster2Perf[0] = 0
$cluster3Perf[0] = 0
$cluster1Factors[0] = 0
$cluster2Factors[0] = 0
$cluster3Factors[0] = 0
FOR i = 0 TO count - 1 DO
dist1 = abs($holderPerf[i] - centroid1)
dist2 = abs($holderPerf[i] - centroid2)
dist3 = abs($holderPerf[i] - centroid3)
IF dist1 <= dist2 AND dist1 <= dist3 THEN
$cluster1Perf[$cluster1Perf[0]+1] = $holderPerf[i]
$cluster1Factors[$cluster1Factors[0]+1] = $holderFactor[i]
$cluster1Perf[0] = $cluster1Perf[0] + 1
$cluster1Factors[0] = $cluster1Factors[0] + 1
ELSIF dist2 <= dist1 AND dist2 <= dist3 THEN
$cluster2Perf[$cluster2Perf[0]+1] = $holderPerf[i]
$cluster2Factors[$cluster2Factors[0]+1] = $holderFactor[i]
$cluster2Perf[0] = $cluster2Perf[0] + 1
$cluster2Factors[0] = $cluster2Factors[0] + 1
ELSE
$cluster3Perf[$cluster3Perf[0]+1] = $holderPerf[i]
$cluster3Factors[$cluster3Factors[0]+1] = $holderFactor[i]
$cluster3Perf[0] = $cluster3Perf[0] + 1
$cluster3Factors[0] = $cluster3Factors[0] + 1
ENDIF
NEXT
centroid1 = 0
centroid2 = 0
centroid3 = 0
IF $cluster1Perf[0] > 0 THEN
FOR i = 1 TO $cluster1Perf[0] DO
centroid1 = centroid1 + $cluster1Perf[i]
NEXT
centroid1 = centroid1 / $cluster1Perf[0]
ENDIF
IF $cluster2Perf[0] > 0 THEN
FOR i = 1 TO $cluster2Perf[0] DO
centroid2 = centroid2 + $cluster2Perf[i]
NEXT
centroid2 = centroid2 / $cluster2Perf[0]
ENDIF
IF $cluster3Perf[0] > 0 THEN
FOR i = 1 TO $cluster3Perf[0] DO
centroid3 = centroid3 + $cluster3Perf[i]
NEXT
centroid3 = centroid3 / $cluster3Perf[0]
ENDIF
IF abs(centroid1 - old1) < epsilon AND abs(centroid2 - old2) < epsilon
AND abs(centroid3 - old3) < epsilon THEN
converged = 1
ENDIF
iter = iter + 1
WEND
//---------------------------------------------------------------//
//-----Cluster seleccionado y nuevo Supertrend-------------------//
//---------------------------------------------------------------//
finalFactor = 0
finalPerf = 0
perf = 0
fact = 0
IF fromCluster = 1 THEN
// Best
IF centroid1 > max(centroid2, centroid3) THEN
FOR j = 1 TO lastset($cluster1Perf) DO
perf = perf + $cluster1Perf[j]
fact = fact + $cluster1Factors[j]
NEXT
finalFactor = fact / lastset($cluster1Factors)
if lastset($cluster1Perf) > 0 then
finalPerf = perf / lastset($cluster1Perf)
else
finalPerf = 0
endif
ELSIF centroid2 > max(centroid1, centroid3) THEN
FOR j = 1 TO lastset($cluster2Perf) DO
perf = perf + $cluster2Perf[j]
fact = fact + $cluster2Factors[j]
NEXT
finalFactor = fact / lastset($cluster2Factors)
if lastset($cluster2Perf) > 0 then
finalPerf = perf / lastset($cluster2Perf)
else
finalPerf = 0
endif
ELSE
FOR j = 1 TO lastset($cluster3Perf) DO
perf = perf + $cluster3Perf[j]
fact = fact + $cluster3Factors[j]
NEXT
finalFactor = fact / lastset($cluster3Factors)
if lastset($cluster3Perf) > 0 then
finalPerf = perf / lastset($cluster3Perf)
else
finalPerf = 0
endif
ENDIF
ELSIF fromCluster = 2 THEN
// Average
IF centroid1 > centroid2 AND centroid1 < centroid3 THEN
FOR j = 1 TO lastset($cluster1Perf) DO
perf = perf + $cluster1Perf[j]
fact = fact + $cluster1Factors[j]
NEXT
finalFactor = fact / lastset($cluster1Factors)
if lastset($cluster1Perf) > 0 then
finalPerf = perf / lastset($cluster1Perf)
else
finalPerf = 0
endif
ELSIF centroid2 > centroid1 AND centroid2 < centroid3 THEN
FOR j = 1 TO lastset($cluster2Perf) DO
perf = perf + $cluster2Perf[j]
fact = fact + $cluster2Factors[j]
NEXT
finalFactor = fact / lastset($cluster2Factors)
if lastset($cluster2Perf) > 0 then
finalPerf = perf / lastset($cluster2Perf)
else
finalPerf = 0
endif
ELSE
FOR j = 1 TO lastset($cluster3Perf) DO
perf = perf + $cluster3Perf[j]
fact = fact + $cluster3Factors[j]
NEXT
finalFactor = fact / lastset($cluster3Factors)
if lastset($cluster3Perf) > 0 then
finalPerf = perf / lastset($cluster3Perf)
else
finalPerf = 0
endif
ENDIF
ELSIF fromCluster = 3 THEN
// Worst
IF centroid1 < min(centroid2, centroid3) THEN
FOR j = 1 TO lastset($cluster1Perf) DO
perf = perf + $cluster1Perf[j]
fact = fact + $cluster1Factors[j]
NEXT
finalFactor = fact / lastset($cluster1Factors)
if lastset($cluster1Perf) > 0 then
finalPerf = perf / lastset($cluster1Perf)
else
finalPerf = 0
endif
ELSIF centroid2 < min(centroid1, centroid3) THEN
FOR j = 1 TO lastset($cluster2Perf) DO
perf = perf + $cluster2Perf[j]
fact = fact + $cluster2Factors[j]
NEXT
finalFactor = fact / lastset($cluster2Factors)
if lastset($cluster2Perf) > 0 then
finalPerf = perf / lastset($cluster2Perf)
else
finalPerf = 0
endif
ELSE
FOR j = 1 TO lastset($cluster3Perf) DO
perf = perf + $cluster3Perf[j]
fact = fact + $cluster3Factors[j]
NEXT
finalFactor = fact / lastset($cluster3Factors)
if lastset($cluster3Perf) > 0 then
finalPerf = perf / lastset($cluster3Perf)
else
finalPerf = 0
endif
ENDIF
ENDIF
//---------------------------------------------------------------//
//-----Renderizado final del Supertrend--------------------------//
//---------------------------------------------------------------//
newup = (high + low) / 2 + atr * finalFactor
newdown = (high + low) / 2 - atr * finalFactor
if close[1] < newupper then
newupper = min(newup, newupper)
else
newupper = newup
endif
if close[1] > newlower then
newlower = max(newdown, newlower)
else
newlower = newdown
endif
if close > newupper then
newOS = 1
elsif close < newlower then
newOS = 0
else
newOS = newOS
endif
if newOS and newOS[1]=0 then
newST = newlower
r = 0
g = 255
transp=0
elsif newOS then
newST = newlower
r = 0
g = 255
transp=255
elsif newOS=0 and newOS[1] then
newST = newupper
r = 255
g = 0
transp=0
else
newST = newupper
r = 255
g = 0
transp=255
endif
//---------------------------------------------------------------//
return newST style(line,2) coloured(r,g,0,transp)