Advertisement
xmd79

Machine Learning: Trend Pulse

Aug 31st, 2023
252
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.13 KB | None | 0 0
  1. //@version=5
  2. indicator("Machine Learning: Trend Pulse", overlay=false)
  3.  
  4. // Input Setup
  5. winSpan = input(70, "Window Size", tooltip="Length of the window for comparing historical price changes.")
  6. k_neighbors = input(30, "Count of k-nearest Neighbors", tooltip="Number of nearest neighbors to consider for estimating the price.")
  7. sampleSpeed = input(40, "Sampling Rate", tooltip="The step size for sampling historical data points.")
  8. histCap = input(100, "Historical Cap", tooltip="The maximum number of past bars to consider for estimation.")
  9.  
  10. // Calculate mean and standard deviation of close prices
  11. avgClose = ta.sma(close, histCap)
  12. stdDevClose = ta.stdev(close, histCap)
  13.  
  14. // Feature extraction: get the last 'winSpan' price changes
  15. deltaPrice(idx) =>
  16. if idx < winSpan
  17. 0.0
  18. else
  19. close[idx] - close[idx - winSpan]
  20.  
  21. // Calculate distance between two windows, using Euclidean distance to measure the similarity between two windows of price changes
  22. // 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.
  23. findDistance(i1, i2) =>
  24. total = 0.0
  25. for i = 0 to winSpan - 1
  26. total := total + math.pow(deltaPrice(i1 - i) - deltaPrice(i2 - i), 2)
  27. math.sqrt(total)
  28.  
  29. // k-NN forecast by sampleSpeed
  30. estimatePrice(id) =>
  31. distArray = array.new_float(0)
  32. for i = winSpan to math.min(id - 1, histCap) by sampleSpeed
  33. array.push(distArray, findDistance(id, i))
  34.  
  35. estimateSum = 0.0
  36. minDist = 99999999.0
  37. minIndex = 0
  38. for j = 1 to k_neighbors
  39. minDist := 99999999.0
  40. minIndex := 0
  41. for m = 0 to array.size(distArray) - 1
  42. if array.get(distArray, m) < minDist
  43. minDist := array.get(distArray, m)
  44. minIndex := m
  45. estimateSum := estimateSum + close[minIndex + 1]
  46. array.set(distArray, minIndex, 99999999.0)
  47.  
  48. // Scale the forecast using z-score
  49. (estimateSum / k_neighbors - avgClose) / stdDevClose * 10 + 50
  50.  
  51. // Calculate estimate and plot
  52. finalEstimate = estimatePrice(bar_index)
  53.  
  54. // Plots
  55. emaplot = plot(finalEstimate, title='Predicted Price', color = color.new(#7c7677, 80), linewidth = 1)
  56.  
  57. // Plots an invisible line at the level of 50 for gradient fills later.
  58. midLinePlot = plot(50, color = na, editable = false, display = display.none)
  59.  
  60. /// Fill the space between the prediction and the mid-line (level 50) with gradients, giving a nice visual indication of 'overbought' and 'oversold' regions.
  61. fill(emaplot, midLinePlot, 70, 60, top_color = color.new(#2a3332, 75), bottom_color = color.new(#6ca800, 100), title = "Overbought Gradient Fill")
  62. fill(emaplot, midLinePlot, 50, 20, top_color = color.new(#a83c91, 100), bottom_color =color.rgb(212, 33, 33), title = "Oversold Gradient Fill")
  63.  
  64. // Plot horizontal lines at levels 20, 50, and 80 to clearly define the 'oversold', 'middle', and 'overbought' regions.
  65. hline(20, color = color.new(#8b3131, 50))
  66. hline(50, color = color.new(color.gray, 50))
  67. hline(80, color = color.new(#2c5c2e, 50))
  68.  
  69. // Bool
  70. showlb = input.bool(false, 'Show Direction prediction?', tooltip = 'display the predicted direction of movement')
  71.  
  72. // Label
  73. if showlb and bar_index == bar_index
  74. predictionDirection = finalEstimate > finalEstimate[1] ? "u" : "d"
  75. predictionColor = finalEstimate > finalEstimate[1] ? color.rgb(41, 92, 80) : color.rgb(85, 31, 54)
  76. label.new(x=bar_index, y=80, text="" + predictionDirection, color=predictionColor, style=label.style_label_center, size = size.tiny)
  77.  
  78. // Get plots
  79. upper = ta.highest(finalEstimate,6)
  80. lower = ta.lowest(finalEstimate,6)
  81. plot(upper, color=color.rgb(23, 49, 33,70))
  82. channel_upper = plot(upper, color = na, editable = false, display = display.none)
  83. channel_lower = plot(lower, color = na, editable = false, display = display.none)
  84. channel_mid = plot(0, color = na, editable = false, display = display.none)
  85.  
  86. // Fill
  87. 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")
  88.  
  89.  
  90.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement