Indicator · Pine Script v6 · On the chart

Phantom Flow Futures Screener (Buy Checklist)

by darup67

A price-chart indicator that extends a futures screener with a buy confirmation engine.

View on GitHub

GitHub stars1on the repository
Pine versionv6current
Lines of code470
Settings40inputs
LicenceCustom licencefile: MPL-2.0
Last update7 days ago22 Oct 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

470 lines of Pine Script v6 from pine/Phantom_Flow_Futures_Screener_1.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

Phantom_Flow_Futures_Screener_1.pine
// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © darup67

//@version=6

// =============================================================================
//  PHANTOM FLOW — FUTURES SCREENER (MNQ FOCUS) + BUY CONFIRMATION ENGINE
//  Personal-use companion to Phantom Flow Core (getphantomflow.com).
//
//  THREE PANELS:
//    1. MNQ FOCUS      — Shift + Oscillator across five timeframes, with a
//                        buy-confirmation score per timeframe.
//    2. FUTURES BOARD  — same engine across 30 markets on one scan timeframe.
//    3. BUY CHECKLIST  — which confirmations are passing on the CHART symbol.
//
//  Pine caps every script at 40 request.security() calls: 5 focus timeframes
//  + 30 board slots = 35. The chart-symbol engine runs locally (0 calls).
// =============================================================================
indicator('Phantom Flow Futures Screener', 'PF Futures', overlay = true, max_labels_count = 100)

// -----------------------------------------------------------------------------
// FOCUS PANEL SETTINGS
// -----------------------------------------------------------------------------
G_FOCUS = 'MNQ Focus'
focusSym  = input.symbol('CME_MINI:MNQ1!', 'Focus contract', group = G_FOCUS)
showFocus = input.bool(true, 'Show focus panel', group = G_FOCUS)
fTF1 = input.timeframe('5',   'TF 1', group = G_FOCUS, inline = 'f1')
fTF2 = input.timeframe('15',  'TF 2', group = G_FOCUS, inline = 'f1')
fTF3 = input.timeframe('60',  'TF 3', group = G_FOCUS, inline = 'f2')
fTF4 = input.timeframe('240', 'TF 4', group = G_FOCUS, inline = 'f2')
fTF5 = input.timeframe('D',   'TF 5', group = G_FOCUS, inline = 'f2')
focusAlert = input.bool(true, 'Alert on focus signals', group = G_FOCUS, tooltip = 'Fires when the focus contract prints a Shift, Oscillator or Confluence signal on any of the five timeframes.')
focusPos   = input.string('Top right', 'Focus panel position', options = ['Top right', 'Top left', 'Bottom right', 'Bottom left', 'Middle right'], group = G_FOCUS)

// -----------------------------------------------------------------------------
// BOARD SETTINGS
// -----------------------------------------------------------------------------
G_BOARD = 'Futures Board'
showBoard     = input.bool(true, 'Show futures board', group = G_BOARD)
scanTF        = input.timeframe('D', 'Board scan timeframe', group = G_BOARD)
confirmedOnly = input.bool(true, 'Confirmed bars only (no repaint)', group = G_BOARD, tooltip = 'On = read the last CLOSED bar. Off = read the live forming bar, which can flip mid-session. Applies to all panels.')
rowMode       = input.string('Signals only', 'Rows to show', options = ['Signals only', 'All markets'], group = G_BOARD)
sigMode       = input.string('Any', 'Signal filter', options = ['Any', 'Shift only', 'Oscillator only', 'Confluence only', 'Buy setups only'], group = G_BOARD)
boardPos      = input.string('Bottom right', 'Board position', options = ['Top right', 'Top left', 'Bottom right', 'Bottom left', 'Middle right'], group = G_BOARD)
boardAlert    = input.bool(true, 'Alert on board signals', group = G_BOARD)
tblSizeInput  = input.string('Tiny', 'Text size', options = ['Tiny', 'Small', 'Normal'], group = G_BOARD)

// -----------------------------------------------------------------------------
// BUY CONFIRMATION ENGINE
// -----------------------------------------------------------------------------
G_BUY = 'Buy Confirmations'
minScore   = input.int(3, 'Minimum score to flag a buy', minval = 0, maxval = 5, group = G_BUY, tooltip = 'A Shift or Oscillator buy only counts as a setup once this many of the five confirmations pass.')
trendLen   = input.int(200, 'Regime EMA length', minval = 10, group = G_BUY)
rsiLen     = input.int(14, 'RSI length', minval = 2, group = G_BUY, inline = 'r')
rsiFloor   = input.float(50, 'floor', step = 1, group = G_BUY, inline = 'r')
volLen     = input.int(20, 'Volume MA length', minval = 2, group = G_BUY, inline = 'v')
volMult    = input.float(1.2, 'multiple', step = 0.1, group = G_BUY, inline = 'v')
adxLen     = input.int(14, 'ADX length', minval = 2, group = G_BUY, inline = 'a')
adxMin     = input.float(20, 'minimum', step = 1, group = G_BUY, inline = 'a')
maxAge     = input.int(5, 'Freshness — max bars since flip', minval = 1, group = G_BUY, tooltip = 'Keeps you from grading a trend that is already 40 bars old as a fresh entry.')
rrMult     = input.float(2.0, 'Target R multiple', step = 0.5, minval = 0.5, group = G_BUY, tooltip = 'Target = entry + this multiple of (entry − Shift stop).')

G_CHART = 'Chart Symbol Signals'
showChartSignals = input.bool(true, 'Plot buy markers on chart', group = G_CHART)
showChecklist    = input.bool(true, 'Show buy checklist panel', group = G_CHART)
showStopLine     = input.bool(true, 'Plot Shift stop line', group = G_CHART)
checklistPos     = input.string('Middle right', 'Checklist position', options = ['Top right', 'Top left', 'Bottom right', 'Bottom left', 'Middle right'], group = G_CHART)

// -----------------------------------------------------------------------------
// SIGNAL ENGINE SETTINGS (mirror Phantom Flow Core defaults)
// -----------------------------------------------------------------------------
G_SHIFT = 'Phantom Shift'
shiftATR     = input.int(10, 'ATR period', minval = 1, group = G_SHIFT)
shiftMult    = input.float(3.0, 'Multiplier', step = 0.1, group = G_SHIFT)
shiftBuiltIn = input.bool(true, 'Use built-in ATR', group = G_SHIFT)

G_OSC = 'Phantom Oscillator'
oscType     = input.string('SMA', 'MA type', options = ['SMA', 'EMA', 'SMMA (RMA)', 'WMA', 'VWMA'], group = G_OSC)
oscLength   = input.int(40, 'MA length', minval = 1, group = G_OSC)
oscLen      = input.int(15, 'Oscillator length', minval = 1, group = G_OSC)
oscThresh   = input.float(0.5, 'Threshold', step = 0.1, group = G_OSC)
oscLookback = input.int(500, 'Normalisation lookback', minval = 100, maxval = 1000, group = G_OSC, tooltip = 'Core uses 1000. Lower = faster scan across 35 requests, slightly different scaling.')

// -----------------------------------------------------------------------------
// FUTURES UNIVERSE — blank a slot to disable it
// -----------------------------------------------------------------------------
G_B1 = 'Board: Equity Index & Volatility'
b01 = input.symbol('CME_MINI:ES1!',      'Slot 01', group = G_B1)
b02 = input.symbol('CME_MINI:NQ1!',      'Slot 02', group = G_B1)
b03 = input.symbol('CME_MINI:RTY1!',     'Slot 03', group = G_B1)
b04 = input.symbol('CBOT_MINI:YM1!',     'Slot 04', group = G_B1)
b05 = input.symbol('CME:NKD1!',          'Slot 05', group = G_B1)
b06 = input.symbol('CBOE_FUTURES:VX1!',  'Slot 06', group = G_B1)

G_B2 = 'Board: Metals'
b07 = input.symbol('COMEX:GC1!', 'Slot 07', group = G_B2)
b08 = input.symbol('COMEX:SI1!', 'Slot 08', group = G_B2)
b09 = input.symbol('COMEX:HG1!', 'Slot 09', group = G_B2)
b10 = input.symbol('NYMEX:PL1!', 'Slot 10', group = G_B2)

G_B3 = 'Board: Energy'
b11 = input.symbol('NYMEX:CL1!',    'Slot 11', group = G_B3)
b12 = input.symbol('NYMEX:NG1!',    'Slot 12', group = G_B3)
b13 = input.symbol('NYMEX:RB1!',    'Slot 13', group = G_B3)
b14 = input.symbol('NYMEX:HO1!',    'Slot 14', group = G_B3)
b15 = input.symbol('ICEEUR:BRN1!',  'Slot 15', group = G_B3)

G_B4 = 'Board: Rates'
b16 = input.symbol('CBOT:ZT1!', 'Slot 16', group = G_B4)
b17 = input.symbol('CBOT:ZF1!', 'Slot 17', group = G_B4)
b18 = input.symbol('CBOT:ZN1!', 'Slot 18', group = G_B4)
b19 = input.symbol('CBOT:ZB1!', 'Slot 19', group = G_B4)
b20 = input.symbol('CBOT:UB1!', 'Slot 20', group = G_B4)

G_B5 = 'Board: FX'
b21 = input.symbol('CME:6E1!', 'Slot 21', group = G_B5)
b22 = input.symbol('CME:6J1!', 'Slot 22', group = G_B5)
b23 = input.symbol('CME:6B1!', 'Slot 23', group = G_B5)
b24 = input.symbol('CME:6A1!', 'Slot 24', group = G_B5)
b25 = input.symbol('CME:6C1!', 'Slot 25', group = G_B5)
b26 = input.symbol('CME:6S1!', 'Slot 26', group = G_B5)

G_B6 = 'Board: Ags & Crypto'
b27 = input.symbol('CBOT:ZC1!', 'Slot 27', group = G_B6)
b28 = input.symbol('CBOT:ZS1!', 'Slot 28', group = G_B6)
b29 = input.symbol('CBOT:ZW1!', 'Slot 29', group = G_B6)
b30 = input.symbol('CME:BTC1!', 'Slot 30', group = G_B6)

// -----------------------------------------------------------------------------
// SIGNAL ENGINE — evaluated in the requested symbol/timeframe context.
// -----------------------------------------------------------------------------
getMA(float src, int len, string maType) =>
    switch maType
        'SMA'        => ta.sma(src, len)
        'EMA'        => ta.ema(src, len)
        'SMMA (RMA)' => ta.rma(src, len)
        'WMA'        => ta.wma(src, len)
        'VWMA'       => ta.vwma(src, len)
        =>              ta.sma(src, len)

pfSignals() =>
    // --- Phantom Shift ---
    float atrS = shiftBuiltIn ? ta.atr(shiftATR) : ta.sma(ta.tr, shiftATR)
    float src  = hl2

    float up  = src - shiftMult * atrS
    float upP = nz(up[1], up)
    up := close[1] > upP ? math.max(up, upP) : up

    float dn  = src + shiftMult * atrS
    float dnP = nz(dn[1], dn)
    dn := close[1] < dnP ? math.min(dn, dnP) : dn

    var int dir = 1
    dir := dir == -1 and close > dnP ? 1 : dir == 1 and close < upP ? -1 : dir

    bool sBuy  = dir ==  1 and dir[1] == -1
    bool sSell = dir == -1 and dir[1] ==  1

    // --- Phantom Oscillator ---
    float maBase = getMA(hl2, oscLength, oscType)
    float diff   = hl2 - maBase
    float rng    = ta.percentile_linear_interpolation(diff, oscLookback, 99)
    float osc    = ta.hma(ta.change(diff / rng, oscLen), 10)

    bool oBuy  = ta.crossover(osc, osc[2])  and osc < -oscThresh
    bool oSell = ta.crossunder(osc, osc[2]) and osc >  oscThresh

    // --- Context ---
    float trailLine = dir == 1 ? up : dn
    int   barsHeld  = nz(ta.barssince(dir != dir[1]), bar_index)

    // --- Buy confirmations ---
    float regimeMA = ta.ema(close, trendLen)
    float rsiVal   = ta.rsi(close, rsiLen)
    float volMA    = ta.sma(volume, volLen)
    [diPlus, diMinus, adxVal] = ta.dmi(adxLen, adxLen)

    bool cRegime = close > regimeMA
    bool cMomo   = rsiVal > rsiFloor and rsiVal > rsiVal[1]
    bool cVol    = na(volume) or volume == 0 ? false : volume > volMA * volMult
    bool cAdx    = adxVal > adxMin and diPlus > diMinus
    bool cFresh  = dir == 1 and barsHeld <= maxAge

    int score = (cRegime ? 1 : 0) + (cMomo ? 1 : 0) + (cVol ? 1 : 0) + (cAdx ? 1 : 0) + (cFresh ? 1 : 0)
    int flags = (cRegime ? 1 : 0) + (cMomo ? 2 : 0) + (cVol ? 4 : 0) + (cAdx ? 8 : 0) + (cFresh ? 16 : 0)

    int b = confirmedOnly ? 1 : 0
    float chg = nz((close[b] / close[b + 1] - 1) * 100)

    [sBuy[b], sSell[b], oBuy[b], oSell[b], dir[b], close[b], chg, osc[b], trailLine[b], barsHeld[b], score[b], flags[b], rsiVal[b]]

// -----------------------------------------------------------------------------
// RESULT BUFFERS (rebuilt every bar)
// -----------------------------------------------------------------------------
array<string> fLbl  = array.new<string>()
array<bool>   fSB   = array.new<bool>()
array<bool>   fSS   = array.new<bool>()
array<bool>   fOB   = array.new<bool>()
array<bool>   fOS   = array.new<bool>()
array<int>    fDir  = array.new<int>()
array<float>  fPx   = array.new<float>()
array<float>  fOsc  = array.new<float>()
array<float>  fLine = array.new<float>()
array<int>    fBars = array.new<int>()
array<int>    fScr  = array.new<int>()

array<string> rSym  = array.new<string>()
array<bool>   rSB   = array.new<bool>()
array<bool>   rSS   = array.new<bool>()
array<bool>   rOB   = array.new<bool>()
array<bool>   rOS   = array.new<bool>()
array<int>    rDir  = array.new<int>()
array<float>  rPx   = array.new<float>()
array<float>  rChg  = array.new<float>()
array<int>    rScr  = array.new<int>()
array<float>  rLine = array.new<float>()

// One request.security call site per request — each keeps its own state.
focusRow(string sym, string tf) =>
    [sb, ss, ob, os, dir, px, chg, osc, ln, bars, scr, flg, rsi] = request.security(sym, tf, pfSignals(), gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_off)
    if showFocus and not na(px)
        fLbl.push(tf == 'D' ? '1D' : tf == 'W' ? '1W' : tf)
        fSB.push(sb), fSS.push(ss), fOB.push(ob), fOS.push(os)
        fDir.push(dir), fPx.push(px), fOsc.push(osc), fLine.push(ln), fBars.push(bars), fScr.push(scr)

boardRow(string sym) =>
    bool enabled = str.length(sym) > 0
    [sb, ss, ob, os, dir, px, chg, osc, ln, bars, scr, flg, rsi] = request.security(enabled ? sym : syminfo.tickerid, scanTF, pfSignals(), gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_off)
    if showBoard and enabled and not na(px)
        rSym.push(sym)
        rSB.push(sb), rSS.push(ss), rOB.push(ob), rOS.push(os)
        rDir.push(dir), rPx.push(px), rChg.push(chg), rScr.push(scr), rLine.push(ln)

focusRow(focusSym, fTF1)
focusRow(focusSym, fTF2)
focusRow(focusSym, fTF3)
focusRow(focusSym, fTF4)
focusRow(focusSym, fTF5)

boardRow(b01), boardRow(b02), boardRow(b03), boardRow(b04), boardRow(b05), boardRow(b06)
boardRow(b07), boardRow(b08), boardRow(b09), boardRow(b10)
boardRow(b11), boardRow(b12), boardRow(b13), boardRow(b14), boardRow(b15)
boardRow(b16), boardRow(b17), boardRow(b18), boardRow(b19), boardRow(b20)
boardRow(b21), boardRow(b22), boardRow(b23), boardRow(b24), boardRow(b25), boardRow(b26)
boardRow(b27), boardRow(b28), boardRow(b29), boardRow(b30)

// Chart symbol — local call, costs zero request.security slots.
[cSB, cSS, cOB, cOS, cDir, cPx, cChg, cOsc, cLine, cBars, cScore, cFlags, cRSI] = pfSignals()

// -----------------------------------------------------------------------------
// PRESENTATION HELPERS
// -----------------------------------------------------------------------------
UP_COL   = #089981
DOWN_COL = #F23645
OSC_UP   = #1dd1c2
OSC_DN   = color.orange
HEAD_BG  = color.new(color.gray, 80)

cleanName(string s) =>
    int p = str.pos(s, ':')
    na(p) ? s : str.substring(s, p + 1)

// Pine has no bitwise operators — decode the flag mask arithmetically.
hasFlag(int f, int bit) =>
    math.floor(f / bit) % 2 == 1

gradeOf(int s) =>
    s >= 5 ? 'A+' : s == 4 ? 'A' : s == 3 ? 'B' : s == 2 ? 'C' : 'D'

gradeCol(int s) =>
    s >= 4 ? UP_COL : s == 3 ? OSC_UP : s == 2 ? color.gray : color.new(color.gray, 40)

isBuySetup(bool sb, bool ob, int scr) =>
    (sb or ob) and scr >= minScore

passesFilter(bool sb, bool ss, bool ob, bool os, int scr) =>
    switch sigMode
        'Shift only'       => sb or ss
        'Oscillator only'  => ob or os
        'Confluence only'  => (sb and ob) or (ss and os)
        'Buy setups only'  => isBuySetup(sb, ob, scr)
        =>                    sb or ss or ob or os

signalText(bool sb, bool ss, bool ob, bool os) =>
    sb and ob ? '★ BUY' : ss and os ? '★ SELL' : sb ? 'Buy' : ss ? 'Sell' : ob ? '◆ Buy' : os ? '◆ Sell' : '—'

signalColor(bool sb, bool ss, bool ob, bool os) =>
    sb and ob ? UP_COL : ss and os ? DOWN_COL : sb ? UP_COL : ss ? DOWN_COL : ob ? OSC_UP : os ? OSC_DN : color.gray

posFrom(string s) =>
    switch s
        'Top right'    => position.top_right
        'Top left'     => position.top_left
        'Bottom right' => position.bottom_right
        'Bottom left'  => position.bottom_left
        =>                position.middle_right

txtSize() =>
    switch tblSizeInput
        'Tiny'   => size.tiny
        'Normal' => size.normal
        =>          size.small

// -----------------------------------------------------------------------------
// CHART SYMBOL — BUY MARKERS, STOP AND TARGET
// -----------------------------------------------------------------------------
bool chartBuy  = showChartSignals and isBuySetup(cSB, cOB, cScore)
bool chartSell = showChartSignals and (cSS or cOS)

float cRisk   = cDir == 1 ? cPx - cLine : na
float cTarget = cDir == 1 ? cPx + rrMult * cRisk : na

plotshape(chartBuy,  'Buy setup',  shape.triangleup,   location.belowbar, UP_COL,   text = 'BUY',  textcolor = UP_COL,   size = size.small)
plotshape(chartSell, 'Sell signal', shape.triangledown, location.abovebar, DOWN_COL, text = 'SELL', textcolor = DOWN_COL, size = size.tiny)

plot(showStopLine ? cLine : na, 'Shift stop', color = cDir == 1 ? UP_COL : DOWN_COL, style = plot.style_linebr, linewidth = 1)

if chartBuy
    label.new(bar_index, low, gradeOf(cScore) + '  ' + str.tostring(cScore) + '/5\nStop ' + str.tostring(cLine, format.mintick) + '\nTgt ' + str.tostring(cTarget, format.mintick), style = label.style_label_up, color = color.new(UP_COL, 82), textcolor = UP_COL, size = size.tiny)

// -----------------------------------------------------------------------------
// PANEL 3 — BUY CHECKLIST (chart symbol)
// -----------------------------------------------------------------------------
var table checkTable = table.new(posFrom(checklistPos), 2, 9, border_width = 1, frame_width = 1, frame_color = color.new(color.gray, 60))

checkCell(int r, string name, bool ok) =>
    table.cell(checkTable, 0, r, name, text_color = color.new(color.white, 20), text_size = txtSize(), text_halign = text.align_left)
    table.cell(checkTable, 1, r, ok ? '✓' : '·', text_color = ok ? UP_COL : color.new(color.gray, 30), text_size = txtSize())

if barstate.islast and showChecklist
    table.clear(checkTable, 0, 0, 1, 8)

    table.cell(checkTable, 0, 0, cleanName(syminfo.tickerid) + ' buy', bgcolor = HEAD_BG, text_color = color.new(color.white, 0), text_size = txtSize())
    table.cell(checkTable, 1, 0, gradeOf(cScore) + ' ' + str.tostring(cScore) + '/5', bgcolor = color.new(gradeCol(cScore), 75), text_color = gradeCol(cScore), text_size = txtSize())

    checkCell(1, 'Regime (EMA' + str.tostring(trendLen) + ')', hasFlag(cFlags, 1))
    checkCell(2, 'Momentum (RSI)',                             hasFlag(cFlags, 2))
    checkCell(3, 'Volume',                                     hasFlag(cFlags, 4))
    checkCell(4, 'Trend strength (ADX)',                       hasFlag(cFlags, 8))
    checkCell(5, 'Fresh flip',                                 hasFlag(cFlags, 16))

    table.cell(checkTable, 0, 6, 'Entry', text_color = color.new(color.white, 20), text_size = txtSize(), text_halign = text.align_left)
    table.cell(checkTable, 1, 6, str.tostring(cPx, format.mintick), text_color = color.new(color.white, 10), text_size = txtSize())
    table.cell(checkTable, 0, 7, 'Stop', text_color = color.new(color.white, 20), text_size = txtSize(), text_halign = text.align_left)
    table.cell(checkTable, 1, 7, str.tostring(cLine, format.mintick), text_color = DOWN_COL, text_size = txtSize())
    table.cell(checkTable, 0, 8, 'Target ' + str.tostring(rrMult, '#.#') + 'R', text_color = color.new(color.white, 20), text_size = txtSize(), text_halign = text.align_left)
    table.cell(checkTable, 1, 8, cDir == 1 ? str.tostring(cTarget, format.mintick) : '—', text_color = UP_COL, text_size = txtSize())

// -----------------------------------------------------------------------------
// PANEL 1 — FOCUS CONTRACT, MULTI-TIMEFRAME
// -----------------------------------------------------------------------------
var table focusTable = table.new(posFrom(focusPos), 7, 8, border_width = 1, frame_width = 1, frame_color = color.new(color.gray, 60))

if barstate.islast and showFocus
    table.clear(focusTable, 0, 0, 6, 7)

    table.cell(focusTable, 0, 0, cleanName(focusSym), bgcolor = HEAD_BG, text_color = color.new(color.white, 0), text_size = txtSize())
    table.cell(focusTable, 1, 0, 'Last',   bgcolor = HEAD_BG, text_color = color.new(color.white, 10), text_size = txtSize())
    table.cell(focusTable, 2, 0, 'Trend',  bgcolor = HEAD_BG, text_color = color.new(color.white, 10), text_size = txtSize())
    table.cell(focusTable, 3, 0, 'Stop',   bgcolor = HEAD_BG, text_color = color.new(color.white, 10), text_size = txtSize())
    table.cell(focusTable, 4, 0, 'Osc',    bgcolor = HEAD_BG, text_color = color.new(color.white, 10), text_size = txtSize())
    table.cell(focusTable, 5, 0, 'Score',  bgcolor = HEAD_BG, text_color = color.new(color.white, 10), text_size = txtSize())
    table.cell(focusTable, 6, 0, 'Signal', bgcolor = HEAD_BG, text_color = color.new(color.white, 10), text_size = txtSize())

    int  ups = 0
    int  n   = fLbl.size()
    string fMsg = ''

    if n > 0
        for i = 0 to n - 1
            string lbl = fLbl.get(i)
            bool   sb  = fSB.get(i)
            bool   ss  = fSS.get(i)
            bool   ob  = fOB.get(i)
            bool   os  = fOS.get(i)
            int    dir = fDir.get(i)
            float  px  = fPx.get(i)
            float  osv = fOsc.get(i)
            float  ln  = fLine.get(i)
            int    bh  = fBars.get(i)
            int    scr = fScr.get(i)

            ups := ups + (dir == 1 ? 1 : 0)
            color sigCol = signalColor(sb, ss, ob, os)
            bool  hit    = sb or ss or ob or os
            bool  buySet = isBuySetup(sb, ob, scr)

            table.cell(focusTable, 0, i + 1, lbl, text_color = color.new(color.white, 10), text_size = txtSize())
            table.cell(focusTable, 1, i + 1, str.tostring(px, format.mintick), text_color = color.new(color.white, 20), text_size = txtSize())
            table.cell(focusTable, 2, i + 1, (dir == 1 ? 'Up ' : 'Dn ') + str.tostring(bh), text_color = dir == 1 ? UP_COL : DOWN_COL, text_size = txtSize(), tooltip = 'Bars held in the current trend')
            table.cell(focusTable, 3, i + 1, str.tostring(ln, format.mintick), text_color = color.new(color.gray, 10), text_size = txtSize(), tooltip = 'Phantom Shift trail level — the flip point / stop')
            table.cell(focusTable, 4, i + 1, str.tostring(osv, '#.##'), text_color = osv > 0 ? OSC_UP : OSC_DN, text_size = txtSize())
            table.cell(focusTable, 5, i + 1, gradeOf(scr) + ' ' + str.tostring(scr), text_color = gradeCol(scr), bgcolor = buySet ? color.new(UP_COL, 80) : na, text_size = txtSize(), tooltip = 'Buy confirmations passing, out of 5')
            table.cell(focusTable, 6, i + 1, signalText(sb, ss, ob, os), text_color = sigCol, bgcolor = hit ? color.new(sigCol, 80) : na, text_size = txtSize())

            if hit
                fMsg := fMsg + (str.length(fMsg) > 0 ? '\n' : '') + lbl + ' ' + signalText(sb, ss, ob, os) + ' [' + gradeOf(scr) + ' ' + str.tostring(scr) + '/5] @ ' + str.tostring(px, format.mintick) + ' stop ' + str.tostring(ln, format.mintick)

        // Alignment summary row
        string alignTxt = str.tostring(ups) + '/' + str.tostring(n) + (ups == n ? ' ALL LONG' : ups == 0 ? ' ALL SHORT' : ' mixed')
        color  alignCol = ups == n ? UP_COL : ups == 0 ? DOWN_COL : color.gray
        table.cell(focusTable, 0, n + 1, 'Align', bgcolor = HEAD_BG, text_color = color.new(color.white, 10), text_size = txtSize())
        table.cell(focusTable, 1, n + 1, alignTxt, bgcolor = color.new(alignCol, 80), text_color = alignCol, text_size = txtSize())
        table.cell(focusTable, 2, n + 1, '', bgcolor = HEAD_BG)
        table.cell(focusTable, 3, n + 1, '', bgcolor = HEAD_BG)
        table.cell(focusTable, 4, n + 1, '', bgcolor = HEAD_BG)
        table.cell(focusTable, 5, n + 1, '', bgcolor = HEAD_BG)
        table.cell(focusTable, 6, n + 1, '', bgcolor = HEAD_BG)

    if focusAlert and str.length(fMsg) > 0
        alert(cleanName(focusSym) + ' — Phantom Flow\n' + fMsg, alert.freq_once_per_bar_close)

// -----------------------------------------------------------------------------
// PANEL 2 — FUTURES BOARD
// -----------------------------------------------------------------------------
var table boardTable = table.new(posFrom(boardPos), 6, 32, border_width = 1, frame_width = 1, frame_color = color.new(color.gray, 60))

if barstate.islast and showBoard
    table.clear(boardTable, 0, 0, 5, 31)

    string headTF = scanTF == '' ? timeframe.period : scanTF
    table.cell(boardTable, 0, 0, 'Futures — ' + headTF, bgcolor = HEAD_BG, text_color = color.new(color.white, 0), text_size = txtSize())
    table.cell(boardTable, 1, 0, 'Last',   bgcolor = HEAD_BG, text_color = color.new(color.white, 10), text_size = txtSize())
    table.cell(boardTable, 2, 0, 'Chg %',  bgcolor = HEAD_BG, text_color = color.new(color.white, 10), text_size = txtSize())
    table.cell(boardTable, 3, 0, 'Trend',  bgcolor = HEAD_BG, text_color = color.new(color.white, 10), text_size = txtSize())
    table.cell(boardTable, 4, 0, 'Score',  bgcolor = HEAD_BG, text_color = color.new(color.white, 10), text_size = txtSize())
    table.cell(boardTable, 5, 0, 'Signal', bgcolor = HEAD_BG, text_color = color.new(color.white, 10), text_size = txtSize())

    int row = 0
    string bMsg = ''

    // Render highest-scoring buy setups first, then everything else.
    for pass = 0 to 1
        if rSym.size() > 0
            for i = 0 to rSym.size() - 1
                string sym = rSym.get(i)
                bool   sb  = rSB.get(i)
                bool   ss  = rSS.get(i)
                bool   ob  = rOB.get(i)
                bool   os  = rOS.get(i)
                int    dir = rDir.get(i)
                float  px  = rPx.get(i)
                float  chg = rChg.get(i)
                int    scr = rScr.get(i)
                float  ln  = rLine.get(i)

                bool buySet = isBuySetup(sb, ob, scr)
                bool hit    = passesFilter(sb, ss, ob, os, scr)
                bool show   = rowMode == 'All markets' or hit
                bool inPass = pass == 0 ? buySet : not buySet

                if show and inPass and row < 31
                    row += 1
                    color sigCol = signalColor(sb, ss, ob, os)
                    table.cell(boardTable, 0, row, cleanName(sym), text_color = color.new(color.white, 10), text_size = txtSize(), text_halign = text.align_left)
                    table.cell(boardTable, 1, row, str.tostring(px, format.mintick), text_color = color.new(color.white, 20), text_size = txtSize())
                    table.cell(boardTable, 2, row, str.tostring(chg, '#.##') + '%', text_color = chg >= 0 ? UP_COL : DOWN_COL, text_size = txtSize())
                    table.cell(boardTable, 3, row, dir == 1 ? 'Up' : 'Down', text_color = dir == 1 ? UP_COL : DOWN_COL, text_size = txtSize())
                    table.cell(boardTable, 4, row, gradeOf(scr) + ' ' + str.tostring(scr), text_color = gradeCol(scr), bgcolor = buySet ? color.new(UP_COL, 80) : na, text_size = txtSize())
                    table.cell(boardTable, 5, row, signalText(sb, ss, ob, os), text_color = sigCol, bgcolor = hit ? color.new(sigCol, 85) : na, text_size = txtSize())

                if hit and pass == 0 and buySet
                    bMsg := bMsg + (str.length(bMsg) > 0 ? '\n' : '') + cleanName(sym) + ': ' + signalText(sb, ss, ob, os) + ' [' + gradeOf(scr) + ' ' + str.tostring(scr) + '/5] @ ' + str.tostring(px, format.mintick) + ' stop ' + str.tostring(ln, format.mintick)

    if row == 0
        table.cell(boardTable, 0, 1, 'No signals', text_color = color.gray, text_size = txtSize())

    if boardAlert and str.length(bMsg) > 0
        alert('Futures board ' + headTF + ' — buy setups\n' + bMsg, alert.freq_once_per_bar_close)

Overview

A focus panel scores one contract across five timeframes, a board scans a list of futures markets on one timeframe, and a checklist panel shows which confirmations pass on the chart symbol. Confirmations cover a minimum score, a long EMA regime, RSI floor, volume multiple, ADX minimum and signal freshness. It can plot buy markers and a stop line, and shows a target based on an R multiple.

Details

Published by

darup67 on GitHub

Type

Indicator, Pine Script v6

Draws

On the price chart

Category

Screeners & dashboards, Trend, Oscillators & momentum

Markets

Indices, Oil & commodities

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Focus contractsymbolCME_MINI:MNQ1!focusSym
Show focus panelbooltrueshowFocus
TF 1timeframe5fTF1
TF 2timeframe15fTF2
TF 3timeframe60fTF3
TF 4timeframe240fTF4
TF 5timeframeDfTF5
Alert on focus signalsbooltruefocusAlert
Focus panel positionstringTop rightfocusPos
Show futures boardbooltrueshowBoard
Board scan timeframetimeframeDscanTF
Confirmed bars only (no repaint)booltrueconfirmedOnly
Show all 40 settings
SettingTypeDefaultVariable
Rows to showstringSignals onlyrowMode
Signal filterstringAnysigMode
Board positionstringBottom rightboardPos
Alert on board signalsbooltrueboardAlert
Text sizestringTinytblSizeInput
Minimum score to flag a buyint3minScore
Regime EMA lengthint200trendLen
RSI lengthint14rsiLen
floorfloat50rsiFloor
Volume MA lengthint20volLen
multiplefloat1.2volMult
ADX lengthint14adxLen
minimumfloat20adxMin
Freshness — max bars since flipint5maxAge
Target R multiplefloat2.0rrMult
Plot buy markers on chartbooltrueshowChartSignals
Show buy checklist panelbooltrueshowChecklist
Plot Shift stop linebooltrueshowStopLine
Checklist positionstringMiddle rightchecklistPos
ATR periodint10shiftATR
Multiplierfloat3.0shiftMult
Use built-in ATRbooltrueshiftBuiltIn
MA typestringSMAoscType
MA lengthint40oscLength
Oscillator lengthint15oscLen
Thresholdfloat0.5oscThresh
Normalisation lookbackint500oscLookback
Slot 01symbolCME_MINI:ES1!b01
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

218 stars

TradersPost Trading Checklist is an overlay indicator that evaluates a suite of popular technical conditions for long and short trade setups. It checks session-anchored VWAP, fast and slow EMA alignments and crosses, 200 SMA, RSI overbought or oversold conditi

Indicator v6 Screeners & dashboardsTrend
Updated 3 months ago · None stated GitHub repository of TradersPost Trading Checklist
53 stars

This indicator analyzes historical candle direction and price range over a configurable lookback window to gauge market trend. It categorizes trend direction using candle count, price range sum, or both. Signals are filtered using a Simple Moving Average to en

Indicator v6 TrendOscillators & momentum
Updated 2 months ago · MPL-2.0 GitHub repository of Candle Counter + MA + RSI + Mode

Pocket Scout - SPY/QQQ

by chris-c-thomas
14 stars

Pocket Scout - SPY/QQQ is a mobile-optimized intraday bias indicator designed for major US equity ETFs and indices. It overlays a 9/21/50 EMA ribbon, session VWAP, prior day high/low/close levels, and intraday high/low lines directly on the main price chart. T

Indicator v6 TrendOscillators & momentum Repaints
Updated 6 months ago · MIT GitHub repository of Pocket Scout - SPY/QQQ

Portfolio Backtester

by f-cksociety
11 stars

The script is a Pine Script v5 indicator that emulates strategy backtesting directly on the price chart. It evaluates modular entry strategies, trade directions, entry stop-loss types such as ATR multiples or fixed percentages, and a wide variety of trade filt

Indicator v5 TrendOscillators & momentum
Updated 4 years ago · MPL-2.0 GitHub repository of Portfolio Backtester

Vein: Pullback identifies temporary counter-trend retracements and signals when they end versus when structure breaks. It calculates a multi-layer confluence score from 0 to 10 based on trend quality, move weakness, structure preservation, and Fibonacci retrac

Indicator v6 TrendOscillators & momentum
Updated 2 days ago · MIT GitHub repository of Vein: Pullback [WavesUnchained]

ForexAlgo

by Harshil427
7 stars

ForexAlgo generates trade signals directly on the price chart using a primary leading indicator, such as the Range Filter, combined with modular confirmation filters. Traders can toggle multiple technical filters, including exponential moving average crosses,

Indicator v5 TrendOscillators & momentum Repaints
Updated 1 year ago · None stated GitHub repository of ForexAlgo

More indicators

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers