2025-06-13[五]:RSI超買超賣指標‧‧
2025-06-13[五]:RSI超買超賣指標‧‧
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © BackQuant
//@version=5
import TradingView/ta/7 as ta
indicator(
"Machine Learning RSI [BackQuant]",
"ML RSI [BackQuant]",
overlay = false,
max_labels_count = 500,
timeframe ="",
timeframe_gaps = true
)
// Define Groups
const string rsi_g = "Relative Strength Index"
const string ml_t = "Machine Learning Thresholds"
const string opt_ = "ML Optimization"
const string ui = "UI Settings"
// User Inputs
// RSI Settings
series float src = input.source(close, "Calculation Source", group =rsi_g, inline ="X")
simple int rsiLength = input.int(14, "RSI Length", minval = 2, group =rsi_g, inline ="X")
simple bool smooth = input.bool(true, "Smooth RSI?", group =rsi_g, inline = "smt")
string maType = input.string("Ema", "Moving Average Type",options = ["SMA", "Hull", "Ema", "Wma", "Dema", "RMA", "LINREG", "TEMA", "ALMA", "T3"], group =rsi_g, inline = "smt")
simple int smoothP = input.int(4, "Smoothing Period", group =rsi_g)
simple int sig = input.int(6, "Sigma for ALMA", group = rsi_g, tooltip = "this is only used if the ALMA is choosen in the Moving Average Type Input")
// Machine Learning Thresholding Settings
simple int minThresh = input.int(10, "Threshold Range Min", inline = "thresh", group = ml_t)
simple int maxThresh = input.int(90, "Max", inline = "thresh", group = ml_t)
simple int step = input.int(5, "Step", inline = "thresh", group = ml_t)
// Optimization Settings
simple float perfAlpha = input.float(10, "Performance Memory", minval = 2,tooltip = "controls the weighting of past data or the smoothness of calculations.", group = opt_)
simple int maxIter = input.int(1000, "Max Clustering Steps", group =opt_)
simple int maxData = input.int(3000, "Max Data Points", group =opt_)
// UI Settings
simple bool showthres = input.bool(true, "Show Threshold Lines?", group = ui)
simple bool paintCandles = input.bool(false, "Color Bars According to Trend?", group = ui)
int linew = input.int(3, "Signal Line Width", 1,4,1, group = ui)
color longcol = input.color(#00ff00, "Long Colour", group = ui, inline = "xxxx")
color shortcol= input.color(#ff0000, "Short Colour", group = ui, inline = "xxxx")
color neucol = input.color(color.gray, "Neutral Colour", group = ui)
// MA Function
ma(src, len, type, almaSig) =>
switch type
"SMA" => ta.sma(src, len)
"Hull" => ta.hma(src, len)
"Ema" => ta.ema(src, len)
"Wma" => ta.wma(src, len)
"Dema" => ta.dema(src, len)
"RMA" => ta.rma(src, len)
"LINREG"=> ta.linreg(src, len, 0)
"TEMA" => ta.tema(src, len)
"ALMA" => ta.alma(src, len, 0, almaSig)
"T3" => ta.t3(src,len, 0.7)
// Calculate RSI
rsi = ta.rsi(src, rsiLength)
// Smooth?
if smooth == true
rsi:=ma(rsi, smoothP, maType, sig)
// Populate threshold array
var factors = array.new_float(0)
if barstate.isfirst
for i = minThresh to maxThresh by step
array.push(factors, i)
// Clustering for RSI
var rsi_values = array.new_float(0)
if last_bar_index - bar_index <= maxData
array.push(rsi_values, rsi)
var centroids = array.new_float(3)
if array.size(rsi_values) > 3
array.set(centroids, 0, array.percentile_linear_interpolation(rsi_values, 25))
array.set(centroids, 1, array.percentile_linear_interpolation(rsi_values, 50))
array.set(centroids, 2, array.percentile_linear_interpolation(rsi_values, 75))
// Initialize clusters
var cluster1 = array.new_float(0)
var cluster2 = array.new_float(0)
var cluster3 = array.new_float(0)
// Function to compare two arrays
f_arrays_equal(arr1, arr2) =>
if array.size(arr1) != array.size(arr2)
false
else
all_equal = true
for i = 0 to array.size(arr1) - 1
if array.get(arr1, i) != array.get(arr2, i)
all_equal := false
break
all_equal
for _ = 0 to maxIter
// Reset clusters at each iteration
cluster1 := array.new_float(0)
cluster2 := array.new_float(0)
cluster3 := array.new_float(0)
for value in rsi_values
distances = array.new_float(3)
for centroid in centroids
array.push(distances, math.abs(value - centroid))
idx = array.indexof(distances, array.min(distances))
if idx == 0
array.push(cluster1, value)
else if idx == 1
array.push(cluster2, value)
else
array.push(cluster3, value)
// Update centroids
new_centroids = array.new_float(3)
array.push(new_centroids, array.avg(cluster1))
array.push(new_centroids, array.avg(cluster2))
array.push(new_centroids, array.avg(cluster3))
if f_arrays_equal(new_centroids, centroids)
break
centroids := new_centroids
// Dynamic thresholds
long_S = array.get(centroids, 2)
short_S = array.get(centroids, 0)
// Cluster plotting arrays
var float cluster1_plot = na
var float cluster2_plot = na
var float cluster3_plot = na
if not na(rsi)
distances = array.new_float(3)
for centroid in centroids
array.push(distances, math.abs(rsi - centroid))
idx = array.indexof(distances, array.min(distances))
cluster1_plot := idx == 0 ? rsi : na
cluster2_plot := idx == 1 ? rsi : na
cluster3_plot := idx == 2 ? rsi : na
// --- Visualization ---
col = rsi > long_S ? longcol : rsi < short_S ? shortcol : neucol
plot(rsi, "RSI", color=col, linewidth = linew) // Main RSI line
// Dynamic thresholds via Machine Learning
plot(showthres?long_S:na, "Long ML Threshold", color=longcol)
plot(showthres?short_S:na, "Short ML Threshold", color=shortcol)
// Plot RSI values in clusters
plot(cluster1_plot, "Cluster 1", color=color.green, linewidth=2, style=plot.style_circles)
plot(cluster2_plot, "Cluster 2", color=color.orange, linewidth=2, style=plot.style_circles)
plot(cluster3_plot, "Cluster 3", color=color.red, linewidth=2, style=plot.style_circles)
barcolor(paintCandles?col:na)
留言
張貼留言