// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.
0 at
[Link]
// BullVisionCapital
//
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@
//
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@
//
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
%#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%
+=#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@
//
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*==+@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@*@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@
//
@@@@@@@@@@@@@@@@@@@@@@@@@@@@*===+@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@#+#@@@@@@@@@@@@@@@@@@@@@@@@@
@@@
//
@@@@@@@@@@@@@@@@@@@@@@@@@@@#====+@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@==#@@@@@@@@@@@@@@@@@@@@@@@@@@
@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@#=====+
%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*===#@@@@@@@@@@@@
@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@#========*#%%%@@%%%%%%%%%%
%@@@@@@@@@%#+====+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@#==============*+===========*
%@#+========+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
%*=============+=============#@*======+#@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
%#+========================#@%==+#
%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%
%##+==================+
%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+============================
===@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
%==================*@@@*=======@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%@@@%#*=============+
+*%#=====%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#==========================+=
====*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*==============================
====+%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@*==========+
+=========================*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@#==========+@%
+====================#+====#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@%
+=========+@@@@#===================#@%+==
%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@#=========+@@@@@@@@@%%%%%
%%*==============@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//
@@@@@@@@@@@@@@@@@@@@@@@@@@@#========+@@@@@@@@@@@@@@@
@@@@@@#========+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@%+=======
%@@@@@@@@@@@@+@@@@@@@@@@@
%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@%+=====*@@@@@@@%@@@%
+==#@@@@@@#
%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+====#@@@@@@@=@@@%
+==#@@@@@===#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#===#@@@@@%*=*%@%
+==#@@@@@==*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%*=#@@@@@#+==%@%
+==#@@@@+=#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%@@@@@@#+==%@%
+==#@@@+=
%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+==
%@@@=@@@@**@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+==
%@@@#@@@#
%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%=
%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@
//
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@
//
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@
//
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@
//@version=5
indicator(" Machine Learning RSI ║ BullVision",shorttitle = "🤖🧠 Machine Learning RSI ║ BullVision🤖🧠",
overlay=false)
//
╔═════════════════════════════════════════════════════════════════════
═════════╗
// ║ ║
// ║ RSI with K-Nearest Neighbors (KNN) Machine Learning ║
// ║ ║
// ║ This indicator enhances the traditional RSI using machine learning. ║
// ║ ║
// ║ The KNN algorithm identifies historical situations most similar to current ║
// ║ market conditions by analyzing multiple features: ║
// ║ - RSI value itself ║
// ║ - Momentum (rate of change) ║
// ║ - Volatility (standard deviation) ║
// ║ - Slope (linear regression) ║
// ║ - Price momentum ║
// ║ ║
// ║ Once these similar historical situations are found, their outcomes are ║
// ║ weighted by similarity to predict how the RSI might behave in the current ║
// ║ situation, creating a more responsive and accurate indicator. ║
// ║ ║
//
╚═════════════════════════════════════════════════════════════════════
═════════╝
// ===== Import Required Libraries =====
import TradingView/ta/7
// ===== Input Parameters =====
//
=====================================================================================
// 📊 RSI Base Settings
//
=====================================================================================
group_rsi = "📊 ================ RSI Base Settings ================"
rsiLength = [Link](14, "RSI Length", minval=1, group=group_rsi)
useSmoothing = [Link](true, "Apply Moving Average", group=group_rsi)
smoothingLength = [Link](3, "MA Length", minval=1, group=group_rsi)
maType = [Link]("ALMA", "Moving Average Type", options=["SMA", "EMA", "DEMA", "TEMA",
"WMA", "VWMA", "SMMA", "HMA", "LSMA", "ALMA"], group=group_rsi)
almaSigma = [Link](4, "ALMA Sigma", minval=1, group=group_rsi)
//
=====================================================================================
// 📏 Threshold Settings
//
=====================================================================================
group_threshold = "📏 ================ Threshold Settings ================"
//useAdaptiveThresholds = [Link](true, "Use Adaptive Thresholds", tooltip="Automatically adjust
overbought/oversold levels based on market conditions", group=group_threshold)
rsiOverbought = [Link](70, " Overbought Level", minval=50, maxval=100, group=group_threshold)
rsiOversold = [Link](30, " Oversold Level", minval=0, maxval=50, group=group_threshold)
//
=====================================================================================
// 🧠 KNN Machine Learning Parameters
//
=====================================================================================
group_knn = "🧠 ================ KNN Machine Learning ================"
useKnn = [Link](true, "Enable KNN Machine Learning", group=group_knn)
knnNeighbors = [Link](5, "K - Number of Neighbors", minval=1, maxval=50, group=group_knn)
knnLookback = [Link](100, "Historical Period for KNN", minval=20, maxval=500, group=group_knn)
knnWeight = [Link](0.4, "ML Weight vs Standard RSI", minval=0.0, maxval=1.0, step=0.1,
group=group_knn)
featureCount = [Link](3, "Number of Features", minval=1, maxval=5, tooltip="Number of
characteristics for finding similar market conditions", group=group_knn)
//
=====================================================================================
// 🔍 Advanced Filtering
//
=====================================================================================
group_filter = "🔍 ================ Advanced Filtering ================"
useFilter = [Link](true, "Apply Additional Smoothing", group=group_filter)
filterMethod = [Link]("Kalman", "Smoothing Method", options=["None", "Kalman", "DoubleEMA",
"ALMA"], group=group_filter)
filterStrength = [Link](0.3, "Smoothing Parameter", minval=0.01, maxval=1.0,step = 0.01,
group=group_filter)
//
=====================================================================================
// 🎨 Visual Settings
//
=====================================================================================
group_visual = "🎨 ================ Visual Settings ================"
neonEffect = [Link](true, "Neon Effect", tooltip="Enable vibrant neon-like colors",
group=group_visual)
colorScheme = [Link]("Classic", "Color Palette", ["Classic", "Deuteranopia", "Protanopia",
"Tritanopia", "Monochrome"], group=group_visual)
colorMode = [Link]("Trend Following", "Coloring Mode", ["None", "Trend Following", "Impulse"],
group=group_visual)
//
=====================================================================================
// COLOR DEFINITION
//
=====================================================================================
// Colors adapted for different types of color blindness
[bullColor, bearColor] = switch colorScheme
"Classic" => [neonEffect ? [Link](0, 255, 187) : [Link](0, 183, 18),
neonEffect ? [Link](255, 17, 0) : [Link](195, 0, 16)]
"Deuteranopia" => [[Link](0, 170, 255), [Link](255, 204, 0)] // Blue/Yellow for red-green color
blindness
"Protanopia" => [[Link](0, 170, 230), [Link](230, 175, 0)] // Blue/Yellow variant
"Tritanopia" => [[Link](255, 112, 0), [Link](0, 33, 171)] // Red/Blue for blue-yellow color
blindness
"Monochrome" => [[Link](222, 226, 230), [Link](73, 80, 87)] // High contrast grayscale
//
=====================================================================================
// RSI Calculation Functions
//
=====================================================================================
// Moving Average wrapper function
// Moving Average wrapper function
calcMovingAverage(type, src, length, sigma) =>
float result = na
if type == "SMA"
result := [Link](src, length)
else if type == "EMA"
result := [Link](src, length)
else if type == "DEMA"
// Double EMA implementation
e1 = [Link](src, length)
e2 = [Link](e1, length)
result := 2 * e1 - e2
else if type == "TEMA"
// Triple EMA implementation
e1 = [Link](src, length)
e2 = [Link](e1, length)
e3 = [Link](e2, length)
result := 3 * (e1 - e2) + e3
else if type == "WMA"
// Weighted Moving Average implementation
norm = 0.0
sum = 0.0
for i = 0 to length - 1
weight = (length - i)
norm := norm + weight
sum := sum + src[i] * weight
result := sum / norm
else if type == "VWMA"
result := [Link](src, length)
else if type == "SMMA"
// Smoothed Moving Average implementation (also known as RMA)
result := [Link](src, length)
else if type == "HMA"
result := [Link](src, length)
else if type == "LSMA"
// Least Squares Moving Average (Linear Regression)
result := [Link](src, length, 0)
else if type == "ALMA"
result := [Link](src, length, 0.85, sigma)
result
//
=====================================================================================
// Calculate base RSI
//
=====================================================================================
baseRsi = [Link](close, rsiLength)
smoothedRsi = calcMovingAverage(maType, baseRsi, smoothingLength, almaSigma)
standardRsi = useSmoothing ? smoothedRsi : baseRsi
//
=====================================================================================
// FEATURE EXTRACTION FUNCTIONS
//
=====================================================================================
// Calculate momentum (rate of change)
getMomentum(source, length) => source - source[length]
// Calculate volatility (standard deviation)
getVolatility(source, length) => [Link](source, length)
// Calculate slope (linear regression difference)
getSlope(source, length) => [Link](source, length, 0) - [Link](source, length, 1)
// Min-max normalization function
normalize(source, length) =>
maxVal = [Link](source, length)
minVal = [Link](source, length)
valueRange = maxVal - minVal
valueRange != 0 ? (source - minVal) / valueRange : 0.5
// Euclidean distance calculation
euclideanDistance(v1, v2) =>
float sum = 0.0
for i = 0 to [Link](v1) - 1
sum := sum + [Link]([Link](v1, i) - [Link](v2, i), 2)
[Link](sum)
//
=====================================================================================
// ADAPTIVE THRESHOLDS
//
=====================================================================================
// Calculates dynamic overbought/oversold levels based on historical RSI distribution
calculateAdaptiveThresholds(src, period, percentile) =>
var rsiValues = array.new_float(0)
// Reset array when period changes
if [Link] or [Link](rsiValues) > period
[Link](rsiValues)
[Link](rsiValues, src)
// Keep array size equal to period
if [Link](rsiValues) > period
[Link](rsiValues)
// Sort values for percentile calculation
sortedValues = [Link](rsiValues)
[Link](sortedValues)
// Find percentile indices
int lowIndex = [Link]([Link](sortedValues) * percentile / 100)
int highIndex = [Link]([Link](sortedValues) * (100 - percentile) / 100)
// Get threshold values (with safety checks)
lowVal = [Link](sortedValues) > 0 and lowIndex < [Link](sortedValues) ? [Link](sortedValues,
lowIndex) : 30
highVal = [Link](sortedValues) > 0 and highIndex < [Link](sortedValues) ?
[Link](sortedValues, highIndex) : 70
[lowVal, highVal]
//
=====================================================================================
// KNN MACHINE LEARNING
//
=====================================================================================
knnEnhancedRsi() =>
float enhancedRsi = standardRsi
float knnDivergence = 0.0
int effectiveK = 0
// Arrays to collect ML extreme candidates
var overBoughtCandidates = array.new_float(0)
var overSoldCandidates = array.new_float(0)
[Link](overBoughtCandidates)
[Link](overSoldCandidates)
// Current point features
var currentPoint = array.new_float(0)
[Link](currentPoint)
[Link](currentPoint, normalize(standardRsi, knnLookback))
if featureCount >= 2
[Link](currentPoint, normalize(getMomentum(standardRsi, 3), knnLookback))
if featureCount >= 3
[Link](currentPoint, normalize(getVolatility(standardRsi, 10), knnLookback))
if featureCount >= 4
[Link](currentPoint, normalize(getSlope(standardRsi, 5), knnLookback))
if featureCount >= 5
[Link](currentPoint, normalize(getMomentum(close, 5), knnLookback))
var distances = array.new_float(0)
var indices = array.new_int(0)
[Link](distances)
[Link](indices)
// Calculate distances to historical points
for i = 1 to knnLookback
if i < bar_index
var historicalPoint = array.new_float(0)
[Link](historicalPoint)
[Link](historicalPoint, normalize(standardRsi[i], knnLookback))
if featureCount >= 2
[Link](historicalPoint, normalize(getMomentum(standardRsi[i], 3), knnLookback))
if featureCount >= 3
[Link](historicalPoint, normalize(getVolatility(standardRsi[i], 10), knnLookback))
if featureCount >= 4
[Link](historicalPoint, normalize(getSlope(standardRsi[i], 5), knnLookback))
if featureCount >= 5
[Link](historicalPoint, normalize(getMomentum(close[i], 5), knnLookback))
if [Link](currentPoint) == [Link](historicalPoint)
dist = euclideanDistance(currentPoint, historicalPoint)
[Link](distances, dist)
[Link](indices, i)
[Link](historicalPoint)
if [Link](distances) > 1
for i = 0 to [Link](distances) - 2
for j = 0 to [Link](distances) - 2 - i
if [Link](distances, j) > [Link](distances, j + 1)
tempDist = [Link](distances, j)
[Link](distances, j, [Link](distances, j + 1))
[Link](distances, j + 1, tempDist)
tempIdx = [Link](indices, j)
[Link](indices, j, [Link](indices, j + 1))
[Link](indices, j + 1, tempIdx)
float weightedSum = 0.0
float weightSum = 0.0
effectiveK := [Link](knnNeighbors, [Link](distances))
if effectiveK > 0
for i = 0 to effectiveK - 1
if i < [Link](distances)
idx = [Link](indices, i)
dist = [Link](distances, i)
weight = dist < 0.0001 ? 1.0 : 1.0 / dist
float neighborRsi = na
if idx < bar_index
neighborRsi := standardRsi[idx - 1]
// Sécurité sur futureReturn
float futureReturn = na
if (idx + 5 < bar_index + 1 and not na(close[idx + 5]) and not na(close[idx]))
futureReturn := close[idx + 5] - close[idx]
// Identification des zones extrêmes
if not na(futureReturn)
if futureReturn > close[idx] * 0.02
[Link](overBoughtCandidates, standardRsi[idx])
if futureReturn < close[idx] * -0.02
[Link](overSoldCandidates, standardRsi[idx])
if not na(neighborRsi)
weightedSum := weightedSum + neighborRsi * weight
weightSum := weightSum + weight
if weightSum > 0.0
knnRsi = weightedSum / weightSum
enhancedRsi := (1.0 - knnWeight) * standardRsi + knnWeight * knnRsi
enhancedRsi := [Link](0.0, [Link](100.0, enhancedRsi))
float diffSum = 0.0
int count = 0
for i = 0 to effectiveK - 1
if i < [Link](distances)
idx = [Link](indices, i)
if idx < bar_index
diffSum := diffSum + [Link](standardRsi - standardRsi[idx])
count := count + 1
knnDivergence := count > 0 ? diffSum / count : 0.0
adaptiveOverboughtML = [Link](overBoughtCandidates) > 0 ? [Link](overBoughtCandidates) :
70
adaptiveOversoldML = [Link](overSoldCandidates) > 0 ? [Link](overSoldCandidates) : 30
[enhancedRsi, knnDivergence, effectiveK, adaptiveOversoldML, adaptiveOverboughtML]
//
=====================================================================================
// APPLY ALGORITHMS
//
=====================================================================================
// Get enhanced RSI from KNN
[knnRsi, knnDivergence, kEffective, adaptiveOversoldML, adaptiveOverboughtML] = knnEnhancedRsi()
actualOversold = rsiOversold
actualOverbought = rsiOverbought
// Use either standard or KNN-enhanced RSI
mlRsi = useKnn ? knnRsi : standardRsi
// Apply advanced filtering if enabled
filteredRsi = switch filterMethod
"None" => mlRsi
"Kalman" =>
var float kfRsi = na
kfRsi := na(kfRsi) ? mlRsi : kfRsi + filterStrength * (mlRsi - kfRsi)
kfRsi
"DoubleEMA" =>
var float ema1 = na
var float ema2 = na
ema1 := [Link](mlRsi, [Link](filterStrength * 10))
ema2 := [Link](ema1, [Link](filterStrength * 5))
ema2
"ALMA" =>
[Link](mlRsi, [Link](filterStrength * 20), 0, 6)
=> mlRsi
// Final RSI value after all processing
finalRsi = useFilter ? filteredRsi : mlRsi
// ===== Color Determination =====
color indicatorColor = switch colorMode
"None" => na
"Trend Following" => finalRsi > 50 ? bullColor : bearColor
"Impulse" => finalRsi > actualOverbought ? bullColor : finalRsi < actualOversold ? bearColor :
finalRsi < 55 and finalRsi > 45 ? [Link] : [Link]
//
=====================================================================================
// VIUSALS AND PLOTS
//
=====================================================================================
// Variables for transparency
t_ = 20 // Secondary transparency for bar coloring
// Main RSI line
rsiLine = plot(finalRsi, "RSI KNN", finalRsi > 50 ? indicatorColor : indicatorColor, 3)
// Median line (level 50)
midLine = plot(50, "50 Level", [Link]([Link], 70), 1)
// Fill between RSI and median line with gradient
fill(rsiLine, midLine, finalRsi > 50 ? finalRsi : 50, finalRsi > 50 ? 50 : finalRsi,
neonEffect ? (finalRsi > 50 ? indicatorColor : #00000000) : #00000000,
neonEffect ? (finalRsi > 50 ? #00000000 : indicatorColor) : #00000000)
// Overbought/oversold zones with gradient
// Overbought zone
obUpper = plot(100, "", [Link](bearColor, 0), display=[Link])
obLower = plot(actualOverbought, "", [Link](bearColor, 0), 1)
obMid = plot((100 + actualOverbought) / 2, "", display=[Link])
// Oversold zone
osUpper = plot(actualOversold, "", [Link](bullColor, 0), 1)
osLower = plot(0, "", [Link](bullColor, 0), display=[Link])
osMid = plot(actualOversold / 2, "", display=[Link])
// Chart bar coloring
barcolor(finalRsi > 50 ? [Link](bullColor, t_) : [Link](bearColor, t_))
//
=====================================================================================
// TABLE
//
=====================================================================================
//
=====================================================================================
// TABLE DISPLAY
//
=====================================================================================
string modeUsed = colorMode
string context = switch colorMode
"Trend Following" => finalRsi > 50 ? "Bullish Trend" : "Bearish Trend"
"Impulse" => finalRsi > actualOverbought ? "Bullish Impulse" :
finalRsi < actualOversold ? "Bearish Impulse" : "None"
=> "None"
string mlStatus = useKnn ? "YES" : "NO"
tableColor = #160d0db3
var table myTable = [Link](position = position.top_right,columns = 4, rows = 6,bgcolor = #160d0db3,
border_color = #160d0db3,border_width = 1, frame_color = #ffffff, frame_width = 1,force_overlay =
true)
if bar_index % 10 == 0 // Met à jour toutes les 10 bougies pour optimiser les perfs
[Link](myTable, 0, 0, "Mode", text_color=[Link], bgcolor=tableColor)
[Link](myTable, 1, 0, modeUsed, text_color=[Link], bgcolor=tableColor)
[Link](myTable, 0, 1, "Detected", text_color=[Link], bgcolor=tableColor)
[Link](myTable, 1, 1, context, text_color=[Link], bgcolor=tableColor)
[Link](myTable, 0, 2, "Machine Learning", text_color=[Link], bgcolor=tableColor)
[Link](myTable, 1, 2, mlStatus, text_color=[Link], bgcolor=tableColor)
[Link](myTable, 0, 3, "OB/OS Thresholds", text_color=[Link], bgcolor=tableColor)
[Link](myTable, 1, 3, [Link](actualOverbought) + " / " + [Link](actualOversold),
text_color=[Link], bgcolor=[Link]([Link], 70))