ajiim

🎁

Oct 5th, 2026
1,174
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 48.62 KB | None | 0 0
  1. //@version=6
  2. indicator("ICT Pro+ | TimmyNQ [TakingProphets]", shorttitle = "ICT Pro+ | TimmyNQ", overlay = true, max_lines_count = 500, max_labels_count = 500, max_boxes_count = 500, max_bars_back = 5000)
  3.  
  4. const string G_CONF = "Confluences"
  5. const string G_HTF = "High Timeframe Gaps"
  6. const string G_KL = "Key Liquidity"
  7. const string G_LRL = "Low Resistance Liquidity"
  8. const string G_KO = "Key Opens"
  9. const string G_KZ = "Killzones / Sessions"
  10. const string G_SMT = "SMT Divergence"
  11.  
  12. conf_ifvgShow = input.bool(true, "Inversion FVGs", inline = "ifvg", group = G_CONF, tooltip = "After a liquidity sweep, the most recent qualifying Fair Value Gap that price closes through is drawn as an inversion box. Max keeps only the most recent N inversion boxes.")
  13. conf_ifvgMax = input.int(2, "Max", minval = 1, maxval = 20, inline = "ifvg", group = G_CONF)
  14. conf_ifvgBull = input.color(#2157f333, "", inline = "ifvg", group = G_CONF)
  15. conf_ifvgBear = input.color(#13172233, "", inline = "ifvg", group = G_CONF)
  16. conf_fvgShow = input.bool(false, "Fair Value Gaps", inline = "fvg", group = G_CONF, tooltip = "Draws the pending gap before it inverts. It flips to the inversion colors the moment price closes through it. Gaps that never invert are removed automatically.")
  17. conf_fvgBull = input.color(#2157f31a, "", inline = "fvg", group = G_CONF)
  18. conf_fvgBear = input.color(#1317221a, "", inline = "fvg", group = G_CONF)
  19. conf_cisdShow = input.bool(true, "CISDs", inline = "cisd", group = G_CONF, tooltip = "After a liquidity sweep, the open of the delivering leg is tracked. A close back through it prints a CISD line. A CISD whose implied stop is violated is removed.")
  20. conf_cisdMax = input.int(2, "Max", minval = 1, maxval = 20, inline = "cisd", group = G_CONF)
  21. conf_cisdBull = input.color(color.black, "Bullish", inline = "cisd_s", group = G_CONF)
  22. conf_cisdBear = input.color(color.black, "Bearish", inline = "cisd_s", group = G_CONF)
  23. conf_cisdStyle = input.string("Solid", "", options = ["Solid", "Dashed", "Dotted"], inline = "cisd_s", group = G_CONF)
  24. conf_cisdThick = input.string("Thin", "", options = ["Thin", "Medium", "Thick"], inline = "cisd_s", group = G_CONF)
  25. conf_lblShow = input.bool(true, "Labels", inline = "clbl", group = G_CONF, tooltip = "Tags FVG and CISD drawings. Inversion boxes are intentionally left unlabeled.")
  26. conf_lblColor = input.color(color.black, "", inline = "clbl", group = G_CONF)
  27. conf_lblSize = input.string("Tiny", "", options = ["Tiny", "Small", "Normal", "Large"], inline = "clbl", group = G_CONF)
  28.  
  29. htf_show = input.bool(true, "Show Gaps", group = G_HTF, tooltip = "Scans two higher timeframes auto-selected from the chart interval and shows only the single closest unmitigated gap per side.")
  30. htf_bullColor = input.color(#787b8633, "Bullish", inline = "htfc", group = G_HTF)
  31. htf_bearColor = input.color(#787b8633, "Bearish", inline = "htfc", group = G_HTF)
  32. htf_border = input.bool(false, "Border", inline = "htfc", group = G_HTF)
  33. htf_lblColor = input.color(#5d606b, "Label", inline = "htfl", group = G_HTF)
  34. htf_lblSize = input.string("Tiny", "", options = ["Tiny", "Small", "Normal", "Large"], inline = "htfl", group = G_HTF)
  35.  
  36. kl_pwShow = input.bool(true, "PWH / PWL", inline = "pw", group = G_KL)
  37. kl_pwColor = input.color(#7e57c2, "", inline = "pw", group = G_KL)
  38. kl_pwStyle = input.string("Solid", "", options = ["Solid", "Dashed", "Dotted"], inline = "pw", group = G_KL)
  39. kl_pwLabel = input.bool(true, "Label", inline = "pw", group = G_KL)
  40. kl_pwSize = input.string("Tiny", "", options = ["Tiny", "Small", "Normal", "Large"], inline = "pw", group = G_KL)
  41. kl_pdShow = input.bool(true, "PDH / PDL", inline = "pd", group = G_KL)
  42. kl_pdColor = input.color(#f57c00, "", inline = "pd", group = G_KL)
  43. kl_pdStyle = input.string("Solid", "", options = ["Solid", "Dashed", "Dotted"], inline = "pd", group = G_KL)
  44. kl_pdLabel = input.bool(true, "Label", inline = "pd", group = G_KL)
  45. kl_pdSize = input.string("Tiny", "", options = ["Tiny", "Small", "Normal", "Large"], inline = "pd", group = G_KL)
  46. kl_asShow = input.bool(true, "Asia H / L", inline = "as", group = G_KL)
  47. kl_asColor = input.color(#f23645, "", inline = "as", group = G_KL)
  48. kl_asStyle = input.string("Solid", "", options = ["Solid", "Dashed", "Dotted"], inline = "as", group = G_KL)
  49. kl_asLabel = input.bool(true, "Label", inline = "as", group = G_KL)
  50. kl_asSize = input.string("Tiny", "", options = ["Tiny", "Small", "Normal", "Large"], inline = "as", group = G_KL)
  51. kl_loShow = input.bool(true, "London H / L", inline = "lo", group = G_KL)
  52. kl_loColor = input.color(#089981, "", inline = "lo", group = G_KL)
  53. kl_loStyle = input.string("Solid", "", options = ["Solid", "Dashed", "Dotted"], inline = "lo", group = G_KL)
  54. kl_loLabel = input.bool(true, "Label", inline = "lo", group = G_KL)
  55. kl_loSize = input.string("Tiny", "", options = ["Tiny", "Small", "Normal", "Large"], inline = "lo", group = G_KL)
  56. kl_athShow = input.bool(true, "All-Time High", inline = "ath", group = G_KL)
  57. kl_athColor = input.color(#9c27b0, "", inline = "ath", group = G_KL)
  58. kl_athStyle = input.string("Solid", "", options = ["Solid", "Dashed", "Dotted"], inline = "ath", group = G_KL)
  59. kl_athLabel = input.bool(true, "Label", inline = "ath", group = G_KL)
  60. kl_athSize = input.string("Tiny", "", options = ["Tiny", "Small", "Normal", "Large"], inline = "ath", group = G_KL)
  61. kl_merge = input.int(8, "Merge Labels Within (Ticks)", minval = 0, group = G_KL, tooltip = "Levels sitting within this many ticks of each other share one label (for example 'ATH / PWH'), ordered by significance. The underlying lines stay separate.")
  62.  
  63. lrl_show = input.bool(true, "Enable", inline = "lrl", group = G_LRL)
  64. lrl_sens = input.string("Medium", "Sensitivity", options = ["Sensitive", "Medium", "Strict"], inline = "lrl", group = G_LRL, tooltip = "Jointly controls the swing strength used to detect the three-point chain and how tight the equidistant slope match must be.\nSensitive: smaller swings, looser match.\nMedium: balanced.\nStrict: major swings, tight match.")
  65. lrl_bullColor = input.color(color.black, "Bullish", inline = "lrlbu", group = G_LRL)
  66. lrl_bullStyle = input.string("Dotted", "", options = ["Solid", "Dashed", "Dotted"], inline = "lrlbu", group = G_LRL)
  67. lrl_bullThick = input.string("Thin", "", options = ["Thin", "Medium", "Thick"], inline = "lrlbu", group = G_LRL)
  68. lrl_bearColor = input.color(color.black, "Bearish", inline = "lrlbe", group = G_LRL)
  69. lrl_bearStyle = input.string("Dotted", "", options = ["Solid", "Dashed", "Dotted"], inline = "lrlbe", group = G_LRL)
  70. lrl_bearThick = input.string("Thin", "", options = ["Thin", "Medium", "Thick"], inline = "lrlbe", group = G_LRL)
  71. lrl_lblSize = input.string("Tiny", "Label Size", options = ["Tiny", "Small", "Normal", "Large"], group = G_LRL)
  72.  
  73. ko_show = input.bool(true, "8:30 AM Open", inline = "ko", group = G_KO, tooltip = "Captures the 8:30 AM New York open each day. It persists for the day and merges its label with nearby liquidity levels.")
  74. ko_color = input.color(#787b86, "", inline = "ko", group = G_KO)
  75. ko_style = input.string("Dotted", "", options = ["Solid", "Dashed", "Dotted"], inline = "ko", group = G_KO)
  76. ko_label = input.bool(true, "Label", inline = "ko", group = G_KO)
  77. ko_size = input.string("Tiny", "", options = ["Tiny", "Small", "Normal", "Large"], inline = "ko", group = G_KO)
  78.  
  79. kz_borders = input.bool(false, "Borders", inline = "kzg", group = G_KZ)
  80. kz_transp = input.bool(true, "Transparency", inline = "kzg", group = G_KZ)
  81. kz_labels = input.bool(true, "Labels", inline = "kzg", group = G_KZ, tooltip = "Global toggles for every session box. Session labels are shown only on 15-minute and lower timeframes. Times are New York.")
  82. kz_asiaShow = input.bool(true, "Asia", inline = "kza", group = G_KZ)
  83. kz_asiaColor = input.color(#9598a1, "", inline = "kza", group = G_KZ)
  84. kz_asiaSess = input.session("2000-0000", "", inline = "kza", group = G_KZ)
  85. kz_asiaBorder = input.string("Solid", "", options = ["Solid", "Dashed", "Dotted"], inline = "kza", group = G_KZ)
  86. kz_lonShow = input.bool(true, "London", inline = "kzl", group = G_KZ)
  87. kz_lonColor = input.color(#9598a1, "", inline = "kzl", group = G_KZ)
  88. kz_lonSess = input.session("0200-0500", "", inline = "kzl", group = G_KZ)
  89. kz_lonBorder = input.string("Solid", "", options = ["Solid", "Dashed", "Dotted"], inline = "kzl", group = G_KZ)
  90. kz_nyamShow = input.bool(true, "NY AM", inline = "kzn", group = G_KZ)
  91. kz_nyamColor = input.color(#9598a1, "", inline = "kzn", group = G_KZ)
  92. kz_nyamSess = input.session("0930-1100", "", inline = "kzn", group = G_KZ)
  93. kz_nyamBorder = input.string("Solid", "", options = ["Solid", "Dashed", "Dotted"], inline = "kzn", group = G_KZ)
  94. kz_nypmShow = input.bool(true, "NY PM", inline = "kzp", group = G_KZ)
  95. kz_nypmColor = input.color(#9598a1, "", inline = "kzp", group = G_KZ)
  96. kz_nypmSess = input.session("1330-1600", "", inline = "kzp", group = G_KZ)
  97. kz_nypmBorder = input.string("Solid", "", options = ["Solid", "Dashed", "Dotted"], inline = "kzp", group = G_KZ)
  98. kz_maxBoxes = input.int(5, "Max Sessions", minval = 1, maxval = 100, group = G_KZ)
  99.  
  100. smt_show = input.bool(true, "Enable", inline = "smt0", group = G_SMT)
  101. smt_pivot = input.string("Normal", "Pivot Strength", options = ["Sensitive", "Normal", "Strict"], inline = "smt0", group = G_SMT, tooltip = "How swings are detected. Sensitive suits 1-3m charts, Strict suits 5-15m charts.")
  102. smt_max = input.int(3, "Max Visible", minval = 1, maxval = 50, inline = "smt1", group = G_SMT)
  103. smt_live = input.bool(true, "Live Tracking", inline = "smt1", group = G_SMT, tooltip = "On: developing SMTs are drawn and trailed in real time.\nOff: SMTs are tracked silently and drawn only once confirmed.")
  104. smt_gap = input.bool(true, "Gap Divergence", group = G_SMT, tooltip = "Adds SMT logic around same-bar Fair Value Gap formation: one symbol prints a gap into fresh liquidity while the correlated symbol does not.")
  105. smt_mode = input.string("Automatic", "Correlated Asset", options = ["Automatic", "Manual"], inline = "smt3", group = G_SMT, tooltip = "Automatic handles NQ-ES, MNQ-MES, YM-ES, MYM-MES, GC-SI and MGC-SIL. Manual uses the symbol selected here.")
  106. smt_manual = input.symbol("CME_MINI:ES1!", "", inline = "smt3", group = G_SMT)
  107. smt_bullColor = input.color(color.black, "Bullish", inline = "smt4", group = G_SMT)
  108. smt_bearColor = input.color(color.black, "Bearish", inline = "smt4", group = G_SMT)
  109. smt_thick = input.string("Thin", "", options = ["Thin", "Medium", "Thick"], inline = "smt4", group = G_SMT)
  110. smt_style = input.string("Solid", "", options = ["Solid", "Dashed", "Dotted"], inline = "smt4", group = G_SMT)
  111. smt_lblShow = input.bool(true, "Labels", inline = "smt5", group = G_SMT)
  112. smt_lblSym = input.bool(true, "Show Symbol", inline = "smt5", group = G_SMT)
  113. smt_lblColor = input.color(#5d606b, "", inline = "smt5", group = G_SMT)
  114. smt_lblSize = input.string("Tiny", "", options = ["Tiny", "Small", "Normal", "Large"], inline = "smt5", group = G_SMT)
  115.  
  116. const string NY_TZ = "America/New_York"
  117. const int MAX_BACK = 4900
  118. const int KL_OFFSET = 7
  119. const int HTF_EXTEND = 35
  120. const int CISD_EXTEND = 10
  121. const int POOL_MAX = 40
  122. const int ARM_EXPIRY = 60
  123. const int CISD_EXPIRY = 60
  124. const int FVG_SCAN_BACK = 10
  125. const int LEG_LOOKBACK = 300
  126. const float IFVG_MIN_ATR = 0.10
  127. const float BE_GATE_ATR = 4.0
  128. const float HTF_MIN_ATR = 0.10
  129. const int HTF_MAX_GAPS = 60
  130. const int WEEKEND_MS = 129600000
  131. const float LRL_BREAK_ATR = 0.25
  132. const int SMT_MAX_SPAN = 120
  133. const int SMT_COMPARE = 3
  134. const int SMT_KEEP = 6
  135. const int SMT_GAP_LOOK = 20
  136. const int SMT_GAP_COOLDOWN = 5
  137. const int RANK_MAX = 6
  138.  
  139. type LiqLevel
  140. float price
  141. int bar
  142.  
  143. type KeyLevel
  144. string name
  145. int rank
  146. bool isHigh = true
  147. bool sweepable = true
  148. float price
  149. int x1
  150. int setBar
  151. bool live = false
  152.  
  153. type Sess
  154. string name
  155. float hi
  156. float lo
  157. int hiBar
  158. int loBar
  159. bool active = false
  160. box bx
  161. array<box> boxes
  162.  
  163. type Setup
  164. bool armed = false
  165. int armBar
  166. float extreme
  167. float gTop
  168. float gBot
  169. int gLeft
  170. box gBox
  171.  
  172. type GapBox
  173. box bx
  174. float top
  175. float bot
  176. bool bull = true
  177. bool live = true
  178.  
  179. type CisdMark
  180. line ln
  181. label lb
  182. float stopPx
  183. bool bull = true
  184. int bar
  185.  
  186. type HtfGap
  187. float top
  188. float bot
  189. int leftTime
  190. string tf
  191.  
  192. type SmtPivot
  193. int bar
  194. float px
  195. float cpx
  196.  
  197. type SmtMark
  198. line ln
  199. label lb
  200.  
  201. f_size(string s) =>
  202. switch s
  203. "Small" => size.small
  204. "Normal" => size.normal
  205. "Large" => size.large
  206. => size.tiny
  207.  
  208. f_style(string s) =>
  209. switch s
  210. "Dashed" => line.style_dashed
  211. "Dotted" => line.style_dotted
  212. => line.style_solid
  213.  
  214. f_width(string s) =>
  215. switch s
  216. "Medium" => 2
  217. "Thick" => 3
  218. => 1
  219.  
  220. f_tfLabel(string tf) =>
  221. switch tf
  222. "1" => "1M"
  223. "5" => "5M"
  224. "15" => "15M"
  225. "60" => "1H"
  226. "240" => "4H"
  227. "D" => "Daily"
  228. "W" => "Weekly"
  229. "M" => "Monthly"
  230. "3M" => "Quarterly"
  231. "12M" => "Yearly"
  232. => tf
  233.  
  234. f_symName(string sym) =>
  235. string out = sym
  236. if str.contains(out, ":")
  237. array<string> parts = str.split(out, ":")
  238. out := array.get(parts, array.size(parts) - 1)
  239. out := str.replace_all(out, "1!", "")
  240. out := str.replace_all(out, "2!", "")
  241. out
  242.  
  243. f_clampX(int x) =>
  244. math.max(x, bar_index - MAX_BACK)
  245.  
  246. f_gapDist(float top, float bot, float px) =>
  247. px > top ? px - top : px < bot ? bot - px : 0.0
  248.  
  249. f_lineHolds(int x1, float y1, int x2, float y2, bool isHigh, float tolPx) =>
  250. bool holds = true
  251. int span = x2 - x1
  252. if span > 0 and bar_index - x1 <= MAX_BACK
  253. float slope = (y2 - y1) / span
  254. for b = x1 to x2
  255. int off = bar_index - b
  256. if off >= 0
  257. float ly = y1 + slope * (b - x1)
  258. float v = isHigh ? high[off] : low[off]
  259. if isHigh ? v > ly + tolPx : v < ly - tolPx
  260. holds := false
  261. break
  262. holds
  263.  
  264. f_legOrigin(int dir) =>
  265. float origin = na
  266. int originOff = na
  267. bool started = false
  268. int lookback = math.min(LEG_LOOKBACK, bar_index)
  269. for i = 0 to lookback
  270. int ct = close[i] > open[i] ? 1 : close[i] < open[i] ? -1 : 0
  271. if ct == dir
  272. started := true
  273. if na(origin) or (dir == 1 ? open[i] < origin : open[i] > origin)
  274. origin := open[i]
  275. originOff := i
  276. else if ct != 0 and started
  277. break
  278. int originBar = na(originOff) ? na : bar_index - originOff
  279. [origin, originBar]
  280.  
  281. int chartSec = timeframe.in_seconds(timeframe.period)
  282. bool isIntra = timeframe.isintraday
  283. float atr14 = ta.atr(14)
  284.  
  285. bool fvgBullNow = low > high[2]
  286. bool fvgBearNow = high < low[2]
  287. float fvgBullSize = low - high[2]
  288. float fvgBearSize = low[2] - high
  289.  
  290. string htfA = chartSec <= 60 ? "5" : chartSec <= 300 ? "15" : chartSec <= 900 ? "60" : chartSec <= 3600 ? "240" : chartSec <= 14400 ? "D" : chartSec <= 86400 ? "W" : chartSec <= 604800 ? "M" : "3M"
  291. string htfB = chartSec <= 60 ? "15" : chartSec <= 300 ? "60" : chartSec <= 900 ? "240" : chartSec <= 3600 ? "D" : chartSec <= 14400 ? "W" : chartSec <= 86400 ? "M" : chartSec <= 604800 ? "3M" : "12M"
  292. string liqTf = chartSec <= 60 ? "15" : chartSec <= 300 ? "60" : chartSec <= 900 ? "240" : chartSec <= 3600 ? "D" : chartSec <= 86400 ? "W" : chartSec <= 604800 ? "M" : "12M"
  293. string athTf = chartSec >= timeframe.in_seconds("M") ? timeframe.period : "M"
  294. int htfAMs = timeframe.in_seconds(htfA) * 1000
  295. int htfBMs = timeframe.in_seconds(htfB) * 1000
  296. bool htfAOk = timeframe.in_seconds(htfA) > chartSec
  297. bool htfBOk = timeframe.in_seconds(htfB) > chartSec
  298.  
  299. bool chgA = timeframe.change(htfA)
  300. bool chgB = timeframe.change(htfB)
  301. bool chgLiq = timeframe.change(liqTf)
  302. bool newDay = timeframe.change("D")
  303. bool newWeek = timeframe.change("W")
  304.  
  305. [aHiN, aLoN, aHiO, aLoO, aClN, aTO, aTM, aTN, aAtr] = request.security(syminfo.tickerid, htfA, [high[1], low[1], high[3], low[3], close[1], time[3], time[2], time[1], ta.atr(14)[1]], lookahead = barmerge.lookahead_on)
  306. [bHiN, bLoN, bHiO, bLoO, bClN, bTO, bTM, bTN, bAtr] = request.security(syminfo.tickerid, htfB, [high[1], low[1], high[3], low[3], close[1], time[3], time[2], time[1], ta.atr(14)[1]], lookahead = barmerge.lookahead_on)
  307. [liqPH, liqPL] = request.security(syminfo.tickerid, liqTf, [ta.pivothigh(high, 2, 2)[1], ta.pivotlow(low, 2, 2)[1]], lookahead = barmerge.lookahead_on)
  308. float athHtf = request.security(syminfo.tickerid, athTf, ta.max(high)[1], lookahead = barmerge.lookahead_on)
  309.  
  310. string smtRoot = syminfo.root
  311. string smtPairRoot = switch smtRoot
  312. "NQ" => "ES"
  313. "ES" => "NQ"
  314. "MNQ" => "MES"
  315. "MES" => "MNQ"
  316. "YM" => "ES"
  317. "MYM" => "MES"
  318. "GC" => "SI"
  319. "SI" => "GC"
  320. "MGC" => "SIL"
  321. "SIL" => "MGC"
  322. => ""
  323. string smtPairPrefix = smtPairRoot == "SI" or smtPairRoot == "GC" or smtPairRoot == "SIL" or smtPairRoot == "MGC" ? "COMEX" : "CME_MINI"
  324. string smtRawSuffix = str.length(syminfo.ticker) > str.length(smtRoot) ? str.substring(syminfo.ticker, str.length(smtRoot)) : ""
  325. string smtSuffix = smtPairPrefix == "COMEX" or smtRawSuffix == "" ? "1!" : smtRawSuffix
  326. string smtAutoSym = smtPairRoot != "" ? smtPairPrefix + ":" + smtPairRoot + smtSuffix : syminfo.tickerid
  327. bool smtActive = smt_show and (smt_mode == "Manual" or smtPairRoot != "")
  328. string smtSym = not smtActive ? syminfo.tickerid : smt_mode == "Manual" ? smt_manual : smtAutoSym
  329. string smtSymName = smt_mode == "Manual" ? f_symName(smt_manual) : smtPairRoot
  330.  
  331. [cmpHi, cmpLo, cmpHi2, cmpLo2] = request.security(smtSym, timeframe.period, [high, low, high[2], low[2]], lookahead = barmerge.lookahead_off, ignore_invalid_symbol = true)
  332.  
  333. int smtLen = smt_pivot == "Sensitive" ? 2 : smt_pivot == "Strict" ? 5 : 3
  334. float smtPH = ta.pivothigh(high, smtLen, smtLen)
  335. float smtPL = ta.pivotlow(low, smtLen, smtLen)
  336. float cmpHiWin = ta.highest(cmpHi, 2 * smtLen + 1)
  337. float cmpLoWin = ta.lowest(cmpLo, 2 * smtLen + 1)
  338. float gapHH = ta.highest(high, SMT_GAP_LOOK)
  339. float gapLL = ta.lowest(low, SMT_GAP_LOOK)
  340. float gapCHH = ta.highest(cmpHi, SMT_GAP_LOOK)
  341. float gapCLL = ta.lowest(cmpLo, SMT_GAP_LOOK)
  342.  
  343. int lrlSwing = lrl_sens == "Sensitive" ? 3 : lrl_sens == "Strict" ? 8 : 5
  344. float lrlTol = lrl_sens == "Sensitive" ? 2.0 : lrl_sens == "Strict" ? 1.35 : 1.6
  345. float lrlPH = ta.pivothigh(high, lrlSwing, lrlSwing)
  346. float lrlPL = ta.pivotlow(low, lrlSwing, lrlSwing)
  347.  
  348. int tAsia = time(timeframe.period, kz_asiaSess, NY_TZ)
  349. int tLon = time(timeframe.period, kz_lonSess, NY_TZ)
  350. int tNyAm = time(timeframe.period, kz_nyamSess, NY_TZ)
  351. int tNyPm = time(timeframe.period, kz_nypmSess, NY_TZ)
  352. bool inAsia = isIntra and not na(tAsia)
  353. bool inLon = isIntra and not na(tLon)
  354. bool inNyAm = isIntra and not na(tNyAm)
  355. bool inNyPm = isIntra and not na(tNyPm)
  356.  
  357. int nyMinute = hour(time, NY_TZ) * 60 + minute(time, NY_TZ)
  358. int barMinutes = math.max(1, int(chartSec / 60))
  359. bool has830 = isIntra and chartSec <= 3600 and nyMinute <= 510 and nyMinute + barMinutes > 510
  360.  
  361. var KeyLevel kPWH = KeyLevel.new(name = "PWH", rank = 2, isHigh = true, sweepable = true)
  362. var KeyLevel kPWL = KeyLevel.new(name = "PWL", rank = 2, isHigh = false, sweepable = true)
  363. var KeyLevel kPDH = KeyLevel.new(name = "PDH", rank = 3, isHigh = true, sweepable = true)
  364. var KeyLevel kPDL = KeyLevel.new(name = "PDL", rank = 3, isHigh = false, sweepable = true)
  365. var KeyLevel kASH = KeyLevel.new(name = "Asia H", rank = 6, isHigh = true, sweepable = true)
  366. var KeyLevel kASL = KeyLevel.new(name = "Asia L", rank = 6, isHigh = false, sweepable = true)
  367. var KeyLevel kLOH = KeyLevel.new(name = "London H", rank = 5, isHigh = true, sweepable = true)
  368. var KeyLevel kLOL = KeyLevel.new(name = "London L", rank = 5, isHigh = false, sweepable = true)
  369. var KeyLevel kATH = KeyLevel.new(name = "ATH", rank = 1, isHigh = true, sweepable = false)
  370. var KeyLevel kOPEN = KeyLevel.new(name = "8:30 Open", rank = 4, isHigh = false, sweepable = false)
  371. var array<KeyLevel> kAll = array.new<KeyLevel>()
  372. if barstate.isfirst
  373. array.push(kAll, kATH)
  374. array.push(kAll, kPWH)
  375. array.push(kAll, kPWL)
  376. array.push(kAll, kPDH)
  377. array.push(kAll, kPDL)
  378. array.push(kAll, kOPEN)
  379. array.push(kAll, kLOH)
  380. array.push(kAll, kLOL)
  381. array.push(kAll, kASH)
  382. array.push(kAll, kASL)
  383.  
  384. var array<LiqLevel> poolHi = array.new<LiqLevel>()
  385. var array<LiqLevel> poolLo = array.new<LiqLevel>()
  386.  
  387. var Sess sAsia = Sess.new(name = "Asia", boxes = array.new<box>())
  388. var Sess sLon = Sess.new(name = "London", boxes = array.new<box>())
  389. var Sess sNyAm = Sess.new(name = "NY AM", boxes = array.new<box>())
  390. var Sess sNyPm = Sess.new(name = "NY PM", boxes = array.new<box>())
  391.  
  392. var Setup bullSet = Setup.new()
  393. var Setup bearSet = Setup.new()
  394. var array<GapBox> ifvgList = array.new<GapBox>()
  395. var array<CisdMark> cisdMarks = array.new<CisdMark>()
  396.  
  397. var array<HtfGap> htfBullGaps = array.new<HtfGap>()
  398. var array<HtfGap> htfBearGaps = array.new<HtfGap>()
  399. var box htfBullBox = na
  400. var box htfBearBox = na
  401.  
  402. var array<float> lrlHiPx = array.new<float>()
  403. var array<int> lrlHiBar = array.new<int>()
  404. var array<float> lrlLoPx = array.new<float>()
  405. var array<int> lrlLoBar = array.new<int>()
  406. var line lrlBearLn = na
  407. var label lrlBearLb = na
  408. var line lrlBullLn = na
  409. var label lrlBullLb = na
  410.  
  411. var array<SmtPivot> smtHighs = array.new<SmtPivot>()
  412. var array<SmtPivot> smtLows = array.new<SmtPivot>()
  413. var array<SmtMark> smtMarks = array.new<SmtMark>()
  414.  
  415. var array<line> klLines = array.new<line>()
  416. var array<label> klLabels = array.new<label>()
  417.  
  418. f_setLevel(KeyLevel k, float px, int x) =>
  419. k.price := px
  420. k.x1 := x
  421. k.setBar := bar_index - 1
  422. k.live := not na(px)
  423. true
  424.  
  425. f_sweepLevel(KeyLevel k) =>
  426. if k.live and k.sweepable and bar_index > k.setBar
  427. if k.isHigh ? high > k.price : low < k.price
  428. k.live := false
  429. true
  430.  
  431. f_poolAdd(array<LiqLevel> pool, float px) =>
  432. if not na(px)
  433. array.push(pool, LiqLevel.new(px, bar_index - 1))
  434. if array.size(pool) > POOL_MAX
  435. array.shift(pool)
  436. true
  437.  
  438. f_sweepPool(array<LiqLevel> pool, bool isHigh) =>
  439. bool hit = false
  440. int n = array.size(pool)
  441. if n > 0
  442. for i = n - 1 to 0
  443. LiqLevel lv = array.get(pool, i)
  444. if bar_index > lv.bar and (isHigh ? high > lv.price : low < lv.price)
  445. hit := true
  446. array.remove(pool, i)
  447. hit
  448.  
  449. f_sessRun(Sess s, bool inS, bool doDraw, color col, string bStyle) =>
  450. bool ended = false
  451. if inS
  452. if not s.active
  453. s.active := true
  454. s.hi := high
  455. s.lo := low
  456. s.hiBar := bar_index
  457. s.loBar := bar_index
  458. s.bx := na
  459. if doDraw
  460. color bg = color.new(col, kz_transp ? 85 : 65)
  461. color bd = kz_borders ? color.new(col, 30) : color.new(col, 100)
  462. string txt = kz_labels and chartSec <= 900 ? s.name : ""
  463. s.bx := box.new(bar_index, high, bar_index, low, border_color = bd, border_width = kz_borders ? 1 : 0, border_style = f_style(bStyle), bgcolor = bg, text = txt, text_size = size.auto, text_color = color.new(col, 45), text_halign = text.align_center, text_valign = text.align_center)
  464. array.push(s.boxes, s.bx)
  465. while array.size(s.boxes) > kz_maxBoxes
  466. box.delete(array.shift(s.boxes))
  467. else
  468. if high > s.hi
  469. s.hi := high
  470. s.hiBar := bar_index
  471. if low < s.lo
  472. s.lo := low
  473. s.loBar := bar_index
  474. if not na(s.bx)
  475. box.set_top(s.bx, s.hi)
  476. box.set_bottom(s.bx, s.lo)
  477. box.set_right(s.bx, bar_index)
  478. else if s.active
  479. s.active := false
  480. ended := true
  481. ended
  482.  
  483. f_clearPending(Setup s, bool killBox) =>
  484. if killBox
  485. box.delete(s.gBox)
  486. s.gBox := na
  487. s.gTop := na
  488. s.gBot := na
  489. s.gLeft := na
  490. true
  491.  
  492. f_setPending(Setup s, float top, float bot, int left, bool bullInv) =>
  493. box.delete(s.gBox)
  494. s.gBox := na
  495. s.gTop := top
  496. s.gBot := bot
  497. s.gLeft := left
  498. if conf_fvgShow
  499. color c = bullInv ? conf_fvgBear : conf_fvgBull
  500. s.gBox := box.new(left, top, bar_index, bot, border_color = color.new(c, 100), border_width = 0, bgcolor = c, text = conf_lblShow ? "FVG" : "", text_size = f_size(conf_lblSize), text_color = conf_lblColor, text_halign = text.align_right, text_valign = text.align_center)
  501. true
  502.  
  503. f_scanGap(bool wantBear) =>
  504. float top = na
  505. float bot = na
  506. int left = na
  507. int lim = math.min(FVG_SCAN_BACK, bar_index - 2)
  508. if lim >= 0
  509. for k = 0 to lim
  510. bool isGap = wantBear ? high[k] < low[k + 2] : low[k] > high[k + 2]
  511. float gSize = wantBear ? low[k + 2] - high[k] : low[k] - high[k + 2]
  512. if isGap and gSize >= IFVG_MIN_ATR * nz(atr14[k])
  513. float gTop = wantBear ? low[k + 2] : low[k]
  514. float gBot = wantBear ? high[k] : high[k + 2]
  515. bool spent = false
  516. if k >= 2
  517. for m = 1 to k - 1
  518. if wantBear ? close[m] > gTop : close[m] < gBot
  519. spent := true
  520. break
  521. if not spent
  522. top := gTop
  523. bot := gBot
  524. left := bar_index - k - 2
  525. break
  526. [top, bot, left]
  527.  
  528. f_invert(Setup s, bool bullInv) =>
  529. float risk = bullInv ? close - s.extreme : s.extreme - close
  530. bool gateOk = not na(risk) and risk > 0 and risk <= BE_GATE_ATR * atr14
  531. if gateOk and conf_ifvgShow
  532. color c = bullInv ? conf_ifvgBull : conf_ifvgBear
  533. box b = s.gBox
  534. if na(b)
  535. b := box.new(s.gLeft, s.gTop, bar_index, s.gBot, border_color = color.new(c, 100), border_width = 0, bgcolor = c)
  536. else
  537. box.set_bgcolor(b, c)
  538. box.set_border_color(b, color.new(c, 100))
  539. box.set_text(b, "")
  540. box.set_right(b, bar_index)
  541. array.push(ifvgList, GapBox.new(b, s.gTop, s.gBot, bullInv, true))
  542. while array.size(ifvgList) > conf_ifvgMax
  543. GapBox old = array.shift(ifvgList)
  544. box.delete(old.bx)
  545. f_clearPending(s, false)
  546. else
  547. f_clearPending(s, true)
  548. s.armed := false
  549. gateOk
  550.  
  551. f_runSetup(Setup s, bool bullInv, bool swept) =>
  552. if swept
  553. bool wasArmed = s.armed
  554. float ext = bullInv ? low : high
  555. s.armed := true
  556. s.armBar := bar_index
  557. s.extreme := wasArmed and not na(s.extreme) ? (bullInv ? math.min(s.extreme, ext) : math.max(s.extreme, ext)) : ext
  558. [sTop, sBot, sLeft] = f_scanGap(bullInv)
  559. if not na(sTop) and (na(s.gLeft) or sLeft > s.gLeft)
  560. f_setPending(s, sTop, sBot, sLeft, bullInv)
  561. else if s.armed
  562. if bullInv ? low < s.extreme : high > s.extreme
  563. s.extreme := bullInv ? low : high
  564. bool newGap = bullInv ? fvgBearNow : fvgBullNow
  565. float newSize = bullInv ? fvgBearSize : fvgBullSize
  566. if newGap and newSize >= IFVG_MIN_ATR * atr14
  567. f_setPending(s, bullInv ? low[2] : low, bullInv ? high : high[2], bar_index - 2, bullInv)
  568. if s.armed and not na(s.gTop)
  569. if not na(s.gBox)
  570. box.set_right(s.gBox, bar_index)
  571. bool through = bullInv ? close > s.gTop : close < s.gBot
  572. if through
  573. f_invert(s, bullInv)
  574. if s.armed and bar_index - s.armBar > ARM_EXPIRY
  575. f_clearPending(s, true)
  576. s.armed := false
  577. true
  578.  
  579. f_cisdDraw(int x1, float lvl, bool bull, float stopPx) =>
  580. color c = bull ? conf_cisdBull : conf_cisdBear
  581. int x2 = bar_index + CISD_EXTEND
  582. line ln = line.new(x1, lvl, x2, lvl, color = c, style = f_style(conf_cisdStyle), width = f_width(conf_cisdThick))
  583. label lb = na
  584. if conf_lblShow
  585. lb := label.new(x2, lvl, bull ? "Bullish CISD" : "Bearish CISD", style = label.style_label_left, color = color.new(c, 100), textcolor = conf_lblColor, size = f_size(conf_lblSize))
  586. array.push(cisdMarks, CisdMark.new(ln, lb, stopPx, bull, bar_index))
  587. while array.size(cisdMarks) > conf_cisdMax
  588. CisdMark old = array.shift(cisdMarks)
  589. line.delete(old.ln)
  590. label.delete(old.lb)
  591. true
  592.  
  593. f_htfProcess(string tfName, int periodMs, float hNew, float lNew, float hOld, float lOld, float cNew, int tOld, int tMid, int tNew, float hAtr) =>
  594. if array.size(htfBullGaps) > 0
  595. for i = array.size(htfBullGaps) - 1 to 0
  596. HtfGap g = array.get(htfBullGaps, i)
  597. if g.tf == tfName and not na(cNew) and cNew < g.bot
  598. array.remove(htfBullGaps, i)
  599. if array.size(htfBearGaps) > 0
  600. for i = array.size(htfBearGaps) - 1 to 0
  601. HtfGap g = array.get(htfBearGaps, i)
  602. if g.tf == tfName and not na(cNew) and cNew > g.top
  603. array.remove(htfBearGaps, i)
  604. bool timesOk = not na(tOld) and not na(tMid) and not na(tNew)
  605. bool weekend = timesOk and ((tMid - tOld) > periodMs + WEEKEND_MS or (tNew - tMid) > periodMs + WEEKEND_MS)
  606. float minSize = HTF_MIN_ATR * nz(hAtr)
  607. if timesOk and not weekend and not na(hNew) and not na(hOld) and not na(lNew) and not na(lOld)
  608. if lNew > hOld and lNew - hOld >= minSize
  609. array.push(htfBullGaps, HtfGap.new(lNew, hOld, tOld, tfName))
  610. if array.size(htfBullGaps) > HTF_MAX_GAPS
  611. array.shift(htfBullGaps)
  612. if hNew < lOld and lOld - hNew >= minSize
  613. array.push(htfBearGaps, HtfGap.new(lOld, hNew, tOld, tfName))
  614. if array.size(htfBearGaps) > HTF_MAX_GAPS
  615. array.shift(htfBearGaps)
  616. true
  617.  
  618. f_closestGap(array<HtfGap> gaps, float px) =>
  619. HtfGap best = na
  620. float bestD = na
  621. for g in gaps
  622. float d = f_gapDist(g.top, g.bot, px)
  623. if na(bestD) or d < bestD
  624. bestD := d
  625. best := g
  626. best
  627.  
  628. f_htfBox(HtfGap g, color c) =>
  629. int rightT = time + HTF_EXTEND * chartSec * 1000
  630. box.new(g.leftTime, g.top, rightT, g.bot, xloc = xloc.bar_time, border_color = htf_border ? color.new(c, 30) : color.new(c, 100), border_width = htf_border ? 1 : 0, bgcolor = c, text = g.tf + " Fair Value Gap", text_size = f_size(htf_lblSize), text_color = htf_lblColor, text_halign = text.align_right, text_valign = text.align_bottom)
  631.  
  632. f_push3(array<float> px, array<int> bx, float p, int b) =>
  633. array.push(px, p)
  634. array.push(bx, b)
  635. if array.size(px) > 3
  636. array.shift(px)
  637. array.shift(bx)
  638. true
  639.  
  640. f_cfg(array<bool> aShow, array<color> aCol, array<string> aSty, array<string> aSiz, array<bool> aLab, bool sh, color col, string st, string sz, bool lb) =>
  641. array.push(aShow, sh)
  642. array.push(aCol, col)
  643. array.push(aSty, st)
  644. array.push(aSiz, sz)
  645. array.push(aLab, lb)
  646. true
  647.  
  648. f_lrlCascade(array<float> px, array<int> bx, bool bearish, float tolR, float breakPx) =>
  649. bool ok = false
  650. if array.size(px) == 3
  651. float p1 = array.get(px, 0)
  652. float p2 = array.get(px, 1)
  653. float p3 = array.get(px, 2)
  654. int b1 = array.get(bx, 0)
  655. int b2 = array.get(bx, 1)
  656. int b3 = array.get(bx, 2)
  657. bool dirOk = bearish ? (p1 > p2 and p2 > p3) : (p1 < p2 and p2 < p3)
  658. int t1 = b2 - b1
  659. int t2 = b3 - b2
  660. if dirOk and t1 > 0 and t2 > 0
  661. float d1 = math.abs(p1 - p2)
  662. float d2 = math.abs(p2 - p3)
  663. float s1 = d1 / t1
  664. float s2 = d2 / t2
  665. bool evenPx = math.max(d1, d2) <= tolR * math.min(d1, d2)
  666. bool evenT = math.max(t1, t2) <= tolR * math.min(t1, t2)
  667. bool evenS = math.max(s1, s2) <= tolR * math.min(s1, s2)
  668. if evenPx and evenT and evenS
  669. ok := f_lineHolds(b1, p1, b3, p3, bearish, breakPx)
  670. ok
  671.  
  672. f_smtText(bool isGap) =>
  673. string base = isGap ? "Gap SMT" : "SMT"
  674. smt_lblSym and str.length(smtSymName) > 0 ? smtSymName + " " + base : base
  675.  
  676. f_smtLine(int x1, float y1, int x2, float y2, bool bull) =>
  677. color c = bull ? smt_bullColor : smt_bearColor
  678. line.new(x1, y1, x2, y2, color = c, style = f_style(smt_style), width = f_width(smt_thick))
  679.  
  680. f_smtLabel(int x, float y, bool bull, bool isGap) =>
  681. label lb = na
  682. if smt_lblShow
  683. lb := label.new(x, y, f_smtText(isGap), style = bull ? label.style_label_up : label.style_label_down, color = color.new(color.black, 100), textcolor = smt_lblColor, size = f_size(smt_lblSize))
  684. lb
  685.  
  686. f_smtCommit(int x1, float y1, int x2, float y2, bool bull, bool isGap) =>
  687. array.push(smtMarks, SmtMark.new(f_smtLine(x1, y1, x2, y2, bull), f_smtLabel(x2, y2, bull, isGap)))
  688. while array.size(smtMarks) > smt_max
  689. SmtMark old = array.shift(smtMarks)
  690. line.delete(old.ln)
  691. label.delete(old.lb)
  692. true
  693.  
  694. f_smtCheckPivot(array<SmtPivot> pivots, SmtPivot cur, bool isHigh) =>
  695. bool found = false
  696. int n = array.size(pivots)
  697. if n > 0 and not na(cur.cpx)
  698. int stopK = math.max(0, n - SMT_COMPARE)
  699. for k = n - 1 to stopK
  700. SmtPivot prev = array.get(pivots, k)
  701. if cur.bar - prev.bar > SMT_MAX_SPAN
  702. break
  703. if not na(prev.cpx)
  704. bool chartExt = isHigh ? cur.px > prev.px : cur.px < prev.px
  705. bool compExt = isHigh ? cur.cpx > prev.cpx : cur.cpx < prev.cpx
  706. if chartExt != compExt
  707. if f_lineHolds(prev.bar, prev.px, cur.bar, cur.px, isHigh, syminfo.mintick)
  708. f_smtCommit(prev.bar, prev.px, cur.bar, cur.px, not isHigh, false)
  709. found := true
  710. break
  711. array.push(pivots, cur)
  712. if array.size(pivots) > SMT_KEEP
  713. array.shift(pivots)
  714. found
  715.  
  716. var float dHi = na
  717. var float dLo = na
  718. var int dHiBar = na
  719. var int dLoBar = na
  720. var int dayStartBar = 0
  721. var float wHi = na
  722. var float wLo = na
  723. var int wHiBar = na
  724. var int wLoBar = na
  725.  
  726. if newDay
  727. if not na(dHi)
  728. f_setLevel(kPDH, dHi, dHiBar)
  729. f_setLevel(kPDL, dLo, dLoBar)
  730. f_poolAdd(poolHi, dHi)
  731. f_poolAdd(poolLo, dLo)
  732. dHi := high
  733. dLo := low
  734. dHiBar := bar_index
  735. dLoBar := bar_index
  736. dayStartBar := bar_index
  737. kOPEN.live := false
  738. else
  739. if na(dHi) or high > dHi
  740. dHi := high
  741. dHiBar := bar_index
  742. if na(dLo) or low < dLo
  743. dLo := low
  744. dLoBar := bar_index
  745.  
  746. if newWeek
  747. if not na(wHi)
  748. f_setLevel(kPWH, wHi, wHiBar)
  749. f_setLevel(kPWL, wLo, wLoBar)
  750. f_poolAdd(poolHi, wHi)
  751. f_poolAdd(poolLo, wLo)
  752. wHi := high
  753. wLo := low
  754. wHiBar := bar_index
  755. wLoBar := bar_index
  756. else
  757. if na(wHi) or high > wHi
  758. wHi := high
  759. wHiBar := bar_index
  760. if na(wLo) or low < wLo
  761. wLo := low
  762. wLoBar := bar_index
  763.  
  764. bool asiaEnded = f_sessRun(sAsia, inAsia, kz_asiaShow, kz_asiaColor, kz_asiaBorder)
  765. bool lonEnded = f_sessRun(sLon, inLon, kz_lonShow, kz_lonColor, kz_lonBorder)
  766. bool nyamEnded = f_sessRun(sNyAm, inNyAm, kz_nyamShow, kz_nyamColor, kz_nyamBorder)
  767. bool nypmEnded = f_sessRun(sNyPm, inNyPm, kz_nypmShow, kz_nypmColor, kz_nypmBorder)
  768.  
  769. if asiaEnded
  770. f_setLevel(kASH, sAsia.hi, sAsia.hiBar)
  771. f_setLevel(kASL, sAsia.lo, sAsia.loBar)
  772. f_poolAdd(poolHi, sAsia.hi)
  773. f_poolAdd(poolLo, sAsia.lo)
  774. if lonEnded
  775. f_setLevel(kLOH, sLon.hi, sLon.hiBar)
  776. f_setLevel(kLOL, sLon.lo, sLon.loBar)
  777. f_poolAdd(poolHi, sLon.hi)
  778. f_poolAdd(poolLo, sLon.lo)
  779. if nyamEnded
  780. f_poolAdd(poolHi, sNyAm.hi)
  781. f_poolAdd(poolLo, sNyAm.lo)
  782. if nypmEnded
  783. f_poolAdd(poolHi, sNyPm.hi)
  784. f_poolAdd(poolLo, sNyPm.lo)
  785.  
  786. if chgLiq
  787. f_poolAdd(poolHi, liqPH)
  788. f_poolAdd(poolLo, liqPL)
  789.  
  790. var float athRun = na
  791. var int athBar = na
  792. if na(athRun) or high > athRun
  793. athRun := high
  794. athBar := bar_index
  795. float athVal = na(athHtf) ? athRun : math.max(athRun, athHtf)
  796. if not na(athVal)
  797. kATH.price := athVal
  798. kATH.x1 := athVal > athRun ? 0 : athBar
  799. kATH.live := true
  800.  
  801. if has830 and not (kOPEN.live and kOPEN.x1 >= dayStartBar)
  802. f_setLevel(kOPEN, open, bar_index)
  803.  
  804. for k in kAll
  805. f_sweepLevel(k)
  806.  
  807. bool sweptHigh = f_sweepPool(poolHi, true)
  808. bool sweptLow = f_sweepPool(poolLo, false)
  809.  
  810. f_runSetup(bullSet, true, sweptLow)
  811. f_runSetup(bearSet, false, sweptHigh)
  812.  
  813. for g in ifvgList
  814. if g.live
  815. box.set_right(g.bx, bar_index)
  816. if g.bull ? close < g.bot : close > g.top
  817. g.live := false
  818.  
  819. var bool cBearArmed = false
  820. var int cBearArmBar = na
  821. var float cBearLevel = na
  822. var int cBearLevelBar = na
  823. var float cBearStop = na
  824. var bool cBullArmed = false
  825. var int cBullArmBar = na
  826. var float cBullLevel = na
  827. var int cBullLevelBar = na
  828. var float cBullStop = na
  829.  
  830. if sweptHigh
  831. [bLegPx, bLegBar] = f_legOrigin(1)
  832. if not na(bLegPx)
  833. cBearStop := cBearArmed and not na(cBearStop) ? math.max(cBearStop, high) : high
  834. cBearArmed := true
  835. cBearArmBar := bar_index
  836. cBearLevel := bLegPx
  837. cBearLevelBar := bLegBar
  838. else if cBearArmed and high > cBearStop
  839. cBearStop := high
  840. [bLegPx2, bLegBar2] = f_legOrigin(1)
  841. if not na(bLegPx2)
  842. cBearLevel := bLegPx2
  843. cBearLevelBar := bLegBar2
  844. if cBearArmed and not na(cBearLevel) and close < cBearLevel
  845. if conf_cisdShow
  846. f_cisdDraw(cBearLevelBar, cBearLevel, false, cBearStop)
  847. cBearArmed := false
  848. else if cBearArmed and bar_index - cBearArmBar > CISD_EXPIRY
  849. cBearArmed := false
  850.  
  851. if sweptLow
  852. [sLegPx, sLegBar] = f_legOrigin(-1)
  853. if not na(sLegPx)
  854. cBullStop := cBullArmed and not na(cBullStop) ? math.min(cBullStop, low) : low
  855. cBullArmed := true
  856. cBullArmBar := bar_index
  857. cBullLevel := sLegPx
  858. cBullLevelBar := sLegBar
  859. else if cBullArmed and low < cBullStop
  860. cBullStop := low
  861. [sLegPx2, sLegBar2] = f_legOrigin(-1)
  862. if not na(sLegPx2)
  863. cBullLevel := sLegPx2
  864. cBullLevelBar := sLegBar2
  865. if cBullArmed and not na(cBullLevel) and close > cBullLevel
  866. if conf_cisdShow
  867. f_cisdDraw(cBullLevelBar, cBullLevel, true, cBullStop)
  868. cBullArmed := false
  869. else if cBullArmed and bar_index - cBullArmBar > CISD_EXPIRY
  870. cBullArmed := false
  871.  
  872. if array.size(cisdMarks) > 0
  873. for i = array.size(cisdMarks) - 1 to 0
  874. CisdMark m = array.get(cisdMarks, i)
  875. if bar_index > m.bar and (m.bull ? low < m.stopPx : high > m.stopPx)
  876. line.delete(m.ln)
  877. label.delete(m.lb)
  878. array.remove(cisdMarks, i)
  879.  
  880. if htfAOk and chgA
  881. f_htfProcess(f_tfLabel(htfA), htfAMs, aHiN, aLoN, aHiO, aLoO, aClN, aTO, aTM, aTN, aAtr)
  882. if htfBOk and chgB
  883. f_htfProcess(f_tfLabel(htfB), htfBMs, bHiN, bLoN, bHiO, bLoO, bClN, bTO, bTM, bTN, bAtr)
  884.  
  885. float lrlBreak = LRL_BREAK_ATR * nz(atr14)
  886.  
  887. if not na(lrlPH)
  888. f_push3(lrlHiPx, lrlHiBar, lrlPH, bar_index - lrlSwing)
  889. if lrl_show and f_lrlCascade(lrlHiPx, lrlHiBar, true, lrlTol, lrlBreak)
  890. line.delete(lrlBearLn)
  891. label.delete(lrlBearLb)
  892. int hx1 = array.get(lrlHiBar, 0)
  893. float hy1 = array.get(lrlHiPx, 0)
  894. int hx3 = array.get(lrlHiBar, 2)
  895. float hy3 = array.get(lrlHiPx, 2)
  896. lrlBearLn := line.new(hx1, hy1, hx3, hy3, color = lrl_bearColor, style = f_style(lrl_bearStyle), width = f_width(lrl_bearThick))
  897. lrlBearLb := label.new(hx3, hy3, "LRL", style = label.style_label_left, color = color.new(lrl_bearColor, 100), textcolor = lrl_bearColor, size = f_size(lrl_lblSize))
  898.  
  899. if not na(lrlPL)
  900. f_push3(lrlLoPx, lrlLoBar, lrlPL, bar_index - lrlSwing)
  901. if lrl_show and f_lrlCascade(lrlLoPx, lrlLoBar, false, lrlTol, lrlBreak)
  902. line.delete(lrlBullLn)
  903. label.delete(lrlBullLb)
  904. int lx1 = array.get(lrlLoBar, 0)
  905. float ly1 = array.get(lrlLoPx, 0)
  906. int lx3 = array.get(lrlLoBar, 2)
  907. float ly3 = array.get(lrlLoPx, 2)
  908. lrlBullLn := line.new(lx1, ly1, lx3, ly3, color = lrl_bullColor, style = f_style(lrl_bullStyle), width = f_width(lrl_bullThick))
  909. lrlBullLb := label.new(lx3, ly3, "LRL", style = label.style_label_left, color = color.new(lrl_bullColor, 100), textcolor = lrl_bullColor, size = f_size(lrl_lblSize))
  910.  
  911. var line smtLiveDevHiLn = na
  912. var label smtLiveDevHiLb = na
  913. var line smtLiveDevLoLn = na
  914. var label smtLiveDevLoLb = na
  915. var int lastGapSmtBar = 0
  916.  
  917. if smtActive
  918. if not na(smtPH)
  919. line.delete(smtLiveDevHiLn)
  920. label.delete(smtLiveDevHiLb)
  921. smtLiveDevHiLn := na
  922. smtLiveDevHiLb := na
  923. int pBar = bar_index - smtLen
  924. float pPx = smtPH
  925. float cPx = cmpHiWin[smtLen]
  926. f_smtCheckPivot(smtHighs, SmtPivot.new(pBar, pPx, cPx), true)
  927.  
  928. if not na(smtPL)
  929. line.delete(smtLiveDevLoLn)
  930. label.delete(smtLiveDevLoLb)
  931. smtLiveDevLoLn := na
  932. smtLiveDevLoLb := na
  933. int pBar = bar_index - smtLen
  934. float pPx = smtPL
  935. float cPx = cmpLoWin[smtLen]
  936. f_smtCheckPivot(smtLows, SmtPivot.new(pBar, pPx, cPx), false)
  937.  
  938. if smt_live and array.size(smtHighs) > 0
  939. SmtPivot lastH = array.last(smtHighs)
  940. if bar_index - lastH.bar <= SMT_MAX_SPAN
  941. bool c1 = high > lastH.px and cmpHi < lastH.cpx
  942. bool c2 = high < lastH.px and cmpHi > lastH.cpx
  943. if (c1 or c2) and f_lineHolds(lastH.bar, lastH.px, bar_index, high, true, syminfo.mintick)
  944. if na(smtLiveDevHiLn)
  945. smtLiveDevHiLn := f_smtLine(lastH.bar, lastH.px, bar_index, high, false)
  946. smtLiveDevHiLb := f_smtLabel(bar_index, high, false, false)
  947. else
  948. line.set_xy2(smtLiveDevHiLn, bar_index, high)
  949. if not na(smtLiveDevHiLb)
  950. label.set_xy(smtLiveDevHiLb, bar_index, high)
  951. else if not na(smtLiveDevHiLn)
  952. line.delete(smtLiveDevHiLn)
  953. label.delete(smtLiveDevHiLb)
  954. smtLiveDevHiLn := na
  955. smtLiveDevHiLb := na
  956.  
  957. if smt_live and array.size(smtLows) > 0
  958. SmtPivot lastL = array.last(smtLows)
  959. if bar_index - lastL.bar <= SMT_MAX_SPAN
  960. bool c1 = low < lastL.px and cmpLo > lastL.cpx
  961. bool c2 = low > lastL.px and cmpLo < lastL.cpx
  962. if (c1 or c2) and f_lineHolds(lastL.bar, lastL.px, bar_index, low, false, syminfo.mintick)
  963. if na(smtLiveDevLoLn)
  964. smtLiveDevLoLn := f_smtLine(lastL.bar, lastL.px, bar_index, low, true)
  965. smtLiveDevLoLb := f_smtLabel(bar_index, low, true, false)
  966. else
  967. line.set_xy2(smtLiveDevLoLn, bar_index, low)
  968. if not na(smtLiveDevLoLb)
  969. label.set_xy(smtLiveDevLoLb, bar_index, low)
  970. else if not na(smtLiveDevLoLn)
  971. line.delete(smtLiveDevLoLn)
  972. label.delete(smtLiveDevLoLb)
  973. smtLiveDevLoLn := na
  974. smtLiveDevLoLb := na
  975.  
  976. if smt_gap and bar_index - lastGapSmtBar > SMT_GAP_COOLDOWN
  977. bool fvgBullCmp = cmpLo > cmpHi2
  978. bool fvgBearCmp = cmpHi < cmpLo2
  979. if fvgBearNow and not fvgBearCmp and high >= gapHH[1] and cmpHi < gapCHH[1]
  980. f_smtCommit(bar_index - 2, high, bar_index, high, false, true)
  981. lastGapSmtBar := bar_index
  982. if fvgBullNow and not fvgBullCmp and low <= gapLL[1] and cmpLo > gapCLL[1]
  983. f_smtCommit(bar_index - 2, low, bar_index, low, true, true)
  984. lastGapSmtBar := bar_index
  985.  
  986. if barstate.islast
  987. if htf_show
  988. box.delete(htfBullBox)
  989. box.delete(htfBearBox)
  990. HtfGap bGap = f_closestGap(htfBullGaps, close)
  991. HtfGap sGap = f_closestGap(htfBearGaps, close)
  992. if not na(bGap)
  993. htfBullBox := f_htfBox(bGap, htf_bullColor)
  994. if not na(sGap)
  995. htfBearBox := f_htfBox(sGap, htf_bearColor)
  996.  
  997. for l in klLines
  998. line.delete(l)
  999. for lb in klLabels
  1000. label.delete(lb)
  1001. array.clear(klLines)
  1002. array.clear(klLabels)
  1003.  
  1004. array<bool> kShows = array.new<bool>()
  1005. array<color> kColors = array.new<color>()
  1006. array<string> kStyles = array.new<string>()
  1007. array<string> kSizes = array.new<string>()
  1008. array<bool> kLabs = array.new<bool>()
  1009.  
  1010. f_cfg(kShows, kColors, kStyles, kSizes, kLabs, kl_athShow, kl_athColor, kl_athStyle, kl_athSize, kl_athLabel)
  1011. f_cfg(kShows, kColors, kStyles, kSizes, kLabs, kl_pwShow, kl_pwColor, kl_pwStyle, kl_pwSize, kl_pwLabel)
  1012. f_cfg(kShows, kColors, kStyles, kSizes, kLabs, kl_pwShow, kl_pwColor, kl_pwStyle, kl_pwSize, kl_pwLabel)
  1013. f_cfg(kShows, kColors, kStyles, kSizes, kLabs, kl_pdShow, kl_pdColor, kl_pdStyle, kl_pdSize, kl_pdLabel)
  1014. f_cfg(kShows, kColors, kStyles, kSizes, kLabs, kl_pdShow, kl_pdColor, kl_pdStyle, kl_pdSize, kl_pdLabel)
  1015. f_cfg(kShows, kColors, kStyles, kSizes, kLabs, ko_show, ko_color, ko_style, ko_size, ko_label)
  1016. f_cfg(kShows, kColors, kStyles, kSizes, kLabs, kl_loShow, kl_loColor, kl_loStyle, kl_loSize, kl_loLabel)
  1017. f_cfg(kShows, kColors, kStyles, kSizes, kLabs, kl_loShow, kl_loColor, kl_loStyle, kl_loSize, kl_loLabel)
  1018. f_cfg(kShows, kColors, kStyles, kSizes, kLabs, kl_asShow, kl_asColor, kl_asStyle, kl_asSize, kl_asLabel)
  1019. f_cfg(kShows, kColors, kStyles, kSizes, kLabs, kl_asShow, kl_asColor, kl_asStyle, kl_asSize, kl_asLabel)
  1020.  
  1021. array<int> activeIdxs = array.new<int>()
  1022. for i = 0 to array.size(kAll) - 1
  1023. KeyLevel kl = array.get(kAll, i)
  1024. bool showOpt = array.get(kShows, i)
  1025. if showOpt and kl.live and not na(kl.price)
  1026. array.push(activeIdxs, i)
  1027. int x1 = f_clampX(kl.x1)
  1028. int x2 = bar_index + KL_OFFSET
  1029. color c = array.get(kColors, i)
  1030. line ln = line.new(x1, kl.price, x2, kl.price, color = c, style = f_style(array.get(kStyles, i)), width = 1)
  1031. array.push(klLines, ln)
  1032.  
  1033. int mCount = array.size(activeIdxs)
  1034. if mCount > 0
  1035. for i = 0 to mCount - 1
  1036. if mCount - 2 - i >= 0
  1037. for j = 0 to mCount - 2 - i
  1038. int idxA = array.get(activeIdxs, j)
  1039. int idxB = array.get(activeIdxs, j + 1)
  1040. if array.get(kAll, idxA).price < array.get(kAll, idxB).price
  1041. array.set(activeIdxs, j, idxB)
  1042. array.set(activeIdxs, j + 1, idxA)
  1043.  
  1044. float tolTicks = kl_merge * syminfo.mintick
  1045. int cursor = 0
  1046. while cursor < mCount
  1047. int startIdx = array.get(activeIdxs, cursor)
  1048. KeyLevel baseKl = array.get(kAll, startIdx)
  1049. int clusterEnd = cursor
  1050.  
  1051. if cursor + 1 <= mCount - 1
  1052. for j = cursor + 1 to mCount - 1
  1053. int nextIdx = array.get(activeIdxs, j)
  1054. KeyLevel nextKl = array.get(kAll, nextIdx)
  1055. if math.abs(baseKl.price - nextKl.price) <= tolTicks
  1056. clusterEnd := j
  1057. else
  1058. break
  1059.  
  1060. string lblText = ""
  1061. int bestRankIdx = -1
  1062. for r = 1 to RANK_MAX
  1063. for k = cursor to clusterEnd
  1064. int curIdx = array.get(activeIdxs, k)
  1065. KeyLevel item = array.get(kAll, curIdx)
  1066. if item.rank == r and array.get(kLabs, curIdx)
  1067. lblText := lblText + (str.length(lblText) > 0 ? " / " : "") + item.name
  1068. if bestRankIdx < 0
  1069. bestRankIdx := curIdx
  1070.  
  1071. if bestRankIdx >= 0
  1072. color lblCol = array.get(kColors, bestRankIdx)
  1073. string lblSz = array.get(kSizes, bestRankIdx)
  1074. label lb = label.new(bar_index + KL_OFFSET, baseKl.price, lblText, style = label.style_label_left, color = color.new(lblCol, 100), textcolor = lblCol, size = f_size(lblSz))
  1075. array.push(klLabels, lb)
  1076.  
  1077. cursor := clusterEnd + 1
Advertisement
Add Comment
Please, Sign In to add comment