xmd79

Double Top/Bottom - Ultimate (OS)

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