Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //@version=6
- indicator("TradeAxis DOL Pro", shorttitle = "TradeAxis DOL Pro", overlay = true, max_lines_count = 500, max_boxes_count = 500, max_labels_count = 500, max_bars_back = 1000)
- const string G_ENGINE = "Engine"
- const string G_GATES = "Quality Gates"
- const string G_SESS = "Session Settings"
- const string G_TARGET = "Active DOL Target"
- const string G_HUD = "Heads-Up Display (HUD)"
- const string G_LADDER = "Candidate Ladder"
- const string G_MS = "Market Structure"
- const string G_IFVG = "Inverted FVGs (iFVG)"
- const string G_LIQ = "Liquidity Levels"
- const string G_COL = "Colors"
- string styleIn = input.string("Day Trading", "Trading Style", options = ["Scalping", "Day Trading", "Swing"], group = G_ENGINE, tooltip = "Selects the three-timeframe engine stack, HTF background scanning and the volatility math.\nScalping: 1H · 15m · 5m\nDay Trading: 1D · 4H · 1H\nSwing: 1W · 1D · 4H")
- float minProbIn = input.float(30.0, "Minimum Probability (PoT %)", minval = 0.0, maxval = 100.0, step = 1.0, group = G_GATES, tooltip = "Targets with a Probability of Touch below this value are rejected.")
- int minConfIn = input.int(40, "Minimum Confidence", minval = 0, maxval = 100, group = G_GATES, tooltip = "Targets with an internal Conviction score below this value are rejected. Raise it to keep the chart clean in choppy or directionless conditions.")
- string tzIn = input.string("America/New_York", "Timezone", options = ["America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles", "America/Sao_Paulo", "Europe/London", "Europe/Berlin", "Europe/Moscow", "Asia/Dubai", "Asia/Kolkata", "Asia/Singapore", "Asia/Hong_Kong", "Asia/Tokyo", "Australia/Sydney", "Etc/UTC", "Exchange"], group = G_SESS, tooltip = "Timezone used to evaluate the session windows below.")
- string sessAsiaIn = input.session("2000-0000", "Asia Session", group = G_SESS)
- string sessLonIn = input.session("0200-0500", "London Session", group = G_SESS)
- string sessNyIn = input.session("0930-1600", "New York Session", group = G_SESS)
- bool showTargetIn = input.bool(true, "Show Active DOL Target", group = G_TARGET)
- bool showTrajIn = input.bool(true, "Trajectory Line", group = G_TARGET, inline = "tg1")
- bool showBandIn = input.bool(true, "Tolerance Band", group = G_TARGET, inline = "tg1")
- bool showAnchorIn = input.bool(true, "Show Anchor", group = G_TARGET)
- int projBarsIn = input.int(24, "Projection Offset (bars)", minval = 5, maxval = 200, group = G_TARGET)
- bool showHudIn = input.bool(true, "Show HUD", group = G_HUD)
- string hudPosIn = input.string("Top Right", "Position", options = ["Top Right", "Middle Right", "Bottom Right", "Top Left", "Middle Left", "Bottom Left", "Top Center", "Bottom Center"], group = G_HUD, inline = "hud")
- string hudSizeIn = input.string("Tiny", "Size", options = ["Tiny", "Small", "Normal"], group = G_HUD, inline = "hud")
- bool showLadderIn = input.bool(false, "Show Candidate Ladder", group = G_LADDER)
- int ladderDepth = input.int(3, "Ladder Depth", minval = 1, maxval = 6, group = G_LADDER)
- bool showBosIn = input.bool(false, "BOS", group = G_MS, inline = "ms")
- bool showMssIn = input.bool(false, "MSS", group = G_MS, inline = "ms")
- bool showCisdIn = input.bool(false, "CISD", group = G_MS, inline = "ms")
- bool showIfvgIn = input.bool(true, "Show iFVGs aligned with the active trajectory", group = G_IFVG)
- bool showLiqIn = input.bool(false, "Show Liquidity Levels", group = G_LIQ)
- bool showPdIn = input.bool(true, "PDH / PDL", group = G_LIQ, inline = "lq1")
- bool showLonIn = input.bool(true, "LON H / L", group = G_LIQ, inline = "lq1")
- bool showAsiaIn = input.bool(true, "ASIA H / L", group = G_LIQ, inline = "lq2")
- bool showNyIn = input.bool(true, "NY H / L", group = G_LIQ, inline = "lq2")
- bool showGapIn = input.bool(true, "NDOG / NWOG", group = G_LIQ, inline = "lq3")
- bool showHtfFvgIn = input.bool(true, "FVG (HTF)", group = G_LIQ, inline = "lq3")
- bool showEqIn = input.bool(true, "EQH / EQL", group = G_LIQ, inline = "lq4")
- color colAccent = input.color(#F2A33A, "DOL / Bull", group = G_COL, inline = "c1")
- color colBear = input.color(#E05A4E, "Bear", group = G_COL, inline = "c1")
- color colNeutral = input.color(#7D7466, "Neutral", group = G_COL, inline = "c1")
- color colIfvg = input.color(#F2A33A, "iFVG", group = G_COL, inline = "c2")
- color colAnchor = input.color(#B07A3C, "Anchor", group = G_COL, inline = "c2")
- color colLadder = input.color(#A88148, "Ladder", group = G_COL, inline = "c2")
- color colPd = input.color(#E3B65E, "PDH/PDL", group = G_COL, inline = "c3")
- color colSess = input.color(#A68B5B, "Sessions", group = G_COL, inline = "c3")
- color colGap = input.color(#C77B30, "Gaps", group = G_COL, inline = "c3")
- color colHtfFvg = input.color(#9C7C48, "HTF FVG", group = G_COL, inline = "c4")
- color colEq = input.color(#D9A441, "EQH/EQL", group = G_COL, inline = "c4")
- color colHudBg = input.color(#0B0907, "HUD Background", group = G_COL, inline = "c5")
- color colHudBorder = input.color(#2C2316, "HUD Border", group = G_COL, inline = "c5")
- color colHudText = input.color(#9A8F7E, "HUD Text", group = G_COL, inline = "c6")
- color colHudValue = input.color(#F3EBDD, "HUD Price", group = G_COL, inline = "c6")
- color colLabelBg = input.color(#17120B, "Label Background", group = G_COL, inline = "c6")
- const int POOL_MAX = 120
- const int ENGINE_LOOKBACK = 400
- const int HTF_PIVOT_LEN = 3
- const int ATR_LEN = 14
- const int CISD_LEN = 20
- const int MAX_GAPS = 40
- const int MAX_IFVG = 24
- const int MAX_MS_OBJ = 60
- const int LEVEL_LABEL_BARS = 6
- const int MAX_LEVEL_DRAW = 40
- const int MAX_IFVG_DRAW = 6
- const float BAND_MULT = 0.33
- const float MIN_DIST_ATR = 0.15
- const float PERSIST_BONUS = 4.0
- const float DRIFT_DAMP = 0.5
- const float IFVG_MULT = 0.25
- string styleCode = styleIn == "Scalping" ? "SCALP" : styleIn == "Swing" ? "SWING" : "DAY"
- string tf1Raw = styleIn == "Scalping" ? "60" : styleIn == "Swing" ? "W" : "D"
- string tf2Raw = styleIn == "Scalping" ? "15" : styleIn == "Swing" ? "D" : "240"
- string tf3Raw = styleIn == "Scalping" ? "5" : styleIn == "Swing" ? "240" : "60"
- int potHorizon = styleIn == "Scalping" ? 48 : styleIn == "Swing" ? 120 : 96
- int volLen = styleIn == "Scalping" ? 34 : styleIn == "Swing" ? 89 : 55
- int driftLen = styleIn == "Scalping" ? 13 : styleIn == "Swing" ? 34 : 21
- float maxDistATR = styleIn == "Scalping" ? 6.0 : styleIn == "Swing" ? 24.0 : 12.0
- float proxK = styleIn == "Scalping" ? 3.0 : styleIn == "Swing" ? 8.0 : 5.0
- int msLen = styleIn == "Scalping" ? 3 : styleIn == "Swing" ? 8 : 5
- int eqLen = styleIn == "Scalping" ? 3 : styleIn == "Swing" ? 8 : 5
- float eqTolMult = styleIn == "Scalping" ? 0.08 : styleIn == "Swing" ? 0.12 : 0.10
- float mergeMult = styleIn == "Scalping" ? 0.35 : styleIn == "Swing" ? 0.60 : 0.50
- float htfGapMult = styleIn == "Scalping" ? 0.30 : styleIn == "Swing" ? 0.45 : 0.40
- type Liq
- float price
- float top
- float bot
- string kind
- string tfLbl
- int tier
- int side
- int bornTime
- float depth
- string cat
- int pol
- type Gap
- float top
- float bot
- int dir
- int bornTime
- type Cluster
- float price
- float bot
- int dir
- string kind
- string tfLbl
- int tier
- float depth
- float domW
- int bornTime
- string key = ""
- float conviction = 0.0
- float pot = 0.0
- float score = 0.0
- float distATR = 0.0
- bool qualified = false
- type SessTrack
- float hi
- float lo
- int hiT
- int loT
- f_safeTF(string tf) =>
- timeframe.in_seconds(tf) < timeframe.in_seconds(timeframe.period) ? timeframe.period : tf
- f_tfLabel(string tf) =>
- int s = timeframe.in_seconds(tf)
- string r = str.tostring(s) + "s"
- if s >= 2592000
- r := str.tostring(math.round(s / 2628003.0)) + "M"
- else if s >= 604800
- r := str.tostring(math.round(s / 604800.0)) + "W"
- else if s >= 86400
- r := str.tostring(math.round(s / 86400.0)) + "D"
- else if s >= 3600 and s % 3600 == 0
- r := str.tostring(math.round(s / 3600.0)) + "H"
- else if s >= 60
- r := str.tostring(math.round(s / 60.0)) + "m"
- r
- f_tier(int sec, int s1, int s2, int s3) =>
- sec >= s1 ? 3 : sec >= s2 ? 2 : sec >= s3 ? 1 : 0
- f_ncdf(float x) =>
- float ax = math.abs(x)
- float t = 1.0 / (1.0 + 0.2316419 * ax)
- float d = 0.3989422804014327 * math.exp(-0.5 * ax * ax)
- float p = d * t * (0.319381530 + t * (-0.356563782 + t * (1.781477937 + t * (-1.821255978 + t * 1.330274429))))
- x >= 0 ? 1.0 - p : p
- f_pot(float dist, float mu, float sigma, int horizon) =>
- float res = 0.0
- if na(dist) or na(sigma)
- res := 0.0
- else if dist <= 0
- res := 1.0
- else if sigma > 0 and horizon > 0
- float m = nz(mu)
- float sT = sigma * math.sqrt(horizon)
- float a = f_ncdf((-dist + m * horizon) / sT)
- float ex = math.min(2.0 * m * dist / (sigma * sigma), 60.0)
- float b = math.exp(ex) * f_ncdf((-dist - m * horizon) / sT)
- res := math.max(0.0, math.min(1.0, a + b))
- res
- f_alignW(int b, int d) =>
- b == d ? 1.0 : b == 0 ? 0.5 : 0.0
- f_bar(float v, int n) =>
- int filled = math.round(math.max(0.0, math.min(100.0, nz(v))) / 100.0 * n)
- string s = ""
- for i = 1 to n
- s := s + (i <= filled ? "█" : "░")
- s
- f_grade(float s) =>
- s >= 72.0 ? "A+" : s >= 55.0 ? "A" : s >= 42.0 ? "B" : "C"
- f_biasTxt(int b) =>
- b == 1 ? "BULL" : b == -1 ? "BEAR" : "NEUTRAL"
- f_biasCol(int b, color bull, color bear, color neu) =>
- b == 1 ? bull : b == -1 ? bear : neu
- f_pos(string p) =>
- switch p
- "Top Left" => position.top_left
- "Top Center" => position.top_center
- "Middle Left" => position.middle_left
- "Middle Right" => position.middle_right
- "Bottom Left" => position.bottom_left
- "Bottom Center" => position.bottom_center
- "Bottom Right" => position.bottom_right
- => position.top_right
- f_size(string s) =>
- switch s
- "Small" => size.small
- "Normal" => size.normal
- => size.tiny
- f_addLevel(array<Liq> arr, float price, float top, float bot, string kind, string tfLbl, int tier, int side, int bornT, float depth, string cat, int pol) =>
- bool dup = false
- for lq in arr
- if lq.kind == kind and lq.tfLbl == tfLbl and math.abs(lq.price - price) < syminfo.mintick * 0.5
- dup := true
- break
- if not dup and not na(price)
- arr.push(Liq.new(price, top, bot, kind, tfLbl, tier, side, bornT, depth, cat, pol))
- if arr.size() > POOL_MAX
- arr.shift()
- not dup
- f_removeKind(array<Liq> arr, string kind) =>
- int n = arr.size()
- if n > 0
- for i = n - 1 to 0
- if arr.get(i).kind == kind
- arr.remove(i)
- n
- f_addEq(array<Liq> arr, float lvl, string kind, string tfLbl, int tier, int side, int bornT, float tolPts) =>
- bool merged = false
- for lq in arr
- if lq.kind == kind and lq.tfLbl == tfLbl and math.abs(lq.price - lvl) <= tolPts
- lq.price := side == 1 ? math.max(lq.price, lvl) : math.min(lq.price, lvl)
- lq.top := lq.price
- lq.bot := lq.price
- lq.depth := lq.depth + 0.4
- merged := true
- break
- if not merged
- f_addLevel(arr, lvl, lvl, lvl, kind, tfLbl, tier, side, bornT, 2.4, "EQ", 0)
- merged
- f_sessLevels(array<Liq> arr, SessTrack s, bool ended, string nm, float dpth, int tr) =>
- if ended and not na(s.hi)
- f_removeKind(arr, nm + " H")
- f_removeKind(arr, nm + " L")
- f_addLevel(arr, s.hi, s.hi, s.hi, nm + " H", "SESS", tr, 1, s.hiT, dpth, "SESS", 0)
- f_addLevel(arr, s.lo, s.lo, s.lo, nm + " L", "SESS", tr, -1, s.loT, dpth, "SESS", 0)
- ended
- f_ingestHtf(array<Liq> arr, bool isNew, bool bullG, float bTop, float bBot, bool bearG, float sTop, float sBot, int midT, float eqh, int eqhT, float eql, int eqlT, float hAtr, float fbAtr, string lbl, int tier, float eqTol) =>
- if isNew
- float a = math.max(nz(hAtr, fbAtr), syminfo.mintick)
- if bullG and not na(bTop) and not na(bBot)
- f_addLevel(arr, (bTop + bBot) / 2.0, bTop, bBot, "FVG", lbl, tier, 0, midT, 1.5 + math.min(1.0, (bTop - bBot) / a), "FVG", 1)
- if bearG and not na(sTop) and not na(sBot)
- f_addLevel(arr, (sTop + sBot) / 2.0, sTop, sBot, "FVG", lbl, tier, 0, midT, 1.5 + math.min(1.0, (sTop - sBot) / a), "FVG", -1)
- if not na(eqh) and not na(eqhT)
- f_addEq(arr, eqh, "EQH", lbl, tier, 1, eqhT, eqTol * a)
- if not na(eql) and not na(eqlT)
- f_addEq(arr, eql, "EQL", lbl, tier, -1, eqlT, eqTol * a)
- isNew
- f_obstacles(Cluster c, array<Cluster> cl, array<Gap> ig, array<Gap> cg, float px) =>
- float n = 0.0
- float lo = math.min(px, c.price)
- float hi = math.max(px, c.price)
- for g in ig
- float mid = (g.top + g.bot) / 2.0
- if g.dir == -c.dir and mid > lo and mid < hi
- n := n + 1.0
- for g in cg
- float mid = (g.top + g.bot) / 2.0
- if g.dir == -c.dir and mid > lo and mid < hi
- n := n + 0.5
- for o in cl
- if o.dir == c.dir and o.tier > c.tier and o.price > lo and o.price < hi
- n := n + 1.0
- n
- f_trimLines(array<line> a, int maxN) =>
- while a.size() > maxN
- line.delete(a.shift())
- a.size()
- f_trimLabels(array<label> a, int maxN) =>
- while a.size() > maxN
- label.delete(a.shift())
- a.size()
- method track(SessTrack s, bool inS, bool wasIn) =>
- if inS and not wasIn
- s.hi := high
- s.lo := low
- s.hiT := time
- s.loT := time
- else if inS
- if na(s.hi) or high > s.hi
- s.hi := high
- s.hiT := time
- if na(s.lo) or low < s.lo
- s.lo := low
- s.loT := time
- s
- f_htfEngine(int pLen, float gapMult, float eqTol) =>
- float atrH = ta.atr(14)
- float ph = ta.pivothigh(high, pLen, pLen)
- float pl = ta.pivotlow(low, pLen, pLen)
- var float sH = na
- var float sL = na
- var int bias = 0
- if not na(ph)
- sH := ph
- if not na(pl)
- sL := pl
- if not na(sH) and close > sH
- bias := 1
- sH := na
- else if not na(sL) and close < sL
- bias := -1
- sL := na
- var float lastPH = na
- var int lastPHT = na
- var float lastPL = na
- var int lastPLT = na
- float eqh = na
- int eqhT = na
- float eql = na
- int eqlT = na
- float tolH = eqTol * nz(atrH, high - low)
- if not na(lastPH) and high > lastPH + tolH
- lastPH := na
- if not na(lastPL) and low < lastPL - tolH
- lastPL := na
- if not na(ph)
- if not na(lastPH) and math.abs(ph - lastPH) <= tolH
- eqh := math.max(ph, lastPH)
- eqhT := lastPHT
- lastPH := ph
- lastPHT := time[pLen]
- if not na(pl)
- if not na(lastPL) and math.abs(pl - lastPL) <= tolH
- eql := math.min(pl, lastPL)
- eqlT := lastPLT
- lastPL := pl
- lastPLT := time[pLen]
- float gapRef = nz(atrH, high - low)
- bool bullG = low > high[2] and (low - high[2]) >= gapMult * gapRef
- bool bearG = high < low[2] and (low[2] - high) >= gapMult * gapRef
- float bTop = low
- float bBot = high[2]
- float sTop = low[2]
- float sBot = high
- int midT = time[1]
- [atrH[1], bias[1], bullG[1], bTop[1], bBot[1], bearG[1], sTop[1], sBot[1], midT[1], eqh[1], eqhT[1], eql[1], eqlT[1], time[1]]
- var string tf1 = f_safeTF(tf1Raw)
- var string tf2 = f_safeTF(tf2Raw)
- var string tf3 = f_safeTF(tf3Raw)
- var int tf1Sec = timeframe.in_seconds(tf1)
- var int tf2Sec = timeframe.in_seconds(tf2)
- var int tf3Sec = timeframe.in_seconds(tf3)
- var string tf1Lbl = f_tfLabel(tf1)
- var string tf2Lbl = f_tfLabel(tf2)
- var string tf3Lbl = f_tfLabel(tf3)
- var string chartLbl = f_tfLabel(timeframe.period)
- var int tier1 = f_tier(tf1Sec, tf1Sec, tf2Sec, tf3Sec)
- var int tier2 = f_tier(tf2Sec, tf1Sec, tf2Sec, tf3Sec)
- var int tier3 = f_tier(tf3Sec, tf1Sec, tf2Sec, tf3Sec)
- var int tierC = f_tier(timeframe.in_seconds(), tf1Sec, tf2Sec, tf3Sec)
- var int tierD = f_tier(86400, tf1Sec, tf2Sec, tf3Sec)
- var int tierW = f_tier(604800, tf1Sec, tf2Sec, tf3Sec)
- var int tierSess = f_tier(14400, tf1Sec, tf2Sec, tf3Sec)
- var string tzUse = tzIn == "Exchange" ? syminfo.timezone : tzIn
- float atrRaw = ta.atr(ATR_LEN)
- float atrC = math.max(nz(atrRaw, high - low), syminfo.mintick)
- float chg = close - nz(close[1], close)
- float sigma = math.max(nz(ta.stdev(chg, volLen)), syminfo.mintick)
- float mu = nz(ta.sma(chg, driftLen)) * DRIFT_DAMP
- int driftSign = mu > 0 ? 1 : mu < 0 ? -1 : 0
- [h1Atr, h1Bias, h1BullG, h1BTop, h1BBot, h1BearG, h1STop, h1SBot, h1MidT, h1Eqh, h1EqhT, h1Eql, h1EqlT, h1T] = request.security(syminfo.tickerid, tf1, f_htfEngine(HTF_PIVOT_LEN, htfGapMult, eqTolMult), lookahead = barmerge.lookahead_on)
- [h2Atr, h2Bias, h2BullG, h2BTop, h2BBot, h2BearG, h2STop, h2SBot, h2MidT, h2Eqh, h2EqhT, h2Eql, h2EqlT, h2T] = request.security(syminfo.tickerid, tf2, f_htfEngine(HTF_PIVOT_LEN, htfGapMult, eqTolMult), lookahead = barmerge.lookahead_on)
- [h3Atr, h3Bias, h3BullG, h3BTop, h3BBot, h3BearG, h3STop, h3SBot, h3MidT, h3Eqh, h3EqhT, h3Eql, h3EqlT, h3T] = request.security(syminfo.tickerid, tf3, f_htfEngine(HTF_PIVOT_LEN, htfGapMult, eqTolMult), lookahead = barmerge.lookahead_on)
- bool h1New = not na(h1T) and (na(h1T[1]) or h1T != h1T[1])
- bool h2New = not na(h2T) and (na(h2T[1]) or h2T != h2T[1])
- bool h3New = not na(h3T) and (na(h3T[1]) or h3T != h3T[1])
- bool isIntra = timeframe.isintraday
- bool inAsia = isIntra and not na(time(timeframe.period, sessAsiaIn, tzUse))
- bool inLon = isIntra and not na(time(timeframe.period, sessLonIn, tzUse))
- bool inNy = isIntra and not na(time(timeframe.period, sessNyIn, tzUse))
- bool wasAsia = inAsia[1]
- bool wasLon = inLon[1]
- bool wasNy = inNy[1]
- var SessTrack stAsia = SessTrack.new()
- var SessTrack stLon = SessTrack.new()
- var SessTrack stNy = SessTrack.new()
- stAsia.track(inAsia, wasAsia)
- stLon.track(inLon, wasLon)
- stNy.track(inNy, wasNy)
- bool asiaEnd = wasAsia and not inAsia
- bool lonEnd = wasLon and not inLon
- bool nyEnd = wasNy and not inNy
- bool newDay = timeframe.change("D")
- bool newWeek = timeframe.change("W")
- float cPH = ta.pivothigh(high, eqLen, eqLen)
- float cPL = ta.pivotlow(low, eqLen, eqLen)
- float msPH = ta.pivothigh(high, msLen, msLen)
- float msPL = ta.pivotlow(low, msLen, msLen)
- bool cBullGap = low > high[2] and (low - high[2]) >= IFVG_MULT * atrC
- bool cBearGap = high < low[2] and (low[2] - high) >= IFVG_MULT * atrC
- bool candleBull = close > open
- bool candleBear = close < open
- bool prevBull = close[1] > open[1]
- bool prevBear = close[1] < open[1]
- float hhN = ta.highest(high, CISD_LEN)
- float llN = ta.lowest(low, CISD_LEN)
- bool newHighN = high >= nz(hhN[1], high)
- bool newLowN = low <= nz(llN[1], low)
- var array<Liq> pool = array.new<Liq>()
- var array<Gap> cGaps = array.new<Gap>()
- var array<Gap> iGaps = array.new<Gap>()
- var array<line> msLines = array.new<line>()
- var array<label> msLabels = array.new<label>()
- var array<line> dynLines = array.new<line>()
- var array<box> dynBoxes = array.new<box>()
- var array<label> dynLabels = array.new<label>()
- var array<Cluster> ladder = array.new<Cluster>()
- var Cluster activeC = na
- var string tgtKey = ""
- var int tgtSinceBar = na
- var int tgtSinceTime = na
- var float tgtPrice = na
- var string tgtKind = ""
- var string lastSweepName = ""
- var int lastSweepDir = 0
- var float dHi = na
- var int dHiT = na
- var float dLo = na
- var int dLoT = na
- var float cLastPH = na
- var int cLastPHT = na
- var float cLastPL = na
- var int cLastPLT = na
- var float swH = na
- var int swHT = na
- var float swL = na
- var int swLT = na
- var int msTrend = 0
- var float curBullOpen = na
- var int curBullT = na
- var float curBearOpen = na
- var int curBearT = na
- var float bullRunOpen = na
- var int bullRunT = na
- var float bearRunOpen = na
- var int bearRunT = na
- var int deliveryState = 0
- bool bosBullEvt = false
- bool bosBearEvt = false
- bool mssBullEvt = false
- bool mssBearEvt = false
- bool cisdBullEvt = false
- bool cisdBearEvt = false
- bool newTgtEvt = false
- bool tgtHitEvt = false
- string hitMsg = ""
- if barstate.isconfirmed
- float tolEq = eqTolMult * atrC
- if newDay
- if not na(dHi) and bar_index > 0
- f_removeKind(pool, "PDH")
- f_removeKind(pool, "PDL")
- f_addLevel(pool, dHi, dHi, dHi, "PDH", "1D", tierD, 1, dHiT, 3.0, "PD", 0)
- f_addLevel(pool, dLo, dLo, dLo, "PDL", "1D", tierD, -1, dLoT, 3.0, "PD", 0)
- dHi := high
- dHiT := time
- dLo := low
- dLoT := time
- else
- if na(dHi) or high > dHi
- dHi := high
- dHiT := time
- if na(dLo) or low < dLo
- dLo := low
- dLoT := time
- if newWeek and not na(close[1]) and timeframe.in_seconds() < 604800
- float gTop = math.max(open, close[1])
- float gBot = math.min(open, close[1])
- if gTop - gBot >= syminfo.mintick
- f_removeKind(pool, "NWOG")
- f_addLevel(pool, (gTop + gBot) / 2.0, gTop, gBot, "NWOG", "1W", tierW, 0, time, 2.6, "GAP", 0)
- else if newDay and isIntra and not na(close[1])
- float gTop = math.max(open, close[1])
- float gBot = math.min(open, close[1])
- if gTop - gBot >= syminfo.mintick
- f_removeKind(pool, "NDOG")
- f_addLevel(pool, (gTop + gBot) / 2.0, gTop, gBot, "NDOG", "1D", tierD, 0, time, 1.8, "GAP", 0)
- f_sessLevels(pool, stAsia, asiaEnd, "ASIA", 1.8, tierSess)
- f_sessLevels(pool, stLon, lonEnd, "LON", 2.2, tierSess)
- f_sessLevels(pool, stNy, nyEnd, "NY", 2.0, tierSess)
- if not na(cLastPH) and high > cLastPH + tolEq
- cLastPH := na
- if not na(cLastPL) and low < cLastPL - tolEq
- cLastPL := na
- if not na(cPH)
- if not na(cLastPH) and math.abs(cPH - cLastPH) <= tolEq
- f_addEq(pool, math.max(cPH, cLastPH), "EQH", chartLbl, tierC, 1, cLastPHT, tolEq)
- cLastPH := cPH
- cLastPHT := time[eqLen]
- if not na(cPL)
- if not na(cLastPL) and math.abs(cPL - cLastPL) <= tolEq
- f_addEq(pool, math.min(cPL, cLastPL), "EQL", chartLbl, tierC, -1, cLastPLT, tolEq)
- cLastPL := cPL
- cLastPLT := time[eqLen]
- f_ingestHtf(pool, h1New, h1BullG, h1BTop, h1BBot, h1BearG, h1STop, h1SBot, h1MidT, h1Eqh, h1EqhT, h1Eql, h1EqlT, h1Atr, atrC, tf1Lbl, tier1, eqTolMult)
- f_ingestHtf(pool, h2New, h2BullG, h2BTop, h2BBot, h2BearG, h2STop, h2SBot, h2MidT, h2Eqh, h2EqhT, h2Eql, h2EqlT, h2Atr, atrC, tf2Lbl, tier2, eqTolMult)
- f_ingestHtf(pool, h3New, h3BullG, h3BTop, h3BBot, h3BearG, h3STop, h3SBot, h3MidT, h3Eqh, h3EqhT, h3Eql, h3EqlT, h3Atr, atrC, tf3Lbl, tier3, eqTolMult)
- float hiRef = math.max(high, nz(close[1], high))
- float loRef = math.min(low, nz(close[1], low))
- int nPool = pool.size()
- if nPool > 0
- for i = nPool - 1 to 0
- Liq lq = pool.get(i)
- bool fresh = lq.bornTime >= time
- float hR = fresh ? high : hiRef
- float lR = fresh ? low : loRef
- bool hit = lq.side == 1 ? high >= lq.price : lq.side == -1 ? low <= lq.price : (hR >= lq.price and lR <= lq.price)
- if hit
- if lq.cat == "SESS"
- lastSweepName := str.replace_all(lq.kind, " ", "-")
- lastSweepDir := lq.side
- pool.remove(i)
- if cBullGap
- cGaps.push(Gap.new(low, high[2], 1, time[1]))
- if cBearGap
- cGaps.push(Gap.new(low[2], high, -1, time[1]))
- int nG = cGaps.size()
- if nG > 0
- for i = nG - 1 to 0
- Gap g = cGaps.get(i)
- if g.dir == 1 and close < g.bot
- g.dir := -1
- iGaps.push(g)
- cGaps.remove(i)
- else if g.dir == -1 and close > g.top
- g.dir := 1
- iGaps.push(g)
- cGaps.remove(i)
- while cGaps.size() > MAX_GAPS
- cGaps.shift()
- int nI = iGaps.size()
- if nI > 0
- for i = nI - 1 to 0
- Gap g = iGaps.get(i)
- if (g.dir == 1 and close < g.bot) or (g.dir == -1 and close > g.top)
- iGaps.remove(i)
- while iGaps.size() > MAX_IFVG
- iGaps.shift()
- if not na(msPH)
- swH := msPH
- swHT := time[msLen]
- if not na(msPL)
- swL := msPL
- swLT := time[msLen]
- if not na(swH) and close > swH and candleBull
- bool isMss = msTrend == -1
- if isMss
- mssBullEvt := true
- else
- bosBullEvt := true
- if (isMss and showMssIn) or (not isMss and showBosIn)
- msLines.push(line.new(swHT, swH, time, swH, xloc.bar_time, extend.none, colAccent, isMss ? line.style_solid : line.style_dashed, 1))
- msLabels.push(label.new(math.round((swHT + time) / 2), swH, isMss ? "MSS" : "BOS", xloc.bar_time, yloc.price, color.new(color.black, 100), label.style_label_down, colAccent, size.tiny))
- msTrend := 1
- swH := na
- if not na(swL) and close < swL and candleBear
- bool isMss = msTrend == 1
- if isMss
- mssBearEvt := true
- else
- bosBearEvt := true
- if (isMss and showMssIn) or (not isMss and showBosIn)
- msLines.push(line.new(swLT, swL, time, swL, xloc.bar_time, extend.none, colBear, isMss ? line.style_solid : line.style_dashed, 1))
- msLabels.push(label.new(math.round((swLT + time) / 2), swL, isMss ? "MSS" : "BOS", xloc.bar_time, yloc.price, color.new(color.black, 100), label.style_label_up, colBear, size.tiny))
- msTrend := -1
- swL := na
- if deliveryState <= 0 and candleBull and not na(bearRunOpen) and close > bearRunOpen
- cisdBullEvt := true
- deliveryState := 1
- if showCisdIn
- msLines.push(line.new(bearRunT, bearRunOpen, time, bearRunOpen, xloc.bar_time, extend.none, colAccent, line.style_dotted, 1))
- msLabels.push(label.new(time, bearRunOpen, "CISD", xloc.bar_time, yloc.price, color.new(color.black, 100), label.style_label_left, colAccent, size.tiny))
- bearRunOpen := na
- if deliveryState >= 0 and candleBear and not na(bullRunOpen) and close < bullRunOpen
- cisdBearEvt := true
- deliveryState := -1
- if showCisdIn
- msLines.push(line.new(bullRunT, bullRunOpen, time, bullRunOpen, xloc.bar_time, extend.none, colBear, line.style_dotted, 1))
- msLabels.push(label.new(time, bullRunOpen, "CISD", xloc.bar_time, yloc.price, color.new(color.black, 100), label.style_label_left, colBear, size.tiny))
- bullRunOpen := na
- if candleBear
- if not prevBear
- curBearOpen := open
- curBearT := time
- if newLowN
- bearRunOpen := curBearOpen
- bearRunT := curBearT
- if candleBull
- if not prevBull
- curBullOpen := open
- curBullT := time
- if newHighN
- bullRunOpen := curBullOpen
- bullRunT := curBullT
- f_trimLines(msLines, MAX_MS_OBJ)
- f_trimLabels(msLabels, MAX_MS_OBJ)
- if not na(tgtPrice)
- if hiRef >= tgtPrice and loRef <= tgtPrice
- tgtHitEvt := true
- hitMsg := "TradeAxis DOL Pro | DOL reached: " + tgtKind + " @ " + str.tostring(tgtPrice, format.mintick) + " on " + syminfo.ticker
- bool runEngine = bar_index > ATR_LEN and (barstate.islast or (barstate.isconfirmed and bar_index >= last_bar_index - ENGINE_LOOKBACK))
- if runEngine
- array<Cluster> clusters = array.new<Cluster>()
- array<float> candPx = array.new<float>()
- array<int> candId = array.new<int>()
- float mergeTol = mergeMult * atrC
- array<float> scores = array.new<float>()
- for [i, lq] in pool
- float dA = math.abs(lq.price - close) / atrC
- if dA >= MIN_DIST_ATR and dA <= maxDistATR
- candPx.push(lq.price)
- candId.push(i)
- if candPx.size() > 0
- array<int> sortIdx = array.sort_indices(candPx, order.ascending)
- Cluster cur = na
- for k = 0 to sortIdx.size() - 1
- Liq lq = pool.get(candId.get(sortIdx.get(k)))
- int d = lq.price > close ? 1 : -1
- float w = lq.depth * (1.0 + 0.25 * lq.tier)
- bool join = false
- if not na(cur)
- join := cur.dir == d and (lq.price - cur.bot) <= mergeTol
- if join
- cur.depth := cur.depth + w
- cur.tier := math.max(cur.tier, lq.tier)
- cur.bornTime := math.min(cur.bornTime, lq.bornTime)
- if w > cur.domW
- cur.price := lq.price
- cur.kind := lq.kind
- cur.tfLbl := lq.tfLbl
- cur.domW := w
- else
- cur := Cluster.new(price = lq.price, bot = lq.price, dir = d, kind = lq.kind, tfLbl = lq.tfLbl, tier = lq.tier, depth = w, domW = w, bornTime = lq.bornTime)
- clusters.push(cur)
- int nCl = clusters.size()
- if nCl > 0
- for c in clusters
- c.key := c.kind + "|" + c.tfLbl + "|" + str.tostring(c.price)
- float dist = math.abs(c.price - close)
- c.distATR := dist / atrC
- float sDepth = 25.0 * (1.0 - math.exp(-c.depth / 4.0))
- float sAlign = 25.0 * (0.45 * f_alignW(nz(h1Bias), c.dir) + 0.35 * f_alignW(nz(h2Bias), c.dir) + 0.20 * f_alignW(nz(h3Bias), c.dir))
- float sFlow = 20.0 * (0.40 * f_alignW(msTrend, c.dir) + 0.30 * f_alignW(deliveryState, c.dir) + 0.30 * f_alignW(driftSign, c.dir))
- float sProx = 15.0 * math.exp(-c.distATR / proxK)
- float sPath = 15.0 / (1.0 + f_obstacles(c, clusters, iGaps, cGaps, close))
- c.conviction := math.min(100.0, math.round(sDepth + sAlign + sFlow + sProx + sPath))
- c.pot := 100.0 * f_pot(dist, mu * c.dir, sigma, potHorizon)
- c.score := 0.55 * c.conviction + 0.45 * c.pot + (c.key == tgtKey ? PERSIST_BONUS : 0.0)
- c.qualified := c.pot >= minProbIn and c.conviction >= minConfIn
- scores.push(c.score)
- activeC := na
- ladder.clear()
- if nCl > 0
- array<int> rankIdx = array.sort_indices(scores, order.descending)
- for k = 0 to rankIdx.size() - 1
- Cluster rc = clusters.get(rankIdx.get(k))
- if rc.qualified
- if na(activeC)
- activeC := rc
- else if ladder.size() < ladderDepth
- ladder.push(rc)
- if not na(activeC)
- if activeC.key != tgtKey
- tgtKey := activeC.key
- tgtSinceBar := bar_index
- tgtSinceTime := time
- newTgtEvt := barstate.isconfirmed
- tgtPrice := activeC.price
- tgtKind := activeC.kind
- else
- tgtKey := ""
- tgtPrice := na
- tgtKind := ""
- bool hasT = not na(activeC)
- string hKind = ""
- string hTf = ""
- float hPx = na
- float hPot = na
- float hConv = na
- float hDistA = na
- float hScore = na
- int hDir = 0
- if hasT
- hKind := activeC.kind
- hTf := activeC.tfLbl
- hPx := activeC.price
- hPot := activeC.pot
- hConv := activeC.conviction
- hDistA := activeC.distATR
- hScore := activeC.score
- hDir := activeC.dir
- if barstate.islast
- for l in dynLines
- line.delete(l)
- dynLines.clear()
- for b in dynBoxes
- box.delete(b)
- dynBoxes.clear()
- for lb in dynLabels
- label.delete(lb)
- dynLabels.clear()
- int barMs = timeframe.in_seconds() * 1000
- int futT = time + projBarsIn * barMs
- int lvlT = time + LEVEL_LABEL_BARS * barMs
- float tol = atrC * BAND_MULT
- if showLiqIn
- int drawn = 0
- for lq in pool
- if drawn >= MAX_LEVEL_DRAW
- break
- bool want = lq.cat == "PD" ? showPdIn : lq.cat == "GAP" ? showGapIn : lq.cat == "FVG" ? showHtfFvgIn : lq.cat == "EQ" ? showEqIn : lq.cat == "SESS" ? (str.startswith(lq.kind, "LON") ? showLonIn : str.startswith(lq.kind, "ASIA") ? showAsiaIn : showNyIn) : false
- float dA = math.abs(lq.price - close) / atrC
- bool clash = hasT and showTargetIn and math.abs(lq.price - nz(hPx)) <= tol
- if want and dA <= maxDistATR * 1.5 and not clash
- drawn += 1
- color lc = lq.cat == "PD" ? colPd : lq.cat == "GAP" ? colGap : lq.cat == "FVG" ? colHtfFvg : lq.cat == "EQ" ? colEq : colSess
- string txt = lq.cat == "FVG" ? "FVG " + lq.tfLbl : lq.cat == "EQ" ? lq.kind + " " + lq.tfLbl : lq.kind
- if lq.cat == "FVG" or lq.cat == "GAP"
- dynBoxes.push(box.new(lq.bornTime, lq.top, lvlT, lq.bot, border_color = color.new(lc, 45), border_width = 1, border_style = line.style_dashed, xloc = xloc.bar_time, bgcolor = color.new(lc, 90), text = txt, text_size = size.tiny, text_color = color.new(lc, 10), text_halign = text.align_right, text_valign = text.align_center))
- else
- string st = lq.cat == "PD" ? line.style_solid : lq.cat == "SESS" ? line.style_dashed : line.style_dotted
- dynLines.push(line.new(lq.bornTime, lq.price, lvlT, lq.price, xloc.bar_time, extend.none, color.new(lc, 25), st, 1))
- dynLabels.push(label.new(lvlT, lq.price, txt, xloc.bar_time, yloc.price, color.new(color.black, 100), label.style_label_left, lc, size.tiny))
- if showIfvgIn and hasT
- int shown = 0
- int nI2 = iGaps.size()
- if nI2 > 0
- for i = nI2 - 1 to 0
- Gap g = iGaps.get(i)
- bool aligned = g.dir == hDir and (g.dir == 1 ? g.bot < close : g.top > close)
- if aligned and shown < MAX_IFVG_DRAW
- shown += 1
- dynBoxes.push(box.new(g.bornTime, g.top, futT, g.bot, border_color = color.new(colIfvg, 25), border_width = 1, xloc = xloc.bar_time, bgcolor = color.new(colIfvg, 86)))
- if showLadderIn and ladder.size() > 0
- for [i, lc2] in ladder
- int leftT = math.max(lc2.bornTime, time - 150 * barMs)
- string ltxt = str.tostring(i + 2) + ". " + lc2.kind + " · " + lc2.tfLbl + " · " + str.tostring(lc2.pot, "0.0") + "%"
- dynBoxes.push(box.new(leftT, lc2.price + tol * 0.5, futT, lc2.price - tol * 0.5, border_color = color.new(colLadder, 40), border_width = 1, border_style = line.style_dotted, xloc = xloc.bar_time, bgcolor = color.new(colLadder, 93), text = ltxt, text_size = size.tiny, text_color = color.new(colLadder, 15), text_halign = text.align_center, text_valign = text.align_center))
- if showAnchorIn and hasT
- Liq anc = na
- float bestD = na
- for lq in pool
- bool okSide = hDir == 1 ? lq.price < close : lq.price > close
- if lq.cat == "FVG" and lq.pol == hDir and okSide
- float dd = math.abs(close - lq.price)
- if na(bestD) or dd < bestD
- bestD := dd
- anc := lq
- if not na(anc)
- int aEnd = time + math.round(projBarsIn * 0.6) * barMs
- dynLines.push(line.new(time - 30 * barMs, anc.price, aEnd, anc.price, xloc.bar_time, extend.none, color.new(colAnchor, 20), line.style_dotted, 1))
- dynLabels.push(label.new(aEnd, anc.price, "+ ANCHOR " + (anc.pol == 1 ? "BFVG" : "SFVG"), xloc.bar_time, yloc.price, colLabelBg, label.style_label_left, colAnchor, size.tiny))
- if showTargetIn and hasT
- int leftT = na(tgtSinceTime) ? time : tgtSinceTime
- int age = na(tgtSinceBar) ? 0 : bar_index - tgtSinceBar
- string bTxt = "1. " + hKind + " · " + str.tostring(age) + " bars"
- dynBoxes.push(box.new(leftT, hPx + tol, futT, hPx - tol, border_color = showBandIn ? color.new(colAccent, 35) : color.new(colAccent, 100), border_width = 1, border_style = line.style_dashed, xloc = xloc.bar_time, bgcolor = showBandIn ? color.new(colAccent, 85) : color.new(colAccent, 100), text = bTxt, text_size = size.tiny, text_color = color.new(colAccent, 25), text_halign = text.align_center, text_valign = text.align_center))
- dynLines.push(line.new(leftT, hPx, futT, hPx, xloc.bar_time, extend.none, color.new(colAccent, 10), line.style_solid, 2))
- if showTrajIn
- dynLines.push(line.new(time, close, futT, hPx, xloc.bar_time, extend.none, color.new(colAccent, 30), line.style_dashed, 1))
- string glyph = age > 0 ? "↻" : "✦"
- string lTxt = "◆ " + f_grade(hScore) + " " + hKind + " " + glyph + "\n" + hTf + " " + str.tostring(hPot, "0.0") + "%"
- dynLabels.push(label.new(futT, hPx, lTxt, xloc.bar_time, yloc.price, colLabelBg, label.style_label_left, colAccent, size.normal, text.align_left))
- var table hud = table.new(f_pos(hudPosIn), 3, 11, bgcolor = colHudBg, frame_color = colHudBorder, frame_width = 1, border_color = colHudBorder, border_width = 1)
- varip bool hudMerged = false
- if barstate.islast and showHudIn
- string sz = f_size(hudSizeIn)
- color hdBg = color.new(colAccent, 93)
- string tgtTxt = hasT ? "◆ " + f_grade(hScore) + " " + hKind : "◇ — NO DOL"
- string pxTxt = hasT ? str.tostring(hPx, format.mintick) : "—"
- string distTxt = hasT ? str.tostring(hDistA, "0.00") + " × " + chartLbl + " ATR " + (hDir == 1 ? "↑" : "↓") : "—"
- string sesTxt = lastSweepDir == 0 ? "—" : (lastSweepDir == -1 ? "▼ DOWN" : "▲ UP") + " → " + lastSweepName
- table.cell(hud, 0, 0, "TRADEAXIS DOL PRO", text_color = colAccent, text_halign = text.align_left, text_size = sz, bgcolor = hdBg, text_formatting = text.format_bold)
- table.cell(hud, 2, 0, styleCode, text_color = colNeutral, text_halign = text.align_right, text_size = sz, bgcolor = hdBg)
- table.cell(hud, 0, 1, tgtTxt, text_color = colAccent, text_halign = text.align_left, text_size = sz)
- table.cell(hud, 2, 1, pxTxt, text_color = colHudValue, text_halign = text.align_right, text_size = sz, text_formatting = text.format_bold)
- table.cell(hud, 0, 2, "PoT " + str.tostring(potHorizon) + "b", text_color = colHudText, text_halign = text.align_left, text_size = sz)
- table.cell(hud, 1, 2, f_bar(nz(hPot), 10), text_color = colAccent, text_halign = text.align_right, text_size = sz)
- table.cell(hud, 2, 2, hasT ? str.tostring(hPot, "0.0") + "%" : "—", text_color = colAccent, text_halign = text.align_right, text_size = sz)
- table.cell(hud, 0, 3, "Conviction", text_color = colHudText, text_halign = text.align_left, text_size = sz)
- table.cell(hud, 1, 3, f_bar(nz(hConv), 10), text_color = colAccent, text_halign = text.align_right, text_size = sz)
- table.cell(hud, 2, 3, hasT ? str.tostring(hConv, "0") : "—", text_color = colAccent, text_halign = text.align_right, text_size = sz)
- table.cell(hud, 0, 4, "Distance", text_color = colHudText, text_halign = text.align_left, text_size = sz)
- table.cell(hud, 1, 4, distTxt, text_color = colAccent, text_halign = text.align_right, text_size = sz)
- table.cell(hud, 0, 5, "Engines", text_color = colHudText, text_halign = text.align_left, text_size = sz)
- table.cell(hud, 1, 5, tf1Lbl + " · " + tf2Lbl + " · " + tf3Lbl, text_color = colHudValue, text_halign = text.align_right, text_size = sz)
- table.cell(hud, 0, 6, "Session", text_color = colHudText, text_halign = text.align_left, text_size = sz)
- table.cell(hud, 1, 6, sesTxt, text_color = lastSweepDir == -1 ? colBear : lastSweepDir == 1 ? colAccent : colNeutral, text_halign = text.align_right, text_size = sz)
- table.cell(hud, 0, 7, "TIMEFRAME BIAS", text_color = colHudText, text_halign = text.align_left, text_size = sz, bgcolor = hdBg)
- table.cell(hud, 0, 8, tf3Lbl, text_color = colHudValue, text_halign = text.align_left, text_size = sz)
- table.cell(hud, 1, 8, "", text_size = sz)
- table.cell(hud, 2, 8, f_biasTxt(nz(h3Bias)), text_color = f_biasCol(nz(h3Bias), colAccent, colBear, colNeutral), text_halign = text.align_right, text_size = sz)
- table.cell(hud, 0, 9, tf2Lbl, text_color = colHudValue, text_halign = text.align_left, text_size = sz)
- table.cell(hud, 1, 9, "", text_size = sz)
- table.cell(hud, 2, 9, f_biasTxt(nz(h2Bias)), text_color = f_biasCol(nz(h2Bias), colAccent, colBear, colNeutral), text_halign = text.align_right, text_size = sz)
- table.cell(hud, 0, 10, tf1Lbl, text_color = colHudValue, text_halign = text.align_left, text_size = sz)
- table.cell(hud, 1, 10, "", text_size = sz)
- table.cell(hud, 2, 10, f_biasTxt(nz(h1Bias)), text_color = f_biasCol(nz(h1Bias), colAccent, colBear, colNeutral), text_halign = text.align_right, text_size = sz)
- if not hudMerged
- table.merge_cells(hud, 0, 0, 1, 0)
- table.merge_cells(hud, 0, 1, 1, 1)
- table.merge_cells(hud, 1, 4, 2, 4)
- table.merge_cells(hud, 1, 5, 2, 5)
- table.merge_cells(hud, 1, 6, 2, 6)
- table.merge_cells(hud, 0, 7, 2, 7)
- hudMerged := true
- if newTgtEvt and hasT
- alert("TradeAxis DOL Pro | New DOL target: " + hKind + " " + hTf + " @ " + str.tostring(hPx, format.mintick) + " | PoT " + str.tostring(hPot, "0.0") + "% | Conviction " + str.tostring(hConv, "0") + " | " + syminfo.ticker, alert.freq_once_per_bar_close)
- if tgtHitEvt
- alert(hitMsg, alert.freq_once_per_bar_close)
- alertcondition(newTgtEvt, "TradeAxis DOL Pro — New DOL Target", "TradeAxis DOL Pro: new Draw on Liquidity target on {{ticker}} ({{interval}})")
- alertcondition(tgtHitEvt, "TradeAxis DOL Pro — DOL Target Reached", "TradeAxis DOL Pro: active DOL target reached on {{ticker}} ({{interval}})")
- alertcondition(bosBullEvt or bosBearEvt, "TradeAxis DOL Pro — BOS", "TradeAxis DOL Pro: validated Break of Structure on {{ticker}} ({{interval}})")
- alertcondition(mssBullEvt or mssBearEvt, "TradeAxis DOL Pro — MSS", "TradeAxis DOL Pro: Market Structure Shift on {{ticker}} ({{interval}})")
- alertcondition(cisdBullEvt or cisdBearEvt, "TradeAxis DOL Pro — CISD", "TradeAxis DOL Pro: Change in State of Delivery on {{ticker}} ({{interval}})")
Advertisement