本页源码来自 TradingView 公开发布的开源脚本,版权归原作者所有, 请遵循其原始许可(Pine 脚本常见 CC BY-NC-SA / MPL-2.0 / MIT)。 本项目仅用于研究检索与许可范围内的移植。
// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/
// © Zeiierman
//@version=5
indicator(title='Machine Learning Momentum Index (MLMI) [Zeiierman]', shorttitle='Machine Learning Momentum Index (MLMI)', overlay=false, precision=1)
// ~~ ToolTips {
t1 ="This parameter controls the number of neighbors to consider while making a prediction using the k-Nearest Neighbors (k-NN) algorithm. By modifying the value of k, you can change how sensitive the prediction is to local fluctuations in the data. \n\nA smaller value of k will make the prediction more sensitive to local variations and can lead to a more erratic prediction line. \n\nA larger value of k will consider more neighbors, thus making the prediction more stable but potentially less responsive to sudden changes."
t2 ="The parameter controls the length of the trend used in computing the momentum. This length refers to the number of periods over which the momentum is calculated, affecting how quickly the indicator reacts to changes in the underlying price movements. \n\nA shorter trend length (smaller momentumWindow) will make the indicator more responsive to short-term price changes, potentially generating more signals but at the risk of more false alarms. \n\nA longer trend length (larger momentumWindow) will make the indicator smoother and less responsive to short-term noise, but it may lag in reacting to significant price changes."
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Input Parameters {
numNeighbors = input(200, title='Prediction Data (k)', tooltip=t1)
momentumWindow = input.int(20, step=2, minval=10, maxval=200, title='Trend Length', tooltip=t2)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Moving Averages & RSI {
MA_quick = ta.wma(close, 5)
MA_slow = ta.wma(close, 20)
rsi_quick = ta.wma(ta.rsi(close, 5),momentumWindow)
rsi_slow = ta.wma(ta.rsi(close, 20),momentumWindow)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Crossover Conditions {
pos = ta.crossover(MA_quick, MA_slow)
neg = ta.crossunder(MA_quick, MA_slow)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Type Definition {
type Data
array<float> parameter1
array<float> parameter2
array<float> priceArray
array<float> resultArray
// Create a Data object
var data = Data.new(array.new_float(1, 0), array.new_float(1, 0), array.new_float(1, 0), array.new_float(1, 0))
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Method that saves the last trade and temporarily holds the current one. {
method storePreviousTrade(Data d, p1, p2) =>
d.parameter1.push(d.parameter1.get(d.parameter1.size() - 1))
d.parameter2.push(d.parameter2.get(d.parameter2.size() - 1))
d.priceArray.push(d.priceArray.get(d.priceArray.size() - 1))
d.resultArray.push(close >= d.priceArray.get(d.priceArray.size() - 1) ? 1 : -1)
d.parameter1.set(d.parameter1.size() - 1, p1)
d.parameter2.set(d.parameter2.size() - 1, p2)
d.priceArray.set(d.priceArray.size() - 1, close)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Method to Make Prediction {
method knnPredict(Data d, p1, p2, k) =>
// Create a Distance Array
distances = array.new_float(0)
n = d.parameter1.size() - 1
for i = 0 to n
distance = math.sqrt(math.pow(p1 - d.parameter1.get(i), 2) + math.pow(p2 - d.parameter2.get(i), 2))
distances.push(distance)
// Get Neighbors
sortedDistances = distances.copy()
sortedDistances.sort()
selectedDistances = sortedDistances.slice( 0, math.min(k, sortedDistances.size()))
maxDist = selectedDistances.max()
neighbors = array.new_float(0)
for i = 0 to distances.size() - 1
if distances.get(i) <= maxDist
neighbors.push(d.resultArray.get(i))
// Return Prediction
prediction = neighbors.sum()
prediction
if pos or neg
data.storePreviousTrade(rsi_slow, rsi_quick)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Plots {
prediction = data.knnPredict(rsi_slow, rsi_quick, numNeighbors)
prediction_= plot(prediction, color=color.new(#426eff, 0), title="MLMI Prediction")
plot(ta.wma(prediction, 20), color=color.new(#31ffc8, 0), title="WMA of MLMI Prediction")
hline(0, title="Mid Level")
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Gradient Fill {
upper = ta.highest(prediction,2000)
lower = ta.lowest(prediction,2000)
upper_ = upper - ta.ema(ta.stdev(prediction,20),20)
lower_ = lower + ta.ema(ta.stdev(prediction,20),20)
channel_upper = plot(upper, color = na, editable = false, display = display.none)
channel_lower = plot(lower, color = na, editable = false, display = display.none)
channel_mid = plot(0, color = na, editable = false, display = display.none)
// ~~ Channel Gradient Fill {
fill(channel_mid, channel_upper, top_value = upper, bottom_value = 0, bottom_color = na, top_color = color.new(color.lime,75),title = "Channel Gradient Fill")
fill(channel_mid, channel_lower, top_value = 0, bottom_value = lower, bottom_color = color.new(color.red,75) , top_color = na,title = "Channel Gradient Fill")
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Overbought/Oversold Gradient Fill {
fill(prediction_, channel_mid, upper, upper_, top_color = color.new(color.lime, 0), bottom_color = color.new(color.green, 100),title = "Overbought Gradient Fill")
fill(prediction_, channel_mid, lower_, lower, top_color = color.new(color.red, 100), bottom_color = color.new(color.red, 0),title = "Oversold Gradient Fill")
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}