xmd79

Goertzel Browser [Loxx]

May 23rd, 2023
243
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 26.59 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. // © loxx
  3.  
  4. //@version=5
  5. indicator("Goertzel Browser [Loxx]", overlay = false, max_lines_count = 500)
  6.  
  7. color greencolor = #2DD204
  8. color redcolor = #D2042D
  9.  
  10. string hpsmth = "Hodrick-Prescott Filter Smoothing"
  11. string zlagsmth = "Zero-lag Moving Average Smoothing"
  12.  
  13. string hpsmthdt = "Hodrick-Prescott Filter Detrending"
  14. string zlagsmthdt = "Zero-lag Moving Average Detrending"
  15. string logZlagRegression = "Logarithmic Zero-lag Moving Average Regression Detrending"
  16.  
  17. string none = "None"
  18.  
  19. // Zero-lag moving average
  20. zeroLagMA(float[] src, int SmoothPer, int BarsTaken)=>
  21. float sum = 0
  22. float sumw = 0
  23. float weight = 0
  24. float[] lwma1 = array.new<float>(BarsTaken, 0)
  25. float[] output = array.new<float>(BarsTaken, 0)
  26. for i = BarsTaken - 1 to 0
  27. for k = 0 to SmoothPer - 1
  28. if i + k >= 0 and i + k < BarsTaken - 1
  29. weight := SmoothPer - k
  30. sumw += weight
  31. sum += weight * array.get(src, i + k)
  32. if sumw != 0
  33. array.set(lwma1, i, sum / sumw)
  34. else
  35. array.set(lwma1, i, 0)
  36. sum := 0
  37. sumw := 0
  38. weight := 0
  39. for i = 0 to BarsTaken - 1
  40. for k = 0 to SmoothPer - 1
  41. if i - k >= 0
  42. weight := SmoothPer - k
  43. sumw += weight
  44. sum += weight * array.get(lwma1, i - k)
  45. if sumw != 0
  46. array.set(output, i, sum / sumw)
  47. else
  48. array.set(output, i, 0)
  49. output
  50.  
  51. // Bartels probability
  52. bartelsProb(int n, int N, Bvalues)=>
  53. float AvgCoeffA = 0
  54. float AvgCoeffB = 0
  55. float AvgIndAmplit = 0
  56. float AvgAmpl = 0
  57. float ExptAmpl = 0
  58. float ARatio = 0
  59. float BP = 0
  60. float[] teta = array.new<float>(n, 0)
  61. float[] vsin = array.new<float>(n, 0)
  62. float[] vcos = array.new<float>(n, 0)
  63. float[] CoeffA = array.new<float>(N, 0)
  64. float[] CoeffB = array.new<float>(N, 0)
  65. float[] IndAmplit = array.new<float>(N, 0)
  66. for i = 0 to n - 1
  67. array.set(teta, i, 1.0 * (i + 1) / n * 2 * math.pi)
  68. array.set(vsin, i, math.sin(array.get(teta, i)))
  69. array.set(vcos, i, math.cos(array.get(teta, i)))
  70. for t = 0 to N - 1
  71. for i = 0 to n - 1
  72. array.set(CoeffA, t, array.get(CoeffA, t) + array.get(vsin, i) * array.get(Bvalues, t * n + i))
  73. array.set(CoeffB, t, array.get(CoeffB, t) + array.get(vcos, i) * array.get(Bvalues, t * n + i))
  74. array.set(IndAmplit, t, math.pow(array.get(CoeffA, t), 2) + math.pow(array.get(CoeffB, t), 2))
  75. for t = 0 to N - 1
  76. AvgCoeffA += array.get(CoeffA, t)
  77. AvgCoeffB += array.get(CoeffB, t)
  78. AvgIndAmplit += array.get(IndAmplit, t)
  79. AvgCoeffA := AvgCoeffA / N
  80. AvgCoeffB := AvgCoeffB / N
  81. AvgAmpl := math.sqrt(math.pow(AvgCoeffA, 2) + math.pow(AvgCoeffB, 2))
  82. AvgIndAmplit := math.sqrt(AvgIndAmplit / N)
  83. ExptAmpl := AvgIndAmplit / math.sqrt(1.0 * N)
  84. ARatio := AvgAmpl / ExptAmpl
  85. BP := 1 / math.exp(math.pow(ARatio, 2))
  86. BP
  87.  
  88. // Detrend Logrithmic Zero-lag Regression
  89. detrendLnZeroLagRegression(float[] src, int SmoothPer, int BarsTaken)=>
  90. float[] RegValue = array.new<float>(BarsTaken, 0)
  91. float[] output = array.new<float>(BarsTaken, 0)
  92. float[] calcValues = zeroLagMA(src, SmoothPer, BarsTaken)
  93. for i = 0 to BarsTaken - 1
  94. array.set(calcValues, i, math.log( array.get(calcValues, i) ) * 100)
  95. float val1 = 0
  96. float val2 = 0
  97. float val3 = 0
  98. float sumy = 0
  99. float sumx = 0
  100. float sumxy = 0
  101. float sumx2 = 0
  102. for i = 0 to BarsTaken - 1
  103. sumy += array.get(calcValues, i)
  104. sumx += i
  105. sumxy += i * array.get(calcValues, i)
  106. sumx2 += i * i
  107. val3 := sumx2 * BarsTaken - sumx * sumx
  108.  
  109. if val3 != 0.0
  110. val2 := (sumxy * BarsTaken - sumx * sumy) / val3
  111. val1 := (sumy - sumx * val2) / BarsTaken
  112. for i = 0 to BarsTaken - 1
  113. array.set(RegValue, i, val1 + val2 * i)
  114. for i = 0 to BarsTaken - 1
  115. array.set(output, i, array.get(calcValues, i) - array.get(RegValue, i))
  116.  
  117. output
  118.  
  119. // Bartels cycle significance test
  120. bartelsCycleTest(float[] src, int G, float[] cyclebuffer, float[] BartelsProb, BartNoCycles, BartSmoothPer)=>
  121. for k = 0 to G - 1
  122. int bpi = math.round(array.get(cyclebuffer, k))
  123. if bpi > 0
  124. bval = detrendLnZeroLagRegression(src, BartSmoothPer, bpi * BartNoCycles)
  125. array.set(BartelsProb, k, (1 - bartelsProb(bpi, BartNoCycles, bval)) * 100)
  126. BartelsProb
  127.  
  128. // Goertzel Browser
  129. goertzel(float[] src, simple int forBar, simple int samplesize, simple int per, simple bool squaredAmp, simple bool useAddition,
  130. simple bool useCosine, simple bool UseCycleStrength, int WindowSizePast,
  131. int WindowSizeFuture, simple bool FilterBartels,
  132. simple int BartNoCycles, simple int BartSmoothPer, simple int BartSigLimit,
  133. simple bool SortBartels, matrix<float> goeWorkPast, matrix<float> goeWorkFuture, float[] cyclebuffer,
  134. float[] amplitudebuffer, float[] phasebuffer, float[] cycleBartelsBuffer)=>
  135.  
  136. int sample = 2 * per
  137. float[] goeWork1 = array.new_float(sample + 1, 0.)
  138. float[] goeWork2 = array.new_float(sample + 1, 0.)
  139. float[] goeWork3 = array.new_float(sample + 1, 0.)
  140. float[] goeWork4 = array.new_float(sample + 1, 0.)
  141.  
  142. float temp1 = array.get(src, forBar + sample - 1)
  143. float temp2 = (array.get(src, forBar) - temp1) / (sample - 1)
  144. float temp3 = 0.
  145.  
  146. for k = sample - 1 to 1
  147. float temp = array.get(src, forBar + k - 1) - (temp1 + temp2 * (sample - k))
  148. array.set(goeWork4, k, temp)
  149. array.set(goeWork3, k, 0.)
  150.  
  151. array.set(goeWork3, 0, 0)
  152.  
  153. for k = 2 to per
  154. float w = 0
  155. float x = 0
  156. float y = 0
  157. float z = math.pow(k, -1)
  158.  
  159. temp1 := 2.0 * math.cos(2.0 * math.pi * z)
  160.  
  161. for i = sample to 1
  162. w := temp1 * x - y + nz(array.get(goeWork4, i))
  163. y := x
  164. x := w
  165.  
  166. temp2 := x - y / 2.0 * temp1
  167. if temp2 == 0.0
  168. temp2 := 0.0000001
  169.  
  170. temp3 := y * math.sin(2.0 * math.pi * z)
  171.  
  172. //Cycle Strength = Cycle Amplitude/ Cycle Length
  173. //as described in “Decoding the Hidden Market Rhythm.
  174. //For trading it is more important to know which cycle
  175. //has the biggest influence to drive the price per bar,
  176. //and not only which cycle has the highest amplitude
  177.  
  178. if UseCycleStrength
  179. if squaredAmp
  180. array.set(goeWork1, k, (math.pow(temp2, 2) + math.pow(temp3, 2)) / k)
  181. else
  182. array.set(goeWork1, k, (math.sqrt(math.pow(temp2, 2) + math.pow(temp3, 2))) / k)
  183. array.set(goeWork2, k, math.atan(temp3 / temp2))
  184. else
  185. if squaredAmp
  186. array.set(goeWork1, k, math.pow(temp2, 2) + math.pow(temp3, 2))
  187. else
  188. array.set(goeWork1, k, math.sqrt(math.pow(temp2, 2) + math.pow(temp3, 2)))
  189. array.set(goeWork2, k, math.atan(temp3 / temp2))
  190.  
  191. if temp2 < 0.0
  192. array.set(goeWork2, k, nz(array.get(goeWork2, k)) + math.pi)
  193. else
  194. if temp3 < 0.0
  195. array.set(goeWork2, k, nz(array.get(goeWork2, k)) + 2.0 * math.pi)
  196.  
  197. for k = 3 to per - 1
  198. if (nz(array.get(goeWork1, k)) > nz(array.get(goeWork1, k + 1)) and nz(array.get(goeWork1, k)) > nz(array.get(goeWork1, k - 1)))
  199. array.set(goeWork3, k, k * math.pow(10, -4))
  200. else
  201. array.set(goeWork3, k, 0.0)
  202.  
  203. // extract cycles
  204. int number_of_cycles = 0
  205. for i = 0 to per + 1
  206. if nz(array.get(goeWork3, i)) > 0.0
  207. number_of_cycles += 1
  208. array.set(cyclebuffer, number_of_cycles, math.round(10000.0 * array.get(goeWork3, i)))
  209. array.set(amplitudebuffer, number_of_cycles, array.get(goeWork1, i))
  210. array.set(phasebuffer, number_of_cycles, array.get(goeWork2, i))
  211.  
  212. // order cycles acc. largest amplitude or cycle strength
  213. if number_of_cycles >= 1
  214. for i = 1 to number_of_cycles - 1
  215. for k = i + 1 to number_of_cycles
  216. if array.get(amplitudebuffer, k) > array.get(amplitudebuffer, i)
  217. y = array.get(amplitudebuffer, i)
  218. w = array.get(cyclebuffer, i)
  219. x = array.get(phasebuffer, i)
  220. array.set(amplitudebuffer, i, array.get(amplitudebuffer, k))
  221. array.set(cyclebuffer, i, array.get(cyclebuffer, k))
  222. array.set(phasebuffer, i, array.get(phasebuffer, k))
  223. array.set(amplitudebuffer, k, y)
  224. array.set(cyclebuffer, k, w)
  225. array.set(phasebuffer, k, x)
  226.  
  227. // Execute Bartels test for cycle significance
  228. if FilterBartels
  229. bartelsCycleTest(src, number_of_cycles, cyclebuffer, cycleBartelsBuffer, BartNoCycles, BartSmoothPer)
  230. int no_Bcycles = 0
  231. float v = 0
  232. //Filter significant cycles
  233. for i = 0 to number_of_cycles - 1
  234. if array.get(cycleBartelsBuffer, i) > BartSigLimit
  235. array.set(amplitudebuffer, no_Bcycles, array.get(amplitudebuffer, i))
  236. array.set(cyclebuffer, no_Bcycles, array.get(cyclebuffer, i))
  237. array.set(phasebuffer, no_Bcycles, array.get(phasebuffer, i))
  238. array.set(cycleBartelsBuffer,no_Bcycles, array.get(cycleBartelsBuffer, i))
  239. no_Bcycles += 1
  240.  
  241. number_of_cycles := no_Bcycles == 0 ? 0 : no_Bcycles
  242.  
  243. //Sort Bartels
  244. if SortBartels and number_of_cycles >= 1
  245. for i = 1 to number_of_cycles - 1
  246. for k = i + 1 to number_of_cycles
  247. if array.get(cycleBartelsBuffer, k) > array.get(cycleBartelsBuffer, i)
  248. y = array.get(amplitudebuffer, i)
  249. w = array.get(cyclebuffer, i)
  250. x = array.get(phasebuffer, i)
  251. v := array.get(cycleBartelsBuffer, i)
  252. array.set(amplitudebuffer, i, array.get(amplitudebuffer, k))
  253. array.set(cyclebuffer, i, array.get(cyclebuffer, k))
  254. array.set(phasebuffer, i, array.get(phasebuffer, k))
  255. array.set(cycleBartelsBuffer, i, array.get(cycleBartelsBuffer, k))
  256. array.set(amplitudebuffer, k, y)
  257. array.set(cyclebuffer, k, w)
  258. array.set(phasebuffer, k, x)
  259. array.set(cycleBartelsBuffer, k, v)
  260. // calculate waves
  261. for i = 1 to number_of_cycles
  262. float amplitude = array.get(amplitudebuffer, i)
  263. float phase = array.get(phasebuffer, i)
  264. float cycle = array.get(cyclebuffer, i)
  265. float sign = 1
  266. if not useAddition
  267. sign := -1
  268. for k = 0 to WindowSizePast - 1
  269. if useCosine
  270. matrix.set(goeWorkPast, k, i, amplitude * math.cos(phase + sign * k * 2.0 * math.pi / cycle))
  271. else
  272. matrix.set(goeWorkPast, k, i, amplitude * math.sin(phase + sign * k * 2.0 * math.pi / cycle))
  273. sign *= -1
  274. for k = 0 to WindowSizeFuture - 1
  275. if useCosine
  276. matrix.set(goeWorkFuture, WindowSizeFuture - k - 1, i, amplitude * math.cos(phase + sign * k * 2.0 * math.pi / cycle))
  277. else
  278. matrix.set(goeWorkFuture, WindowSizeFuture - k - 1, i, amplitude * math.sin(phase + sign * k * 2.0 * math.pi / cycle))
  279. number_of_cycles
  280.  
  281. // Hodrick-Prescott Filter
  282. hodrickPrescottFilter(float[] src, float lamb, int per)=>
  283. H1 = 0., H2 = 0., H3 = 0., H4 = 0., H5 = 0.,
  284. HH1 = 0., HH2 = 0., HH3 = 0., HH5 = 0.
  285. HB = 0., HC = 0., Z = 0.
  286. float[] a = array.new<float>(per, 0.)
  287. float[] b = array.new<float>(per, 0.)
  288. float[] c = array.new<float>(per, 0.)
  289. float[] output = array.new<float>(per, 0.)
  290. for i = 0 to per - 1
  291. array.set(output, i, array.get(src, i))
  292. array.set(a, 0, 1.0 + lamb)
  293. array.set(b, 0, -2.0 * lamb)
  294. array.set(c, 0, lamb)
  295. for i = 1 to per - 3
  296. array.set(a, i, 6.0 * lamb + 1.0)
  297. array.set(b, i, -4.0 * lamb)
  298. array.set(c, i, lamb)
  299. array.set(a, 1, 5.0 * lamb + 1)
  300. array.set(a, per - 1, 1.0 + lamb)
  301. array.set(a, per - 2, 5.0 * lamb + 1.0)
  302. array.set(b, per - 2, -2.0 * lamb)
  303. array.set(b, per - 1, 0.)
  304. array.set(c, per - 2, 0.)
  305. array.set(c, per - 1, 0.)
  306. for i = 0 to per - 1
  307. Z := array.get(a, i) - H4 * H1 - HH5 * HH2
  308. if (Z == 0)
  309. break
  310. HB := array.get(b, i)
  311. HH1 := H1
  312. H1 := (HB - H4 * H2) / Z
  313. array.set(b, i, H1)
  314. HC := array.get(c, i)
  315. HH2 := H2
  316. H2 := HC / Z
  317. array.set(c, i, H2)
  318. array.set(a, i, (array.get(src, i) - HH3 * HH5 - H3 * H4) / Z)
  319. HH3 := H3
  320. H3 := array.get(a, i)
  321. H4 := HB - H5 * HH1
  322. HH5 := H5
  323. H5 := HC
  324. H2 := 0
  325. H1 := array.get(a, per - 1)
  326. array.set(output, per - 1, H1)
  327. for i = per - 2 to 0
  328. array.set(output, i, array.get(a, i) - array.get(b, i) * H1 - array.get(c, i) * H2)
  329. H2 := H1
  330. H1 := array.get(output, i)
  331. output
  332.  
  333. // Detrending options
  334. detrendCenteredMA(float[] src, int period1, int period2, int calcBars, string DTmethod)=>
  335. if DTmethod == hpsmthdt
  336. calcValues1 = hodrickPrescottFilter(src, 0.0625 / math.pow(math.sin(math.pi / period1), 4), calcBars)
  337. calcValues2 = hodrickPrescottFilter(src, 0.0625 / math.pow(math.sin(math.pi / period2), 4), calcBars)
  338. for i = 0 to calcBars - 1
  339. array.set(src, i, array.get(calcValues1, i) - array.get(calcValues2, i))
  340. if DTmethod == zlagsmthdt
  341. calcValues1 = zeroLagMA(src, period1, calcBars)
  342. calcValues2 = zeroLagMA(src, period2, calcBars)
  343. for i = 0 to calcBars - 1
  344. array.set(src, i, array.get(calcValues1, i) - array.get(calcValues2, i))
  345.  
  346. // BarToCalculate: This setting determines the starting bar for cycle calculations.
  347. // Set it to 0 for the current (open) bar, or any number > 0 for closed bars
  348. // (specific bar depends on the value entered).
  349.  
  350. // UseCosineForWaves: Choose between sine or cosine for wave reconstruction.
  351. // Cosine is the preferred method for Goertzel calculations.
  352.  
  353. // UseAdditionForSteps: Determines how previous bar phases are reconstructed.
  354. // If set to true, it adds steps to the current phase. If set to false, it
  355. // subtracts steps from the current phase.
  356.  
  357. // UseSquaredAmp: Useful for adding many cycles, but may be misleading
  358. // with 2 or 3 cycles. Recommended usage.
  359.  
  360. // UseTopCycles: Sorts by largest amplitude or cycle strength. Not necessarily the
  361. // waves with the largest Bartels cycle significance, but often show significant values.
  362. // Use cycle strength and Bartels >50 and select cycles with strength >1. Do not
  363. // use more than 10 cycles.
  364.  
  365. // WindowSizeFuture: The size in bars to extend into the future.
  366.  
  367. // Cycle List: If true, it will use up to 5 chosen cycles. Non-consecutive cycles
  368. // can be used, e.g., 1st, 3rd, and 5th cycles.
  369.  
  370. // Subtract Noise: Only works when UseTopCycles < max. shown cycles in cycle list.
  371.  
  372. // Bartels Cycle Significance Test: Applied to every extracted Goertzel cycle.
  373.  
  374. // Smoothing: Original time series data can be smoothed with Hodrick
  375. // Prescott filter or Absolutely No Lag LWMA.
  376.  
  377. // Detrending: Various methods are available, including Absolutely
  378. // No Lag LWMA, a linear regression of the log-transformed
  379. // smoothed time series data, and the HP algorithm.
  380.  
  381. // SampleSize: Calculated as BartNoCycles * MaxCycLength + BarToCalculate.
  382. // WindowSizePast must be >= SampleSize.
  383.  
  384. // UseCycleStrength: Used as an alternative to amplitude before the Bartels test.
  385.  
  386. float src = input.source(close, "Source", group = "Basic Settings")
  387. int MaxPer = input.int(120, "Max Period", minval = 2, group = "Basic Settings")
  388. int WindowSizePast = input.int(100, "Window Size Past", group = "Basic Settings")
  389. int WindowSizeFuture = input.int(100, "Window Size Future", group = "Basic Settings")
  390. int StartAtCycle = input.int(1, "Start Cycle At", group = "Basic Settings")
  391. int UseTopCycles = input.int(2, "Use Top Cycles", group = "Basic Settings")
  392. int BarToCalculate = input.int(1, "Bar to Calculate", group = "Basic Settings")
  393.  
  394. int Cycle1 = input.int(1, "Cycle 1", group = "Compound Cycle Settings")
  395. int Cycle2 = input.int(1, "Cycle 2", group = "Compound Cycle Settings")
  396. int Cycle3 = input.int(1, "Cycle 3", group = "Compound Cycle Settings")
  397. int Cycle4 = input.int(1, "Cycle 4", group = "Compound Cycle Settings")
  398. int Cycle5 = input.int(1, "Cycle 5", group = "Compound Cycle Settings")
  399.  
  400. string detrendornot = input.string(zlagsmth, "Smoothing Mode", options = [none, hpsmth, zlagsmth, hpsmthdt, zlagsmthdt, logZlagRegression], group = "Source Price Detrending/Smoothing Settings")
  401.  
  402. int DT_ZLper1 = input.int(10, "Zero-lag Moving Average Fast Period", group = "Source Price Detrending Settings")
  403. int DT_ZLper2 = input.int(40, "Zero-lag Moving Average Slow Period", group = "Source Price Detrending Settings")
  404. int DT_HPper1 = input.int(20, "Hodrick-Prescott Filter Fast Period", group = "Source Price Detrending Settings")
  405. int DT_HPper2 = input.int(80, "Hodrick-Prescott Filter Slow Period", group = "Source Price Detrending Settings")
  406. int DT_RegZLsmoothPer = input.int(5, "Logarithmic Zero-lag Moving Average Regression Period", group = "Source Price Detrending Settings")
  407.  
  408. int HPsmoothPer = input.int(20, "Hodrick-Prescott Filter Period", group = "Source Price Smoothing Settings")
  409. int ZLMAsmoothPer = input.int(10, "Zero-lag Moving Average Period", group = "Source Price Smoothing Settings")
  410.  
  411. bool FilterBartels = input.bool(true, "Filter Bartels", group = "Bartels Cycle Significance Settings")
  412. int BartNoCycles = input.int(5, "Bartel Number of Cycles", group = "Bartels Cycle Significance Settings")
  413. int BartSmoothPer = input.int(2, "Bartel Smoothing Period", group = "Bartels Cycle Significance Settings")
  414. int BartSigLimit = input.int(50, "Bartel Signal Limit", group = "Bartels Cycle Significance Settings")
  415. bool SortBartels = input.bool(false, "Sort Bartels", group = "Bartels Cycle Significance Settings")
  416.  
  417. bool squaredAmp = input.bool(true, "Squared Amplitude",group = "Miscellaneous Filter Settings")
  418. bool useAddition = input.bool(false, "Use Addition", group = "Miscellaneous Filter Settings")
  419. bool useCosine = input.bool(true, "Use Cosine", group = "Miscellaneous Filter Settings")
  420. bool SubtractNoise = input.bool(false, "Subtract Noise", group = "Miscellaneous Filter Settings")
  421. bool UseCycleList = input.bool(false, "Use Cycle List", group = "Miscellaneous Filter Settings")
  422. bool UseCycleStrength = input.bool(true, "Use Cycle Strength", group = "Miscellaneous Filter Settings")
  423.  
  424. bool showTable = input.bool(true, "Show Table", group = "UI Options")
  425.  
  426. var pvlines = array.new_line(0)
  427. var fvlines = array.new_line(0)
  428.  
  429. plot(0, "Zero-line", color = color.gray)
  430.  
  431. if barstate.isfirst
  432. for i = 0 to 250 - 1
  433. array.push(pvlines, line.new(na, na, na, na))
  434. array.push(fvlines, line.new(na, na, na, na))
  435.  
  436. if barstate.islastconfirmedhistory
  437.  
  438. WindowSizePast := math.max(WindowSizePast, 2 * MaxPer)
  439. WindowSizeFuture := math.max(WindowSizeFuture, 2 * MaxPer)
  440.  
  441. matrix<float> goeWorkPast = matrix.new<float>(WindowSizePast, WindowSizePast, 0)
  442. matrix<float> goeWorkFuture = matrix.new<float>(WindowSizeFuture, WindowSizeFuture, 0)
  443.  
  444. SampleSize = BartNoCycles * MaxPer + BarToCalculate
  445.  
  446. float[] cyclebuffer = array.new<float>(MaxPer + 1, 0)
  447. float[] amplitudebuffer = array.new<float>(MaxPer + 1, 0)
  448. float[] phasebuffer = array.new<float>(MaxPer + 1, 0)
  449. float[] cycleBartelsBuffer = array.new<float>(MaxPer * 3, 0)
  450. float[] srcVal = array.new<float>(SampleSize, 0)
  451.  
  452. for i = 0 to SampleSize - 1
  453. array.set(srcVal, i, nz(src[i]))
  454.  
  455. if detrendornot == hpsmthdt
  456. detrendCenteredMA(srcVal, DT_HPper1, DT_HPper2, SampleSize, detrendornot)
  457. if detrendornot == zlagsmthdt
  458. detrendCenteredMA(srcVal, DT_ZLper1, DT_ZLper2, SampleSize, detrendornot)
  459. if detrendornot == logZlagRegression
  460. srcVal := detrendLnZeroLagRegression(srcVal, DT_RegZLsmoothPer, SampleSize)
  461.  
  462. if detrendornot == hpsmth
  463. srcVal := hodrickPrescottFilter(srcVal, 0.0625/math.pow(math.sin(math.pi / HPsmoothPer), 4), SampleSize)
  464. if detrendornot == zlagsmth
  465. srcVal := zeroLagMA(srcVal, ZLMAsmoothPer, SampleSize)
  466.  
  467. int number_of_cycles = goertzel(srcVal, BarToCalculate, SampleSize, MaxPer, squaredAmp, useAddition, useCosine, UseCycleStrength, WindowSizePast,
  468. WindowSizeFuture, FilterBartels, BartNoCycles, BartSmoothPer, BartSigLimit,
  469. SortBartels, goeWorkPast, goeWorkFuture, cyclebuffer, amplitudebuffer, phasebuffer, cycleBartelsBuffer)
  470.  
  471. // epgoertzel = end pointed goertzel goertzel is non-endpointed goertzelFuture is goertzel projection into the future
  472. float[] epgoertzel = array.new<float>(WindowSizePast + 1, 0)
  473. float[] goertzel = array.new<float>(WindowSizePast + 1, 0)
  474. float[] goertzelFuture = array.new<float>(WindowSizeFuture + 1, 0)
  475.  
  476. // past bar calc. of composite wave
  477. for i = 0 to WindowSizePast - 1
  478. array.set(goertzel, i, 0)
  479. if UseCycleList
  480. if Cycle1 > 0
  481. array.set(goertzel, i, array.get(goertzel, i) + matrix.get(goeWorkPast, i, Cycle1))
  482. if Cycle2 > 0
  483. array.set(goertzel, i, array.get(goertzel, i) + matrix.get(goeWorkPast, i, Cycle2))
  484. if Cycle3 > 0
  485. array.set(goertzel, i, array.get(goertzel, i) + matrix.get(goeWorkPast, i, Cycle3))
  486. if Cycle4 > 0
  487. array.set(goertzel, i, array.get(goertzel, i) + matrix.get(goeWorkPast, i, Cycle4))
  488. if Cycle5 > 0
  489. array.set(goertzel, i, array.get(goertzel, i) + matrix.get(goeWorkPast, i, Cycle5))
  490. else
  491. for k = StartAtCycle to StartAtCycle + UseTopCycles - 1
  492. array.set(goertzel, i, array.get(goertzel, i) + matrix.get(goeWorkPast, i, k))
  493. if SubtractNoise
  494. if number_of_cycles >= 1
  495. for k = StartAtCycle + UseTopCycles - 1 to number_of_cycles - 1
  496. array.set(goertzel, i, array.get(goertzel, i) - matrix.get(goeWorkPast, i, k))
  497.  
  498. // future bar calc. of composite wave
  499. for i = 0 to WindowSizePast - 1
  500. array.set(goertzelFuture, i, 0)
  501. if UseCycleList
  502. if Cycle1 > 0
  503. array.set(goertzelFuture, i, array.get(goertzelFuture, i) + matrix.get(goeWorkFuture, i, Cycle1))
  504. if Cycle2 > 0
  505. array.set(goertzelFuture, i, array.get(goertzelFuture, i) + matrix.get(goeWorkFuture, i, Cycle2))
  506. if Cycle3 > 0
  507. array.set(goertzelFuture, i, array.get(goertzelFuture, i) + matrix.get(goeWorkFuture, i, Cycle3))
  508. if Cycle4 > 0
  509. array.set(goertzelFuture, i, array.get(goertzelFuture, i) + matrix.get(goeWorkFuture, i, Cycle4))
  510. if Cycle5 > 0
  511. array.set(goertzelFuture, i, array.get(goertzelFuture, i) + matrix.get(goeWorkFuture, i, Cycle5))
  512. else
  513. for k = StartAtCycle to StartAtCycle + UseTopCycles - 1
  514. array.set(goertzelFuture, i, array.get(goertzelFuture, i) + matrix.get(goeWorkFuture, i, k))
  515. if SubtractNoise
  516. if number_of_cycles >= 1
  517. for k = StartAtCycle + UseTopCycles to number_of_cycles
  518. array.set(goertzelFuture, i, array.get(goertzelFuture, i) - matrix.get(goeWorkFuture, i, k))
  519.  
  520.  
  521. float[] pv = goertzel
  522. int npast = array.size(pv)
  523.  
  524. for i = 0 to npast - 2
  525. pvline = array.get(pvlines, i)
  526. colorout = i < array.size(pv) - 2 ? array.get(pv, i) > array.get(pv, i + 1) ? greencolor : redcolor: na
  527. line.set_xy1(pvline, bar_index - i - 1, array.get(pv, i + 1))
  528. line.set_xy2(pvline, bar_index - i, array.get(pv, i))
  529. line.set_color(pvline, colorout)
  530. line.set_style(pvline, line.style_solid)
  531. line.set_width(pvline, 3)
  532.  
  533. float[] fv = goertzelFuture
  534. int nfut = array.size(fv)
  535. array.reverse(fv)
  536.  
  537. for i = 1 to nfut - 3
  538. fvline = array.get(fvlines, i - 1)
  539. colorout = i < array.size(fv) - 2 ? array.get(fv, i) > array.get(fv, i + 1) ? color.fuchsia : color.yellow : na
  540. line.set_xy1(fvline, bar_index + i, array.get(fv, i))
  541. line.set_xy2(fvline, bar_index + i + 1, array.get(fv, i + 1))
  542. line.set_color(fvline, colorout)
  543. line.set_style(fvline, line.style_dotted)
  544. line.set_width(fvline, 2)
  545.  
  546. if number_of_cycles >= 1 and showTable
  547. var table3 = table.new(position = position.top_right, columns = 10, rows = number_of_cycles + 2, bgcolor = color.yellow, border_width = 1)
  548.  
  549. string Amp = "Amplitude"
  550. if UseCycleStrength
  551. Amp := "Cycle Strength"
  552.  
  553. float fmax = array.max(amplitudebuffer)
  554. float coeff = math.max(math.ceil(math.log(fmax) / math.log(10)) -2, -4)
  555.  
  556. table.cell(table_id = table3, column = 0, row = 0, text = "Rank")
  557. table.cell(table_id = table3, column = 1, row = 0, text = "Period")
  558. table.cell(table_id = table3, column = 2, row = 0, text = "Bartel")
  559. table.cell(table_id = table3, column = 3, row = 0, text = Amp)
  560. table.cell(table_id = table3, column = 4, row = 0, text = "Phase")
  561.  
  562. for i = 1 to number_of_cycles - 2
  563. buffer = array.get(cyclebuffer, i)
  564. amp = array.get(amplitudebuffer, i) / math.pow(10, coeff) * 10
  565. phase = (array.get(phasebuffer, i) % 2 * math.pi) * 180 / math.pi
  566. bartel = array.get(cycleBartelsBuffer, i)
  567. temparr = array.new<float>(5, 0)
  568. array.set(temparr, 0, i)
  569. array.set(temparr, 1, buffer)
  570. array.set(temparr, 2, bartel)
  571. array.set(temparr, 3, amp)
  572. array.set(temparr, 4, phase)
  573.  
  574. for k = 0 to 4
  575. tempout = array.get(temparr, k)
  576. table.cell(table_id = table3, column = k, row = i + 1, text = str.tostring(tempout, "#.###"))
Advertisement
Add Comment
Please, Sign In to add comment