# Machine Learning: kNN (New Approach) for ThinkOrSwim

#### samer800

##### Well-known member I added Kernel calc method as well and signals.

The k-nearest neighbors (kNN) algorithm is a method for data classification and prediction, commonly used in data science and algorithmic trading.

It is effective when the training data is large, but determining the main parameter, K (a number of nearest neighbors), can be difficult. In algorithmic trading, kNN performs on par with other techniques like SVM and Random Forest.

The input data is a series of prices over time without any particular features, and the output is the next bar's price.

To compute the algorithm, we need to determine the parameter K, calculate the distance between the instance and all the training samples, rank the distance and determine nearest neighbors based on the K'th minimum distance, gather the values of the nearest neighbors, and use the average of nearest neighbors as the prediction value of the instance.

The original logic of the algorithm was slightly modified, and as a result, it approximates the simple moving average (20).

CODE:

CSS:
``````#// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
#indicator("Machine Learning: kNN (New Approach)",
# Converted and mod by [email protected]    - 03/2023
#//-- Inputs
input BarColor = yes;
input ShowLabel = yes;
input ShowOutcomes  = {"Line", "Predict", default "Both"};    # 'Show Outcomes'
input UseChartTimeframe = yes;
input Resolution    = AggregationPeriod.FIVE_MIN;    # 'Resolution'
input filterType = {"Volatility", "Volume", "Regime", "True Range", "All", default "None"}; # 'Filter Signals by'
input PredictionCalc = {Default "Average", "Rational Quadratic", "gaussian"};
input VolumeThreshold = 49;
input regimeThreshold = -0.1;
input usePrice   = yes;    # 'Use Price Data for Signal Generation?')
input Lag = 2;
input NoOfDataPoints = 10;     # 'No of Data Points'
input NoOfNearestNeighbors = 100;    # 'No of Nearest Neighbors'
input NonRepainting    = no;     # 'Non-Repainting'
input PivotPointLag  = 5;                 # 'Pivot Point Lag'
input zScoreLag  = 20;                # 'Z-Score Lag'

#---
def na = Double.NaN;
def src = ohlc4;    # 'Projection Base'
def agg = GetAggregationPeriod();
def Rep = if NonRepainting then 1 else 0;
def last = IsNaN(close[-Rep]);# and isNaN(close[-2]);
def TF = if UseChartTimeframe then agg else Resolution;
def k = NoOfNearestNeighbors;
def curve   = ShowOutcomes == ShowOutcomes."Line";
def Predict = ShowOutcomes == ShowOutcomes."Predict";
def Both    = ShowOutcomes == ShowOutcomes."Both";
def Avg = PredictionCalc==PredictionCalc."Average";
def h = if UseChartTimeframe then high[Rep] else high(Period = TF)[Rep];
def l = if UseChartTimeframe then low[Rep] else low(Period = TF)[Rep];
def c = if UseChartTimeframe then close[Rep] else close(Period = TF)[Rep];
def v = if UseChartTimeframe then volume[Rep] else volume(Period = TF)[Rep];

#--- Color
DefineGlobalColor("green" , CreateColor(0, 128, 255));
DefineGlobalColor("Red"   , CreateColor(255, 0, 128));
DefineGlobalColor("c_green" , CreateColor(0,153,136));
DefineGlobalColor("c_red"  , CreateColor(204,51,17));
#rationalQuadratic(series float _src, simple int _lookback, simple float _relativeWeight, simple int startAtBar) =>
input _src = close;
input _lookback = 8;
input _relativeWeight = 8;
input startAtBar = 25;
def _currentWeight;# = 0.
def _cumulativeWeight;# = 0.
def size = if !IsNaN(_src) then size + 1 else size;
def _size = if size >= 2000 then 1900 else size;
_currentWeight =  fold i = 0 to _size + startAtBar with p do
p + GetValue(_src, i) * (Power(1 + (Power(i, 2) / ((Power(_lookback, 2) * 2 * _relativeWeight))), -_relativeWeight));
_cumulativeWeight =  fold i1 = 0 to _size + startAtBar with p1 do
p1 +  (Power(1 + (Power(i1, 2) / ((Power(_lookback, 2) * 2 * _relativeWeight))), -_relativeWeight));
def yhat = _currentWeight / _cumulativeWeight;
plot out = yhat;
}
#gaussian(series float _src, simple int _lookback, simple int startAtBar) =>
script gaussian {
input _src = close;
input _lookback = 8;
input startAtBar = 25;
def _currentWeight;# = 0.
def _cumulativeWeight;# = 0.
def size = if !IsNaN(_src) then size + 1 else size;
def _size = if size >= 2000 then 1900 else size;
_currentWeight = fold i = 0 to _size + startAtBar with q do
q +  GetValue(_src, i) * Exp(-Power(i, 2) / (2 * Power(_lookback, 2)));
_cumulativeWeight = fold i1 = 0 to _size + startAtBar with q1 do
q1 + Exp(-Power(i1, 2) / (2 * Power(_lookback, 2)));
def yhat = _currentWeight / _cumulativeWeight;
plot out = yhat;
}
#minimax(ds, p, min, max) =>  // normalize to price
script minimax {
input ds = close;
input p = 10;
input min = low;
input max = high;#  // normalize to price
def hi = Highest(ds, p);
def lo = Lowest(ds, p);
def minimax = (max - min) * (ds - lo) / (hi - lo) + min;
plot out = minimax;
}
#volumeBreak(thres) =>
def rsivol   = RSI(Price = v, Length = 14);
def osc      = HullMovingAvg(rsivol, 10);
def volumeBreak = osc > VolumeThreshold;
#volatilityBreak(volmin, volmax) =>
def tr     = TrueRange(h, c, l);
def atrMin = WildersAverage(tr, 1);
def atrMax = WildersAverage(tr, 10);
def volatilityBreak = atrMin > atrMax;
# @regime_filter
def value1;# = 0.0
def value2;# = 0.0
def klmf;# = 0.0
value1 = 0.2 * (src - src) + 0.8 * (value1);
value2 = 0.1 * (high - low) + 0.8 * (value2);
def omega = AbsValue(value1 / value2);
def alpha = (-power(omega,2) + sqrt(power(omega, 4) + 16 * power(omega,2))) / 8;
klmf = alpha * src + (1 - alpha) * (klmf);
def absCurveSlope = AbsValue(klmf - klmf);
def exponentialAverageAbsCurveSlope = 1.0 * ExpAverage(absCurveSlope, 200);
def normalized_slope_decline = (absCurveSlope - exponentialAverageAbsCurveSlope) / exponentialAverageAbsCurveSlope;
def regime = normalized_slope_decline >= regimeThreshold;
def trFilt = atr(Length=1) > atr(Length=10);
def all = volatilityBreak and volumeBreak and Regime and trFilt;

def filter = if filterType == filterType."Volatility" then volatilityBreak else
if filterType == filterType."Volume" then volumeBreak else
if filterType == filterType."Regime" then Regime else
if filterType == filterType."True Range" then trFilt else
if filterType == filterType."All" then all else yes;
#--- Logic
def nearest_neighbors;

def d = fold i = 0 to NoOfDataPoints - 1 with p do
AbsValue(c[i] - GetValue(c, i + 1));

def size = fold i1 = 0 to NoOfDataPoints  - 1  with p1 do
if !IsNaN(d[i1]) then p1 + 1 else p1;

def new_neighbor = fold i2 = 0 to NoOfDataPoints - 1 with p2 do
if d[i2] < Min(d[i2], If(size[i2] > k, k, 0)) then GetValue(c, i2 + 1) else c[i2];

nearest_neighbors = fold i3 = 0 to NoOfDataPoints - 1 with p3 do
GetValue(new_neighbor, -i3);

def predAvg = Average(nearest_neighbors, NoOfDataPoints);
def predRQ = rationalQuadratic(nearest_neighbors, NoOfDataPoints, NoOfDataPoints, NoOfNearestNeighbors);
def loss   = gaussian(nearest_neighbors, NoOfDataPoints, NoOfNearestNeighbors);

def prediction = if Avg then predAvg else if kernel then predRQ else loss;
def synth_ds = Log(AbsValue(Power(C, 2) - 1) + .5);
def synth = synth_ds;

def scaled_loss = minimax(prediction, NoOfDataPoints - Lag, Lowest(synth, NoOfDataPoints), Highest(synth, NoOfDataPoints));
def scaled_pred = minimax(prediction, NoOfDataPoints, Lowest(synth, NoOfDataPoints), Highest(synth, NoOfDataPoints));

#-- signals
def signal =  if usePrice then
if synth < scaled_loss and filter then -1 else
if synth > scaled_loss and filter then 1 else signal else
if (scaled_loss crosses below scaled_pred) and filter then -1 else
if (scaled_loss crosses above scaled_pred) and filter then 1 else signal;
def changed = (signal - signal);
def hp_counter = if changed then 0 else hp_counter + 1;

def startLongTrade  = changed and signal > 0;
def startShortTrade = changed and signal < 0;

#-- Pred
def dir  = if prediction < c[!AdjustPrediction] then 1 else
if prediction > c[!AdjustPrediction] then -1 else 0;
def ordinary_color = dir;
def ph = if h == Highest(h, PivotPointLag) then h else 0;
def pl = if l == Lowest(l, PivotPointLag)  then l else 0;
def pivot_color = if ph and dir ==  1 then 1 else
if pl and dir == -1 then -1 else 0;
#zscore_color(data, LAGZ, dir) =>
def zs = (C - Average(C, zScoreLag)) / StDev(C, zScoreLag);
def zsCon = zs / (zScoreLag / 5);
def zscore_color = if zsCon > 0 and dir == 1 then 1 else
if zsCon < 0 and dir == -1 then -1 else 0;
#//-- Logic

#def nn     = nearest_neighbors;
def pred   = prediction;
def clr    = if zsc then zscore_color else
if Pvt then pivot_color else ordinary_color;

#//-- Visuals

plot kNNCurve = if IsNaN(close) then na else if (curve or Both) then pred else na;#, 'kNN Curve'
kNNCurve.SetLineWeight(2);
kNNCurve.AssignValueColor(if clr > 0 then GlobalColor("green") else
if clr < 0 then GlobalColor("red") else Color.DARK_GRAY);

plot Predc = if last and last[Rep + 1] and (Predict or Both) then src else na;
Predc.AssignValueColor(if clr > 0 then GlobalColor("green") else
if clr < 0 then GlobalColor("red") else Color.DARK_GRAY);
Predc.SetPaintingStrategy(PaintingStrategy.POINTS);
Predc.SetLineWeight(3);

#--- Labels
AddLabel(ShowLabel, if clr > 0 then "Prediction: UP" else
if clr < 0 then "Prediction: Down" else "Prediction: Nutral",
if clr > 0 then Color.GREEN else
if clr < 0 then GlobalColor("red") else Color.DARK_GRAY);
#-- Bar Colors
AssignPriceColor(if !BarColor then Color.CURRENT else
if clr > 0 then GlobalColor("c_green") else
if clr < 0 then GlobalColor("c_red") else Color.DARK_GRAY);
#-- Bubbles

#--- END CODE``````

Last edited by a moderator:
• • NellyN, MohamedAmarragy, wtf_dude and 6 others

#### samer800

##### Well-known member
This is not knn
probably not. I used the same creator indicator name.

#### Trendsauti

##### New member
VIP
This is hot!! Can you create a scan for it to be able to scan when it shows "Long" or "Short"?
Thank you so much in advance!

#### mcdon030

##### Member
I was really very interested to see the difference between my version and yours, but echoing bigworm above …. Not a math guy but this looks very different than everything I know of NN. Thanks for the port, though. Always enjoy new toys #### TechGuy

##### New member I added Kernel calc method as well and signals.

The k-nearest neighbors (kNN) algorithm is a method for data classification and prediction, commonly used in data science and algorithmic trading.

It is effective when the training data is large, but determining the main parameter, K (a number of nearest neighbors), can be difficult. In algorithmic trading, kNN performs on par with other techniques like SVM and Random Forest.

The input data is a series of prices over time without any particular features, and the output is the next bar's price.

To compute the algorithm, we need to determine the parameter K, calculate the distance between the instance and all the training samples, rank the distance and determine nearest neighbors based on the K'th minimum distance, gather the values of the nearest neighbors, and use the average of nearest neighbors as the prediction value of the instance.

The original logic of the algorithm was slightly modified, and as a result, it approximates the simple moving average (20).

CODE:

CSS:
``````#// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
#indicator("Machine Learning: kNN (New Approach)",
# Converted and mod by [email protected]    - 03/2023
#//-- Inputs
input BarColor = yes;
input ShowLabel = yes;
input ShowOutcomes  = {"Line", "Predict", default "Both"};    # 'Show Outcomes'
input UseChartTimeframe = yes;
input Resolution    = AggregationPeriod.FIVE_MIN;    # 'Resolution'
input filterType = {"Volatility", "Volume", "Regime", "True Range", "All", default "None"}; # 'Filter Signals by'
input PredictionCalc = {Default "Average", "Rational Quadratic", "gaussian"};
input VolumeThreshold = 49;
input regimeThreshold = -0.1;
input usePrice   = yes;    # 'Use Price Data for Signal Generation?')
input Lag = 2;
input NoOfDataPoints = 10;     # 'No of Data Points'
input NoOfNearestNeighbors = 100;    # 'No of Nearest Neighbors'
input NonRepainting    = no;     # 'Non-Repainting'
input PivotPointLag  = 5;                 # 'Pivot Point Lag'
input zScoreLag  = 20;                # 'Z-Score Lag'

#---
def na = Double.NaN;
def src = ohlc4;    # 'Projection Base'
def agg = GetAggregationPeriod();
def Rep = if NonRepainting then 1 else 0;
def last = IsNaN(close[-Rep]);# and isNaN(close[-2]);
def TF = if UseChartTimeframe then agg else Resolution;
def k = NoOfNearestNeighbors;
def curve   = ShowOutcomes == ShowOutcomes."Line";
def Predict = ShowOutcomes == ShowOutcomes."Predict";
def Both    = ShowOutcomes == ShowOutcomes."Both";
def Avg = PredictionCalc==PredictionCalc."Average";
def h = if UseChartTimeframe then high[Rep] else high(Period = TF)[Rep];
def l = if UseChartTimeframe then low[Rep] else low(Period = TF)[Rep];
def c = if UseChartTimeframe then close[Rep] else close(Period = TF)[Rep];
def v = if UseChartTimeframe then volume[Rep] else volume(Period = TF)[Rep];

#--- Color
DefineGlobalColor("green" , CreateColor(0, 128, 255));
DefineGlobalColor("Red"   , CreateColor(255, 0, 128));
DefineGlobalColor("c_green" , CreateColor(0,153,136));
DefineGlobalColor("c_red"  , CreateColor(204,51,17));
#rationalQuadratic(series float _src, simple int _lookback, simple float _relativeWeight, simple int startAtBar) =>
input _src = close;
input _lookback = 8;
input _relativeWeight = 8;
input startAtBar = 25;
def _currentWeight;# = 0.
def _cumulativeWeight;# = 0.
def size = if !IsNaN(_src) then size + 1 else size;
def _size = if size >= 2000 then 1900 else size;
_currentWeight =  fold i = 0 to _size + startAtBar with p do
p + GetValue(_src, i) * (Power(1 + (Power(i, 2) / ((Power(_lookback, 2) * 2 * _relativeWeight))), -_relativeWeight));
_cumulativeWeight =  fold i1 = 0 to _size + startAtBar with p1 do
p1 +  (Power(1 + (Power(i1, 2) / ((Power(_lookback, 2) * 2 * _relativeWeight))), -_relativeWeight));
def yhat = _currentWeight / _cumulativeWeight;
plot out = yhat;
}
#gaussian(series float _src, simple int _lookback, simple int startAtBar) =>
script gaussian {
input _src = close;
input _lookback = 8;
input startAtBar = 25;
def _currentWeight;# = 0.
def _cumulativeWeight;# = 0.
def size = if !IsNaN(_src) then size + 1 else size;
def _size = if size >= 2000 then 1900 else size;
_currentWeight = fold i = 0 to _size + startAtBar with q do
q +  GetValue(_src, i) * Exp(-Power(i, 2) / (2 * Power(_lookback, 2)));
_cumulativeWeight = fold i1 = 0 to _size + startAtBar with q1 do
q1 + Exp(-Power(i1, 2) / (2 * Power(_lookback, 2)));
def yhat = _currentWeight / _cumulativeWeight;
plot out = yhat;
}
#minimax(ds, p, min, max) =>  // normalize to price
script minimax {
input ds = close;
input p = 10;
input min = low;
input max = high;#  // normalize to price
def hi = Highest(ds, p);
def lo = Lowest(ds, p);
def minimax = (max - min) * (ds - lo) / (hi - lo) + min;
plot out = minimax;
}
#volumeBreak(thres) =>
def rsivol   = RSI(Price = v, Length = 14);
def osc      = HullMovingAvg(rsivol, 10);
def volumeBreak = osc > VolumeThreshold;
#volatilityBreak(volmin, volmax) =>
def tr     = TrueRange(h, c, l);
def atrMin = WildersAverage(tr, 1);
def atrMax = WildersAverage(tr, 10);
def volatilityBreak = atrMin > atrMax;
# @regime_filter
def value1;# = 0.0
def value2;# = 0.0
def klmf;# = 0.0
value1 = 0.2 * (src - src) + 0.8 * (value1);
value2 = 0.1 * (high - low) + 0.8 * (value2);
def omega = AbsValue(value1 / value2);
def alpha = (-power(omega,2) + sqrt(power(omega, 4) + 16 * power(omega,2))) / 8;
klmf = alpha * src + (1 - alpha) * (klmf);
def absCurveSlope = AbsValue(klmf - klmf);
def exponentialAverageAbsCurveSlope = 1.0 * ExpAverage(absCurveSlope, 200);
def normalized_slope_decline = (absCurveSlope - exponentialAverageAbsCurveSlope) / exponentialAverageAbsCurveSlope;
def regime = normalized_slope_decline >= regimeThreshold;
def trFilt = atr(Length=1) > atr(Length=10);
def all = volatilityBreak and volumeBreak and Regime and trFilt;

def filter = if filterType == filterType."Volatility" then volatilityBreak else
if filterType == filterType."Volume" then volumeBreak else
if filterType == filterType."Regime" then Regime else
if filterType == filterType."True Range" then trFilt else
if filterType == filterType."All" then all else yes;
#--- Logic
def nearest_neighbors;

def d = fold i = 0 to NoOfDataPoints - 1 with p do
AbsValue(c[i] - GetValue(c, i + 1));

def size = fold i1 = 0 to NoOfDataPoints  - 1  with p1 do
if !IsNaN(d[i1]) then p1 + 1 else p1;

def new_neighbor = fold i2 = 0 to NoOfDataPoints - 1 with p2 do
if d[i2] < Min(d[i2], If(size[i2] > k, k, 0)) then GetValue(c, i2 + 1) else c[i2];

nearest_neighbors = fold i3 = 0 to NoOfDataPoints - 1 with p3 do
GetValue(new_neighbor, -i3);

def predAvg = Average(nearest_neighbors, NoOfDataPoints);
def predRQ = rationalQuadratic(nearest_neighbors, NoOfDataPoints, NoOfDataPoints, NoOfNearestNeighbors);
def loss   = gaussian(nearest_neighbors, NoOfDataPoints, NoOfNearestNeighbors);

def prediction = if Avg then predAvg else if kernel then predRQ else loss;
def synth_ds = Log(AbsValue(Power(C, 2) - 1) + .5);
def synth = synth_ds;

def scaled_loss = minimax(prediction, NoOfDataPoints - Lag, Lowest(synth, NoOfDataPoints), Highest(synth, NoOfDataPoints));
def scaled_pred = minimax(prediction, NoOfDataPoints, Lowest(synth, NoOfDataPoints), Highest(synth, NoOfDataPoints));

#-- signals
def signal =  if usePrice then
if synth < scaled_loss and filter then -1 else
if synth > scaled_loss and filter then 1 else signal else
if (scaled_loss crosses below scaled_pred) and filter then -1 else
if (scaled_loss crosses above scaled_pred) and filter then 1 else signal;
def changed = (signal - signal);
def hp_counter = if changed then 0 else hp_counter + 1;

def startLongTrade  = changed and signal > 0;
def startShortTrade = changed and signal < 0;

#-- Pred
def dir  = if prediction < c[!AdjustPrediction] then 1 else
if prediction > c[!AdjustPrediction] then -1 else 0;
def ordinary_color = dir;
def ph = if h == Highest(h, PivotPointLag) then h else 0;
def pl = if l == Lowest(l, PivotPointLag)  then l else 0;
def pivot_color = if ph and dir ==  1 then 1 else
if pl and dir == -1 then -1 else 0;
#zscore_color(data, LAGZ, dir) =>
def zs = (C - Average(C, zScoreLag)) / StDev(C, zScoreLag);
def zsCon = zs / (zScoreLag / 5);
def zscore_color = if zsCon > 0 and dir == 1 then 1 else
if zsCon < 0 and dir == -1 then -1 else 0;
#//-- Logic

#def nn     = nearest_neighbors;
def pred   = prediction;
def clr    = if zsc then zscore_color else
if Pvt then pivot_color else ordinary_color;

#//-- Visuals

plot kNNCurve = if IsNaN(close) then na else if (curve or Both) then pred else na;#, 'kNN Curve'
kNNCurve.SetLineWeight(2);
kNNCurve.AssignValueColor(if clr > 0 then GlobalColor("green") else
if clr < 0 then GlobalColor("red") else Color.DARK_GRAY);

plot Predc = if last and last[Rep + 1] and (Predict or Both) then src else na;
Predc.AssignValueColor(if clr > 0 then GlobalColor("green") else
if clr < 0 then GlobalColor("red") else Color.DARK_GRAY);
Predc.SetPaintingStrategy(PaintingStrategy.POINTS);
Predc.SetLineWeight(3);

#--- Labels
AddLabel(ShowLabel, if clr > 0 then "Prediction: UP" else
if clr < 0 then "Prediction: Down" else "Prediction: Nutral",
if clr > 0 then Color.GREEN else
if clr < 0 then GlobalColor("red") else Color.DARK_GRAY);
#-- Bar Colors
AssignPriceColor(if !BarColor then Color.CURRENT else
if clr > 0 then GlobalColor("c_green") else
if clr < 0 then GlobalColor("c_red") else Color.DARK_GRAY);
#-- Bubbles

#--- END CODE`````` I added Kernel calc method as well and signals.

The k-nearest neighbors (kNN) algorithm is a method for data classification and prediction, commonly used in data science and algorithmic trading.

It is effective when the training data is large, but determining the main parameter, K (a number of nearest neighbors), can be difficult. In algorithmic trading, kNN performs on par with other techniques like SVM and Random Forest.

The input data is a series of prices over time without any particular features, and the output is the next bar's price.

To compute the algorithm, we need to determine the parameter K, calculate the distance between the instance and all the training samples, rank the distance and determine nearest neighbors based on the K'th minimum distance, gather the values of the nearest neighbors, and use the average of nearest neighbors as the prediction value of the instance.

The original logic of the algorithm was slightly modified, and as a result, it approximates the simple moving average (20).

CODE:

CSS:
``````#// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
#indicator("Machine Learning: kNN (New Approach)",
# Converted and mod by [email protected]    - 03/2023
#//-- Inputs
input BarColor = yes;
input ShowLabel = yes;
input ShowOutcomes  = {"Line", "Predict", default "Both"};    # 'Show Outcomes'
input UseChartTimeframe = yes;
input Resolution    = AggregationPeriod.FIVE_MIN;    # 'Resolution'
input filterType = {"Volatility", "Volume", "Regime", "True Range", "All", default "None"}; # 'Filter Signals by'
input PredictionCalc = {Default "Average", "Rational Quadratic", "gaussian"};
input VolumeThreshold = 49;
input regimeThreshold = -0.1;
input usePrice   = yes;    # 'Use Price Data for Signal Generation?')
input Lag = 2;
input NoOfDataPoints = 10;     # 'No of Data Points'
input NoOfNearestNeighbors = 100;    # 'No of Nearest Neighbors'
input NonRepainting    = no;     # 'Non-Repainting'
input PivotPointLag  = 5;                 # 'Pivot Point Lag'
input zScoreLag  = 20;                # 'Z-Score Lag'

#---
def na = Double.NaN;
def src = ohlc4;    # 'Projection Base'
def agg = GetAggregationPeriod();
def Rep = if NonRepainting then 1 else 0;
def last = IsNaN(close[-Rep]);# and isNaN(close[-2]);
def TF = if UseChartTimeframe then agg else Resolution;
def k = NoOfNearestNeighbors;
def curve   = ShowOutcomes == ShowOutcomes."Line";
def Predict = ShowOutcomes == ShowOutcomes."Predict";
def Both    = ShowOutcomes == ShowOutcomes."Both";
def Avg = PredictionCalc==PredictionCalc."Average";
def h = if UseChartTimeframe then high[Rep] else high(Period = TF)[Rep];
def l = if UseChartTimeframe then low[Rep] else low(Period = TF)[Rep];
def c = if UseChartTimeframe then close[Rep] else close(Period = TF)[Rep];
def v = if UseChartTimeframe then volume[Rep] else volume(Period = TF)[Rep];

#--- Color
DefineGlobalColor("green" , CreateColor(0, 128, 255));
DefineGlobalColor("Red"   , CreateColor(255, 0, 128));
DefineGlobalColor("c_green" , CreateColor(0,153,136));
DefineGlobalColor("c_red"  , CreateColor(204,51,17));
#rationalQuadratic(series float _src, simple int _lookback, simple float _relativeWeight, simple int startAtBar) =>
input _src = close;
input _lookback = 8;
input _relativeWeight = 8;
input startAtBar = 25;
def _currentWeight;# = 0.
def _cumulativeWeight;# = 0.
def size = if !IsNaN(_src) then size + 1 else size;
def _size = if size >= 2000 then 1900 else size;
_currentWeight =  fold i = 0 to _size + startAtBar with p do
p + GetValue(_src, i) * (Power(1 + (Power(i, 2) / ((Power(_lookback, 2) * 2 * _relativeWeight))), -_relativeWeight));
_cumulativeWeight =  fold i1 = 0 to _size + startAtBar with p1 do
p1 +  (Power(1 + (Power(i1, 2) / ((Power(_lookback, 2) * 2 * _relativeWeight))), -_relativeWeight));
def yhat = _currentWeight / _cumulativeWeight;
plot out = yhat;
}
#gaussian(series float _src, simple int _lookback, simple int startAtBar) =>
script gaussian {
input _src = close;
input _lookback = 8;
input startAtBar = 25;
def _currentWeight;# = 0.
def _cumulativeWeight;# = 0.
def size = if !IsNaN(_src) then size + 1 else size;
def _size = if size >= 2000 then 1900 else size;
_currentWeight = fold i = 0 to _size + startAtBar with q do
q +  GetValue(_src, i) * Exp(-Power(i, 2) / (2 * Power(_lookback, 2)));
_cumulativeWeight = fold i1 = 0 to _size + startAtBar with q1 do
q1 + Exp(-Power(i1, 2) / (2 * Power(_lookback, 2)));
def yhat = _currentWeight / _cumulativeWeight;
plot out = yhat;
}
#minimax(ds, p, min, max) =>  // normalize to price
script minimax {
input ds = close;
input p = 10;
input min = low;
input max = high;#  // normalize to price
def hi = Highest(ds, p);
def lo = Lowest(ds, p);
def minimax = (max - min) * (ds - lo) / (hi - lo) + min;
plot out = minimax;
}
#volumeBreak(thres) =>
def rsivol   = RSI(Price = v, Length = 14);
def osc      = HullMovingAvg(rsivol, 10);
def volumeBreak = osc > VolumeThreshold;
#volatilityBreak(volmin, volmax) =>
def tr     = TrueRange(h, c, l);
def atrMin = WildersAverage(tr, 1);
def atrMax = WildersAverage(tr, 10);
def volatilityBreak = atrMin > atrMax;
# @regime_filter
def value1;# = 0.0
def value2;# = 0.0
def klmf;# = 0.0
value1 = 0.2 * (src - src) + 0.8 * (value1);
value2 = 0.1 * (high - low) + 0.8 * (value2);
def omega = AbsValue(value1 / value2);
def alpha = (-power(omega,2) + sqrt(power(omega, 4) + 16 * power(omega,2))) / 8;
klmf = alpha * src + (1 - alpha) * (klmf);
def absCurveSlope = AbsValue(klmf - klmf);
def exponentialAverageAbsCurveSlope = 1.0 * ExpAverage(absCurveSlope, 200);
def normalized_slope_decline = (absCurveSlope - exponentialAverageAbsCurveSlope) / exponentialAverageAbsCurveSlope;
def regime = normalized_slope_decline >= regimeThreshold;
def trFilt = atr(Length=1) > atr(Length=10);
def all = volatilityBreak and volumeBreak and Regime and trFilt;

def filter = if filterType == filterType."Volatility" then volatilityBreak else
if filterType == filterType."Volume" then volumeBreak else
if filterType == filterType."Regime" then Regime else
if filterType == filterType."True Range" then trFilt else
if filterType == filterType."All" then all else yes;
#--- Logic
def nearest_neighbors;

def d = fold i = 0 to NoOfDataPoints - 1 with p do
AbsValue(c[i] - GetValue(c, i + 1));

def size = fold i1 = 0 to NoOfDataPoints  - 1  with p1 do
if !IsNaN(d[i1]) then p1 + 1 else p1;

def new_neighbor = fold i2 = 0 to NoOfDataPoints - 1 with p2 do
if d[i2] < Min(d[i2], If(size[i2] > k, k, 0)) then GetValue(c, i2 + 1) else c[i2];

nearest_neighbors = fold i3 = 0 to NoOfDataPoints - 1 with p3 do
GetValue(new_neighbor, -i3);

def predAvg = Average(nearest_neighbors, NoOfDataPoints);
def predRQ = rationalQuadratic(nearest_neighbors, NoOfDataPoints, NoOfDataPoints, NoOfNearestNeighbors);
def loss   = gaussian(nearest_neighbors, NoOfDataPoints, NoOfNearestNeighbors);

def prediction = if Avg then predAvg else if kernel then predRQ else loss;
def synth_ds = Log(AbsValue(Power(C, 2) - 1) + .5);
def synth = synth_ds;

def scaled_loss = minimax(prediction, NoOfDataPoints - Lag, Lowest(synth, NoOfDataPoints), Highest(synth, NoOfDataPoints));
def scaled_pred = minimax(prediction, NoOfDataPoints, Lowest(synth, NoOfDataPoints), Highest(synth, NoOfDataPoints));

#-- signals
def signal =  if usePrice then
if synth < scaled_loss and filter then -1 else
if synth > scaled_loss and filter then 1 else signal else
if (scaled_loss crosses below scaled_pred) and filter then -1 else
if (scaled_loss crosses above scaled_pred) and filter then 1 else signal;
def changed = (signal - signal);
def hp_counter = if changed then 0 else hp_counter + 1;

def startLongTrade  = changed and signal > 0;
def startShortTrade = changed and signal < 0;

#-- Pred
def dir  = if prediction < c[!AdjustPrediction] then 1 else
if prediction > c[!AdjustPrediction] then -1 else 0;
def ordinary_color = dir;
def ph = if h == Highest(h, PivotPointLag) then h else 0;
def pl = if l == Lowest(l, PivotPointLag)  then l else 0;
def pivot_color = if ph and dir ==  1 then 1 else
if pl and dir == -1 then -1 else 0;
#zscore_color(data, LAGZ, dir) =>
def zs = (C - Average(C, zScoreLag)) / StDev(C, zScoreLag);
def zsCon = zs / (zScoreLag / 5);
def zscore_color = if zsCon > 0 and dir == 1 then 1 else
if zsCon < 0 and dir == -1 then -1 else 0;
#//-- Logic

#def nn     = nearest_neighbors;
def pred   = prediction;
def clr    = if zsc then zscore_color else
if Pvt then pivot_color else ordinary_color;

#//-- Visuals

plot kNNCurve = if IsNaN(close) then na else if (curve or Both) then pred else na;#, 'kNN Curve'
kNNCurve.SetLineWeight(2);
kNNCurve.AssignValueColor(if clr > 0 then GlobalColor("green") else
if clr < 0 then GlobalColor("red") else Color.DARK_GRAY);

plot Predc = if last and last[Rep + 1] and (Predict or Both) then src else na;
Predc.AssignValueColor(if clr > 0 then GlobalColor("green") else
if clr < 0 then GlobalColor("red") else Color.DARK_GRAY);
Predc.SetPaintingStrategy(PaintingStrategy.POINTS);
Predc.SetLineWeight(3);

#--- Labels
AddLabel(ShowLabel, if clr > 0 then "Prediction: UP" else
if clr < 0 then "Prediction: Down" else "Prediction: Nutral",
if clr > 0 then Color.GREEN else
if clr < 0 then GlobalColor("red") else Color.DARK_GRAY);
#-- Bar Colors
AssignPriceColor(if !BarColor then Color.CURRENT else
if clr > 0 then GlobalColor("c_green") else
if clr < 0 then GlobalColor("c_red") else Color.DARK_GRAY);
#-- Bubbles

#--- END CODE``````
Your approach sounded very interesting to me. I tried it on several stocks. Here is one example for AAPL. Many of the other symbols I tried looked the same for the L or S and Prediction. The stocks seem to be going in the opposite direction of the L or S in both the historical and current bars. But, the Prediction is showing something different for the current bar. What does the small dot next to the current bar represent? Can you please help me on the interpretation? I added Kernel calc method as well and signals.

The k-nearest neighbors (kNN) algorithm is a method for data classification and prediction, commonly used in data science and algorithmic trading.

It is effective when the training data is large, but determining the main parameter, K (a number of nearest neighbors), can be difficult. In algorithmic trading, kNN performs on par with other techniques like SVM and Random Forest.

The input data is a series of prices over time without any particular features, and the output is the next bar's price.

To compute the algorithm, we need to determine the parameter K, calculate the distance between the instance and all the training samples, rank the distance and determine nearest neighbors based on the K'th minimum distance, gather the values of the nearest neighbors, and use the average of nearest neighbors as the prediction value of the instance.

The original logic of the algorithm was slightly modified, and as a result, it approximates the simple moving average (20).

CODE:

CSS:
``````#// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
#indicator("Machine Learning: kNN (New Approach)",
# Converted and mod by [email protected]    - 03/2023
#//-- Inputs
input BarColor = yes;
input ShowLabel = yes;
input ShowOutcomes  = {"Line", "Predict", default "Both"};    # 'Show Outcomes'
input UseChartTimeframe = yes;
input Resolution    = AggregationPeriod.FIVE_MIN;    # 'Resolution'
input filterType = {"Volatility", "Volume", "Regime", "True Range", "All", default "None"}; # 'Filter Signals by'
input PredictionCalc = {Default "Average", "Rational Quadratic", "gaussian"};
input VolumeThreshold = 49;
input regimeThreshold = -0.1;
input usePrice   = yes;    # 'Use Price Data for Signal Generation?')
input Lag = 2;
input NoOfDataPoints = 10;     # 'No of Data Points'
input NoOfNearestNeighbors = 100;    # 'No of Nearest Neighbors'
input NonRepainting    = no;     # 'Non-Repainting'
input PivotPointLag  = 5;                 # 'Pivot Point Lag'
input zScoreLag  = 20;                # 'Z-Score Lag'

#---
def na = Double.NaN;
def src = ohlc4;    # 'Projection Base'
def agg = GetAggregationPeriod();
def Rep = if NonRepainting then 1 else 0;
def last = IsNaN(close[-Rep]);# and isNaN(close[-2]);
def TF = if UseChartTimeframe then agg else Resolution;
def k = NoOfNearestNeighbors;
def curve   = ShowOutcomes == ShowOutcomes."Line";
def Predict = ShowOutcomes == ShowOutcomes."Predict";
def Both    = ShowOutcomes == ShowOutcomes."Both";
def Avg = PredictionCalc==PredictionCalc."Average";
def h = if UseChartTimeframe then high[Rep] else high(Period = TF)[Rep];
def l = if UseChartTimeframe then low[Rep] else low(Period = TF)[Rep];
def c = if UseChartTimeframe then close[Rep] else close(Period = TF)[Rep];
def v = if UseChartTimeframe then volume[Rep] else volume(Period = TF)[Rep];

#--- Color
DefineGlobalColor("green" , CreateColor(0, 128, 255));
DefineGlobalColor("Red"   , CreateColor(255, 0, 128));
DefineGlobalColor("c_green" , CreateColor(0,153,136));
DefineGlobalColor("c_red"  , CreateColor(204,51,17));
#rationalQuadratic(series float _src, simple int _lookback, simple float _relativeWeight, simple int startAtBar) =>
input _src = close;
input _lookback = 8;
input _relativeWeight = 8;
input startAtBar = 25;
def _currentWeight;# = 0.
def _cumulativeWeight;# = 0.
def size = if !IsNaN(_src) then size + 1 else size;
def _size = if size >= 2000 then 1900 else size;
_currentWeight =  fold i = 0 to _size + startAtBar with p do
p + GetValue(_src, i) * (Power(1 + (Power(i, 2) / ((Power(_lookback, 2) * 2 * _relativeWeight))), -_relativeWeight));
_cumulativeWeight =  fold i1 = 0 to _size + startAtBar with p1 do
p1 +  (Power(1 + (Power(i1, 2) / ((Power(_lookback, 2) * 2 * _relativeWeight))), -_relativeWeight));
def yhat = _currentWeight / _cumulativeWeight;
plot out = yhat;
}
#gaussian(series float _src, simple int _lookback, simple int startAtBar) =>
script gaussian {
input _src = close;
input _lookback = 8;
input startAtBar = 25;
def _currentWeight;# = 0.
def _cumulativeWeight;# = 0.
def size = if !IsNaN(_src) then size + 1 else size;
def _size = if size >= 2000 then 1900 else size;
_currentWeight = fold i = 0 to _size + startAtBar with q do
q +  GetValue(_src, i) * Exp(-Power(i, 2) / (2 * Power(_lookback, 2)));
_cumulativeWeight = fold i1 = 0 to _size + startAtBar with q1 do
q1 + Exp(-Power(i1, 2) / (2 * Power(_lookback, 2)));
def yhat = _currentWeight / _cumulativeWeight;
plot out = yhat;
}
#minimax(ds, p, min, max) =>  // normalize to price
script minimax {
input ds = close;
input p = 10;
input min = low;
input max = high;#  // normalize to price
def hi = Highest(ds, p);
def lo = Lowest(ds, p);
def minimax = (max - min) * (ds - lo) / (hi - lo) + min;
plot out = minimax;
}
#volumeBreak(thres) =>
def rsivol   = RSI(Price = v, Length = 14);
def osc      = HullMovingAvg(rsivol, 10);
def volumeBreak = osc > VolumeThreshold;
#volatilityBreak(volmin, volmax) =>
def tr     = TrueRange(h, c, l);
def atrMin = WildersAverage(tr, 1);
def atrMax = WildersAverage(tr, 10);
def volatilityBreak = atrMin > atrMax;
# @regime_filter
def value1;# = 0.0
def value2;# = 0.0
def klmf;# = 0.0
value1 = 0.2 * (src - src) + 0.8 * (value1);
value2 = 0.1 * (high - low) + 0.8 * (value2);
def omega = AbsValue(value1 / value2);
def alpha = (-power(omega,2) + sqrt(power(omega, 4) + 16 * power(omega,2))) / 8;
klmf = alpha * src + (1 - alpha) * (klmf);
def absCurveSlope = AbsValue(klmf - klmf);
def exponentialAverageAbsCurveSlope = 1.0 * ExpAverage(absCurveSlope, 200);
def normalized_slope_decline = (absCurveSlope - exponentialAverageAbsCurveSlope) / exponentialAverageAbsCurveSlope;
def regime = normalized_slope_decline >= regimeThreshold;
def trFilt = atr(Length=1) > atr(Length=10);
def all = volatilityBreak and volumeBreak and Regime and trFilt;

def filter = if filterType == filterType."Volatility" then volatilityBreak else
if filterType == filterType."Volume" then volumeBreak else
if filterType == filterType."Regime" then Regime else
if filterType == filterType."True Range" then trFilt else
if filterType == filterType."All" then all else yes;
#--- Logic
def nearest_neighbors;

def d = fold i = 0 to NoOfDataPoints - 1 with p do
AbsValue(c[i] - GetValue(c, i + 1));

def size = fold i1 = 0 to NoOfDataPoints  - 1  with p1 do
if !IsNaN(d[i1]) then p1 + 1 else p1;

def new_neighbor = fold i2 = 0 to NoOfDataPoints - 1 with p2 do
if d[i2] < Min(d[i2], If(size[i2] > k, k, 0)) then GetValue(c, i2 + 1) else c[i2];

nearest_neighbors = fold i3 = 0 to NoOfDataPoints - 1 with p3 do
GetValue(new_neighbor, -i3);

def predAvg = Average(nearest_neighbors, NoOfDataPoints);
def predRQ = rationalQuadratic(nearest_neighbors, NoOfDataPoints, NoOfDataPoints, NoOfNearestNeighbors);
def loss   = gaussian(nearest_neighbors, NoOfDataPoints, NoOfNearestNeighbors);

def prediction = if Avg then predAvg else if kernel then predRQ else loss;
def synth_ds = Log(AbsValue(Power(C, 2) - 1) + .5);
def synth = synth_ds;

def scaled_loss = minimax(prediction, NoOfDataPoints - Lag, Lowest(synth, NoOfDataPoints), Highest(synth, NoOfDataPoints));
def scaled_pred = minimax(prediction, NoOfDataPoints, Lowest(synth, NoOfDataPoints), Highest(synth, NoOfDataPoints));

#-- signals
def signal =  if usePrice then
if synth < scaled_loss and filter then -1 else
if synth > scaled_loss and filter then 1 else signal else
if (scaled_loss crosses below scaled_pred) and filter then -1 else
if (scaled_loss crosses above scaled_pred) and filter then 1 else signal;
def changed = (signal - signal);
def hp_counter = if changed then 0 else hp_counter + 1;

def startLongTrade  = changed and signal > 0;
def startShortTrade = changed and signal < 0;

#-- Pred
def dir  = if prediction < c[!AdjustPrediction] then 1 else
if prediction > c[!AdjustPrediction] then -1 else 0;
def ordinary_color = dir;
def ph = if h == Highest(h, PivotPointLag) then h else 0;
def pl = if l == Lowest(l, PivotPointLag)  then l else 0;
def pivot_color = if ph and dir ==  1 then 1 else
if pl and dir == -1 then -1 else 0;
#zscore_color(data, LAGZ, dir) =>
def zs = (C - Average(C, zScoreLag)) / StDev(C, zScoreLag);
def zsCon = zs / (zScoreLag / 5);
def zscore_color = if zsCon > 0 and dir == 1 then 1 else
if zsCon < 0 and dir == -1 then -1 else 0;
#//-- Logic

#def nn     = nearest_neighbors;
def pred   = prediction;
def clr    = if zsc then zscore_color else
if Pvt then pivot_color else ordinary_color;

#//-- Visuals

plot kNNCurve = if IsNaN(close) then na else if (curve or Both) then pred else na;#, 'kNN Curve'
kNNCurve.SetLineWeight(2);
kNNCurve.AssignValueColor(if clr > 0 then GlobalColor("green") else
if clr < 0 then GlobalColor("red") else Color.DARK_GRAY);

plot Predc = if last and last[Rep + 1] and (Predict or Both) then src else na;
Predc.AssignValueColor(if clr > 0 then GlobalColor("green") else
if clr < 0 then GlobalColor("red") else Color.DARK_GRAY);
Predc.SetPaintingStrategy(PaintingStrategy.POINTS);
Predc.SetLineWeight(3);

#--- Labels
AddLabel(ShowLabel, if clr > 0 then "Prediction: UP" else
if clr < 0 then "Prediction: Down" else "Prediction: Nutral",
if clr > 0 then Color.GREEN else
if clr < 0 then GlobalColor("red") else Color.DARK_GRAY);
#-- Bar Colors
AssignPriceColor(if !BarColor then Color.CURRENT else
if clr > 0 then GlobalColor("c_green") else
if clr < 0 then GlobalColor("c_red") else Color.DARK_GRAY);
#-- Bubbles

#--- END CODE`````` I added Kernel calc method as well and signals.

The k-nearest neighbors (kNN) algorithm is a method for data classification and prediction, commonly used in data science and algorithmic trading.

It is effective when the training data is large, but determining the main parameter, K (a number of nearest neighbors), can be difficult. In algorithmic trading, kNN performs on par with other techniques like SVM and Random Forest.

The input data is a series of prices over time without any particular features, and the output is the next bar's price.

To compute the algorithm, we need to determine the parameter K, calculate the distance between the instance and all the training samples, rank the distance and determine nearest neighbors based on the K'th minimum distance, gather the values of the nearest neighbors, and use the average of nearest neighbors as the prediction value of the instance.

The original logic of the algorithm was slightly modified, and as a result, it approximates the simple moving average (20).

CODE:

CSS:
``````#// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
#indicator("Machine Learning: kNN (New Approach)",
# Converted and mod by [email protected]    - 03/2023
#//-- Inputs
input BarColor = yes;
input ShowLabel = yes;
input ShowOutcomes  = {"Line", "Predict", default "Both"};    # 'Show Outcomes'
input UseChartTimeframe = yes;
input Resolution    = AggregationPeriod.FIVE_MIN;    # 'Resolution'
input filterType = {"Volatility", "Volume", "Regime", "True Range", "All", default "None"}; # 'Filter Signals by'
input PredictionCalc = {Default "Average", "Rational Quadratic", "gaussian"};
input VolumeThreshold = 49;
input regimeThreshold = -0.1;
input usePrice   = yes;    # 'Use Price Data for Signal Generation?')
input Lag = 2;
input NoOfDataPoints = 10;     # 'No of Data Points'
input NoOfNearestNeighbors = 100;    # 'No of Nearest Neighbors'
input NonRepainting    = no;     # 'Non-Repainting'
input PivotPointLag  = 5;                 # 'Pivot Point Lag'
input zScoreLag  = 20;                # 'Z-Score Lag'

#---
def na = Double.NaN;
def src = ohlc4;    # 'Projection Base'
def agg = GetAggregationPeriod();
def Rep = if NonRepainting then 1 else 0;
def last = IsNaN(close[-Rep]);# and isNaN(close[-2]);
def TF = if UseChartTimeframe then agg else Resolution;
def k = NoOfNearestNeighbors;
def curve   = ShowOutcomes == ShowOutcomes."Line";
def Predict = ShowOutcomes == ShowOutcomes."Predict";
def Both    = ShowOutcomes == ShowOutcomes."Both";
def Avg = PredictionCalc==PredictionCalc."Average";
def h = if UseChartTimeframe then high[Rep] else high(Period = TF)[Rep];
def l = if UseChartTimeframe then low[Rep] else low(Period = TF)[Rep];
def c = if UseChartTimeframe then close[Rep] else close(Period = TF)[Rep];
def v = if UseChartTimeframe then volume[Rep] else volume(Period = TF)[Rep];

#--- Color
DefineGlobalColor("green" , CreateColor(0, 128, 255));
DefineGlobalColor("Red"   , CreateColor(255, 0, 128));
DefineGlobalColor("c_green" , CreateColor(0,153,136));
DefineGlobalColor("c_red"  , CreateColor(204,51,17));
#rationalQuadratic(series float _src, simple int _lookback, simple float _relativeWeight, simple int startAtBar) =>
input _src = close;
input _lookback = 8;
input _relativeWeight = 8;
input startAtBar = 25;
def _currentWeight;# = 0.
def _cumulativeWeight;# = 0.
def size = if !IsNaN(_src) then size + 1 else size;
def _size = if size >= 2000 then 1900 else size;
_currentWeight =  fold i = 0 to _size + startAtBar with p do
p + GetValue(_src, i) * (Power(1 + (Power(i, 2) / ((Power(_lookback, 2) * 2 * _relativeWeight))), -_relativeWeight));
_cumulativeWeight =  fold i1 = 0 to _size + startAtBar with p1 do
p1 +  (Power(1 + (Power(i1, 2) / ((Power(_lookback, 2) * 2 * _relativeWeight))), -_relativeWeight));
def yhat = _currentWeight / _cumulativeWeight;
plot out = yhat;
}
#gaussian(series float _src, simple int _lookback, simple int startAtBar) =>
script gaussian {
input _src = close;
input _lookback = 8;
input startAtBar = 25;
def _currentWeight;# = 0.
def _cumulativeWeight;# = 0.
def size = if !IsNaN(_src) then size + 1 else size;
def _size = if size >= 2000 then 1900 else size;
_currentWeight = fold i = 0 to _size + startAtBar with q do
q +  GetValue(_src, i) * Exp(-Power(i, 2) / (2 * Power(_lookback, 2)));
_cumulativeWeight = fold i1 = 0 to _size + startAtBar with q1 do
q1 + Exp(-Power(i1, 2) / (2 * Power(_lookback, 2)));
def yhat = _currentWeight / _cumulativeWeight;
plot out = yhat;
}
#minimax(ds, p, min, max) =>  // normalize to price
script minimax {
input ds = close;
input p = 10;
input min = low;
input max = high;#  // normalize to price
def hi = Highest(ds, p);
def lo = Lowest(ds, p);
def minimax = (max - min) * (ds - lo) / (hi - lo) + min;
plot out = minimax;
}
#volumeBreak(thres) =>
def rsivol   = RSI(Price = v, Length = 14);
def osc      = HullMovingAvg(rsivol, 10);
def volumeBreak = osc > VolumeThreshold;
#volatilityBreak(volmin, volmax) =>
def tr     = TrueRange(h, c, l);
def atrMin = WildersAverage(tr, 1);
def atrMax = WildersAverage(tr, 10);
def volatilityBreak = atrMin > atrMax;
# @regime_filter
def value1;# = 0.0
def value2;# = 0.0
def klmf;# = 0.0
value1 = 0.2 * (src - src) + 0.8 * (value1);
value2 = 0.1 * (high - low) + 0.8 * (value2);
def omega = AbsValue(value1 / value2);
def alpha = (-power(omega,2) + sqrt(power(omega, 4) + 16 * power(omega,2))) / 8;
klmf = alpha * src + (1 - alpha) * (klmf);
def absCurveSlope = AbsValue(klmf - klmf);
def exponentialAverageAbsCurveSlope = 1.0 * ExpAverage(absCurveSlope, 200);
def normalized_slope_decline = (absCurveSlope - exponentialAverageAbsCurveSlope) / exponentialAverageAbsCurveSlope;
def regime = normalized_slope_decline >= regimeThreshold;
def trFilt = atr(Length=1) > atr(Length=10);
def all = volatilityBreak and volumeBreak and Regime and trFilt;

def filter = if filterType == filterType."Volatility" then volatilityBreak else
if filterType == filterType."Volume" then volumeBreak else
if filterType == filterType."Regime" then Regime else
if filterType == filterType."True Range" then trFilt else
if filterType == filterType."All" then all else yes;
#--- Logic
def nearest_neighbors;

def d = fold i = 0 to NoOfDataPoints - 1 with p do
AbsValue(c[i] - GetValue(c, i + 1));

def size = fold i1 = 0 to NoOfDataPoints  - 1  with p1 do
if !IsNaN(d[i1]) then p1 + 1 else p1;

def new_neighbor = fold i2 = 0 to NoOfDataPoints - 1 with p2 do
if d[i2] < Min(d[i2], If(size[i2] > k, k, 0)) then GetValue(c, i2 + 1) else c[i2];

nearest_neighbors = fold i3 = 0 to NoOfDataPoints - 1 with p3 do
GetValue(new_neighbor, -i3);

def predAvg = Average(nearest_neighbors, NoOfDataPoints);
def predRQ = rationalQuadratic(nearest_neighbors, NoOfDataPoints, NoOfDataPoints, NoOfNearestNeighbors);
def loss   = gaussian(nearest_neighbors, NoOfDataPoints, NoOfNearestNeighbors);

def prediction = if Avg then predAvg else if kernel then predRQ else loss;
def synth_ds = Log(AbsValue(Power(C, 2) - 1) + .5);
def synth = synth_ds;

def scaled_loss = minimax(prediction, NoOfDataPoints - Lag, Lowest(synth, NoOfDataPoints), Highest(synth, NoOfDataPoints));
def scaled_pred = minimax(prediction, NoOfDataPoints, Lowest(synth, NoOfDataPoints), Highest(synth, NoOfDataPoints));

#-- signals
def signal =  if usePrice then
if synth < scaled_loss and filter then -1 else
if synth > scaled_loss and filter then 1 else signal else
if (scaled_loss crosses below scaled_pred) and filter then -1 else
if (scaled_loss crosses above scaled_pred) and filter then 1 else signal;
def changed = (signal - signal);
def hp_counter = if changed then 0 else hp_counter + 1;

def startLongTrade  = changed and signal > 0;
def startShortTrade = changed and signal < 0;

#-- Pred
def dir  = if prediction < c[!AdjustPrediction] then 1 else
if prediction > c[!AdjustPrediction] then -1 else 0;
def ordinary_color = dir;
def ph = if h == Highest(h, PivotPointLag) then h else 0;
def pl = if l == Lowest(l, PivotPointLag)  then l else 0;
def pivot_color = if ph and dir ==  1 then 1 else
if pl and dir == -1 then -1 else 0;
#zscore_color(data, LAGZ, dir) =>
def zs = (C - Average(C, zScoreLag)) / StDev(C, zScoreLag);
def zsCon = zs / (zScoreLag / 5);
def zscore_color = if zsCon > 0 and dir == 1 then 1 else
if zsCon < 0 and dir == -1 then -1 else 0;
#//-- Logic

#def nn     = nearest_neighbors;
def pred   = prediction;
def clr    = if zsc then zscore_color else
if Pvt then pivot_color else ordinary_color;

#//-- Visuals

plot kNNCurve = if IsNaN(close) then na else if (curve or Both) then pred else na;#, 'kNN Curve'
kNNCurve.SetLineWeight(2);
kNNCurve.AssignValueColor(if clr > 0 then GlobalColor("green") else
if clr < 0 then GlobalColor("red") else Color.DARK_GRAY);

plot Predc = if last and last[Rep + 1] and (Predict or Both) then src else na;
Predc.AssignValueColor(if clr > 0 then GlobalColor("green") else
if clr < 0 then GlobalColor("red") else Color.DARK_GRAY);
Predc.SetPaintingStrategy(PaintingStrategy.POINTS);
Predc.SetLineWeight(3);

#--- Labels
AddLabel(ShowLabel, if clr > 0 then "Prediction: UP" else
if clr < 0 then "Prediction: Down" else "Prediction: Nutral",
if clr > 0 then Color.GREEN else
if clr < 0 then GlobalColor("red") else Color.DARK_GRAY);
#-- Bar Colors
AssignPriceColor(if !BarColor then Color.CURRENT else
if clr > 0 then GlobalColor("c_green") else
if clr < 0 then GlobalColor("c_red") else Color.DARK_GRAY);
#-- Bubbles

#--- END CODE``````
This is hot!! Can you create a scan for it to be able to scan when it shows "Long" or "Short"?
Thank you so much in advance! I added Kernel calc method as well and signals.

The k-nearest neighbors (kNN) algorithm is a method for data classification and prediction, commonly used in data science and algorithmic trading.

It is effective when the training data is large, but determining the main parameter, K (a number of nearest neighbors), can be difficult. In algorithmic trading, kNN performs on par with other techniques like SVM and Random Forest.

The input data is a series of prices over time without any particular features, and the output is the next bar's price.

To compute the algorithm, we need to determine the parameter K, calculate the distance between the instance and all the training samples, rank the distance and determine nearest neighbors based on the K'th minimum distance, gather the values of the nearest neighbors, and use the average of nearest neighbors as the prediction value of the instance.

The original logic of the algorithm was slightly modified, and as a result, it approximates the simple moving average (20).

CODE:

CSS:
``````#// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
#indicator("Machine Learning: kNN (New Approach)",
# Converted and mod by [email protected]    - 03/2023
#//-- Inputs
input BarColor = yes;
input ShowLabel = yes;
input ShowOutcomes  = {"Line", "Predict", default "Both"};    # 'Show Outcomes'
input UseChartTimeframe = yes;
input Resolution    = AggregationPeriod.FIVE_MIN;    # 'Resolution'
input filterType = {"Volatility", "Volume", "Regime", "True Range", "All", default "None"}; # 'Filter Signals by'
input PredictionCalc = {Default "Average", "Rational Quadratic", "gaussian"};
input VolumeThreshold = 49;
input regimeThreshold = -0.1;
input usePrice   = yes;    # 'Use Price Data for Signal Generation?')
input Lag = 2;
input NoOfDataPoints = 10;     # 'No of Data Points'
input NoOfNearestNeighbors = 100;    # 'No of Nearest Neighbors'
input NonRepainting    = no;     # 'Non-Repainting'
input PivotPointLag  = 5;                 # 'Pivot Point Lag'
input zScoreLag  = 20;                # 'Z-Score Lag'

#---
def na = Double.NaN;
def src = ohlc4;    # 'Projection Base'
def agg = GetAggregationPeriod();
def Rep = if NonRepainting then 1 else 0;
def last = IsNaN(close[-Rep]);# and isNaN(close[-2]);
def TF = if UseChartTimeframe then agg else Resolution;
def k = NoOfNearestNeighbors;
def curve   = ShowOutcomes == ShowOutcomes."Line";
def Predict = ShowOutcomes == ShowOutcomes."Predict";
def Both    = ShowOutcomes == ShowOutcomes."Both";
def Avg = PredictionCalc==PredictionCalc."Average";
def h = if UseChartTimeframe then high[Rep] else high(Period = TF)[Rep];
def l = if UseChartTimeframe then low[Rep] else low(Period = TF)[Rep];
def c = if UseChartTimeframe then close[Rep] else close(Period = TF)[Rep];
def v = if UseChartTimeframe then volume[Rep] else volume(Period = TF)[Rep];

#--- Color
DefineGlobalColor("green" , CreateColor(0, 128, 255));
DefineGlobalColor("Red"   , CreateColor(255, 0, 128));
DefineGlobalColor("c_green" , CreateColor(0,153,136));
DefineGlobalColor("c_red"  , CreateColor(204,51,17));
#rationalQuadratic(series float _src, simple int _lookback, simple float _relativeWeight, simple int startAtBar) =>
input _src = close;
input _lookback = 8;
input _relativeWeight = 8;
input startAtBar = 25;
def _currentWeight;# = 0.
def _cumulativeWeight;# = 0.
def size = if !IsNaN(_src) then size + 1 else size;
def _size = if size >= 2000 then 1900 else size;
_currentWeight =  fold i = 0 to _size + startAtBar with p do
p + GetValue(_src, i) * (Power(1 + (Power(i, 2) / ((Power(_lookback, 2) * 2 * _relativeWeight))), -_relativeWeight));
_cumulativeWeight =  fold i1 = 0 to _size + startAtBar with p1 do
p1 +  (Power(1 + (Power(i1, 2) / ((Power(_lookback, 2) * 2 * _relativeWeight))), -_relativeWeight));
def yhat = _currentWeight / _cumulativeWeight;
plot out = yhat;
}
#gaussian(series float _src, simple int _lookback, simple int startAtBar) =>
script gaussian {
input _src = close;
input _lookback = 8;
input startAtBar = 25;
def _currentWeight;# = 0.
def _cumulativeWeight;# = 0.
def size = if !IsNaN(_src) then size + 1 else size;
def _size = if size >= 2000 then 1900 else size;
_currentWeight = fold i = 0 to _size + startAtBar with q do
q +  GetValue(_src, i) * Exp(-Power(i, 2) / (2 * Power(_lookback, 2)));
_cumulativeWeight = fold i1 = 0 to _size + startAtBar with q1 do
q1 + Exp(-Power(i1, 2) / (2 * Power(_lookback, 2)));
def yhat = _currentWeight / _cumulativeWeight;
plot out = yhat;
}
#minimax(ds, p, min, max) =>  // normalize to price
script minimax {
input ds = close;
input p = 10;
input min = low;
input max = high;#  // normalize to price
def hi = Highest(ds, p);
def lo = Lowest(ds, p);
def minimax = (max - min) * (ds - lo) / (hi - lo) + min;
plot out = minimax;
}
#volumeBreak(thres) =>
def rsivol   = RSI(Price = v, Length = 14);
def osc      = HullMovingAvg(rsivol, 10);
def volumeBreak = osc > VolumeThreshold;
#volatilityBreak(volmin, volmax) =>
def tr     = TrueRange(h, c, l);
def atrMin = WildersAverage(tr, 1);
def atrMax = WildersAverage(tr, 10);
def volatilityBreak = atrMin > atrMax;
# @regime_filter
def value1;# = 0.0
def value2;# = 0.0
def klmf;# = 0.0
value1 = 0.2 * (src - src) + 0.8 * (value1);
value2 = 0.1 * (high - low) + 0.8 * (value2);
def omega = AbsValue(value1 / value2);
def alpha = (-power(omega,2) + sqrt(power(omega, 4) + 16 * power(omega,2))) / 8;
klmf = alpha * src + (1 - alpha) * (klmf);
def absCurveSlope = AbsValue(klmf - klmf);
def exponentialAverageAbsCurveSlope = 1.0 * ExpAverage(absCurveSlope, 200);
def normalized_slope_decline = (absCurveSlope - exponentialAverageAbsCurveSlope) / exponentialAverageAbsCurveSlope;
def regime = normalized_slope_decline >= regimeThreshold;
def trFilt = atr(Length=1) > atr(Length=10);
def all = volatilityBreak and volumeBreak and Regime and trFilt;

def filter = if filterType == filterType."Volatility" then volatilityBreak else
if filterType == filterType."Volume" then volumeBreak else
if filterType == filterType."Regime" then Regime else
if filterType == filterType."True Range" then trFilt else
if filterType == filterType."All" then all else yes;
#--- Logic
def nearest_neighbors;

def d = fold i = 0 to NoOfDataPoints - 1 with p do
AbsValue(c[i] - GetValue(c, i + 1));

def size = fold i1 = 0 to NoOfDataPoints  - 1  with p1 do
if !IsNaN(d[i1]) then p1 + 1 else p1;

def new_neighbor = fold i2 = 0 to NoOfDataPoints - 1 with p2 do
if d[i2] < Min(d[i2], If(size[i2] > k, k, 0)) then GetValue(c, i2 + 1) else c[i2];

nearest_neighbors = fold i3 = 0 to NoOfDataPoints - 1 with p3 do
GetValue(new_neighbor, -i3);

def predAvg = Average(nearest_neighbors, NoOfDataPoints);
def predRQ = rationalQuadratic(nearest_neighbors, NoOfDataPoints, NoOfDataPoints, NoOfNearestNeighbors);
def loss   = gaussian(nearest_neighbors, NoOfDataPoints, NoOfNearestNeighbors);

def prediction = if Avg then predAvg else if kernel then predRQ else loss;
def synth_ds = Log(AbsValue(Power(C, 2) - 1) + .5);
def synth = synth_ds;

def scaled_loss = minimax(prediction, NoOfDataPoints - Lag, Lowest(synth, NoOfDataPoints), Highest(synth, NoOfDataPoints));
def scaled_pred = minimax(prediction, NoOfDataPoints, Lowest(synth, NoOfDataPoints), Highest(synth, NoOfDataPoints));

#-- signals
def signal =  if usePrice then
if synth < scaled_loss and filter then -1 else
if synth > scaled_loss and filter then 1 else signal else
if (scaled_loss crosses below scaled_pred) and filter then -1 else
if (scaled_loss crosses above scaled_pred) and filter then 1 else signal;
def changed = (signal - signal);
def hp_counter = if changed then 0 else hp_counter + 1;

def startLongTrade  = changed and signal > 0;
def startShortTrade = changed and signal < 0;

#-- Pred
def dir  = if prediction < c[!AdjustPrediction] then 1 else
if prediction > c[!AdjustPrediction] then -1 else 0;
def ordinary_color = dir;
def ph = if h == Highest(h, PivotPointLag) then h else 0;
def pl = if l == Lowest(l, PivotPointLag)  then l else 0;
def pivot_color = if ph and dir ==  1 then 1 else
if pl and dir == -1 then -1 else 0;
#zscore_color(data, LAGZ, dir) =>
def zs = (C - Average(C, zScoreLag)) / StDev(C, zScoreLag);
def zsCon = zs / (zScoreLag / 5);
def zscore_color = if zsCon > 0 and dir == 1 then 1 else
if zsCon < 0 and dir == -1 then -1 else 0;
#//-- Logic

#def nn     = nearest_neighbors;
def pred   = prediction;
def clr    = if zsc then zscore_color else
if Pvt then pivot_color else ordinary_color;

#//-- Visuals

plot kNNCurve = if IsNaN(close) then na else if (curve or Both) then pred else na;#, 'kNN Curve'
kNNCurve.SetLineWeight(2);
kNNCurve.AssignValueColor(if clr > 0 then GlobalColor("green") else
if clr < 0 then GlobalColor("red") else Color.DARK_GRAY);

plot Predc = if last and last[Rep + 1] and (Predict or Both) then src else na;
Predc.AssignValueColor(if clr > 0 then GlobalColor("green") else
if clr < 0 then GlobalColor("red") else Color.DARK_GRAY);
Predc.SetPaintingStrategy(PaintingStrategy.POINTS);
Predc.SetLineWeight(3);

#--- Labels
AddLabel(ShowLabel, if clr > 0 then "Prediction: UP" else
if clr < 0 then "Prediction: Down" else "Prediction: Nutral",
if clr > 0 then Color.GREEN else
if clr < 0 then GlobalColor("red") else Color.DARK_GRAY);
#-- Bar Colors
AssignPriceColor(if !BarColor then Color.CURRENT else
if clr > 0 then GlobalColor("c_green") else
if clr < 0 then GlobalColor("c_red") else Color.DARK_GRAY);
#-- Bubbles

#--- END CODE``````
Your approach looked very interesting. So. I applied it to many stocks. I cant paste a chart in this reply but, can you pull up APPL for example for the many symbols I pulled up. It looks like the prices are going the opposite direction of the L and S fro the historical one year period. But the Prediction for the current bar says up. Perhaps I am not using the system as you suggest. Also, what doe the little do next to the current bar mean? I really appreciate your assistance.

• ChristianS

#### mashume

##### Well-known member
VIP
I was really very interested to see the difference between my version and yours, but echoing bigworm above …. Not a math guy but this looks very different than everything I know of NN. Thanks for the port, though. Always enjoy new toys Have a version of something you can share with us??? I'd be interested to see the differences too!
Thanks,
-mashume

• #### MerryDay

Staff member
Staff
VIP
This script is a conversion of a Tradingview Indicator.
Maybe this is just a bad indicator. Tradingview does have a slew of those.
Maybe the OP is a genius and we aren't seeing it.

To all future posters:
We can't tell you what the OP was thinking when he named this script.
We can't tell you why the OP designed the signals as he had.
I am putting an end to these questions because they are unanswerable on this forum.
You will need to take it up with the OP on Tradingview

If you want to ask questions about what the indicator does or how members are using it,
or you would like some type of customizations, those are allowed.

If you want to share how you are using this indicator, it is appreciated.

Otherwise,
To really get a sense of whether an indicator is valuable, take a look at how it performs across different timeframes and instruments. Analyze its performance over different historical periods. And decide what works best for you!

Last edited:
• samer800 and JoeDV

#### acford2

##### New member
Quick question, this looks awesome, how many candles does this lag, and does it repaint even if you turn the repaint option off?

#### MerryDay

Staff member
Staff
VIP
Quick question, this looks awesome, how many candles does this lag, and does it repaint even if you turn the repaint option off?

The lag is determined by how you configure your settings:
input PivotPointLag = 5; # 'Pivot Point Lag'
input zScoreLag = 20; # 'Z-Score Lag'

I have not worked with this code.
A casual perusal did not find any obvious repainting code.
As with most indicators the current candle will repaint until closed.

When reviewing threads found on the forum. Make note of the ones that have a "repaints" prefix.

If you're encountering something that's giving you some repainting worries. We need you to give us more information. Could you elaborate on what you're seeing? The more details you can provide, the better we'll be able to assist you.

Last edited:

### Not the exact question you're looking for?

87k+ Posts
198 Online ## The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
• Exclusive indicators
• Proven strategies & setups
• Private Discord community
• Exclusive members-only content
• 1 full year of unlimited support

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?