xmd79

Double Top/Bottom - Ultimate (OS)

Sep 24th, 2021
166
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.38 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. // © HeWhoMustNotBeNamed
  3.  
  4. // __ __ __ __ __ __ __ __ __ __ __ _______ __ __ __
  5. // / | / | / | _ / |/ | / \ / | / | / \ / | / | / \ / \ / | / |
  6. // $$ | $$ | ______ $$ | / \ $$ |$$ |____ ______ $$ \ /$$ | __ __ _______ _$$ |_ $$ \ $$ | ______ _$$ |_ $$$$$$$ | ______ $$ \ $$ | ______ _____ ____ ______ ____$$ |
  7. // $$ |__$$ | / \ $$ |/$ \$$ |$$ \ / \ $$$ \ /$$$ |/ | / | / |/ $$ | $$$ \$$ | / \ / $$ | $$ |__$$ | / \ $$$ \$$ | / \ / \/ \ / \ / $$ |
  8. // $$ $$ |/$$$$$$ |$$ /$$$ $$ |$$$$$$$ |/$$$$$$ |$$$$ /$$$$ |$$ | $$ |/$$$$$$$/ $$$$$$/ $$$$ $$ |/$$$$$$ |$$$$$$/ $$ $$< /$$$$$$ |$$$$ $$ | $$$$$$ |$$$$$$ $$$$ |/$$$$$$ |/$$$$$$$ |
  9. // $$$$$$$$ |$$ $$ |$$ $$/$$ $$ |$$ | $$ |$$ | $$ |$$ $$ $$/$$ |$$ | $$ |$$ \ $$ | __ $$ $$ $$ |$$ | $$ | $$ | __ $$$$$$$ |$$ $$ |$$ $$ $$ | / $$ |$$ | $$ | $$ |$$ $$ |$$ | $$ |
  10. // $$ | $$ |$$$$$$$$/ $$$$/ $$$$ |$$ | $$ |$$ \__$$ |$$ |$$$/ $$ |$$ \__$$ | $$$$$$ | $$ |/ |$$ |$$$$ |$$ \__$$ | $$ |/ |$$ |__$$ |$$$$$$$$/ $$ |$$$$ |/$$$$$$$ |$$ | $$ | $$ |$$$$$$$$/ $$ \__$$ |
  11. // $$ | $$ |$$ |$$$/ $$$ |$$ | $$ |$$ $$/ $$ | $/ $$ |$$ $$/ / $$/ $$ $$/ $$ | $$$ |$$ $$/ $$ $$/ $$ $$/ $$ |$$ | $$$ |$$ $$ |$$ | $$ | $$ |$$ |$$ $$ |
  12. // $$/ $$/ $$$$$$$/ $$/ $$/ $$/ $$/ $$$$$$/ $$/ $$/ $$$$$$/ $$$$$$$/ $$$$/ $$/ $$/ $$$$$$/ $$$$/ $$$$$$$/ $$$$$$$/ $$/ $$/ $$$$$$$/ $$/ $$/ $$/ $$$$$$$/ $$$$$$$/
  13. //
  14. //
  15. //
  16. //@version=4
  17. study("Double Top/Bottom - Ultimate (OS)", shorttitle="W/M - Ultimate(OS)", overlay=true, max_lines_count=500, max_labels_count=500)
  18. length = input(10, step=5, minval=5)
  19. showZigzag = input(false)
  20. showPivots = input(true)
  21. showStats = input(true)
  22. bullishColor = input(color.green)
  23. bullTrapColor = input(color.orange)
  24. bearishColor = input(color.red)
  25. bearTrapColor = input(color.lime)
  26. textColor = input(color.black)
  27.  
  28. MaxRiskPerReward = input(30, step=5, minval=5, maxval=100)
  29. DisplayRiskPerReward = input(true)
  30. var zigzagvalues = array.new_float(0)
  31. var zigzagindexes = array.new_int(0)
  32. var zigzagdir = array.new_int(0)
  33.  
  34. var doubleTopBottomValues = array.new_float(3)
  35. var doubleTopBottomIndexes = array.new_int(3)
  36. var doubleTopBottomDir = array.new_int(3)
  37.  
  38. int max_array_size = 10
  39. max_bars_back(high, 5000)
  40. max_bars_back(low, 5000)
  41. pivots(length)=>
  42. float ph = highestbars(high, length) == 0 ? high : na
  43. float pl = lowestbars(low, length) == 0 ? low : na
  44. dir = 0
  45. dir := iff(ph and na(pl), 1, iff(pl and na(ph), -1, dir[1]))
  46. [dir, ph, pl]
  47.  
  48. add_to_array(value, index, dir)=>
  49. mult = array.size(zigzagvalues) < 2? 1 :
  50. (dir*value > dir*array.get(zigzagvalues,1))? 2 : 1
  51. array.unshift(zigzagindexes, index)
  52. array.unshift(zigzagvalues, value)
  53. array.unshift(zigzagdir, dir*mult)
  54. if array.size(zigzagindexes) > max_array_size
  55. array.pop(zigzagindexes)
  56. array.pop(zigzagvalues)
  57. array.pop(zigzagdir)
  58.  
  59. add_to_zigzag(dir, dirchanged, ph, pl, index)=>
  60. value = (dir == 1? ph : pl)
  61. if array.size(zigzagvalues) == 0 or dirchanged
  62. add_to_array(value, index, dir)
  63. else if(dir == 1 and value > array.get(zigzagvalues, 0)) or (dir == -1 and value < array.get(zigzagvalues, 0))
  64. array.shift(zigzagvalues)
  65. array.shift(zigzagindexes)
  66. array.shift(zigzagdir)
  67. add_to_array(value, index, dir)
  68.  
  69. zigzag(length)=>
  70. [dir, ph, pl] = pivots(length)
  71. dirchanged = change(dir)
  72. if(ph or pl)
  73. add_to_zigzag(dir, dirchanged, ph, pl, bar_index)
  74.  
  75. calculate_double_pattern()=>
  76. doubleTop = false
  77. doubleTopConfirmation = 0
  78. doubleBottom = false
  79. doubleBottomConfirmation = 0
  80. if(array.size(zigzagvalues) >= 4)
  81. index = array.get(zigzagindexes, 1)
  82. value = array.get(zigzagvalues, 1)
  83. highLow = array.get(zigzagdir, 1)
  84.  
  85. lindex = array.get(zigzagindexes, 2)
  86. lvalue = array.get(zigzagvalues, 2)
  87. lhighLow = array.get(zigzagdir, 2)
  88.  
  89. llindex = array.get(zigzagindexes, 3)
  90. llvalue = array.get(zigzagvalues, 3)
  91. llhighLow = array.get(zigzagdir, 3)
  92. risk = abs(value-llvalue)
  93. reward = abs(value-lvalue)
  94. riskPerReward = risk*100/(risk+reward)
  95.  
  96. if(highLow == 1 and llhighLow == 2 and lhighLow < 0 and riskPerReward < MaxRiskPerReward)
  97. doubleTop := true
  98. if(highLow == -1 and llhighLow == -2 and lhighLow > 0 and riskPerReward < MaxRiskPerReward)
  99. doubleBottom := true
  100.  
  101. if(doubleTop or doubleBottom)
  102. array.set(doubleTopBottomValues, 0, value)
  103. array.set(doubleTopBottomValues, 1, lvalue)
  104. array.set(doubleTopBottomValues, 2, llvalue)
  105.  
  106. array.set(doubleTopBottomIndexes, 0, index)
  107. array.set(doubleTopBottomIndexes, 1, lindex)
  108. array.set(doubleTopBottomIndexes, 2, llindex)
  109.  
  110. array.set(doubleTopBottomDir, 0, highLow)
  111. array.set(doubleTopBottomDir, 1, lhighLow)
  112. array.set(doubleTopBottomDir, 2, llhighLow)
  113.  
  114. [doubleTop, doubleBottom]
  115.  
  116. get_crossover_info(doubleTop, doubleBottom)=>
  117. index = array.get(doubleTopBottomIndexes, 0)
  118. value = array.get(doubleTopBottomValues, 0)
  119. highLow = array.get(doubleTopBottomDir, 0)
  120.  
  121. lindex = array.get(doubleTopBottomIndexes, 1)
  122. lvalue = array.get(doubleTopBottomValues, 1)
  123. lhighLow = array.get(doubleTopBottomDir, 1)
  124.  
  125. llindex = array.get(doubleTopBottomIndexes, 2)
  126. llvalue = array.get(doubleTopBottomValues, 2)
  127. llhighLow = array.get(doubleTopBottomDir, 2)
  128.  
  129. latestDoubleTop = false
  130. latestDoubleBottom = false
  131. latestDoubleTop := doubleTop ? true : doubleBottom? false : latestDoubleTop[1]
  132. latestDoubleBottom := doubleBottom? true : doubleTop? false : latestDoubleBottom[1]
  133.  
  134. doubleTopConfirmation = 0
  135. doubleBottomConfirmation = 0
  136. doubleTopConfirmation := latestDoubleTop? (crossunder(low, lvalue) ? 1 : crossover(high, llvalue) ? -1 : 0) : 0
  137. doubleBottomConfirmation := latestDoubleBottom? (crossover(high, lvalue) ? 1 : crossunder(low, llvalue) ? -1 : 0) : 0
  138. [doubleTopConfirmation, doubleBottomConfirmation]
  139.  
  140. draw_double_pattern(doubleTop,doubleBottom,doubleTopConfirmation,doubleBottomConfirmation)=>
  141. index = array.get(doubleTopBottomIndexes, 0)
  142. value = array.get(doubleTopBottomValues, 0)
  143. highLow = array.get(doubleTopBottomDir, 0)
  144.  
  145. lindex = array.get(doubleTopBottomIndexes, 1)
  146. lvalue = array.get(doubleTopBottomValues, 1)
  147. lhighLow = array.get(doubleTopBottomDir, 1)
  148.  
  149. llindex = array.get(doubleTopBottomIndexes, 2)
  150. llvalue = array.get(doubleTopBottomValues, 2)
  151. llhighLow = array.get(doubleTopBottomDir, 2)
  152.  
  153. isBullish = true
  154. isBullish := (doubleTop or doubleBottom)? doubleTop : isBullish[1]
  155.  
  156. risk = abs(value-llvalue)
  157. reward = abs(value-lvalue)
  158. riskPerReward = risk*100/(risk+reward)
  159.  
  160. base = line.new(x1=index, y1=value,
  161. x2 = llindex, y2=llvalue,
  162. color=doubleTop? bearishColor : bullishColor, width=2, style=line.style_solid)
  163. l1 = line.new(x1=index, y1=value,
  164. x2 = lindex, y2=lvalue,
  165. color=doubleTop? bearishColor : bullishColor, width=2, style=line.style_dotted)
  166. l2 = line.new(x1=lindex, y1=lvalue,
  167. x2 = llindex, y2=llvalue,
  168. color=doubleTop? bearishColor : bullishColor, width=2, style=line.style_dotted)
  169. labelText = (doubleTop? "Double Top" : "Double Bottom") + (DisplayRiskPerReward ? " RR - "+tostring(riskPerReward) : "")
  170.  
  171. baseLabel = label.new(x=index, y=value, text=labelText, yloc=doubleTop?yloc.abovebar:yloc.belowbar,
  172. color=doubleTop?bearishColor:bullishColor,
  173. style=doubleTop?label.style_label_down:label.style_label_up,
  174. textcolor=textColor, size=size.normal)
  175.  
  176. if not (doubleTop or doubleBottom)
  177. line.delete(base)
  178. line.delete(l1)
  179. line.delete(l2)
  180. label.delete(baseLabel)
  181.  
  182. var doubleTopCount = 0
  183. var doubleBottomCount = 0
  184. doubleTopCount := doubleTop? nz(doubleTopCount[1],0) + 1 : nz(doubleTopCount[1],0)
  185. doubleBottomCount := doubleBottom? nz(doubleBottomCount[1],0) + 1 : nz(doubleBottomCount[1],0)
  186.  
  187. if(line.get_x2(base) == line.get_x2(base[1]))
  188. line.delete(base[1])
  189. line.delete(l1[1])
  190. line.delete(l2[1])
  191. label.delete(baseLabel[1])
  192. doubleTopCount := doubleTop? doubleTopCount -1 : doubleTopCount
  193. doubleBottomCount := doubleBottom? doubleBottomCount -1 : doubleBottomCount
  194.  
  195.  
  196. if(barstate.islast)
  197. lres = line.new(x1=bar_index, y1=lvalue,
  198. x2 = lindex, y2=lvalue,
  199. color=isBullish? bearishColor : bullishColor, width=2, style=line.style_dashed, extend=extend.left)
  200. lsup = line.new(x1=bar_index, y1=llvalue,
  201. x2 = llindex, y2=llvalue,
  202. color=isBullish? bullishColor : bearishColor , width=2, style=line.style_dashed, extend=extend.left)
  203.  
  204.  
  205. doubleTopConfirmationCount = doubleTopConfirmation>0? 1 : 0
  206. doubleBottomConfirmationCount = doubleBottomConfirmation>0? 1:0
  207. doubleTopInvalidationCount = doubleTopConfirmation<0? 1 : 0
  208. doubleBottomInvalidationCount = doubleBottomConfirmation<0? 1:0
  209.  
  210. if(doubleTopConfirmation != 0 or doubleBottomConfirmation !=0)
  211. if(doubleTopConfirmation>0 or doubleBottomConfirmation > 0)
  212. lresbreak = line.new(x1=lindex, y1=lvalue,
  213. x2 = bar_index, y2=lvalue,
  214. color=isBullish? bearishColor : bullishColor, width=2, style=line.style_dashed)
  215. if(line.get_x1(lresbreak[1]) == line.get_x1(lresbreak))
  216. doubleTopConfirmationCount := 0
  217. doubleBottomConfirmationCount := 0
  218. doubleTopInvalidationCount := 0
  219. doubleBottomInvalidationCount := 0
  220. line.delete(lresbreak)
  221. lresbreak := lresbreak[1]
  222. else if(doubleTopConfirmation<0 or doubleBottomConfirmation < 0)
  223. lsupbreak = line.new(x1=llindex, y1=llvalue,
  224. x2 = bar_index, y2=llvalue,
  225. color=isBullish? bullishColor : bearishColor , width=2, style=line.style_dashed)
  226. if(line.get_x1(lsupbreak[1]) == line.get_x1(lsupbreak))
  227. doubleTopInvalidationCount := 0
  228. doubleBottomInvalidationCount := 0
  229. doubleTopConfirmationCount := 0
  230. doubleBottomConfirmationCount := 0
  231. line.delete(lsupbreak)
  232. lsupbreak := lsupbreak[1]
  233. doubleTopConfirmationCount := nz(doubleTopConfirmationCount[1],0)+doubleTopConfirmationCount
  234. doubleBottomConfirmationCount := nz(doubleBottomConfirmationCount[1],0)+doubleBottomConfirmationCount
  235. doubleTopInvalidationCount := nz(doubleTopInvalidationCount[1],0)+doubleTopInvalidationCount
  236. doubleBottomInvalidationCount := nz(doubleBottomInvalidationCount[1],0)+doubleBottomInvalidationCount
  237. [doubleTopCount, doubleBottomCount, doubleTopConfirmationCount, doubleBottomConfirmationCount, doubleTopInvalidationCount, doubleBottomInvalidationCount]
  238.  
  239. zigzag(length)
  240.  
  241. [doubleTop, doubleBottom] = calculate_double_pattern()
  242. [doubleTopConfirmation, doubleBottomConfirmation] = get_crossover_info(doubleTop, doubleBottom)
  243. [doubleTopCount, doubleBottomCount,
  244. doubleTopConfirmationCount, doubleBottomConfirmationCount,
  245. doubleTopInvalidationCount, doubleBottomInvalidationCount] = draw_double_pattern(doubleTop,doubleBottom,doubleTopConfirmation,doubleBottomConfirmation)
  246.  
  247. var stats = table.new(position = position.top_right, columns = 5, rows = 5, border_width = 1)
  248. if(barstate.islast and showStats)
  249. colorWorst = color.rgb(255, 153, 51)
  250. colorBest = color.rgb(51, 204, 51)
  251. colorBad = color.rgb(255, 204, 153)
  252. colorGood = color.rgb(204, 255, 204)
  253. colorNeutral = color.rgb(255, 255, 204)
  254.  
  255. dtConfirmationPercent = doubleTopConfirmationCount+doubleTopInvalidationCount == 0? 0.5 : doubleTopConfirmationCount/(doubleTopConfirmationCount+doubleTopInvalidationCount)
  256. dbConfirmationPercent = (doubleBottomConfirmationCount+doubleBottomInvalidationCount) == 0? 0.5 : doubleBottomConfirmationCount/(doubleBottomConfirmationCount+doubleBottomInvalidationCount)
  257.  
  258. dtColor = dtConfirmationPercent >= 0.8? colorBest :
  259. dtConfirmationPercent >= 0.6? colorGood :
  260. dtConfirmationPercent >= 0.4? colorNeutral :
  261. dtConfirmationPercent >= 0.2? colorBad : colorWorst
  262. dbColor = dbConfirmationPercent >= 0.8? colorBest :
  263. dbConfirmationPercent >= 0.6? colorGood :
  264. dbConfirmationPercent >= 0.4? colorNeutral :
  265. dbConfirmationPercent >= 0.2? colorBad : colorWorst
  266. table.cell(table_id = stats, column = 0, row = 0 , text = "", bgcolor=color.black, text_color=color.white)
  267. table.cell(table_id = stats, column = 0, row = 1 , text = "Double Top", bgcolor=color.black, text_color=color.white)
  268. table.cell(table_id = stats, column = 0, row = 2 , text = "Double Bottom", bgcolor=color.black, text_color=color.white)
  269.  
  270. table.cell(table_id = stats, column = 1, row = 0 , text = "Count", bgcolor=color.black, text_color=color.white)
  271. table.cell(table_id = stats, column = 2, row = 0 , text = "Confirmation", bgcolor=color.black, text_color=color.white)
  272. table.cell(table_id = stats, column = 3, row = 0 , text = "Invalidation", bgcolor=color.black, text_color=color.white)
  273.  
  274. table.cell(table_id = stats, column = 1, row = 1, text = tostring(doubleTopCount), bgcolor=dtColor)
  275. table.cell(table_id = stats, column = 1, row = 2, text = tostring(doubleBottomCount), bgcolor=dbColor)
  276.  
  277. table.cell(table_id = stats, column = 2, row = 1, text = tostring(doubleTopConfirmationCount), bgcolor=dtColor)
  278. table.cell(table_id = stats, column = 3, row = 1, text = tostring(doubleTopInvalidationCount), bgcolor=dtColor)
  279.  
  280. table.cell(table_id = stats, column = 2, row = 2, text = tostring(doubleBottomConfirmationCount), bgcolor=dbColor)
  281. table.cell(table_id = stats, column = 3, row = 2, text = tostring(doubleBottomInvalidationCount), bgcolor=dbColor)
  282.  
  283. if(barstate.islast and array.size(zigzagindexes) > 1)
  284. lastHigh = 0.0
  285. lastLow = 0.0
  286. for x = 0 to array.size(zigzagindexes)-1
  287. i = array.size(zigzagindexes)-1-x
  288. index = array.get(zigzagindexes, i)
  289. value = array.get(zigzagvalues, i)
  290. highLow = array.get(zigzagdir, i)
  291. index_offset = bar_index-index
  292.  
  293. labelText = highLow ==2 ? "HH" : highLow == 1? "LH" : highLow == -1? "HL" : "LL"
  294. labelColor = highLow ==2 ? bullishColor : highLow == 1? bullTrapColor : highLow == -1? bearTrapColor : bearishColor
  295. labelStyle = highLow > 0? label.style_label_down : label.style_label_up
  296. // labelLocation = highLow > 0? yloc.abovebar : yloc.belowbar
  297. labelLocation = yloc.price
  298. if(showPivots)
  299. label.new(x=index, y = value, text=labelText, xloc=xloc.bar_index, yloc=labelLocation, style=labelStyle, size=size.tiny,
  300. color=labelColor, textcolor=textColor)
  301. if(i < array.size(zigzagindexes)-1 and showZigzag)
  302. indexLast = array.get(zigzagindexes, i+1)
  303. valueLast = array.get(zigzagvalues, i+1)
  304. line.new(x1=index, y1=value,
  305. x2 = indexLast, y2=valueLast,
  306. color=labelColor, width=2, style=line.style_solid)
  307. alertcondition(doubleBottom, "Double Bottom", "Probable double bottom observed for {{ticker}} on {{interval}} timeframe")
  308. alertcondition(doubleBottomConfirmation > 0, "Double Bottom Confirmation", "Double bottom confirmation observed for {{ticker}} on {{interval}} timeframe")
  309. alertcondition(doubleBottomConfirmation < 0, "Double Bottom Invalidation", "Double bottom invalidation observed for {{ticker}} on {{interval}} timeframe")
  310. alertcondition(doubleTop, "Double Top", "Probable double top observed for {{ticker}} on {{interval}} timeframe")
  311. alertcondition(doubleTopConfirmation > 0, "Double Top Confirmation", "Double top confirmation observed for {{ticker}} on {{interval}} timeframe")
  312. alertcondition(doubleTopConfirmation < 0, "Double Top Invalidation", "Double top invalidation observed for {{ticker}} on {{interval}} timeframe")
Advertisement
Add Comment
Please, Sign In to add comment