xmd79

Obj_XABCD_Harmonic

Dec 20th, 2022
463
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.27 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. // © reees
  3.  
  4. //@version=5
  5.  
  6. // @description Harmonic XABCD Pattern object and associated methods. Easily validate, draw, and get information about harmonic patterns. See example code at the end of the script for details.
  7. library("Obj_XABCD_Harmonic",true)
  8.  
  9. import reees/TA/69 as t
  10. import reees/Draw/22 as draw
  11. import reees/Utilities/4 as u
  12.  
  13. // @type Validation and scoring parameters for a Harmonic Pattern object (xabcd_harmonic)
  14. // @field pct_error Allowed % error of leg retracement ratio versus the defined harmonic ratio
  15. // @field pct_asym Allowed leg length/period asymmetry % (a leg is considered invalid if it is this % longer or shorter than the average length of the other legs)
  16. // @field types Array of pattern types to validate (1=Gartley, 2=Bat, 3=Butterfly, 4=Crab, 5=Shark, 6=Cypher)
  17. // @field w_e Weight of ratio % error (used in score calculation, dft = 1)
  18. // @field w_p Weight of PRZ confluence (used in score calculation, dft = 1)
  19. // @field w_d Weight of Point D / PRZ confluence (used in score calculation, dft = 1)
  20. export type harmonic_params
  21. float pct_error = 15.0
  22. float pct_asym = 250.0
  23. int[] types
  24. float w_e = 1.0
  25. float w_p = 1.0
  26. float w_d = 1.0
  27.  
  28. // @function Create a harmonic parameters object (used by xabcd_harmonic object for pattern validation and scoring).
  29. // @param pct_error Allowed % error of leg retracement ratio versus the defined harmonic ratio
  30. // @param pct_asym Allowed leg length/period asymmetry % (a leg is considered invalid if it is this % longer or shorter than the average length of the other legs)
  31. // @param types Array of pattern types to validate (1=Gartley, 2=Bat, 3=Butterfly, 4=Crab, 5=Shark, 6=Cypher)
  32. // @param w_e Weight of ratio % error (used in score calculation, dft = 1)
  33. // @param w_p Weight of PRZ confluence (used in score calculation, dft = 1)
  34. // @param w_d Weight of Point D / PRZ confluence (used in score calculation, dft = 1)
  35. // @returns harmonic_params object instance. It is recommended to store and reuse this object for multiple xabcd_harmonic objects rather than creating new params objects unnecessarily.
  36. export init_params(float pct_error=15.0, float pct_asym=250.0, int[] types=na, float w_e=1, float w_p=1, float w_d=1) =>
  37. harmonic_params.new(pct_error,
  38. pct_asym,
  39. na(types)?array.from(1,2,3,4,5,6):types,
  40. w_e,
  41. w_p,
  42. w_d)
  43.  
  44. // @type Harmonic Pattern object
  45. // @field bull Bullish pattern flag
  46. // @field tp Pattern type (1=Gartley, 2=Bat, 3=Butterfly, 4=Crab, 5=Shark, 6=Cypher)
  47. // @field xX Point X bar index
  48. // @field xY Point X price/level
  49. // @field aX Point A bar index
  50. // @field aY Point A price/level
  51. // @field bX Point B bar index
  52. // @field bY Point B price/level
  53. // @field cX Point C bar index
  54. // @field cY Point C price/level
  55. // @field dX Point D bar index
  56. // @field dY Point D price/level
  57. // @field r_xb XAB ratio
  58. // @field re_xb XAB ratio % error
  59. // @field r_ac ABC ratio
  60. // @field re_ac ABC ratio % error
  61. // @field r_bd BCD ratio
  62. // @field re_bd BCD ratio % error
  63. // @field r_xd XAD or XCD ratio, depending on pattern type
  64. // @field re_xd XAD ratio % error
  65. // @field score Total score
  66. // @field score_eAvg Avg % error
  67. // @field score_prz PRZ score
  68. // @field score_eD Point D/PRZ confluence score
  69. // @field prz_bN BCD retracement near
  70. // @field prz_bF BCD retracement far
  71. // @field prz_xN XAD/XCD retracement near
  72. // @field prz_xF XAD/XCD retracement far
  73. // @field t1Hit Target 1 flag
  74. // @field t1 Target 1 level
  75. // @field t2Hit Target 2 flag
  76. // @field t2 Target 2 level
  77. // @field sHit Stop flag
  78. // @field stop Stop level
  79. // @field entry Entry level
  80. // @field eHit Entry flag
  81. // @field eX Entry bar index
  82. // @field eY Enty price/level
  83. // @field pLines Pattern lines
  84. // @field pLabel Pattern label
  85. // @field pid Pattern ID
  86. // @field params harmonic_params for validating and scoring the pattern
  87. export type xabcd_harmonic
  88. // *** Type ***
  89. bool bull // Bullish flag
  90. int tp // Type (1=Gartley, 2=Bat, 3=Butterfly, 4=Crab, 5=Shark, 6=Cypher)
  91. // *** Coordinates ***
  92. int xX
  93. float xY
  94. int aX
  95. float aY
  96. int bX
  97. float bY
  98. int cX
  99. float cY
  100. int dX
  101. float dY
  102. // *** Values ***
  103. float r_xb // XAB ratio
  104. float re_xb // XAB ratio % error
  105. float r_ac // etc...
  106. float re_ac
  107. float r_bd
  108. float re_bd
  109. float r_xd // XAD or XCD, depending on pattern type
  110. float re_xd
  111. // Score
  112. float score // total score
  113. float score_eAvg // avg % error
  114. // float sym // leg length symmetry
  115. float score_prz // PRZ score
  116. float score_eD // Point D/PRZ confluence score
  117. // PRZ
  118. float prz_bN // BCD retracement near
  119. float prz_bF // BCD retracement far
  120. float prz_xN // XAD/XCD retracement near
  121. float prz_xF // XAD/XCD retracement far
  122. // State flags/values
  123. bool t1Hit // target 1 flag
  124. float t1 // target 1 level
  125. bool t2Hit // target 2 flag
  126. float t2 // target 2 level
  127. bool sHit // stop-loss flag
  128. float stop // stop-loss level
  129. float entry // entry level
  130. bool eHit // entry flag
  131. int eX // entry bar index
  132. float eY // entry level
  133. // *** Drawings ***
  134. line[] pLines
  135. label pLabel
  136. //
  137. string pid // Pattern ID
  138. harmonic_params params // Validation parameters
  139.  
  140.  
  141. //*******************************************************************
  142. // Object functions/methods
  143. //*******************************************************************
  144.  
  145. // (private) Pattern ID
  146. pid(p) =>
  147. str.tostring(p.tp) + "_"
  148. + str.tostring(p.xX) + "_"
  149. + str.tostring(p.aX) + "_"
  150. + str.tostring(p.bX) + "_"
  151. + str.tostring(p.cX) + "_"
  152. + str.tostring(p.dX)
  153.  
  154. // (private) Set pattern ID
  155. set_pid(p) =>
  156. p.pid := pid(p)
  157.  
  158. // (private) Get the highest scoring pattern type. It's unlikely that a complete pattern will be valid for more than one harmonic,
  159. // but it's possible (especially if your validation parameters are more inclusive).
  160. highestScoringType(tps,params,xX,xY,aX,aY,bX,bY,cX,cY,dX,dY) =>
  161. int hst = na
  162. float hs=0.0, float hs1=0.0, float hs2=0.0, float hs3=0.0
  163. for tp in tps
  164. [eavg,asym,eD,prz,_,_,_] = t.harmonic_xabcd_score(tp+1,xX,xY,aX,aY,bX,bY,cX,cY,dX,dY)
  165. s = t.harmonic_xabcd_scoreTot(asym,eavg,prz,eD,tp+1,0.0,params.w_e,params.w_p,params.w_d)
  166. if s>hs
  167. hst := tp+1
  168. hs := s
  169. hs1 := eavg
  170. hs2 := eD
  171. hs3 := prz
  172. [hst,hs,hs1,hs2,hs3]
  173.  
  174. validAbcd(bull,aY,bY,cY,dY) =>
  175. if bull
  176. aY > bY and cY > bY and (na(dY) or cY > dY)
  177. else
  178. aY < bY and cY < bY and (na(dY) or cY < dY)
  179.  
  180. // @function Initialize an xabcd_harmonic object instance.
  181. // If the pattern is valid, an xabcd_harmonic object instance is returned. If you want to specify your
  182. // own validation and scoring parameters, you can do so by passing a harmonic_params object (params).
  183. // Or, if you prefer to do your own validation, you can explicitly pass the harmonic pattern type (tp)
  184. // and validation will be skipped. You can also pass in an existing xabcd_harmonic instance if you wish
  185. // to re-initialize it (e.g. for re-validation and/or re-scoring).
  186. // @param xX Point X bar index
  187. // @param xY Point X price/level
  188. // @param aX Point A bar index
  189. // @param aY Point A price/level
  190. // @param bX Point B bar index
  191. // @param bY Point B price/level
  192. // @param cX Point C bar index
  193. // @param cY Point C price/level
  194. // @param dX Point D bar index
  195. // @param dY Point D price/level
  196. // @param params harmonic_params used to validate and score the pattern. Validation will be skipped if a type (tp) is explicitly passed in.
  197. // @param tp Pattern type
  198. // @param p xabcd_harmonic object instance to initialize (optional, for re-validation/re-scoring)
  199. // @returns xabcd_harmonic object instance if a valid harmonic, else na
  200. export init(int xX=na, float xY=na, int aX=na, float aY=na, int bX=na, float bY=na, int cX=na, float cY=na,int dX=na,float dY=na,
  201. harmonic_params params=na, int tp=na, xabcd_harmonic p=na) =>
  202.  
  203. xabcd_harmonic obj = p
  204. int validType = tp>0 and tp<7 ? tp : na
  205. float[] scores = array.new_float()
  206. par = na(params) ? init_params() : params
  207.  
  208. // Validate XABCD pattern
  209. bull = xY < aY
  210. if validAbcd(bull,aY,bY,cY,dY) == false
  211. validType := na
  212. // Validate Harmonic pattern
  213. else if na(validType)
  214. tps = u.intToBoolArr(par.types,7)
  215. [f,h1,h2,h3,h4,h5,h6] =
  216. t.harmonic_xabcd_validate(xX,xY,aX,aY,bX,bY,cX,cY,dX,dY,par.pct_error,par.pct_asym,
  217. array.get(tps,1),array.get(tps,2),array.get(tps,3),array.get(tps,4),array.get(tps,5),array.get(tps,6))
  218. intTps = u.boolToIntArr(array.from(h1,h2,h3,h4,h5,h6))
  219. if array.size(intTps) == 1
  220. validType := array.pop(intTps)+1
  221. else if array.size(intTps) > 1
  222. [hst,s,s1,s2,s3] = highestScoringType(intTps,par,xX,xY,aX,aY,bX,bY,cX,cY,dX,dY)
  223. scores := array.from(s,s1,s2,s3)
  224. validType := hst
  225. else
  226. validType := na
  227.  
  228. // Create object if we have a valid type (or type was explicitly passed)
  229. if not na(validType)
  230. obj := na(p) ? xabcd_harmonic.new() : p
  231. [xbr,xbre] = t.harmonic_xabcd_rAndE(validType,"xab",aY-bY,aY-xY)
  232. [acr,acre] = t.harmonic_xabcd_rAndE(validType,"abc",cY-bY,aY-bY)
  233. [bdr,bdre] = t.harmonic_xabcd_rAndE(validType,"bcd",cY-dY,cY-bY)
  234. [xdr,xdre] = t.harmonic_xabcd_rAndE(validType,"xad",aY-dY,aY-xY)
  235. if array.size(scores) == 0
  236. [eavg,asym,eD,przscore,_,cpl1,cpl2] = t.harmonic_xabcd_score(validType,xX,xY,aX,aY,bX,bY,cX,cY,dX,dY)
  237. s = t.harmonic_xabcd_scoreTot(asym,eavg,przscore,eD,validType,0.0,par.w_e,par.w_p,par.w_d)
  238. scores := array.from(s,eavg,eD,przscore)
  239. [bcN,bcF,xaN,xaF] = t.harmonic_xabcd_prz(validType,xY,aY,bY,cY)
  240. obj.bull := bull
  241. obj.xX := xX
  242. obj.xY := xY
  243. obj.aX := aX
  244. obj.aY := aY
  245. obj.bX := bX
  246. obj.bY := bY
  247. obj.cX := cX
  248. obj.cY := cY
  249. obj.dX := dX
  250. obj.dY := dY
  251. obj.tp := validType
  252. obj.r_xb := xbr
  253. obj.re_xb := xbre
  254. obj.r_ac := acr
  255. obj.re_ac := acre
  256. obj.r_bd := bdr
  257. obj.re_bd := bdre
  258. obj.r_xd := xdr
  259. obj.re_xd := xdre
  260. obj.score := array.get(scores,0)
  261. obj.score_eAvg := array.get(scores,1)
  262. obj.score_prz := array.get(scores,3)
  263. obj.score_eD := array.get(scores,2)
  264. obj.prz_bN := bcN
  265. obj.prz_bF := bcF
  266. obj.prz_xN := xaN
  267. obj.prz_xF := xaF
  268. obj.pLines := array.new_line()
  269. set_pid(obj)
  270. obj
  271.  
  272. // *** Get/Set ***
  273.  
  274. // @function Get the pattern name
  275. // @param p Instance of xabcd_harmonic object
  276. // @returns Pattern name (string)
  277. export get_name(xabcd_harmonic p) =>
  278. a = p.bull ? "Bullish" : "Bearish"
  279. b = switch p.tp
  280. 1 => "Gartley"
  281. 2 => "Bat"
  282. 3 => "Butterfly"
  283. 4 => "Crab"
  284. 5 => "Shark"
  285. 6 => "Cypher"
  286. => "Undefined harmonic"
  287. a + " " + b
  288.  
  289. // @function Get the pattern symbol
  290. // @param p Instance of xabcd_harmonic object
  291. // @returns Pattern symbol (1 byte string)
  292. export get_symbol(xabcd_harmonic p) =>
  293. t.harmonic_xabcd_symbol(p.tp)
  294.  
  295. // @function Get the Pattern ID. Patterns of the same type with the same coordinates will have the same Pattern ID.
  296. // @param p Instance of xabcd_harmonic object
  297. // @returns Pattern ID (string)
  298. export get_pid(xabcd_harmonic p) =>
  299. if na(p.pid)
  300. set_pid(p)
  301. p.pid
  302.  
  303. // @function Set value for a target. Use the calc_target parameter to automatically calculate the target for a specific harmonic ratio.
  304. // @param p Instance of xabcd_harmonic object
  305. // @param target Target (1 or 2)
  306. // @param target_lvl Target price/level (required if calc_target is not specified)
  307. // @param calc_target Target to auto calculate (required if target is not specified)
  308. // Options: [".382 AD", ".5 AD", ".618 AD", "1.272 AD", "1.618 AD"
  309. // ".382 XA", ".5 XA" ,".618 XA", "1.272 XA", "1.618 XA",
  310. // ".382 CD", ".5 CD", ".618 CD", "1.272 CD", "1.618 CD",
  311. // "A", "B", "C"]
  312. // @returns Target price/level (float)
  313. export set_target(xabcd_harmonic p, int target=1, float target_lvl=na, string calc_target=".618 AD") =>
  314. if na(target_lvl)
  315. [t,_,_] = t.harmonic_xabcd_targets(p.xY,p.aY,p.bY,p.cY,p.dY,calc_target)
  316. if target==1
  317. p.t1 := t
  318. else
  319. p.t2 := t
  320. else
  321. if target==1
  322. p.t1 := target_lvl
  323. else
  324. p.t2 := target_lvl
  325.  
  326. // *** Functions ***
  327.  
  328. // @function Erase the pattern
  329. // @param p Instance of xabcd_harmonic object
  330. // @returns p
  331. export erase_pattern(xabcd_harmonic p) =>
  332. for l in p.pLines
  333. line.delete(l)
  334. p.pLines := array.new_line()
  335. p
  336.  
  337. // @function Draw the pattern
  338. // @param p Instance of xabcd_harmonic object
  339. // @returns Pattern lines
  340. // [l1,l2,l3,l4,l5,l6]
  341. export draw_pattern(xabcd_harmonic p, color clr) =>
  342. erase_pattern(p)
  343. [lower,higher] = t.harmonic_xabcd_przClosest(p.prz_bN,p.prz_bF,p.prz_xN,p.prz_xF)
  344. float iE = na(p.dX) ? (p.bull?higher:lower) : na // potential point D for incomplete pattern
  345. [l1,l2,l3,l4,l5,l6] = draw.xabcd(p.xX,p.xY,p.aX,p.aY,p.bX,p.bY,p.cX,p.cY,p.dX,p.dY,iE,p.bull,color.new(clr,20),color.new(clr,20))
  346. p.pLines := array.from(l1,l2,l3,l4,l5,l6)
  347. [l1,l2,l3,l4,l5,l6]
  348.  
  349. // @function Erase the pattern label
  350. // @param p Instance of xabcd_harmonic object
  351. // @returns p
  352. export erase_label(xabcd_harmonic p) =>
  353. if not na(p.pLabel)
  354. label.delete(p.pLabel)
  355. p
  356.  
  357. // @function Draw the pattern label. Default text is the pattern name.
  358. // @param p Instance of xabcd_harmonic object
  359. // @param txt Label text
  360. // @param tooltip Tooltip text
  361. // @param clr Label color
  362. // @param txt_clr Text color
  363. // @returns Label
  364. export draw_label(xabcd_harmonic p, color clr=color.gray, color txt_clr=color.white, string txt=na, string tooltip=na) =>
  365. erase_label(p)
  366. lbstyle = p.bull ? label.style_label_up : label.style_label_down
  367. incLbstyle = p.bull ? label.style_label_down : label.style_label_up
  368. t = not na(txt) ? txt : get_name(p)
  369. lbl =
  370. if not na(p.dX) // Completed pattern
  371. label.new(p.dX,p.dY,text=t,textcolor=txt_clr,size=size.small,style=lbstyle,tooltip=tooltip,color=clr)
  372. else // Incomplete pattern
  373. if array.size(p.pLines)>0
  374. l4 = array.get(p.pLines,3)
  375. not na(l4) ? label.new(line.get_x2(l4),line.get_y2(l4),text=t,tooltip=tooltip,textcolor=txt_clr,size=size.small,style=lbstyle,color=clr)
  376. : label.new(p.cX,p.cY,text=t,tooltip=tooltip,textcolor=txt_clr,size=size.small,style=lbstyle,color=clr)
  377. else
  378. label.new(p.cX,p.cY,text=t,tooltip=tooltip,textcolor=txt_clr,size=size.small,style=lbstyle,color=clr)
  379. p.pLabel := lbl
  380.  
  381.  
  382.  
  383. //********************************
  384. // Example / Test code
  385. //********************************
  386.  
  387. // Use your preferred zig-zag method to get the XABCD pattern coordinates.
  388. // Coordinates are hard-coded here for simplicity of the example.
  389. // ADA 4h gartley
  390. var int xX = 10681
  391. var float xY = .344
  392. var int aX = 10714
  393. var float aY = .296
  394. var int bX = 10743
  395. var float bY = .322
  396. var int cX = 10752
  397. var float cY = .3
  398. var int dX = 10796
  399. var float dY = .329
  400.  
  401. if bar_index == 10796
  402. // *** Instantiate the xabcd_harmonic ***
  403. // [0] Simply pass in the pattern coordinates and the pattern will be automatically validated.
  404. // If the pattern is valid, an xabcd_harmonic object instance is returned. If you prefer to do
  405. // your own validation, you can skip it by explicitly passing a type (tp) to the init() function.
  406. // Or, if you want to specify the validation and scoring parameters, you can do so by passing a
  407. // harmonic_params object to the init() function.
  408. pat = init(xX, xY, aX, aY, bX, bY, cX, cY, dX, dY)
  409. // pat = init(xX, xY, aX, aY, bX, bY, cX, cY) // pattern can be incomplete, i.e. point D not yet established
  410.  
  411. if not na(pat)
  412. // *** When a valid xabcd_harmonic is initialized... ***
  413. // [1] We know what type of harmonic pattern we have (pat.tp field)
  414. name = get_name(pat) + " (" + get_symbol(pat) + ")" // get pattern name and symbol with exported functions
  415. u.print(name)
  416.  
  417. // [2] PRZ levels are automatically calculated
  418. // e.g. pat.prz_bN, pat.prz_xN, pat.prz_bF, pat.prz_xF
  419. draw.level(pat.prz_bN,na(pat.dX)?pat.cX:pat.dX,length=100,padding=.5,txt="Near BC PRZ level") // illustrate near BC PRZ retracement level
  420. draw.level(pat.prz_xN,na(pat.dX)?pat.cX:pat.dX,length=100,padding=.5,txt="Near XA PRZ level") // illustrate near XA PRZ retracement level
  421.  
  422. // [3] Scores are calculated to represent the quality of the harmonic pattern
  423. // e.g. pat.score, pat.score_prz, pat.score_eAvg, pat.score_eD
  424. u.print(("Leg avg retracement % error: " + str.tostring(pat.score_eAvg*100,"#.#") + "%"),position.bottom_left) // illustrate avg leg retracement % error score
  425.  
  426. // [4] Easily draw the pattern and a label
  427. draw_pattern(pat, color.red)
  428. draw_label(pat, color.new(color.red,70))
  429.  
  430. // [5] Set targets. You can specify the a specific target level, or have the target automatically calculated for a specific
  431. // harmonic retracement ratio of a pattern leg
  432. // e.g. ".618 AD" or "1.272 XA"
  433. set_target(pat, 1, calc_target=".618 AD")
  434. set_target(pat, 2, calc_target="1.272 XA")
  435. draw.level(pat.t1,na(pat.dX)?pat.cX:pat.dX,length=100,padding=.5,txt="Target 1") // illustrate target 1
  436. draw.level(pat.t2,na(pat.dX)?pat.cX:pat.dX,length=100,padding=.5,txt="Target 2") // illustrate target 2
  437.  
  438. //erase_pattern(pat)
  439. //erase_label(pat)
  440.  
  441. // [6] Set stop/entry values, and track trades with state flags
  442. // e.g. pat.stop, pat.entry, pat.sHit, pat.eHit, pat.t1Hit, pat.t2Hit
  443.  
  444.  
  445.  
Advertisement
Add Comment
Please, Sign In to add comment