Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //@version=5
- indicator("Machine Learning: Trend Pulse", overlay=false)
- // Input Setup
- winSpan = input(70, "Window Size", tooltip="Length of the window for comparing historical price changes.")
- k_neighbors = input(30, "Count of k-nearest Neighbors", tooltip="Number of nearest neighbors to consider for estimating the price.")
- sampleSpeed = input(40, "Sampling Rate", tooltip="The step size for sampling historical data points.")
- histCap = input(100, "Historical Cap", tooltip="The maximum number of past bars to consider for estimation.")
- // Calculate mean and standard deviation of close prices
- avgClose = ta.sma(close, histCap)
- stdDevClose = ta.stdev(close, histCap)
- // Feature extraction: get the last 'winSpan' price changes
- deltaPrice(idx) =>
- if idx < winSpan
- 0.0
- else
- close[idx] - close[idx - winSpan]
- // Calculate distance between two windows, using Euclidean distance to measure the similarity between two windows of price changes
- // Lorentzian Distance, Manhattan Distance, Chebyshev Distance - these are all distances tested and make miniature changes, no point to add them here as options to choose.
- findDistance(i1, i2) =>
- total = 0.0
- for i = 0 to winSpan - 1
- total := total + math.pow(deltaPrice(i1 - i) - deltaPrice(i2 - i), 2)
- math.sqrt(total)
- // k-NN forecast by sampleSpeed
- estimatePrice(id) =>
- distArray = array.new_float(0)
- for i = winSpan to math.min(id - 1, histCap) by sampleSpeed
- array.push(distArray, findDistance(id, i))
- estimateSum = 0.0
- minDist = 99999999.0
- minIndex = 0
- for j = 1 to k_neighbors
- minDist := 99999999.0
- minIndex := 0
- for m = 0 to array.size(distArray) - 1
- if array.get(distArray, m) < minDist
- minDist := array.get(distArray, m)
- minIndex := m
- estimateSum := estimateSum + close[minIndex + 1]
- array.set(distArray, minIndex, 99999999.0)
- // Scale the forecast using z-score
- (estimateSum / k_neighbors - avgClose) / stdDevClose * 10 + 50
- // Calculate estimate and plot
- finalEstimate = estimatePrice(bar_index)
- // Plots
- emaplot = plot(finalEstimate, title='Predicted Price', color = color.new(#7c7677, 80), linewidth = 1)
- // Plots an invisible line at the level of 50 for gradient fills later.
- midLinePlot = plot(50, color = na, editable = false, display = display.none)
- /// Fill the space between the prediction and the mid-line (level 50) with gradients, giving a nice visual indication of 'overbought' and 'oversold' regions.
- fill(emaplot, midLinePlot, 70, 60, top_color = color.new(#2a3332, 75), bottom_color = color.new(#6ca800, 100), title = "Overbought Gradient Fill")
- fill(emaplot, midLinePlot, 50, 20, top_color = color.new(#a83c91, 100), bottom_color =color.rgb(212, 33, 33), title = "Oversold Gradient Fill")
- // Plot horizontal lines at levels 20, 50, and 80 to clearly define the 'oversold', 'middle', and 'overbought' regions.
- hline(20, color = color.new(#8b3131, 50))
- hline(50, color = color.new(color.gray, 50))
- hline(80, color = color.new(#2c5c2e, 50))
- // Bool
- showlb = input.bool(false, 'Show Direction prediction?', tooltip = 'display the predicted direction of movement')
- // Label
- if showlb and bar_index == bar_index
- predictionDirection = finalEstimate > finalEstimate[1] ? "u" : "d"
- predictionColor = finalEstimate > finalEstimate[1] ? color.rgb(41, 92, 80) : color.rgb(85, 31, 54)
- label.new(x=bar_index, y=80, text="" + predictionDirection, color=predictionColor, style=label.style_label_center, size = size.tiny)
- // Get plots
- upper = ta.highest(finalEstimate,6)
- lower = ta.lowest(finalEstimate,6)
- plot(upper, color=color.rgb(23, 49, 33,70))
- 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)
- // Fill
- fill(channel_mid, channel_upper, top_value = upper, bottom_value = 0, bottom_color = na, top_color = color.new(#00c4e6, 85),title = "Channel Gradient Fill 11")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement