Advertisement
xmd79

Hurst Spectral Analysis Oscillator

Feb 10th, 2023
227
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.17 KB | None | 0 0
  1. // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
  2. // © BarefootJoey
  3.  
  4. // ██████████████████████████████████████████████████████████████████████
  5. // █▄─▄─▀██▀▄─██▄─▄▄▀█▄─▄▄─█▄─▄▄─█─▄▄─█─▄▄─█─▄─▄─███▄─▄█─▄▄─█▄─▄▄─█▄─█─▄█
  6. // ██─▄─▀██─▀─███─▄─▄██─▄█▀██─▄███─██─█─██─███─███─▄█─██─██─██─▄█▀██▄─▄██
  7. // █▄▄▄▄██▄▄█▄▄█▄▄█▄▄█▄▄▄▄▄█▄▄▄███▄▄▄▄█▄▄▄▄██▄▄▄██▄▄▄███▄▄▄▄█▄▄▄▄▄██▄▄▄██
  8.  
  9. //@version=5
  10. indicator('Hurst Spectral Analysis Oscillator', overlay=false, format=format.price, precision=3)
  11.  
  12. //-------------------------------Inputs-------------------------------//
  13. source = input(hl2, 'Source', group="Bandpass Settings")
  14. bandWidth = input.float(0.025, 'Bandwidth', minval=0.0, maxval=1.0, group="Bandpass Settings")
  15. periodBandpassh = input.float(4.3, '5 Day      ', minval=2, inline="1", group="Cycle Settings")
  16. periodBandpassf = input.float(8.5, '10 Day    ', minval=2, inline="2", group="Cycle Settings")
  17. periodBandpass2 = input.float(17, '20 Day    ', minval=2, inline="3", group="Cycle Settings")
  18. periodBandpass4 = input.float(34.1, '40 Day    ', minval=2, inline="4", group="Cycle Settings")
  19. periodBandpass8 = input.float(68.2, '80 Day    ', minval=2, inline="5", group="Cycle Settings")
  20. periodBandpass16 = input.float(136.4, '20 Week ', minval=2, inline="6", group="Cycle Settings")
  21. periodBandpass32 = input.float(272.8, '40 Week ', minval=2, inline="7", group="Cycle Settings")
  22. periodBandpass64 = input.float(545.6, '18 Month', minval=2, inline="8", group="Cycle Settings")
  23. periodBandpass128 = input.float(1636.8, '54 Month', minval=2, inline="9", group="Cycle Settings")
  24. periodBandpass256 = input.float(3273.6, '9 Year    ', minval=2, inline="10", group="Cycle Settings")
  25. periodBandpass512 = input.float(6547.2, '18 Year  ', minval=2, inline="11", group="Cycle Settings")
  26. // Color Selection
  27. colh = input.color(color.purple, " ", inline="1", group="Cycle Settings")
  28. colf = input.color(color.blue, " ", inline="2", group="Cycle Settings")
  29. col2 = input.color(color.aqua, " ", inline="3", group="Cycle Settings")
  30. col4 = input.color(color.green, " ", inline="4", group="Cycle Settings")
  31. col8 = input.color(color.yellow, " ", inline="5", group="Cycle Settings")
  32. col16 = input.color(color.orange, " ", inline="6", group="Cycle Settings")
  33. col32 = input.color(color.red, " ", inline="7", group="Cycle Settings")
  34. col64 = input.color(#856c44, " ", inline="8", group="Cycle Settings")
  35. col128 = input.color(color.black, " ", inline="9", group="Cycle Settings")
  36. col256 = input.color(color.gray, " ", inline="10", group="Cycle Settings")
  37. col512 = input.color(color.white, " ", inline="11", group="Cycle Settings")
  38. colcompu = input.color(color.new(#00ff0a, 70), "Composite Model Candle Colors", inline="12", group="Cycle Settings")
  39. colcompd = input.color(color.new(#ff0000, 70), " ", inline="12", group="Cycle Settings")
  40. // Composite Selection
  41. comph = input.bool(true, "Composite", inline="1", group="Cycle Settings")
  42. compf = input.bool(true, "Composite", inline="2", group="Cycle Settings")
  43. comp2 = input.bool(true, "Composite", inline="3", group="Cycle Settings")
  44. comp4 = input.bool(true, "Composite", inline="4", group="Cycle Settings")
  45. comp8 = input.bool(true, "Composite", inline="5", group="Cycle Settings")
  46. comp16 = input.bool(true, "Composite", inline="6", group="Cycle Settings")
  47. comp32 = input.bool(true, "Composite", inline="7", group="Cycle Settings")
  48. comp64 = input.bool(true, "Composite", inline="8", group="Cycle Settings")
  49. comp128 = input.bool(true, "Composite", inline="9", group="Cycle Settings")
  50. comp256 = input.bool(true, "Composite", inline="10", group="Cycle Settings")
  51. comp512 = input.bool(true, "Composite", inline="11", group="Cycle Settings")
  52. // Analysis Inputs
  53. sig_in = input.string("None", "Bandpass for Analysis", options=["5 Day", "10 Day", "20 Day", "40 Day", "80 Day", "20 Week", "40 Week", "18 Month", "54 Month", "9 Year", "18 Year", "None"], group="Analysis Settings")
  54. decimals = input.int(2, 'Price Decimals', minval=0, maxval=10, group="Analysis Settings")
  55. position = input.string(position.bottom_right, "Analysis Position", [position.top_center, position.top_right, position.middle_right, position.bottom_right, position.bottom_center, position.bottom_left, position.middle_left, position.top_left], group="Analysis Settings")
  56. size = input.string(size.small, "Text Size", [size.tiny, size.small, size.normal, size.large, size.huge], group="Analysis Settings")
  57.  
  58. //-------------------------------Functions & Calculations-------------------------------//
  59. // @TMPascoe found & offered this bandpass by @HPotter found here https://www.tradingview.com/script/A1jhw5fG-Bandpass-Filter/
  60. // @BarefootJoey turned the code into a function and made it accept float Period
  61. bpf(Series, float Period, Delta) =>
  62. float tmpbpf = na
  63. var beta = math.cos(3.14 * (360 / Period) / 180)
  64. var gamma = 1 / math.cos(3.14 * (720 * Delta / Period) / 180)
  65. var alpha = gamma - math.sqrt(gamma * gamma - 1)
  66. tmpbpf := 0.5 * (1 - alpha) * (Series - Series[2]) + beta * (1 + alpha) * nz(tmpbpf[1]) - alpha * nz(tmpbpf[2])
  67. // Individual Bandpass Filters
  68. BPFh = bpf(source, periodBandpassh, bandWidth)
  69. BPFf = bpf(source, periodBandpassf, bandWidth)
  70. BPF2 = bpf(source, periodBandpass2, bandWidth)
  71. BPF4 = bpf(source, periodBandpass4, bandWidth)
  72. BPF8 = bpf(source, periodBandpass8, bandWidth)
  73. BPF16 = bpf(source, periodBandpass16, bandWidth)
  74. BPF32 = bpf(source, periodBandpass32, bandWidth)
  75. BPF64 = bpf(source, periodBandpass64, bandWidth)
  76. BPF128 = bpf(source, periodBandpass128, bandWidth)
  77. BPF256 = bpf(source, periodBandpass256, bandWidth)
  78. BPF512 = bpf(source, periodBandpass512, bandWidth)
  79. // Composite
  80. compBPF = (comph?BPFh:0) + (compf?BPFf:0) + (comp2?BPF2:0) + (comp4?BPF4:0) + (comp8?BPF8:0) + (comp16?BPF16:0) + (comp32?BPF32:0) + (comp64?BPF64:0) + (comp128?BPF128:0) + (comp256?BPF256:0) + (comp512?BPF512:0)
  81. col = ta.change(compBPF) > 0 ? colcompu : colcompd
  82.  
  83. // Cycle Analysis
  84. // Truncate Decimals
  85. truncate(number, pricedecimals) =>
  86. factor = math.pow(10, pricedecimals)
  87. int(number * factor) / factor
  88. // Switch output/plot for analytics
  89. sig_out = sig_in == "5 Day" ? BPFh : sig_in == "10 Day" ? BPFf : sig_in == "20 Day" ? BPF2 : sig_in == "40 Day" ? BPF4 : sig_in == "80 Day" ? BPF8 : sig_in == "20 Week" ? BPF16 : sig_in == "40 Week" ? BPF32 : sig_in == "18 Month" ? BPF64 : sig_in == "54 Month" ? BPF128 : sig_in == "9 Year" ? BPF256 : sig_in == "18 Year" ? BPF512 : na
  90. period_out = sig_in == "5 Day" ? periodBandpassh : sig_in == "10 Day" ? periodBandpassf : sig_in == "20 Day" ? periodBandpass2 : sig_in == "40 Day" ? periodBandpass4 : sig_in == "80 Day" ? periodBandpass8 : sig_in == "20 Week" ? periodBandpass16 : sig_in == "40 Week" ? periodBandpass32 : sig_in == "18 Month" ? periodBandpass64 : sig_in == "54 Month" ? periodBandpass128 : sig_in == "9 Year" ? periodBandpass256 : sig_in == "18 Year" ? periodBandpass512 : 1 // :na
  91. col_out = sig_in == "5 Day" ? colh : sig_in == "10 Day" ? colf : sig_in == "20 Day" ? col2 : sig_in == "40 Day" ? col4 : sig_in == "80 Day" ? col8 : sig_in == "20 Week" ? col16 : sig_in == "40 Week" ? col32 : sig_in == "18 Month" ? col64 : sig_in == "54 Month" ? col128 : sig_in == "9 Year" ? col256 : sig_in == "18 Year" ? col512 : color.gray
  92. // Highs/Lows
  93. hi = sig_out[2]<sig_out[1] and sig_out[1]>sig_out
  94. lo = sig_out[2]>sig_out[1] and sig_out[1]<sig_out
  95. // Define Crosses
  96. midcross = ta.cross(sig_out, 0)
  97. midcrossbars = ta.barssince(midcross)
  98. midcrossbars2 = ta.barssince(midcross)[1]
  99. last_wavelength = ta.barssince(midcross) - ta.barssince(midcross)
  100. // Bars Since Last Amp Hi & Lo
  101. xhi = ta.barssince(hi)
  102. xlo = ta.barssince(lo)
  103. // Wavelength
  104. wavelength = math.round(math.abs(xhi-xlo)*2)
  105. // Last Amp Hi & Lo
  106. bpfphi = ta.highest(sig_out,math.round(period_out))
  107. bpfamphi = ta.valuewhen(bpfphi, sig_out, 0)
  108. bpfplo = ta.lowest(sig_out,math.round(period_out))
  109. bpfamplo = ta.valuewhen(bpfplo, sig_out, 0)
  110. tot_amp = bpfphi - bpfplo
  111. // Estimates/Forecasts
  112. next_peak = -math.abs(xhi-wavelength)
  113. next_trough = -math.abs(xlo-wavelength)
  114. next_node = math.abs(xhi-xlo)-midcrossbars
  115. // Highlight background of next peak/node/trough
  116. next_peak_col = color.new(color.red,hi?75:100)
  117. next_node_col = color.new(color.gray, midcross?75:100)
  118. next_trough_col = color.new(color.green, lo?75:100)
  119. // Sentiment
  120. amp_sent = bpfphi>math.abs(bpfplo)?"🟢":bpfphi<math.abs(bpfplo)?"🔴":"⚪"
  121. bbwavelen = wavelength>period_out?"🟢":wavelength<period_out?"🔴":"⚪"
  122. bbpt = -next_peak<-next_trough?"Bullish🟢":-next_peak>-next_trough?"Bearish🔴":"Neutral⚪"
  123. // Analytics Tooltip 📏🧮⏳🎰🤖🎭🔮📈📉🔁🌊🔴🟢⚪
  124. labeltt= "🔄 Cycle: " + str.tostring(sig_in) + "/" + str.tostring(period_out) + " bars" +
  125. "\n📏 Period (⊺): ~" + str.tostring(math.abs(xhi-xlo)) + " bars" +
  126. "\n🌊 Wavelength (λ): ~" + str.tostring(wavelength) + " bars " + bbwavelen +
  127. "\n⚖ Delta (∆) Amplitude (ª): " + str.tostring(truncate(tot_amp, decimals)) + " " + amp_sent +
  128. "\n📈 Peak (ª): " + str.tostring(truncate(bpfphi, decimals)) + ", " + str.tostring(xhi) + " bars ago" +
  129. "\n🔀 Node: " + str.tostring(midcrossbars) + " bars ago" +
  130. "\n📉 Trough (ª): " + str.tostring(truncate(bpfplo, decimals)) + ", " + str.tostring(xlo) + " bars ago" +
  131. "\n\n🔮 Estimates: " + bbpt +
  132. "\n📈 Next Peak: " + str.tostring(-next_peak) + "ish bars " +
  133. "\n🔀 Next Node: " + str.tostring(next_node) + "ish bars" +
  134. "\n📉 Next Trough: " + str.tostring(-next_trough) + "ish bars "
  135.  
  136. // ------------------------------- Plots, Displays, Outputs -------------------------------//
  137. plot(0, "Midline", color.new(color.gray,30), style=plot.style_histogram)
  138. plot(BPFh, '5 Day', color=color.new(colh, 0), linewidth=sig_in == "5 Day" ? 3 : 1)
  139. plot(BPFf, '10 Day', color=color.new(colf, 0), linewidth=sig_in == "10 Day" ? 3 : 1)
  140. plot(BPF2, '20 Day', color=color.new(col2, 0), linewidth=sig_in == "20 Day" ? 3 : 1)
  141. plot(BPF4, '40 Day', color=color.new(col4, 0), linewidth=sig_in == "40 Day" ? 3 : 1)
  142. plot(BPF8, '80 Day', color=color.new(col8, 0), linewidth=sig_in == "80 Day" ? 3 : 1)
  143. plot(BPF16, '20 Week', color=color.new(col16, 0), linewidth=sig_in == "20 Week" ? 3 : 1)
  144. plot(BPF32, '40 Week', color=color.new(col32, 0), linewidth=sig_in == "40 Week" ? 3 : 1)
  145. plot(BPF64, '18 Month', color=color.new(col64, 0), linewidth=sig_in == "18 Month" ? 3 : 1)
  146. plot(BPF128, '54 Month', color=color.new(col128, 0), linewidth=sig_in == "54 Month" ? 3 : 1, display=display.none)
  147. plot(BPF256, '9 Year', color=color.new(col256, 0), linewidth=sig_in == "9 Year" ? 3 : 1, display=display.none)
  148. plot(BPF512, '18 Year', color=color.new(col512, 0), linewidth=sig_in == "18 Year" ? 3 : 1, display=display.none)
  149.  
  150. plotcandle(compBPF[1], ta.lowest(compBPF,1), math.min(compBPF,compBPF[1]), compBPF, color=col, wickcolor=color.new(col,100), bordercolor=col, title='Composite Candles', display=display.none)
  151.  
  152. bgcolor(color=next_peak_col, title="Peak Estimate", offset=wavelength)
  153. bgcolor(color=next_node_col, title="Node Estimate", offset=wavelength)
  154. bgcolor(color=next_trough_col, title="Trough Estimate", offset=wavelength)
  155.  
  156. plotshape(hi, "Actual Peak", shape.triangledown, location.top, color.rgb(255, 0, 0, 33), size=size.tiny)
  157. plotshape(lo, "Actual Trough", shape.triangleup, location.bottom, color.rgb(0, 255, 8, 33), size=size.tiny)
  158.  
  159. var table Ticker = na
  160. table.delete(Ticker)
  161. Ticker := table.new(position, 1, 1)
  162. if barstate.islast
  163. table.cell(Ticker, 0, 0,
  164. text = "🔄 Cycle Analysis",
  165. text_size = size,
  166. text_color = color.new(col_out,0),
  167. tooltip = sig_in!="None"?labeltt:"No Bandpass selected. Double click to open & change Settings.")
  168.  
  169. // EoS made w/ ❤ by @BarefootJoey ✌💗📈
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement