xmd79

Linear regression trend lines

Apr 18th, 2023
348
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.26 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. // © legend507
  3.  
  4. //@version=5
  5. indicator("Linear regression trend lines", overlay=true)
  6.  
  7. // Config group 1 - Controls # of days to use for trendline calc and which data to use (open or close).
  8. group1 = "LINEAR REGRESSION SETTING"
  9. lengthInput = input.int(30, title="Length", minval = 1, maxval = 5000, group=group1) // By default use 30 bars. Use 1 bar = 1 day then it's roughly 1 month ago.
  10. sourceInput = input.source(close, title="Source", group=group1)
  11.  
  12. // Config groups 2 - Controls if a line is visible.
  13. group2 = "LINEAR REGRESSION SWITCH"
  14. useDev1Input = input.bool(true, title="Large LinReg On / Off", group=group2)
  15. useDev2Input = input.bool(true, title="Medium LinReg On / Off", group=group2)
  16. useDev3Input = input.bool(true, title="Small LinReg On / Off", group=group2)
  17.  
  18. useUpperDevInput = true
  19. upperMultInput = 3.0
  20. useLowerDevInput = true
  21. lowerMultInput = 3.0
  22. useUpperDevInput2 = true
  23. upperMultInput2 = 2.0
  24. useLowerDevInput2 = true
  25. lowerMultInput2 = 2.0
  26. useUpperDevInput3 = true
  27. upperMultInput3 = 1.0
  28. useLowerDevInput3 = true
  29. lowerMultInput3 = 1.0
  30.  
  31. // Config group 3 - Controls if lines are extended longer on the left / right.
  32. group3 = "LINEAR REGRESSION EXTEND LINES"
  33. extendLeftInput = input.bool(false, "Extend Lines Left", group=group3)
  34. extendRightInput = input.bool(true, "Extend Lines Right", group=group3)
  35. extendStyle = switch
  36. extendLeftInput and extendRightInput => extend.both
  37. extendLeftInput => extend.left
  38. extendRightInput => extend.right
  39. => extend.none
  40.  
  41. // Config group 4 - Controls line width.
  42. group4 = "LINEAR REGRESSION WIDTH"
  43. a_lwidth = input.int(2, title='Large LinReg Width', minval=0, maxval=10, group=group4)
  44. b_lwidth = input.int(1, title='Medium LinReg Width', minval=0, maxval=10, group=group4)
  45. c_lwidth = input.int(1, title='Small LinReg Width', minval=0, maxval=10, group=group4)
  46. d_lwidth = input.int(2, title='Base Line LinReg Width', minval=0, maxval=10, group=group4)
  47.  
  48. // Config group 5 - Controls line solid, dotted, dashed, etc.
  49. group5 = "LINEAR REGRESSION STYLE"
  50. A_LineStyle_Type = input.string(title='Large LinReg Type', defval='Dotted', options=['Dashed', 'Dotted', 'Solid'], group=group5)
  51. A_Line_Type = A_LineStyle_Type == 'Dashed' ? line.style_dashed : A_LineStyle_Type == 'Dotted' ? line.style_dotted : line.style_solid
  52. B_LineStyle_Type = input.string(title='Medium LinReg Type', defval='Solid', options=['Dashed', 'Dotted', 'Solid'], group=group5)
  53. B_Line_Type = B_LineStyle_Type == 'Dashed' ? line.style_dashed : B_LineStyle_Type == 'Dotted' ? line.style_dotted : line.style_solid
  54. C_LineStyle_Type = input.string(title='Small LinReg Type', defval='Dashed', options=['Dashed', 'Dotted', 'Solid'], group=group5)
  55. C_Line_Type = C_LineStyle_Type == 'Dashed' ? line.style_dashed : C_LineStyle_Type == 'Dotted' ? line.style_dotted : line.style_solid
  56. D_LineStyle_Type = input.string(title='Base Line LinReg Type', defval='Solid', options=['Dashed', 'Dotted', 'Solid'], group=group5)
  57. D_Line_Type = D_LineStyle_Type == 'Dashed' ? line.style_dashed : D_LineStyle_Type == 'Dotted' ? line.style_dotted : line.style_solid
  58.  
  59. // Config group 6 - Controls line colors.
  60. group6 = "LINEAR REGRESSION COLOR"
  61. colorLarge = input.color(color.new(#ffffff, 0), "Large Linreg", inline=group6, group=group6) // Outer line color default: white
  62. colorMedium = input.color(color.new(#ff0000, 0), "Medium Linreg", inline=group6, group=group6) // Middle line color defaul: red
  63. colorSmall = input.color(color.new(#ffa500, 0), "Small Linreg", inline=group6, group=group6) // Narror line color default: orange
  64. colorBase = input.color(color.new(#0c3299, 0), "Base Line", inline=group6, group=group6) // Baseline color default: blue
  65.  
  66. // Calculate slope based on input parameter & # of bars to use.
  67. // (This slope calculation is genius.)
  68. calcSlope(source, length) =>
  69. max_bars_back(source, 5000)
  70. // Check if current bar is last or we are only using 1 bar to calculate slope.
  71. if not barstate.islast or length <= 1
  72. [float(na), float(na), float(na)]
  73. else
  74. sumX = 0.0
  75. sumY = 0.0
  76. sumXSqr = 0.0
  77. sumXY = 0.0
  78. for i = 0 to length - 1 by 1
  79. val = source[i]
  80. per = i + 1.0
  81. sumX += per // Sum of 1, 2, 3, ... until length
  82. sumY += val // Sum of price value (default: close)
  83. sumXSqr += per * per
  84. sumXY += val * per
  85. slope = (length * sumXY - sumX * sumY) / (length * sumXSqr - sumX * sumX)
  86. average = sumY / length
  87. intercept = average - slope * sumX / length + slope
  88. [slope, average, intercept]
  89.  
  90. // Slope, average, intercept.
  91. [s, a, i] = calcSlope(sourceInput, lengthInput)
  92.  
  93. // Calculate standard deviation.
  94. calcDev(source, length, slope, average, intercept) =>
  95. upDev = 0.0
  96. dnDev = 0.0
  97. stdDevAcc = 0.0
  98. dsxx = 0.0
  99. dsyy = 0.0
  100. dsxy = 0.0
  101. periods = length - 1
  102. daY = intercept + slope * periods / 2
  103. val = intercept
  104. for j = 0 to periods by 1
  105. price = high[j] - val
  106. if price > upDev
  107. upDev := price
  108. price := val - low[j]
  109. if price > dnDev
  110. dnDev := price
  111. price := source[j]
  112. dxt = price - average
  113. dyt = val - daY
  114. price -= val
  115. stdDevAcc += price * price
  116. dsxx += dxt * dxt
  117. dsyy += dyt * dyt
  118. dsxy += dxt * dyt
  119. val += slope
  120. stdDev = math.sqrt(stdDevAcc / (periods == 0 ? 1 : periods))
  121. pearsonR = dsxx == 0 or dsyy == 0 ? 0 : dsxy / math.sqrt(dsxx * dsyy)
  122. [stdDev, pearsonR, upDev, dnDev]
  123.  
  124. [stdDev, pearsonR, upDev, dnDev] = calcDev(sourceInput, lengthInput, s, a, i)
  125.  
  126. // Draw trendlines based on returns of calcSlope and calcDev.
  127. drawTrendlines(lengthInput, s, a, i, stdDev, pearsonR, upDev, dnDev) =>
  128. // linreg base function
  129. startPrice = i + s * (lengthInput - 1)
  130. endPrice = i
  131. var line baseLine = na
  132. if na(baseLine) and not na(startPrice)
  133. baseLine := line.new(bar_index - lengthInput + 1, startPrice, bar_index, endPrice, width=d_lwidth, style=D_Line_Type, extend=extendStyle, color=colorBase)
  134. else
  135. line.set_xy1(baseLine, bar_index - lengthInput + 1, startPrice)
  136. line.set_xy2(baseLine, bar_index, endPrice)
  137. na
  138.  
  139. // large linreg function
  140. upperStartPrice = startPrice + (useUpperDevInput ? upperMultInput * stdDev : upDev)
  141. upperEndPrice = endPrice + (useUpperDevInput ? upperMultInput * stdDev : upDev)
  142. var line upper = na
  143. lowerStartPrice = startPrice + (useLowerDevInput ? -lowerMultInput * stdDev : -dnDev)
  144. lowerEndPrice = endPrice + (useLowerDevInput ? -lowerMultInput * stdDev : -dnDev)
  145. var line lower = na
  146. if na(upper) and not na(upperStartPrice)
  147. upper := useDev1Input ? line.new(bar_index - lengthInput + 1, upperStartPrice, bar_index, upperEndPrice, width=a_lwidth, style=A_Line_Type, extend=extendStyle, color=colorLarge) : na
  148. else
  149. line.set_xy1(upper, bar_index - lengthInput + 1, upperStartPrice)
  150. line.set_xy2(upper, bar_index, upperEndPrice)
  151. na
  152. if na(lower) and not na(lowerStartPrice)
  153. lower := useDev1Input ? line.new(bar_index - lengthInput + 1, lowerStartPrice, bar_index, lowerEndPrice, width=a_lwidth, style=A_Line_Type, extend=extendStyle, color=colorLarge) : na
  154. else
  155. line.set_xy1(lower, bar_index - lengthInput + 1, lowerStartPrice)
  156. line.set_xy2(lower, bar_index, lowerEndPrice)
  157. na
  158.  
  159. // medium linreg function
  160. upperStartPrice2 = startPrice + (useUpperDevInput2 ? upperMultInput2 * stdDev : upDev)
  161. upperEndPrice2 = endPrice + (useUpperDevInput2 ? upperMultInput2 * stdDev : upDev)
  162. var line upper2 = na
  163. lowerStartPrice2 = startPrice + (useLowerDevInput2 ? -lowerMultInput2 * stdDev : -dnDev)
  164. lowerEndPrice2 = endPrice + (useLowerDevInput2 ? -lowerMultInput2 * stdDev : -dnDev)
  165. var line lower2 = na
  166. if na(upper2) and not na(upperStartPrice2)
  167. upper2 := useDev2Input ? line.new(bar_index - lengthInput + 1, upperStartPrice2, bar_index, upperEndPrice2, width=b_lwidth, style=B_Line_Type, extend=extendStyle, color=colorMedium) : na
  168. else
  169. line.set_xy1(upper2, bar_index - lengthInput + 1, upperStartPrice2)
  170. line.set_xy2(upper2, bar_index, upperEndPrice2)
  171. na
  172. if na(lower2) and not na(lowerStartPrice2)
  173. lower2 := useDev2Input ? line.new(bar_index - lengthInput + 1, lowerStartPrice2, bar_index, lowerEndPrice2, width=b_lwidth, style=B_Line_Type, extend=extendStyle, color=colorMedium) : na
  174. else
  175. line.set_xy1(lower2, bar_index - lengthInput + 1, lowerStartPrice2)
  176. line.set_xy2(lower2, bar_index, lowerEndPrice2)
  177. na
  178.  
  179. // small linreg fuction
  180. upperStartPrice3 = startPrice + (useUpperDevInput3 ? upperMultInput3 * stdDev : upDev)
  181. upperEndPrice3 = endPrice + (useUpperDevInput3 ? upperMultInput3 * stdDev : upDev)
  182. var line upper3 = na
  183. lowerStartPrice3 = startPrice + (useLowerDevInput3 ? -lowerMultInput3 * stdDev : -dnDev)
  184. lowerEndPrice3 = endPrice + (useLowerDevInput3 ? -lowerMultInput3 * stdDev : -dnDev)
  185. var line lower3 = na
  186. if na(upper3) and not na(upperStartPrice3)
  187. upper3 := useDev3Input ? line.new(bar_index - lengthInput + 1, upperStartPrice3, bar_index, upperEndPrice3, width=c_lwidth, style=C_Line_Type, extend=extendStyle, color=colorSmall) : na
  188. else
  189. line.set_xy1(upper3, bar_index - lengthInput + 1, upperStartPrice3)
  190. line.set_xy2(upper3, bar_index, upperEndPrice3)
  191. na
  192. if na(lower3) and not na(lowerStartPrice3)
  193. lower3 := useDev3Input ? line.new(bar_index - lengthInput + 1, lowerStartPrice3, bar_index, lowerEndPrice3, width=c_lwidth, style=C_Line_Type, extend=extendStyle, color=colorSmall) : na
  194. else
  195. line.set_xy1(lower3, bar_index - lengthInput + 1, lowerStartPrice3)
  196. line.set_xy2(lower3, bar_index, lowerEndPrice3)
  197. na
  198.  
  199. // Add tag to show slope to indicate strength of the trend.
  200. slopeLabel = label.new(bar_index - lengthInput + 1, upperStartPrice)
  201. label.set_text(slopeLabel, str.tostring(pearsonR)) // pearsonR is what is used in the official regression tool.
  202.  
  203. drawTrendlines(lengthInput, s, a, i, stdDev, pearsonR, upDev, dnDev)
Advertisement
Add Comment
Please, Sign In to add comment