Advertisement
xmd79

Quadratic & Linear Time Series Regression [SS]

Sep 27th, 2023
200
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.51 KB | None | 0 0
  1. // /$$$$$$ /$$ /$$
  2. // /$$__ $$ | $$ | $$
  3. //| $$ \__//$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$$
  4. //| $$$$$$|_ $$_/ /$$__ $$| $$ /$$//$$__ $$ /$$__ $$ /$$_____/|_ $$_/ /$$__ $$| $$ /$$//$$__ $$ /$$_____/
  5. // \____ $$ | $$ | $$$$$$$$ \ $$/$$/| $$$$$$$$| $$ \__/| $$$$$$ | $$ | $$$$$$$$ \ $$/$$/| $$$$$$$$| $$$$$$
  6. // /$$ \ $$ | $$ /$$| $$_____/ \ $$$/ | $$_____/| $$ \____ $$ | $$ /$$| $$_____/ \ $$$/ | $$_____/ \____ $$
  7. //| $$$$$$/ | $$$$/| $$$$$$$ \ $/ | $$$$$$$| $$ /$$$$$$$/ | $$$$/| $$$$$$$ \ $/ | $$$$$$$ /$$$$$$$/
  8. // \______/ \___/ \_______/ \_/ \_______/|__/ |_______/ \___/ \_______/ \_/ \_______/|_______/
  9. // © Steversteves
  10. //@version=5
  11. indicator("Quadratic & Linear Time Series Regression [SS]", shorttitle = "Quadratic & Linear Regression [SS]", overlay=true, max_bars_back = 5000)
  12. // Groups //
  13. g0 = "Timeframe Select"
  14. g1 = "Setting and Analysis Type"
  15. g2 = "Standard Deviation Extensions"
  16.  
  17. // User inputs //
  18. start_time = input.time(timestamp("20 Jul 2022 00:00 +000"), title = "Start time for Period", confirm = true, group = g0)
  19. typeselect = input.string("Quadratic Time Series", "Select Regression Type", ["Quadratic Time Series", "Linear Regression Time Series"], group = g1)
  20. showrngtbl = input.bool(true, "Show Range Table", group = g1)
  21. showstats = input.bool(true, "Show Statistics Table", group = g1)
  22. pltfills = input.bool(true, "Plot Fills", group = g1)
  23. ci_input = input.float(1.96, "Confidence Interval Input", group = g1)
  24. stdevi = input.string("None", "Add Additional Standard Deviation Bands", ["None", "One", "Two", "Three"], group = g2)
  25. stdev1 = input.float(2, "Standard Deviation Input 1", group = g2)
  26. stdev2 = input.float(3, "Standard Deviation Input 2", group = g2)
  27. stdev3 = input.float(4, "Standard Deviation Input 3", group = g2)
  28.  
  29.  
  30. // Define Variables
  31. float x1 = 0.0
  32. float x2 = 0.0
  33. float y = 0.0
  34. float result = 0.0
  35.  
  36. // Define analysis type
  37. if typeselect == "Quadratic Time Series"
  38. x1 := time
  39. x2 := math.pow(time,2)
  40. y := close
  41.  
  42. if typeselect == "Linear Regression Time Series"
  43. x1 := time
  44. x2 := 0
  45. y := close
  46.  
  47. int candle = 0
  48.  
  49. // Regression
  50. x1_sq = array.new_float()
  51. x2_sq = array.new_float()
  52. x1_array = array.new_float()
  53. x2_array = array.new_float()
  54. x1_y = array.new_float()
  55. x2_y = array.new_float()
  56. x1_x2 = array.new_float()
  57. y_array = array.new_float()
  58. candle_a = array.new_float()
  59. result_a = array.new_float()
  60.  
  61. for i = 0 to 4999
  62. if time[i] >= start_time
  63. array.push(x1_sq, (x1[i] * x1[i]))
  64. array.push(x2_sq, (x2[i] * x2[i]))
  65. array.push(x1_array, x1[i])
  66. array.push(x2_array, x2[i])
  67. array.push(x1_y, (x1[i] * y[i]))
  68. array.push(x2_y, (x2[i] * y[i]))
  69. array.push(x1_x2, (x1[i] * x2[i]))
  70. array.push(y_array, y[i])
  71. array.push(candle_a, candle + 1)
  72.  
  73. x1_sq_sum = array.sum(x1_sq)
  74. x2_sq_sum = array.sum(x2_sq)
  75. x1_sum = array.sum(x1_array)
  76. x2_sum = array.sum(x2_array)
  77. x1_y_sum = array.sum(x1_y)
  78. x2_y_sum = array.sum(x2_y)
  79. x1_x2_sum = array.sum(x1_x2)
  80. y_sum = array.sum(y_array)
  81.  
  82. i1_x = x1_sq_sum - (math.pow(x1_sum, 2) / array.size(y_array))
  83. i2_x = x2_sq_sum - (math.pow(x2_sum, 2) / array.size(y_array))
  84. i1_y = x1_y_sum - ((x1_sum * y_sum) / array.size(y_array))
  85. i2_y = x2_y_sum - ((x2_sum * y_sum) / array.size(y_array))
  86.  
  87. len = array.size(y_array)
  88. ix1x2 = x1_x2_sum - ((x1_sum * x2_sum) / array.size(y_array))
  89.  
  90. b1 = ((i2_x * i1_y) - (ix1x2 * i2_y)) / ((i1_x * i2_x) - math.pow(ix1x2, 2))
  91. b2 = ((i1_x * i2_y) - (ix1x2 * i1_y)) / ((i1_x * i2_x) - math.pow(ix1x2, 2))
  92. b0 = (y_sum / len) - (b1 * (x1_sum / len)) - (b2 * (x2_sum / len))
  93.  
  94. quad_result = (x1 * b1) + (x2 * b2) + b0
  95. //
  96. lin_reg_b1 = x1_y_sum - (x1_sum * y_sum) / len
  97. bbb2 = x1_sq_sum - (math.pow(x1_sum, 2) / len)
  98. slope = (lin_reg_b1 / bbb2)
  99.  
  100. abc = y_sum - (slope * x1_sum)
  101. abc1 = abc / array.size(y_array)
  102.  
  103. lin_reg_result = (x1 * slope) + abc1
  104.  
  105. if typeselect == "Quadratic Time Series"
  106. result := quad_result
  107. if typeselect == "Linear Regression Time Series"
  108. result := lin_reg_result
  109.  
  110. for i = 0 to 4999
  111. if time[i] >= start_time
  112. array.push(result_a, result[i])
  113.  
  114. se_residuals = array.new_float()
  115.  
  116. for i = 0 to len
  117. array.push(se_residuals, (result[i] - y[i]) * (result[i] - y[i]))
  118.  
  119. se_add = array.sum(se_residuals)
  120.  
  121. r1 = se_add / (len - 2)
  122. se= math.sqrt(r1)
  123. candle_count = array.sum(candle_a)
  124.  
  125. // Colours
  126. color black = color.rgb(0, 0, 0)
  127. color white = color.white
  128. color outer_c = color.new(color.red, 85)
  129. color outer_b = color.new(color.orange, 85)
  130. color outer_a = color.new(color.yellow, 85)
  131. color inner = color.new(color.lime, 85)
  132. color outer = color.new(color.red, 70)
  133.  
  134.  
  135. h = plot(result, color = inner)
  136. ii = plot(result + se, color = inner)
  137. j = plot(result - se, color = inner)
  138.  
  139. fill(h, ii, color = pltfills ? inner : na)
  140. fill(h, j, color= pltfills ? inner : na)
  141. tss = se_add + se_add
  142.  
  143. // Correlation
  144. float pr = 0.0
  145. float r2 = 0.0
  146.  
  147. cov = array.covariance(x1_x2, y_array)
  148. lin_cov = array.covariance(y_array, x1_array)
  149. x1_x2_sd = array.stdev(x1_x2)
  150. y_sd = array.stdev(y_array)
  151. x1_sd = array.stdev(x1_array)
  152.  
  153. quad_cor = cov / (x1_x2_sd * y_sd)
  154. lin_cor = lin_cov / (x1_sd * y_sd)
  155.  
  156. r2_quad = math.pow(quad_cor, 2)
  157. r2_lin = math.pow(lin_cor, 2)
  158.  
  159.  
  160.  
  161. if typeselect == "Quadratic Time Series"
  162. pr := quad_cor
  163. r2 := r2_quad
  164.  
  165. if typeselect == "Linear Regression Time Series"
  166. pr := lin_cor
  167. r2 := r2_lin
  168.  
  169. best_fit = math.max(quad_cor, lin_cor)
  170. least_variance = math.max(r2_quad, r2_lin)
  171.  
  172. string best_fit_res = best_fit == quad_cor ? "The Quadratic Regression Approach has a Stronger relationship for this data" : best_fit == lin_cor ? "The Linear Regression Approach has a Strnger Relationship for this data." : na
  173. string least_variance_res = least_variance == r2_quad? "The Quad Regression explains the variance in data better than the LinReg Model" : least_variance == r2_lin ? "The Lin regression explains the variance in data better than the QuadReg Model." : na
  174. // Extension of Standard Deviation Bands
  175. stdev_extend_1 = se * stdev1
  176. stdev_extend_2 = se * stdev2
  177. stdev_extend_3 = se * stdev3
  178.  
  179.  
  180. f_confidence_interval(array1, array2) =>
  181. upper_bound = 0.0
  182. lower_bound = 0.0
  183. ci_conv = 0.0
  184. // Standard Error
  185. avg1 = array.avg(array1)
  186. avg2 = array.avg(array2)
  187. asd1 = array.stdev(array1)
  188. asd2 = array.stdev(array2)
  189. se1 = (math.pow(asd1,2) / array.size(array1))
  190. se2 = (math.pow(asd2,2) / array.size(array2))
  191. se3 = (se1 + se2)
  192. s_er = math.sqrt(se3)
  193. // Confidence interval
  194. avg_dif = (avg1 - avg2)
  195. ci = s_er * ci_input
  196. upper_bound := avg_dif + ci
  197. lower_bound := avg_dif - ci
  198. ci_conv := (ci_input - 1) * 100
  199. [upper_bound, lower_bound, ci_conv]
  200.  
  201. [ci_upper, ci_lower, ci_conversion] = f_confidence_interval(y_array, result_a)
  202.  
  203.  
  204.  
  205.  
  206. // SD 1 band
  207. a = plot(stdevi == "One" or stdevi == "Two" or stdevi == "Three" ? result + stdev_extend_1 : na, color = outer_a)
  208. b = plot(stdevi == "One" or stdevi == "Two" or stdevi == "Three" ? result - stdev_extend_1: na, color = outer_a)
  209.  
  210. // SD 2 Bands
  211. c = plot(stdevi == "Two" or stdevi == "Three" ? result + stdev_extend_2 : na, color = outer_b)
  212. d = plot(stdevi == "Two" or stdevi == "Three" ? result - stdev_extend_2: na, color = outer_b)
  213.  
  214. // SD 3 Band
  215. e = plot(stdevi == "Three" ? result + stdev_extend_3 : na, color = outer_c)
  216. f = plot(stdevi == "Three" ? result - stdev_extend_3: na, color = outer_c)
  217.  
  218. fill(a, ii, color = pltfills ? outer_a : na)
  219. fill(a, c, color = pltfills ? outer_b : na)
  220. fill(c, e, color = pltfills ? outer_c : na)
  221. fill(j, b, color = pltfills ? outer_a : na)
  222. fill(b, d, color = pltfills ? outer_b : na)
  223. fill(d, f, color = pltfills ? outer_c : na)
  224.  
  225. var table data = table.new(position.bottom_right, 5, 8, bgcolor = black,frame_color = white, frame_width = 2)
  226. if showstats
  227. table.cell(data, 1, 1, text = "R2 = " + str.tostring(math.round(r2, 4)), bgcolor = black, text_color = white)
  228. table.cell(data, 1, 2, text = "Pearson Correlation = " + str.tostring(math.round(pr,2)), bgcolor = black, text_color = white)
  229. table.cell(data, 1, 4, text = "Upper Bound Confidence Interval " + str.tostring(math.round(ci_conversion)) + "% = " + str.tostring(math.round(ci_upper,2)) + "\n Lower Bound Confidence Interval " + str.tostring(math.round(ci_conversion)) + "% = " + str.tostring(math.round(ci_lower,2)), bgcolor = black, text_color = white)
  230. table.cell(data, 1, 5, text = str.tostring(best_fit_res), bgcolor = black, text_color = white)
  231. table.cell(data, 1, 6, text = str.tostring(least_variance_res), bgcolor = black, text_color = white)
  232. table.cell(data, 1, 7, text = "Total Candles in Period = " + str.tostring(candle_count), bgcolor = black, text_color = white)
  233.  
  234. // Range
  235. f_condition_counter(condition, candlecount) =>
  236. perc_success = 0.0
  237. num_success = 0.0
  238. var int pass = 0
  239.  
  240. for i = 0 to 5000
  241. if time[i] >= start_time
  242. if condition[i] and barstate.islast
  243. pass := pass + 1
  244. num_success := pass
  245. perc_success := (pass / candlecount) * 100
  246. [perc_success, num_success]
  247. // Extensions of Standard Deviation
  248. pos_stdev_extend_1 = result + (se * stdev1)
  249. pos_stdev_extend_2 = result + (se * stdev2)
  250. pos_stdev_extend_3 = result + (se * stdev3)
  251.  
  252. neg_stdev_extend_1 = result - (se * stdev1)
  253. neg_stdev_extend_2 = result - (se * stdev2)
  254. neg_stdev_extend_3 = result - (se * stdev3)
  255.  
  256.  
  257. // Within Range Counter
  258.  
  259. bool within_range = close <= result + se and close >= result - se
  260. bool outside_range = close > result + se or close < result - se
  261. bool within_pos_1 = close > result + se and close < pos_stdev_extend_1
  262. bool within_pos_2 = close >= pos_stdev_extend_1 and close < pos_stdev_extend_2
  263. bool within_pos_3 = close >= pos_stdev_extend_2 and close <= pos_stdev_extend_3
  264. bool pos_outside = close >= pos_stdev_extend_3
  265. bool within_neg_1 = close < result - se and close > neg_stdev_extend_1
  266. bool within_neg_2 = close <= neg_stdev_extend_1 and close > neg_stdev_extend_2
  267. bool within_neg_3 = close <= neg_stdev_extend_2 and close > neg_stdev_extend_3
  268. bool neg_outside = close <= neg_stdev_extend_3
  269.  
  270. [within_rng_perc, within_rng_num] = f_condition_counter(within_range, candle_count)
  271. [within_pos1_perc, within_pos1_num] = f_condition_counter(within_pos_1, candle_count)
  272. [within_pos2_perc, within_pos2_num] = f_condition_counter(within_pos_2, candle_count)
  273. [within_pos3_perc, within_pos3_num] = f_condition_counter(within_pos_3, candle_count)
  274. [pos_outside_perc, pos_outside_num] = f_condition_counter(pos_outside, candle_count)
  275.  
  276. [within_neg1_perc, within_neg1_num] = f_condition_counter(within_neg_1, candle_count)
  277. [within_neg2_perc, within_neg2_num] = f_condition_counter(within_neg_2, candle_count)
  278. [within_neg3_perc, within_neg3_num] = f_condition_counter(within_neg_3, candle_count)
  279. [neg_outside_perc, neg_outside_num] = f_condition_counter(neg_outside, candle_count)
  280.  
  281. var table count_table = table.new(position.middle_right, 5, 11, bgcolor = black, frame_color = white, frame_width = 2)
  282. neg_sd1 = (stdev1 * -1)
  283. neg_sd2 = (stdev2 * -1)
  284. neg_sd3 = (stdev3 * -1)
  285.  
  286. // Price Ranges
  287.  
  288. rng_ucl = result + se
  289. rng_lcl = result - se
  290. if showrngtbl
  291. table.cell(count_table, 1, 1, text = "Condition", bgcolor=black, text_color = white)
  292. table.cell(count_table, 2, 1, text = "%", bgcolor=black, text_color = white)
  293. table.cell(count_table, 3, 1, text = "# Candles", bgcolor=black, text_color = white)
  294. table.cell(count_table, 4, 1, text = "Price Range", bgcolor=black, text_color = white)
  295.  
  296.  
  297.  
  298.  
  299. table.cell(count_table, 1, 2, text = "Below Range", bgcolor = outer, text_color = white)
  300. table.cell(count_table, 1, 3, text = str.tostring(neg_sd3) + " SD", bgcolor = outer_c, text_color = white)
  301. table.cell(count_table, 1, 4, text = str.tostring(neg_sd2) + " SD", bgcolor = outer_b, text_color = white)
  302. table.cell(count_table, 1, 5, text = str.tostring(neg_sd1) + " SD", bgcolor = outer_a, text_color = white)
  303. table.cell(count_table, 1, 6, text = "In Range", bgcolor = inner, text_color = white)
  304. table.cell(count_table, 1, 7, text = str.tostring(stdev1) + " SD", bgcolor = outer_a, text_color = white)
  305. table.cell(count_table, 1, 8, text = str.tostring(stdev2) + " SD", bgcolor = outer_b, text_color = white)
  306. table.cell(count_table, 1, 9, text = str.tostring(stdev3) + " SD", bgcolor = outer_c, text_color = white)
  307. table.cell(count_table, 1, 10, text = "Above Range", bgcolor = outer, text_color = white)
  308.  
  309. table.cell(count_table, 2, 2, text = str.tostring(math.round(neg_outside_perc)) + "%", bgcolor = outer, text_color = white)
  310. table.cell(count_table, 2, 3, text = str.tostring(math.round(within_neg3_perc)) + "%", bgcolor = outer_c, text_color = white)
  311. table.cell(count_table, 2, 4, text = str.tostring(math.round(within_neg2_perc)) + "%", bgcolor = outer_b, text_color = white)
  312. table.cell(count_table, 2, 5, text = str.tostring(math.round(within_neg1_perc)) + "%", bgcolor = outer_a, text_color = white)
  313. table.cell(count_table, 2, 6, text = str.tostring(math.round(within_rng_perc)) + "%", bgcolor = inner, text_color = white)
  314. table.cell(count_table, 2, 7, text = str.tostring(math.round(within_pos1_perc)) + "%", bgcolor = outer_a, text_color = white)
  315. table.cell(count_table, 2, 8, text = str.tostring(math.round(within_pos2_perc)) + "%", bgcolor = outer_b, text_color = white)
  316. table.cell(count_table, 2, 9, text = str.tostring(math.round(within_pos3_perc)) + "%", bgcolor = outer_c, text_color = white)
  317. table.cell(count_table, 2, 10, text = str.tostring(math.round(pos_outside_perc)) + "%", bgcolor = outer, text_color = white)
  318.  
  319. table.cell(count_table, 3, 2, text = str.tostring(neg_outside_num), bgcolor = outer, text_color = white)
  320. table.cell(count_table, 3, 3, text = str.tostring(within_neg3_num), bgcolor = outer_c, text_color = white)
  321. table.cell(count_table, 3, 4, text = str.tostring(within_neg2_num), bgcolor = outer_b, text_color = white)
  322. table.cell(count_table, 3, 5, text = str.tostring(within_neg1_num), bgcolor = outer_a, text_color = white)
  323. table.cell(count_table, 3, 6, text = str.tostring(within_rng_num), bgcolor = inner, text_color = white)
  324. table.cell(count_table, 3, 7, text = str.tostring(within_pos1_num), bgcolor = outer_a, text_color = white)
  325. table.cell(count_table, 3, 8, text = str.tostring(within_pos2_num), bgcolor = outer_b, text_color = white)
  326. table.cell(count_table, 3, 9, text = str.tostring(within_pos3_num), bgcolor = outer_c, text_color = white)
  327. table.cell(count_table, 3, 10, text = str.tostring(pos_outside_num), bgcolor = outer, text_color = white)
  328.  
  329.  
  330.  
  331. table.cell(count_table, 4, 2, text = "<= " + str.tostring(math.round(neg_stdev_extend_3,2)), bgcolor = outer, text_color = white)
  332. table.cell(count_table, 4, 3, text = str.tostring(math.round(neg_stdev_extend_2,2)) + " to " + str.tostring(math.round(neg_stdev_extend_3,2)), bgcolor = outer_c, text_color = white)
  333. table.cell(count_table, 4, 4, text = str.tostring(math.round(neg_stdev_extend_1,2)) + " to " + str.tostring(math.round(neg_stdev_extend_2, 2)), bgcolor = outer_b, text_color = white)
  334. table.cell(count_table, 4, 5, text = str.tostring(math.round(rng_lcl,2)) + " to " + str.tostring(math.round(neg_stdev_extend_1)), bgcolor = outer_a, text_color = white)
  335. table.cell(count_table, 4, 6, text = str.tostring(math.round(rng_lcl,2)) + " to " + str.tostring(math.round(rng_ucl)), bgcolor = inner, text_color = white)
  336. table.cell(count_table, 4, 7, text = str.tostring(math.round(rng_ucl,2)) + " to " + str.tostring(math.round(pos_stdev_extend_1,2)), bgcolor = outer_a, text_color = white)
  337. table.cell(count_table, 4, 8, text = str.tostring(math.round(pos_stdev_extend_1,2)) + " to " + str.tostring(math.round(pos_stdev_extend_2,2)), bgcolor = outer_b, text_color = white)
  338. table.cell(count_table, 4, 9, text = str.tostring(math.round(pos_stdev_extend_2,2)) + " to " + str.tostring(math.round(pos_stdev_extend_3,2)), bgcolor = outer_c, text_color = white)
  339. table.cell(count_table, 4, 10, text = ">= " + str.tostring(math.round(pos_stdev_extend_3,2)), bgcolor = outer, text_color = white)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement