Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //@version=6
- indicator("AlexTradesNQ Model", shorttitle = "AlexTradesNQ Model", overlay = true, max_lines_count = 500, max_labels_count = 500, max_boxes_count = 500, max_bars_back = 500, dynamic_requests = true)
- const string G_LVL = "Liquidity Levels (EQH / EQL)"
- const string G_FVG = "Fair Value Gaps"
- const string G_FIB = "Leg & Fibonacci"
- const string G_SIG = "Entry Signals"
- const string G_ALT = "Alerts"
- const string TT_LVTF = "Level timeframe slot: on/off toggle, timeframe and color. Disabled slots are not calculated. Timeframes below the chart timeframe are skipped."
- const string TT_RET = "How deep a candle must retrace toward a tracked swing for the test to count, as a percentage of the move away from the swing."
- const string TT_MAXLV = "Maximum number of levels kept above and below price. The oldest levels beyond the cap are removed."
- const string TT_RMBRK = "When enabled, a level is deleted the moment a chart candle closes through it. When disabled, the level stays on the chart dimmed and frozen at the break point."
- const string TT_EXT = "How many bars all drawings extend past the latest candle (levels, FVG boxes, fibonacci lines and open trade lines)."
- const string TT_FVTF = "FVG timeframe slot: on/off toggle, timeframe, bullish color and bearish color. These are also the leg retrace targets of the entry model. Timeframes below the chart timeframe are skipped."
- const string TT_PLOT = "Master toggle for drawing the boxes. Signal logic keeps running with plotting off."
- const string TT_MERGE = "Combines overlapping same-direction gaps into one labeled box. Display only."
- const string TT_RMMIT = "Removes a box once price closes through the far side of the gap; when disabled the box is dimmed and frozen instead."
- const string TT_NEAR = "How many unmitigated gaps stay visible, ranked by distance from the current price. Hidden gaps remain fully tracked."
- const string TT_SHFIB = "Toggles the fibonacci drawings. The leg logic keeps running with drawing off."
- const string TT_LEGLN = "Pivot length that defines a leg on the chart timeframe. Larger values produce fewer, larger legs and confirm swings later."
- const string TT_FILL = "Optional fill between the 0.5 and 1 lines."
- const string TT_AGE = "Maximum age of a gap on the scan timeframes (5m-1m) before it can no longer become an IFVG."
- const string TT_TOUT = "A setup that has not produced an entry within this many chart bars is abandoned."
- bool lvOn1 = input.bool(true, "", inline = "lv1", group = G_LVL)
- string lvTf1 = input.timeframe("15", "", inline = "lv1", group = G_LVL)
- color lvCol1 = input.color(#B2B5BE, "", inline = "lv1", group = G_LVL, tooltip = TT_LVTF)
- bool lvOn2 = input.bool(true, "", inline = "lv2", group = G_LVL)
- string lvTf2 = input.timeframe("30", "", inline = "lv2", group = G_LVL)
- color lvCol2 = input.color(#42A5F5, "", inline = "lv2", group = G_LVL, tooltip = TT_LVTF)
- bool lvOn3 = input.bool(true, "", inline = "lv3", group = G_LVL)
- string lvTf3 = input.timeframe("60", "", inline = "lv3", group = G_LVL)
- color lvCol3 = input.color(#FFA726, "", inline = "lv3", group = G_LVL, tooltip = TT_LVTF)
- bool lvOn4 = input.bool(true, "", inline = "lv4", group = G_LVL)
- string lvTf4 = input.timeframe("240", "", inline = "lv4", group = G_LVL)
- color lvCol4 = input.color(#AB47BC, "", inline = "lv4", group = G_LVL, tooltip = TT_LVTF)
- bool lvOn5 = input.bool(true, "", inline = "lv5", group = G_LVL)
- string lvTf5 = input.timeframe("D", "", inline = "lv5", group = G_LVL)
- color lvCol5 = input.color(#FFEB3B, "", inline = "lv5", group = G_LVL, tooltip = TT_LVTF)
- int lvMinRet = input.int(90, "Min Retracement %", minval = 50, maxval = 99, group = G_LVL, tooltip = TT_RET)
- int lvMax = input.int(8, "Max Levels Per Side", minval = 1, maxval = 25, group = G_LVL, tooltip = TT_MAXLV)
- bool lvRemoveBrk = input.bool(true, "Remove Broken Levels", group = G_LVL, tooltip = TT_RMBRK)
- string lvStyleIn = input.string("Solid", "Line Style / Width", options = ["Solid", "Dashed", "Dotted"], inline = "lvst", group = G_LVL)
- int lvWidth = input.int(1, "", minval = 1, maxval = 4, inline = "lvst", group = G_LVL)
- string lvSizeIn = input.string("Small", "Label Size", options = ["Tiny", "Small", "Normal"], group = G_LVL)
- int extBars = input.int(12, "Extend Right (Bars)", minval = 0, maxval = 500, group = G_LVL, tooltip = TT_EXT)
- bool fvOn1 = input.bool(true, "", inline = "fv1", group = G_FVG)
- string fvTf1 = input.timeframe("5", "", inline = "fv1", group = G_FVG)
- color fvBull1 = input.color(color.new(#9598A1, 85), "", inline = "fv1", group = G_FVG)
- color fvBear1 = input.color(color.new(#9598A1, 85), "", inline = "fv1", group = G_FVG, tooltip = TT_FVTF)
- bool fvOn2 = input.bool(true, "", inline = "fv2", group = G_FVG)
- string fvTf2 = input.timeframe("15", "", inline = "fv2", group = G_FVG)
- color fvBull2 = input.color(color.new(#9598A1, 85), "", inline = "fv2", group = G_FVG)
- color fvBear2 = input.color(color.new(#9598A1, 85), "", inline = "fv2", group = G_FVG, tooltip = TT_FVTF)
- bool fvOn3 = input.bool(true, "", inline = "fv3", group = G_FVG)
- string fvTf3 = input.timeframe("30", "", inline = "fv3", group = G_FVG)
- color fvBull3 = input.color(color.new(#9598A1, 85), "", inline = "fv3", group = G_FVG)
- color fvBear3 = input.color(color.new(#9598A1, 85), "", inline = "fv3", group = G_FVG, tooltip = TT_FVTF)
- bool fvOn4 = input.bool(true, "", inline = "fv4", group = G_FVG)
- string fvTf4 = input.timeframe("60", "", inline = "fv4", group = G_FVG)
- color fvBull4 = input.color(color.new(#9598A1, 85), "", inline = "fv4", group = G_FVG)
- color fvBear4 = input.color(color.new(#9598A1, 85), "", inline = "fv4", group = G_FVG, tooltip = TT_FVTF)
- bool fvgPlot = input.bool(true, "Plot FVGs", group = G_FVG, tooltip = TT_PLOT)
- bool fvgLabelOn = input.bool(true, "Label / Color", inline = "fvl", group = G_FVG)
- color fvgLabelCol = input.color(color.new(#787B86, 20), "", inline = "fvl", group = G_FVG)
- bool fvgMerge = input.bool(true, "Merge Overlapping FVGs", group = G_FVG, tooltip = TT_MERGE)
- bool fvgRemoveMit = input.bool(true, "Remove Mitigated", group = G_FVG, tooltip = TT_RMMIT)
- int fvgNearest = input.int(2, "Show Nearest FVGs", minval = 1, maxval = 25, group = G_FVG, tooltip = TT_NEAR)
- bool showFib = input.bool(true, "Show Fibonacci", group = G_FIB, tooltip = TT_SHFIB)
- int legLen = input.int(10, "Leg Swing Length", minval = 2, maxval = 100, group = G_FIB, tooltip = TT_LEGLN)
- color fibLongCol = input.color(#26A69A, "0.5 Long / Short Colors", inline = "f05", group = G_FIB)
- color fibShortCol = input.color(#F23645, "", inline = "f05", group = G_FIB)
- color fib01Col = input.color(#D1D4DC, "0 / 1 Lines Color", group = G_FIB)
- bool fibFillOn = input.bool(false, "Retrace Zone Fill", inline = "ffill", group = G_FIB)
- color fibFillCol = input.color(color.new(#26A69A, 90), "", inline = "ffill", group = G_FIB, tooltip = TT_FILL)
- int ifvgAge = input.int(60, "IFVG Max Gap Age (Minutes)", minval = 5, maxval = 1440, group = G_SIG, tooltip = TT_AGE)
- int setupTimeout = input.int(500, "Setup Timeout (Bars)", minval = 20, maxval = 5000, group = G_SIG, tooltip = TT_TOUT)
- color sigLongCol = input.color(#26A69A, "Long / Short Colors", inline = "sgc", group = G_SIG)
- color sigShortCol = input.color(#F23645, "", inline = "sgc", group = G_SIG)
- color entryCol = input.color(#2962FF, "Entry / TP / SL Colors", inline = "trc", group = G_SIG)
- color tpCol = input.color(#26A69A, "", inline = "trc", group = G_SIG)
- color slCol = input.color(#F23645, "", inline = "trc", group = G_SIG)
- string sigSizeIn = input.string("Small", "Label Size", options = ["Tiny", "Small", "Normal"], group = G_SIG)
- bool altLong = input.bool(true, "Long Signal", group = G_ALT)
- bool altShort = input.bool(true, "Short Signal", group = G_ALT)
- bool altTP = input.bool(true, "TP Hit", group = G_ALT)
- bool altSL = input.bool(true, "SL Hit", group = G_ALT)
- bool altLvl = input.bool(false, "Liquidity Level Break", group = G_ALT)
- const int FVG_MAX = 25
- const int LEG_TARGET_MAX = 12
- const int MAX_TRADES = 30
- const int V_MAX_BARS = 8
- const int V_MAX_COUNTER = 3
- const int CASCADE_WAIT_MS = 300000
- const int STREAM_MAX = 40
- const int SCAN_GAP_MAX = 30
- color TRANSPARENT = color.new(#000000, 100)
- int chartSec = timeframe.in_seconds(timeframe.period)
- int barMs = chartSec * 1000
- int extMs = extBars * barMs
- string lvLineStyle = lvStyleIn == "Dashed" ? line.style_dashed : lvStyleIn == "Dotted" ? line.style_dotted : line.style_solid
- string lvSize = lvSizeIn == "Tiny" ? size.tiny : lvSizeIn == "Normal" ? size.normal : size.small
- string sigSize = sigSizeIn == "Tiny" ? size.tiny : sigSizeIn == "Normal" ? size.normal : size.small
- var array<int> SWING_LENS = array.from(5, 10, 15)
- type ScanGap
- float top
- float bottom
- bool isBull
- int formTime
- type Stream
- array<float> o
- array<float> h
- array<float> l
- array<float> c
- array<int> t
- array<ScanGap> gaps
- type SwingTrack
- float price = na
- int swTime = na
- float deepest = na
- bool pending = false
- type Level
- float price
- bool isHigh
- int mask
- int touches
- int startTime
- int lastTouch
- bool broken = false
- int breakTime = na
- line ln
- label lb
- type FVG
- float top
- float bottom
- bool isBull
- int slot
- int startTime
- int closeTime
- bool mitigated = false
- int mitTime = na
- type Target
- FVG gap
- bool tapped = false
- type Leg
- int dir
- array<Target> targets
- bool active = false
- float origin = na
- int originBar = na
- int originTime = na
- float ext = na
- int extBar = na
- int startBar = na
- bool tap05 = false
- bool armed = false
- float turn = na
- int turnBar = na
- int counter = 0
- int tapMask = 0
- int candIdx = -1
- int candStart = na
- line l1
- line l0
- line l05
- line diag
- label b1
- label b0
- label b05
- linefill lf
- type Trade
- int dir
- float entry
- float sl
- float tp
- int entryBar
- int entryTime
- string legTfs
- string ifvgTf
- int result = 0
- label sig
- line le
- line lsl
- line ltp
- label bE
- label bSL
- label bTP
- line f1
- line f0
- line f05
- line fdiag
- label fb1
- label fb0
- label fb05
- linefill flf
- f_tfName(string tf) =>
- int sec = timeframe.in_seconds(tf)
- string nm = ""
- if sec < 60
- nm := str.tostring(sec) + "s"
- else if sec < 3600
- nm := str.tostring(math.round(sec / 60.0)) + "m"
- else if sec < 86400
- nm := str.tostring(math.round(sec / 3600.0)) + "H"
- else if sec == 86400
- nm := "D"
- else if sec < 604800
- nm := str.tostring(math.round(sec / 86400.0)) + "D"
- else if sec == 604800
- nm := "W"
- else if sec < 2419200
- nm := str.tostring(math.round(sec / 604800.0)) + "W"
- else
- nm := "M"
- nm
- f_px(float p) =>
- str.tostring(p, format.mintick)
- f_bit(int i) =>
- int(math.pow(2, i))
- f_has(int mask, int i) =>
- math.floor(mask / f_bit(i)) % 2 == 1
- f_set(int mask, int i) =>
- f_has(mask, i) ? mask : mask + f_bit(i)
- f_maskText(int mask, array<string> names, array<int> secs) =>
- array<int> idx = array.new<int>()
- array<int> sv = array.new<int>()
- for i = 0 to names.size() - 1
- if f_has(mask, i)
- idx.push(i)
- sv.push(secs.get(i))
- string txt = ""
- if idx.size() > 0
- array<int> ordIdx = sv.sort_indices(order.ascending)
- for k = 0 to ordIdx.size() - 1
- txt := txt + (k == 0 ? "" : " + ") + names.get(idx.get(ordIdx.get(k)))
- txt
- f_maskTop(int mask, array<int> secs) =>
- int best = -1
- int bestSec = -1
- for i = 0 to secs.size() - 1
- if f_has(mask, i) and secs.get(i) > bestSec
- best := i
- bestSec := secs.get(i)
- math.max(best, 0)
- f_dim(color c) =>
- color.new(c, math.min(100.0, color.t(c) + (100.0 - color.t(c)) * 0.6))
- f_newStream() =>
- Stream.new(array.new<float>(), array.new<float>(), array.new<float>(), array.new<float>(), array.new<int>(), array.new<ScanGap>())
- f_streamPush(Stream s, float pO, float pH, float pL, float pC, int pT) =>
- s.o.push(pO)
- s.h.push(pH)
- s.l.push(pL)
- s.c.push(pC)
- s.t.push(pT)
- if s.o.size() > STREAM_MAX
- s.o.shift()
- s.h.shift()
- s.l.shift()
- s.c.shift()
- s.t.shift()
- true
- f_htf(string tf) =>
- [rO, rH, rL, rC, rT] = request.security(syminfo.tickerid, tf, [open[1], high[1], low[1], close[1], time[1]], lookahead = barmerge.lookahead_on)
- int tfSec = timeframe.in_seconds(tf)
- bool same = tfSec == chartSec
- bool fresh = not na(rT) and (na(rT[1]) or rT != rT[1])
- bool isNew = same ? barstate.isconfirmed : fresh
- [same ? open : rO, same ? high : rH, same ? low : rL, same ? close : rC, same ? time : rT, same ? time_close : rT + tfSec * 1000, isNew]
- array<string> lvlNames = array.from(f_tfName(lvTf1), f_tfName(lvTf2), f_tfName(lvTf3), f_tfName(lvTf4), f_tfName(lvTf5))
- array<int> lvlSecs = array.from(timeframe.in_seconds(lvTf1), timeframe.in_seconds(lvTf2), timeframe.in_seconds(lvTf3), timeframe.in_seconds(lvTf4), timeframe.in_seconds(lvTf5))
- array<color> lvlCols = array.from(lvCol1, lvCol2, lvCol3, lvCol4, lvCol5)
- array<bool> lvlOn = array.from(lvOn1 and lvlSecs.get(0) >= chartSec, lvOn2 and lvlSecs.get(1) >= chartSec, lvOn3 and lvlSecs.get(2) >= chartSec, lvOn4 and lvlSecs.get(3) >= chartSec, lvOn5 and lvlSecs.get(4) >= chartSec)
- array<string> fvgNames = array.from(f_tfName(fvTf1), f_tfName(fvTf2), f_tfName(fvTf3), f_tfName(fvTf4))
- array<int> fvgSecs = array.from(timeframe.in_seconds(fvTf1), timeframe.in_seconds(fvTf2), timeframe.in_seconds(fvTf3), timeframe.in_seconds(fvTf4))
- array<color> fvgBullCols = array.from(fvBull1, fvBull2, fvBull3, fvBull4)
- array<color> fvgBearCols = array.from(fvBear1, fvBear2, fvBear3, fvBear4)
- array<bool> fvgOn = array.from(fvOn1 and fvgSecs.get(0) >= chartSec, fvOn2 and fvgSecs.get(1) >= chartSec, fvOn3 and fvgSecs.get(2) >= chartSec, fvOn4 and fvgSecs.get(3) >= chartSec)
- array<string> scanNames = array.from("5m", "4m", "3m", "2m", "1m")
- array<int> scanSec = array.from(300, 240, 180, 120, 60)
- array<bool> scanOn = array.from(300 >= chartSec, 240 >= chartSec, 180 >= chartSec, 120 >= chartSec, 60 >= chartSec)
- array<bool> ifvgL = array.new<bool>(5, false)
- array<bool> ifvgS = array.new<bool>(5, false)
- array<bool> pushL = array.new<bool>(5, false)
- array<bool> pushS = array.new<bool>(5, false)
- array<string> alertQ = array.new<string>()
- var array<Stream> lvStreams = array.new<Stream>()
- var array<Stream> fvStreams = array.new<Stream>()
- var array<Stream> scanStreams = array.new<Stream>()
- var array<SwingTrack> swHigh = array.new<SwingTrack>()
- var array<SwingTrack> swLow = array.new<SwingTrack>()
- var array<Level> eqhLevels = array.new<Level>()
- var array<Level> eqlLevels = array.new<Level>()
- var array<FVG> fvgAll = array.new<FVG>()
- var array<box> fvgBoxes = array.new<box>()
- var array<Trade> trades = array.new<Trade>()
- var Leg longLeg = Leg.new(dir = 1, targets = array.new<Target>())
- var Leg shortLeg = Leg.new(dir = -1, targets = array.new<Target>())
- if barstate.isfirst
- for i = 0 to 4
- lvStreams.push(f_newStream())
- scanStreams.push(f_newStream())
- for i = 0 to 3
- fvStreams.push(f_newStream())
- for i = 0 to 14
- swHigh.push(SwingTrack.new())
- swLow.push(SwingTrack.new())
- f_levelText(Level lv) =>
- f_maskText(lv.mask, lvlNames, lvlSecs) + (lv.isHigh ? " EQH" : " EQL")
- f_levelDraw(Level lv) =>
- color baseCol = lvlCols.get(f_maskTop(lv.mask, lvlSecs))
- color drawCol = lv.broken ? f_dim(baseCol) : baseCol
- int rightX = lv.broken ? lv.breakTime : time + extMs
- string txt = f_levelText(lv)
- string tip = "Touches: " + str.tostring(lv.touches)
- if na(lv.ln)
- lv.ln := line.new(lv.startTime, lv.price, rightX, lv.price, xloc = xloc.bar_time, color = drawCol, style = lvLineStyle, width = lvWidth)
- lv.lb := label.new(rightX, lv.price, txt, xloc = xloc.bar_time, color = TRANSPARENT, style = label.style_label_left, textcolor = drawCol, size = lvSize, tooltip = tip)
- else
- line.set_x1(lv.ln, lv.startTime)
- line.set_x2(lv.ln, rightX)
- line.set_color(lv.ln, drawCol)
- label.set_x(lv.lb, rightX)
- label.set_text(lv.lb, txt)
- label.set_textcolor(lv.lb, drawCol)
- label.set_tooltip(lv.lb, tip)
- true
- f_levelRemove(Level lv) =>
- line.delete(lv.ln)
- label.delete(lv.lb)
- true
- f_levelCreate(bool isHigh, float price, int slot, int swTime) =>
- array<Level> side = isHigh ? eqhLevels : eqlLevels
- Level found = na
- if side.size() > 0
- for lvItem in side
- if not lvItem.broken and lvItem.price == price
- found := lvItem
- break
- if na(found)
- Level nl = Level.new(price, isHigh, f_bit(slot), 1, swTime, time)
- side.push(nl)
- f_levelDraw(nl)
- if side.size() > lvMax
- f_levelRemove(side.shift())
- else
- if found.lastTouch != time
- found.touches := found.touches + 1
- found.lastTouch := time
- found.mask := f_set(found.mask, slot)
- found.startTime := math.min(found.startTime, swTime)
- f_levelDraw(found)
- true
- f_testSwing(SwingTrack sw, bool isHigh, int slot, float pO, float pH, float pL, float pC) =>
- if not na(sw.price)
- bool broke = isHigh ? pH > sw.price : pL < sw.price
- if broke
- sw.price := na
- sw.pending := false
- else
- bool confirmCandle = isHigh ? pC < pO : pC > pO
- bool oppCandle = isHigh ? pC > pO : pC < pO
- bool created = false
- if sw.pending
- sw.pending := false
- if confirmCandle
- f_levelCreate(isHigh, sw.price, slot, sw.swTime)
- created := true
- if not created
- float move = isHigh ? sw.price - sw.deepest : sw.deepest - sw.price
- float thr = isHigh ? sw.deepest + move * lvMinRet / 100.0 : sw.deepest - move * lvMinRet / 100.0
- bool tested = move > 0 and (isHigh ? pH >= thr : pL <= thr)
- if tested
- if confirmCandle
- f_levelCreate(isHigh, sw.price, slot, sw.swTime)
- created := true
- else if oppCandle
- sw.pending := true
- if created
- sw.deepest := isHigh ? pL : pH
- else
- sw.deepest := isHigh ? math.min(sw.deepest, pL) : math.max(sw.deepest, pH)
- true
- f_swingProcess(int slot, Stream s) =>
- int sz = s.h.size()
- float cO = s.o.get(sz - 1)
- float cH = s.h.get(sz - 1)
- float cL = s.l.get(sz - 1)
- float cC = s.c.get(sz - 1)
- for k = 0 to 2
- int n = SWING_LENS.get(k)
- SwingTrack trH = swHigh.get(slot * 3 + k)
- SwingTrack trL = swLow.get(slot * 3 + k)
- f_testSwing(trH, true, slot, cO, cH, cL, cC)
- f_testSwing(trL, false, slot, cO, cH, cL, cC)
- if sz >= 2 * n + 1
- int p = sz - 1 - n
- float pivH = s.h.get(p)
- float pivL = s.l.get(p)
- bool isPH = true
- bool isPL = true
- for i = sz - 1 - 2 * n to sz - 1
- if i != p
- float hi = s.h.get(i)
- float lo = s.l.get(i)
- if i < p ? hi >= pivH : hi > pivH
- isPH := false
- if i < p ? lo <= pivL : lo < pivL
- isPL := false
- if isPH or isPL
- float minAfter = s.l.get(p + 1)
- float maxAfter = s.h.get(p + 1)
- for j = p + 1 to sz - 1
- minAfter := math.min(minAfter, s.l.get(j))
- maxAfter := math.max(maxAfter, s.h.get(j))
- if isPH
- trH.price := pivH
- trH.swTime := s.t.get(p)
- trH.deepest := minAfter
- trH.pending := false
- if isPL
- trL.price := pivL
- trL.swTime := s.t.get(p)
- trL.deepest := maxAfter
- trL.pending := false
- true
- f_levelSlot(int slot, bool enabled, bool isNew, float pO, float pH, float pL, float pC, int pT) =>
- if enabled and isNew and not na(pC)
- Stream s = lvStreams.get(slot)
- f_streamPush(s, pO, pH, pL, pC, pT)
- f_swingProcess(slot, s)
- true
- f_levelsBreakCheck(array<Level> side) =>
- if side.size() > 0
- for i = side.size() - 1 to 0
- Level lv = side.get(i)
- if not lv.broken and (lv.isHigh ? close > lv.price : close < lv.price)
- if altLvl
- alertQ.push("AlexTradesNQ Model | Liquidity Level Break: " + f_levelText(lv) + " @ " + f_px(lv.price))
- if lvRemoveBrk
- f_levelRemove(lv)
- side.remove(i)
- else
- lv.broken := true
- lv.breakTime := time
- f_levelDraw(lv)
- true
- f_levelsExtend(array<Level> side) =>
- if side.size() > 0
- for lvExt in side
- if not lvExt.broken and not na(lvExt.ln)
- line.set_x2(lvExt.ln, time + extMs)
- label.set_x(lvExt.lb, time + extMs)
- true
- f_legAddTarget(Leg lg, FVG g) =>
- if lg.active and g.isBull == (lg.dir == 1) and not g.mitigated and g.closeTime > lg.originTime
- lg.targets.push(Target.new(g))
- if lg.targets.size() > LEG_TARGET_MAX
- lg.targets.shift()
- true
- f_fvgSlot(int slot, bool enabled, bool isNew, float pO, float pH, float pL, float pC, int pT, int pCT) =>
- if enabled and isNew and not na(pC)
- Stream s = fvStreams.get(slot)
- f_streamPush(s, pO, pH, pL, pC, pT)
- int n = s.h.size()
- if n >= 3
- float h1 = s.h.get(n - 3)
- float l1 = s.l.get(n - 3)
- float h3 = s.h.get(n - 1)
- float l3 = s.l.get(n - 1)
- int t1 = s.t.get(n - 3)
- FVG g = na
- if l3 > h1
- g := FVG.new(l3, h1, true, slot, t1, pCT)
- else if h3 < l1
- g := FVG.new(l1, h3, false, slot, t1, pCT)
- if not na(g)
- fvgAll.push(g)
- if fvgAll.size() > FVG_MAX
- fvgAll.shift()
- f_legAddTarget(longLeg, g)
- f_legAddTarget(shortLeg, g)
- true
- f_fvgMitigation() =>
- if fvgAll.size() > 0
- for i = fvgAll.size() - 1 to 0
- FVG g = fvgAll.get(i)
- if not g.mitigated and ((g.isBull and close < g.bottom) or (not g.isBull and close > g.top))
- g.mitigated := true
- g.mitTime := time
- if g.mitigated and fvgRemoveMit
- fvgAll.remove(i)
- true
- f_scanSlot(int k, bool isNew, float pO, float pH, float pL, float pC, int pT) =>
- int ageMs = ifvgAge * 60000
- Stream s = scanStreams.get(k)
- if scanOn.get(k) and isNew and not na(pC)
- f_streamPush(s, pO, pH, pL, pC, pT)
- if s.gaps.size() > 0
- for i = s.gaps.size() - 1 to 0
- ScanGap sg = s.gaps.get(i)
- if pT - sg.formTime > ageMs
- s.gaps.remove(i)
- else if not sg.isBull and pC > sg.top
- ifvgL.set(k, true)
- s.gaps.remove(i)
- else if sg.isBull and pC < sg.bottom
- ifvgS.set(k, true)
- s.gaps.remove(i)
- int n = s.h.size()
- if n >= 3
- float h1 = s.h.get(n - 3)
- float l1 = s.l.get(n - 3)
- float h3 = s.h.get(n - 1)
- float l3 = s.l.get(n - 1)
- if l3 > h1
- s.gaps.push(ScanGap.new(l3, h1, true, pT))
- else if h3 < l1
- s.gaps.push(ScanGap.new(l1, h3, false, pT))
- if s.gaps.size() > SCAN_GAP_MAX
- s.gaps.shift()
- if scanOn.get(k) and scanSec.get(k) > chartSec and s.gaps.size() > 0
- bool pl = false
- bool ps = false
- for pg in s.gaps
- if time - pg.formTime <= ageMs
- if not pg.isBull and close > pg.top
- pl := true
- if pg.isBull and close < pg.bottom
- ps := true
- pushL.set(k, pl)
- pushS.set(k, ps)
- true
- f_legResetProgress(Leg lg) =>
- lg.tap05 := false
- lg.armed := false
- lg.turn := na
- lg.turnBar := na
- lg.counter := 0
- lg.tapMask := 0
- if lg.targets.size() > 0
- for tgR in lg.targets
- tgR.tapped := false
- true
- f_legKill(Leg lg) =>
- line.delete(lg.l1)
- line.delete(lg.l0)
- line.delete(lg.l05)
- line.delete(lg.diag)
- label.delete(lg.b1)
- label.delete(lg.b0)
- label.delete(lg.b05)
- linefill.delete(lg.lf)
- lg.l1 := na
- lg.l0 := na
- lg.l05 := na
- lg.diag := na
- lg.b1 := na
- lg.b0 := na
- lg.b05 := na
- lg.lf := na
- f_legResetProgress(lg)
- lg.targets.clear()
- lg.active := false
- lg.candIdx := -1
- lg.candStart := na
- true
- f_legStart(Leg lg, float oPx, int oBar, int oTime, float ePx, int eBar) =>
- f_legKill(lg)
- lg.active := true
- lg.origin := oPx
- lg.originBar := oBar
- lg.originTime := oTime
- lg.ext := ePx
- lg.extBar := eBar
- lg.startBar := bar_index
- if fvgAll.size() > 0
- for fg in fvgAll
- f_legAddTarget(lg, fg)
- true
- f_fibDraw(Leg lg, int x2) =>
- if lg.active
- bool isL = lg.dir == 1
- float p1 = lg.origin
- float p0 = lg.ext
- float p5 = (p1 + p0) / 2.0
- color c5 = isL ? fibLongCol : fibShortCol
- if na(lg.l1)
- lg.l1 := line.new(lg.originBar, p1, x2, p1, color = fib01Col, width = 1)
- lg.l0 := line.new(lg.extBar, p0, x2, p0, color = fib01Col, width = 1)
- lg.l05 := line.new(lg.originBar, p5, x2, p5, color = c5, width = 1)
- lg.diag := line.new(lg.originBar, p1, lg.extBar, p0, color = color.new(c5, 40), style = line.style_dotted, width = 1)
- lg.b1 := label.new(x2, p1, "", color = TRANSPARENT, style = label.style_label_left, textcolor = fib01Col, size = size.tiny)
- lg.b0 := label.new(x2, p0, "", color = TRANSPARENT, style = label.style_label_left, textcolor = fib01Col, size = size.tiny)
- lg.b05 := label.new(x2, p5, "", color = c5, style = label.style_label_left, textcolor = color.white, size = size.tiny)
- if fibFillOn
- lg.lf := linefill.new(lg.l05, lg.l1, fibFillCol)
- else
- line.set_xy1(lg.l1, lg.originBar, p1)
- line.set_xy2(lg.l1, x2, p1)
- line.set_xy1(lg.l0, lg.extBar, p0)
- line.set_xy2(lg.l0, x2, p0)
- line.set_xy1(lg.l05, lg.originBar, p5)
- line.set_xy2(lg.l05, x2, p5)
- line.set_xy1(lg.diag, lg.originBar, p1)
- line.set_xy2(lg.diag, lg.extBar, p0)
- label.set_xy(lg.b1, x2, p1)
- label.set_xy(lg.b0, x2, p0)
- label.set_xy(lg.b05, x2, p5)
- label.set_text(lg.b1, "1 (" + f_px(p1) + ")")
- label.set_text(lg.b0, "0 (" + f_px(p0) + ")")
- label.set_text(lg.b05, "0.5 (" + f_px(p5) + ")")
- true
- f_legUpdate(Leg lg) =>
- if lg.active
- bool isL = lg.dir == 1
- bool hasCand = lg.candIdx >= 0
- bool extended = isL ? high > lg.ext : low < lg.ext
- if extended
- lg.ext := isL ? high : low
- lg.extBar := bar_index
- if not hasCand
- f_legResetProgress(lg)
- if lg.targets.size() > 0
- for i = lg.targets.size() - 1 to 0
- if lg.targets.get(i).gap.mitigated
- lg.targets.remove(i)
- if hasCand
- lg.turn := isL ? math.min(nz(lg.turn, low), low) : math.max(nz(lg.turn, high), high)
- else
- float fib05 = (lg.origin + lg.ext) / 2.0
- if not extended
- if isL ? low <= fib05 : high >= fib05
- lg.tap05 := true
- if lg.targets.size() > 0
- for tg in lg.targets
- if isL ? low <= tg.gap.top : high >= tg.gap.bottom
- tg.tapped := true
- int tapM = 0
- if lg.targets.size() > 0
- for tg2 in lg.targets
- if tg2.tapped
- tapM := f_set(tapM, tg2.gap.slot)
- lg.tapMask := tapM
- if lg.armed and tapM == 0
- lg.armed := false
- lg.turn := na
- lg.turnBar := na
- lg.counter := 0
- if not lg.armed
- if lg.tap05 and tapM > 0
- lg.armed := true
- lg.turn := isL ? low : high
- lg.turnBar := bar_index
- lg.counter := 0
- else
- bool newTurn = isL ? low < lg.turn : high > lg.turn
- if newTurn
- lg.turn := isL ? low : high
- lg.turnBar := bar_index
- lg.counter := 0
- else
- if isL ? close < open : close > open
- lg.counter := lg.counter + 1
- if bar_index - lg.turnBar > V_MAX_BARS or lg.counter > V_MAX_COUNTER
- f_legResetProgress(lg)
- true
- f_legCandidate(Leg lg) =>
- bool release = false
- if lg.active
- bool isL = lg.dir == 1
- int best = -1
- for k = 0 to 4
- if best < 0 and scanOn.get(k) and (isL ? ifvgL.get(k) : ifvgS.get(k))
- best := k
- if best >= 0 and ((lg.candIdx < 0 and lg.armed) or (lg.candIdx >= 0 and best < lg.candIdx))
- lg.candIdx := best
- lg.candStart := time
- if lg.candIdx >= 0
- bool hold = false
- if lg.candIdx > 0
- for j = 0 to lg.candIdx - 1
- if scanOn.get(j) and scanSec.get(j) > chartSec and (isL ? pushL.get(j) : pushS.get(j))
- hold := true
- if hold and time - lg.candStart >= CASCADE_WAIT_MS
- hold := false
- release := not hold
- release
- f_legEndCheck(Leg lg) =>
- if lg.active and lg.candIdx < 0
- bool through = lg.dir == 1 ? close < lg.origin : close > lg.origin
- if through or bar_index - lg.startBar > setupTimeout
- f_legKill(lg)
- true
- f_tradeTip(Trade tr) =>
- string res = tr.result == 1 ? "TP Hit" : tr.result == -1 ? "SL Hit" : "Running"
- (tr.dir == 1 ? "Long" : "Short") + "\nLeg FVG: " + tr.legTfs + "\nIFVG: " + tr.ifvgTf + "\nTime: " + str.format_time(tr.entryTime, "yyyy-MM-dd HH:mm", syminfo.timezone) + "\nEntry: " + f_px(tr.entry) + "\nSL: " + f_px(tr.sl) + "\nTP: " + f_px(tr.tp) + "\nResult: " + res
- f_tradeClear(Trade tr) =>
- line.delete(tr.le)
- line.delete(tr.lsl)
- line.delete(tr.ltp)
- label.delete(tr.bE)
- label.delete(tr.bSL)
- label.delete(tr.bTP)
- line.delete(tr.f1)
- line.delete(tr.f0)
- line.delete(tr.f05)
- line.delete(tr.fdiag)
- label.delete(tr.fb1)
- label.delete(tr.fb0)
- label.delete(tr.fb05)
- linefill.delete(tr.flf)
- true
- f_openTrade(Leg lg) =>
- bool isL = lg.dir == 1
- float entryPx = close
- float slPx = isL ? math.min(nz(lg.turn, low), low) : math.max(nz(lg.turn, high), high)
- float risk = math.abs(entryPx - slPx)
- if risk <= 0
- risk := syminfo.mintick
- slPx := isL ? entryPx - risk : entryPx + risk
- float tpPx = isL ? entryPx + risk : entryPx - risk
- string legTxt = lg.tapMask > 0 ? f_maskText(lg.tapMask, fvgNames, fvgSecs) : "-"
- string ifvgTxt = scanNames.get(lg.candIdx)
- Trade tr = Trade.new(dir = lg.dir, entry = entryPx, sl = slPx, tp = tpPx, entryBar = bar_index, entryTime = time, legTfs = legTxt, ifvgTf = ifvgTxt)
- color sigCol = isL ? sigLongCol : sigShortCol
- int x2 = bar_index + extBars
- tr.sig := label.new(bar_index, isL ? low : high, isL ? "L" : "S", yloc = isL ? yloc.belowbar : yloc.abovebar, color = sigCol, style = isL ? label.style_label_up : label.style_label_down, textcolor = color.white, size = sigSize, tooltip = f_tradeTip(tr))
- tr.le := line.new(bar_index, entryPx, x2, entryPx, color = entryCol, width = 1)
- tr.lsl := line.new(bar_index, slPx, x2, slPx, color = slCol, width = 1)
- tr.ltp := line.new(bar_index, tpPx, x2, tpPx, color = tpCol, width = 1)
- tr.bE := label.new(x2, entryPx, "Entry: " + f_px(entryPx), color = TRANSPARENT, style = label.style_label_left, textcolor = entryCol, size = sigSize)
- tr.bSL := label.new(x2, slPx, "SL: " + f_px(slPx), color = TRANSPARENT, style = label.style_label_left, textcolor = slCol, size = sigSize)
- tr.bTP := label.new(x2, tpPx, "TP: " + f_px(tpPx), color = TRANSPARENT, style = label.style_label_left, textcolor = tpCol, size = sigSize)
- if showFib
- f_fibDraw(lg, bar_index)
- tr.f1 := lg.l1
- tr.f0 := lg.l0
- tr.f05 := lg.l05
- tr.fdiag := lg.diag
- tr.fb1 := lg.b1
- tr.fb0 := lg.b0
- tr.fb05 := lg.b05
- tr.flf := lg.lf
- lg.l1 := na
- lg.l0 := na
- lg.l05 := na
- lg.diag := na
- lg.b1 := na
- lg.b0 := na
- lg.b05 := na
- lg.lf := na
- trades.push(tr)
- if trades.size() > MAX_TRADES
- f_tradeClear(trades.shift())
- if isL and altLong
- alertQ.push("AlexTradesNQ Model | Long Signal | Entry: " + f_px(entryPx) + " | SL: " + f_px(slPx) + " | TP: " + f_px(tpPx))
- if not isL and altShort
- alertQ.push("AlexTradesNQ Model | Short Signal | Entry: " + f_px(entryPx) + " | SL: " + f_px(slPx) + " | TP: " + f_px(tpPx))
- f_legKill(lg)
- true
- f_legStep(Leg lg) =>
- f_legUpdate(lg)
- if f_legCandidate(lg)
- f_openTrade(lg)
- f_legEndCheck(lg)
- true
- f_tradesUpdate() =>
- if trades.size() > 0
- for tr in trades
- if tr.result == 0 and bar_index > tr.entryBar
- bool isL = tr.dir == 1
- bool hitSL = isL ? low <= tr.sl : high >= tr.sl
- bool hitTP = isL ? high >= tr.tp : low <= tr.tp
- if hitSL or hitTP
- tr.result := hitSL ? -1 : 1
- f_tradeClear(tr)
- label.set_tooltip(tr.sig, f_tradeTip(tr))
- string side = isL ? "Long" : "Short"
- if hitSL and altSL
- alertQ.push("AlexTradesNQ Model | SL Hit (" + side + ") @ " + f_px(tr.sl))
- if not hitSL and altTP
- alertQ.push("AlexTradesNQ Model | TP Hit (" + side + ") @ " + f_px(tr.tp))
- true
- f_tradesExtend() =>
- if trades.size() > 0
- int x2 = bar_index + extBars
- for trx in trades
- if trx.result == 0
- line.set_x2(trx.le, x2)
- line.set_x2(trx.lsl, x2)
- line.set_x2(trx.ltp, x2)
- label.set_x(trx.bE, x2)
- label.set_x(trx.bSL, x2)
- label.set_x(trx.bTP, x2)
- true
- f_fvgRender() =>
- if fvgBoxes.size() > 0
- for bx in fvgBoxes
- box.delete(bx)
- fvgBoxes.clear()
- if fvgPlot and fvgAll.size() > 0
- int rightX = time + extMs
- if not fvgRemoveMit
- for mg in fvgAll
- if mg.mitigated
- color mc = f_dim(mg.isBull ? fvgBullCols.get(mg.slot) : fvgBearCols.get(mg.slot))
- string mtxt = fvgLabelOn ? fvgNames.get(mg.slot) + " FVG" : ""
- fvgBoxes.push(box.new(mg.startTime, mg.top, mg.mitTime, mg.bottom, border_color = TRANSPARENT, border_width = 1, xloc = xloc.bar_time, bgcolor = mc, text = mtxt, text_size = size.tiny, text_color = f_dim(fvgLabelCol), text_halign = text.align_right, text_valign = text.align_bottom))
- array<float> gTop = array.new<float>()
- array<float> gBot = array.new<float>()
- array<int> gStart = array.new<int>()
- array<int> gMask = array.new<int>()
- array<bool> gBull = array.new<bool>()
- for d = 0 to 1
- bool wantBull = d == 0
- array<float> bots = array.new<float>()
- array<int> ids = array.new<int>()
- for i = 0 to fvgAll.size() - 1
- FVG cg = fvgAll.get(i)
- if not cg.mitigated and cg.isBull == wantBull
- bots.push(cg.bottom)
- ids.push(i)
- if ids.size() > 0
- array<int> ordB = bots.sort_indices(order.ascending)
- float cTop = na
- float cBot = na
- int cStart = na
- int cMask = 0
- for k = 0 to ordB.size() - 1
- FVG sg = fvgAll.get(ids.get(ordB.get(k)))
- if na(cTop) or not fvgMerge or sg.bottom > cTop
- if not na(cTop)
- gTop.push(cTop)
- gBot.push(cBot)
- gStart.push(cStart)
- gMask.push(cMask)
- gBull.push(wantBull)
- cTop := sg.top
- cBot := sg.bottom
- cStart := sg.startTime
- cMask := f_bit(sg.slot)
- else
- cTop := math.max(cTop, sg.top)
- cStart := math.min(cStart, sg.startTime)
- cMask := f_set(cMask, sg.slot)
- gTop.push(cTop)
- gBot.push(cBot)
- gStart.push(cStart)
- gMask.push(cMask)
- gBull.push(wantBull)
- if gTop.size() > 0
- array<float> dist = array.new<float>()
- for i = 0 to gTop.size() - 1
- float zt = gTop.get(i)
- float zb = gBot.get(i)
- dist.push(close > zt ? close - zt : close < zb ? zb - close : 0.0)
- array<int> rank = dist.sort_indices(order.ascending)
- int shown = math.min(fvgNearest, rank.size())
- for k = 0 to shown - 1
- int gi = rank.get(k)
- int topS = f_maskTop(gMask.get(gi), fvgSecs)
- color zc = gBull.get(gi) ? fvgBullCols.get(topS) : fvgBearCols.get(topS)
- string ztxt = fvgLabelOn ? f_maskText(gMask.get(gi), fvgNames, fvgSecs) + " FVG" : ""
- fvgBoxes.push(box.new(gStart.get(gi), gTop.get(gi), rightX, gBot.get(gi), border_color = TRANSPARENT, border_width = 1, xloc = xloc.bar_time, bgcolor = zc, text = ztxt, text_size = size.tiny, text_color = fvgLabelCol, text_halign = text.align_right, text_valign = text.align_bottom))
- true
- [lo1, lh1, ll1, lc1, lt1, lct1, ln1] = f_htf(lvTf1)
- [lo2, lh2, ll2, lc2, lt2, lct2, ln2] = f_htf(lvTf2)
- [lo3, lh3, ll3, lc3, lt3, lct3, ln3] = f_htf(lvTf3)
- [lo4, lh4, ll4, lc4, lt4, lct4, ln4] = f_htf(lvTf4)
- [lo5, lh5, ll5, lc5, lt5, lct5, ln5] = f_htf(lvTf5)
- [fo1, fh1, fl1, fc1, ft1, fct1, fn1] = f_htf(fvTf1)
- [fo2, fh2, fl2, fc2, ft2, fct2, fn2] = f_htf(fvTf2)
- [fo3, fh3, fl3, fc3, ft3, fct3, fn3] = f_htf(fvTf3)
- [fo4, fh4, fl4, fc4, ft4, fct4, fn4] = f_htf(fvTf4)
- [so1, sh1, sl1, sc1, st1, sct1, sn1] = f_htf("5")
- [so2, sh2, sl2, sc2, st2, sct2, sn2] = f_htf("4")
- [so3, sh3, sl3, sc3, st3, sct3, sn3] = f_htf("3")
- [so4, sh4, sl4, sc4, st4, sct4, sn4] = f_htf("2")
- [so5, sh5, sl5, sc5, st5, sct5, sn5] = f_htf("1")
- float legPH = ta.pivothigh(high, legLen, legLen)
- float legPL = ta.pivotlow(low, legLen, legLen)
- float hiAfter = ta.highest(high, legLen)
- int hiAfterOff = ta.highestbars(high, legLen)
- float loAfter = ta.lowest(low, legLen)
- int loAfterOff = ta.lowestbars(low, legLen)
- int legOriginTime = time[legLen]
- f_levelSlot(0, lvlOn.get(0), ln1, lo1, lh1, ll1, lc1, lt1)
- f_levelSlot(1, lvlOn.get(1), ln2, lo2, lh2, ll2, lc2, lt2)
- f_levelSlot(2, lvlOn.get(2), ln3, lo3, lh3, ll3, lc3, lt3)
- f_levelSlot(3, lvlOn.get(3), ln4, lo4, lh4, ll4, lc4, lt4)
- f_levelSlot(4, lvlOn.get(4), ln5, lo5, lh5, ll5, lc5, lt5)
- f_fvgSlot(0, fvgOn.get(0), fn1, fo1, fh1, fl1, fc1, ft1, fct1)
- f_fvgSlot(1, fvgOn.get(1), fn2, fo2, fh2, fl2, fc2, ft2, fct2)
- f_fvgSlot(2, fvgOn.get(2), fn3, fo3, fh3, fl3, fc3, ft3, fct3)
- f_fvgSlot(3, fvgOn.get(3), fn4, fo4, fh4, fl4, fc4, ft4, fct4)
- f_fvgMitigation()
- f_levelsBreakCheck(eqhLevels)
- f_levelsBreakCheck(eqlLevels)
- f_scanSlot(0, sn1, so1, sh1, sl1, sc1, st1)
- f_scanSlot(1, sn2, so2, sh2, sl2, sc2, st2)
- f_scanSlot(2, sn3, so3, sh3, sl3, sc3, st3)
- f_scanSlot(3, sn4, so4, sh4, sl4, sc4, st4)
- f_scanSlot(4, sn5, so5, sh5, sl5, sc5, st5)
- if not na(legPH) and not shortLeg.armed and shortLeg.candIdx < 0
- f_legStart(shortLeg, legPH, bar_index - legLen, legOriginTime, loAfter, bar_index + loAfterOff)
- if not na(legPL) and not longLeg.armed and longLeg.candIdx < 0
- f_legStart(longLeg, legPL, bar_index - legLen, legOriginTime, hiAfter, bar_index + hiAfterOff)
- f_tradesUpdate()
- f_legStep(longLeg)
- f_legStep(shortLeg)
- if barstate.islast
- f_fvgRender()
- f_levelsExtend(eqhLevels)
- f_levelsExtend(eqlLevels)
- if showFib
- f_fibDraw(longLeg, bar_index + extBars)
- f_fibDraw(shortLeg, bar_index + extBars)
- f_tradesExtend()
- if alertQ.size() > 0
- for msg in alertQ
- alert(msg, alert.freq_once_per_bar_close)
Add Comment
Please, Sign In to add comment