//@version=6
strategy(
title="MNQ Multi-Trigger Trend Continuation",
shorttitle="MNQ MTTC",
overlay=true,
pyramiding=0,
initial_capital=50000,
default_qty_type=strategy.fixed,
default_qty_value=1,
commission_type=strategy.commission.cash_per_contract,
commission_value=0.47,
slippage=1,
process_orders_on_close=true,
calc_on_order_fills=true,
calc_on_every_tick=false,
max_bars_back=5000,
max_labels_count=300,
max_lines_count=100,
max_boxes_count=100
)
//=============================================================================
// OVERVIEW
//=============================================================================
// Ground-up trend-continuation strategy for MNQ, built from a synthesis of
// patterns already proven across this repo plus the research in the
// quant-research-notes skill. Four independent, individually-toggleable
// entry triggers share one regime gate, one risk model, and one dashboard,
// so their relative performance can be compared and tuned separately in
// Strategy Tester (each trade's comment/alert tags which trigger fired):
//
// 1. PULLBACK RECLAIM -- retrace to the trend EMA, reclaim with a
// quality candle. Simplest, most frequent signals.
// 2. SECOND-FLIP RE-ENTRY -- requires a genuine counter-trend excursion
// AND a second flip back into bias before arming, then a break of the
// prior bar's extreme to confirm. A confirmed-bar-level approximation
// of MTF_Second_Flip_Continuation_v1_2.pine's fuller intrabar
// reconstruction -- deliberately simplified for this combined script.
// 3. LIQUIDITY SWEEP + RECLAIM -- needs a real stop-run beyond a stored
// swing pivot before reclaiming it. Most selective; wants real volume.
// 4. ADAPTIVE TREND FLOW -- an adaptive fast/slow-EMA basis with
// stdev-scaled bands and a SuperTrend-style flip, entry logic adapted
// from "Adaptive Trend Flow [QuantAlgo]" (c) QuantAlgo, MPL 2.0. The
// state machine is an exact structural port that recomputes every
// bar like the source (no internal confirmation gate -- that would
// only fight the source's own real-time behavior for no backtest
// benefit, since section 23's commonEntryPass is the one checkpoint
// that already keeps every trigger's actual order submission
// confirmed-bar-only); the only real adaptation is gating by
// finalBias/regimeArmed so a flow flip fires as an entry only when
// it agrees with the already-armed regime direction.
//
// REGIME GATE -- built as a genuine two-threshold hysteresis band, not one
// shared cutoff, per Dai, Yang, Zhang & Zhu (2016) "Optimal Trend Following
// Trading Rules" (quant-research-notes reference #6): the provably optimal
// trend-following rule arms on a STRICT threshold and only exits the regime
// on a distinctly LOOSER one, with a no-trade zone between them. Here that
// becomes regimeEnterMin (strict, arms new entries) vs. regimeHoldMin
// (loose, merely keeps the regime alive) applied to a continuous 0-100
// trend-quality score -- not a literal Wonham-filter probability, but the
// same structural idea using tools Pine already has.
//
// Per the same skill's synthesis notes: the regime gate stays a pure gate
// and never touches stop/target sizing (paper #2's finding); no trigger's
// weights were grid-search-optimized against this repo's own data (paper
// #3's flagged pitfall) -- they are principled, interpretable starting
// points, meant to be walk-forward tuned in the Python quantor pipeline,
// not trusted as-is. Session window is a fully open input, not hardcoded
// RTH or 24h, per request.
//=============================================================================
//=============================================================================
// 01. INPUT GROUPS
//=============================================================================
const string G_SESSION = "01 - Session"
const string G_BIAS = "02 - HTF Bias"
const string G_REGIME = "03 - Trend Quality / Regime Gate"
const string G_TRIGGERS = "04 - Entry Triggers"
const string G_PULLBACK = "05 - Pullback Reclaim Trigger"
const string G_FLIP = "06 - Second-Flip Trigger"
const string G_SWEEP = "07 - Liquidity Sweep Trigger"
const string G_FLOW = "07B - Adaptive Trend Flow Trigger"
const string G_RISK = "08 - Risk Management"
const string G_DAILY = "09 - Daily Controls"
const string G_DISPLAY = "10 - Dashboard and Display"
//=============================================================================
// 02. SESSION INPUTS
//=============================================================================
string tradingSession = input.session("0930-1600", "Trading Session", tooltip="Type any window -- e.g. 0000-2359 for effectively 24h, or 1800-1600 for the Globex overnight-through-RTH session. Not hardcoded to RTH.", group=G_SESSION)
string sessionTimezone = input.string("America/New_York", "Session Timezone", group=G_SESSION)
bool restrictToSession = input.bool(true, "Restrict Entries To Session Window", group=G_SESSION)
bool closeAtSessionEnd = input.bool(false, "Close Position At Session End", group=G_SESSION)
//=============================================================================
// 03. HTF BIAS INPUTS
//=============================================================================
string biasTF1 = input.timeframe("60", "Bias TF 1", group=G_BIAS)
string biasTF2 = input.timeframe("240", "Bias TF 2", group=G_BIAS)
int biasEmaLen = input.int(50, "Bias EMA Length", minval=5, group=G_BIAS)
//=============================================================================
// 04. TREND QUALITY / REGIME GATE INPUTS
//=============================================================================
int adxLen = input.int(14, "ADX Length", minval=2, group=G_REGIME)
float adxNormLo = input.float(15.0, "ADX Norm Low (0 pts)", minval=0, group=G_REGIME)
float adxNormHi = input.float(35.0, "ADX Norm High (full pts)", minval=1, group=G_REGIME)
int chopLen = input.int(14, "Choppiness Length", minval=2, group=G_REGIME)
float chopBest = input.float(38.2, "Choppiness Best (full pts)", minval=0, group=G_REGIME)
float chopWorst = input.float(61.8, "Choppiness Worst (0 pts)", minval=0, group=G_REGIME)
int efficiencyLen = input.int(14, "Efficiency Ratio Length", minval=2, group=G_REGIME)
float efficiencyLo = input.float(0.15, "Efficiency Low (0 pts)", minval=0, maxval=1, step=0.01, group=G_REGIME)
float efficiencyHi = input.float(0.60, "Efficiency High (full pts)", minval=0, maxval=1, step=0.01, group=G_REGIME)
int persistenceLen = input.int(3, "Persistence Bars", minval=1, group=G_REGIME)
float regimeEnterMin = input.float(70.0, "Regime Enter Threshold (strict)", minval=0, maxval=100, tooltip="Trend-quality score required to ARM a new regime -- the strict threshold. See the header note on paper #6's two-threshold hysteresis result.", group=G_REGIME)
float regimeHoldMin = input.float(45.0, "Regime Hold Threshold (loose)", minval=0, maxval=100, tooltip="Trend-quality score required merely to REMAIN in an already-armed regime. Deliberately looser than the enter threshold and deliberately not the same input -- the whole point of the hysteresis band.", group=G_REGIME)
//=============================================================================
// 05. ENTRY TRIGGER TOGGLES
//=============================================================================
bool useTriggerPullback = input.bool(true, "Enable: Pullback Reclaim", group=G_TRIGGERS)
bool useTriggerFlip = input.bool(true, "Enable: Second-Flip Re-Entry", group=G_TRIGGERS)
bool useTriggerSweep = input.bool(true, "Enable: Liquidity Sweep + Reclaim", group=G_TRIGGERS)
bool useTriggerFlow = input.bool(true, "Enable: Adaptive Trend Flow", group=G_TRIGGERS)
//=============================================================================
// 06. PULLBACK RECLAIM TRIGGER INPUTS
//=============================================================================
int pullbackTrendEmaLen = input.int(21, "Pullback Trend EMA", minval=2, group=G_PULLBACK)
int pullbackLookback = input.int(8, "Pullback Lookback Bars", minval=1, group=G_PULLBACK)
float pullbackMinBodyPct = input.float(0.45, "Minimum Reclaim Body %", minval=0, maxval=1, step=0.05, group=G_PULLBACK)
//=============================================================================
// 07. SECOND-FLIP TRIGGER INPUTS
//=============================================================================
int flipEmaLen = input.int(21, "Flip Reference EMA", minval=2, group=G_FLIP)
int flipMemoryBars = input.int(30, "Flip Memory, Bars", minval=5, maxval=200, tooltip="A flip count resets if no second flip completes within this many bars.", group=G_FLIP)
int flipConfirmWindow = input.int(4, "Break Confirmation Window, Bars", minval=1, maxval=20, tooltip="After the second flip arms, price must break the prior bar's extreme within this many bars.", group=G_FLIP)
//=============================================================================
// 08. LIQUIDITY SWEEP TRIGGER INPUTS
//=============================================================================
int sweepPivotLength = input.int(5, "Swing Pivot Length", minval=1, maxval=20, group=G_SWEEP)
int sweepStoredLevels = input.int(15, "Stored Liquidity Levels", minval=5, maxval=100, group=G_SWEEP)
float sweepMinDistanceAtr = input.float(0.10, "Minimum Sweep Distance / ATR", minval=0.01, maxval=2.0, step=0.01, group=G_SWEEP)
float sweepMinWickPct = input.float(0.35, "Minimum Rejection Wick %", minval=0, maxval=1, step=0.01, group=G_SWEEP)
int sweepConfirmWindow = input.int(2, "Reclaim Confirmation Window, Bars", minval=0, maxval=10, group=G_SWEEP)
//=============================================================================
// 08B. ADAPTIVE TREND FLOW TRIGGER INPUTS
//=============================================================================
// Adapted from "Adaptive Trend Flow [QuantAlgo]" (c) QuantAlgo, MPL 2.0.
int atfLength = input.int(10, "Main Length", minval=2, group=G_FLOW)
int atfSmoothLen = input.int(14, "Smoothing Length", minval=2, group=G_FLOW)
float atfSensitivity = input.float(2.0, "Sensitivity", minval=0.1, step=0.1, group=G_FLOW)
//=============================================================================
// 09. RISK MANAGEMENT INPUTS
//=============================================================================
int contracts = input.int(1, "MNQ Contracts", minval=1, maxval=50, group=G_RISK)
int atrLen = input.int(14, "ATR Length", minval=2, group=G_RISK)
float atrStopMultiplier = input.float(1.5, "ATR Stop Multiplier", minval=0.1, step=0.1, group=G_RISK)
float structuralStopBufferAtr = input.float(0.10, "Stop Buffer Beyond Structure / ATR", minval=0, maxval=2, step=0.05, group=G_RISK)
float rrTarget = input.float(2.0, "Risk-Reward Target", minval=0.25, step=0.25, group=G_RISK)
bool useBreakEven = input.bool(true, "Use Break-Even", group=G_RISK)
float breakEvenAtR = input.float(1.0, "Break-Even Trigger, R", minval=0.25, step=0.25, group=G_RISK)
//=============================================================================
// 10. DAILY CONTROLS INPUTS
//=============================================================================
int maxTradesPerDay = input.int(4, "Maximum Trades Per Day", minval=1, group=G_DAILY)
int cooldownBars = input.int(8, "Cooldown Bars", minval=0, tooltip="Measured from both the last signal bar and the last CLOSED-trade bar.", group=G_DAILY)
//=============================================================================
// 11. DASHBOARD AND DISPLAY INPUTS
//=============================================================================
bool showDashboard = input.bool(true, "Show Dashboard", group=G_DISPLAY)
string dashboardPos = input.string("Top Right", "Dashboard Position", options=["Top Right", "Top Left", "Bottom Right", "Bottom Left"], group=G_DISPLAY)
bool showEmas = input.bool(true, "Show EMAs", group=G_DISPLAY)
bool showEntryMarkers = input.bool(true, "Show Entry Markers", group=G_DISPLAY)
//=============================================================================
// 12. COLORS AND HELPERS
//=============================================================================
color C_BULL = color.rgb(0, 145, 255)
color C_BEAR = color.rgb(165, 85, 235)
color C_READY = color.rgb(20, 185, 105)
color C_WAIT = color.rgb(245, 155, 25)
color C_STOP = color.rgb(240, 65, 80)
color C_NEUTRAL = color.rgb(95, 110, 130)
f_high(float v, float worst, float best) =>
na(v) ? 0.0 : v <= worst ? 0.0 : v >= best ? 1.0 : (v - worst) / math.max(best - worst, 0.000001)
f_low(float v, float best, float worst) =>
na(v) ? 0.0 : v <= best ? 1.0 : v >= worst ? 0.0 : (worst - v) / math.max(worst - best, 0.000001)
f_price(float v) =>
na(v) ? "-" : str.tostring(v, format.mintick)
f_num(float v) =>
na(v) ? "-" : str.tostring(v, "#.0")
//=============================================================================
// 13. SESSION STATE
//=============================================================================
bool inTradingSession = not na(time(timeframe.period, tradingSession, sessionTimezone))
bool entrySessionPass = not restrictToSession or inTradingSession
int sessionEndMOD = int(str.tonumber(str.substring(tradingSession, 5, 7))) * 60 + int(str.tonumber(str.substring(tradingSession, 7, 9)))
int barCloseMOD = hour(time_close, sessionTimezone) * 60 + minute(time_close, sessionTimezone)
bool finalSessionBar = inTradingSession and barCloseMOD == sessionEndMOD
int dayId = year(time, sessionTimezone) * 10000 + month(time, sessionTimezone) * 100 + dayofmonth(time, sessionTimezone)
bool newSessionDay = barstate.isfirst or dayId != dayId[1]
//=============================================================================
// 14. HTF BIAS
//=============================================================================
f_htfBiasSnapshot() =>
float c = close[1]
float e = ta.ema(close, biasEmaLen)[1]
[c, e]
[htf1Close, htf1Ema] = request.security(syminfo.tickerid, biasTF1, f_htfBiasSnapshot(), gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_on)
[htf2Close, htf2Ema] = request.security(syminfo.tickerid, biasTF2, f_htfBiasSnapshot(), gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_on)
bool htf1Bull = not na(htf1Close) and not na(htf1Ema) and htf1Close > htf1Ema
bool htf1Bear = not na(htf1Close) and not na(htf1Ema) and htf1Close < htf1Ema
bool htf2Bull = not na(htf2Close) and not na(htf2Ema) and htf2Close > htf2Ema
bool htf2Bear = not na(htf2Close) and not na(htf2Ema) and htf2Close < htf2Ema
int finalBiasRaw = htf1Bull and htf2Bull ? 1 : htf1Bear and htf2Bear ? -1 : 0
//=============================================================================
// 15. TREND-QUALITY SCORE AND HYSTERESIS REGIME GATE
//=============================================================================
// Score components are principled, interpretable starting weights -- not
// grid-search-optimized against this repo's own data (see the header note
// on paper #3's flagged overfitting pitfall). Walk-forward tune in quantor
// before trusting them.
[plusDI, minusDI, adxExec] = ta.dmi(adxLen, adxLen)
float chopTrueRangeSum = math.sum(ta.tr(true), chopLen)
float chopHighest = ta.highest(high, chopLen)
float chopLowest = ta.lowest(low, chopLen)
float chopRange = chopHighest - chopLowest
float chopValue = chopRange > 0 and chopLen > 1 ? 100.0 * math.log10(chopTrueRangeSum / chopRange) / math.log10(chopLen) : na
float avgAbsChange = ta.sma(math.abs(ta.change(close)), efficiencyLen)
float efficiencyPath = not na(avgAbsChange) ? avgAbsChange * efficiencyLen : na
float efficiencyRatio = not na(efficiencyPath) and efficiencyPath > 0 and bar_index >= efficiencyLen ? math.abs(close - close[efficiencyLen]) / efficiencyPath : 0.0
bool risingPersist = ta.rising(close, persistenceLen)
bool fallingPersist = ta.falling(close, persistenceLen)
bool persistenceAgrees = (finalBiasRaw == 1 and risingPersist) or (finalBiasRaw == -1 and fallingPersist)
float regimeScore = 100.0 * (
f_high(adxExec, adxNormLo, adxNormHi) * 0.30 +
f_low(nz(chopValue, chopWorst), chopBest, chopWorst) * 0.25 +
f_high(efficiencyRatio, efficiencyLo, efficiencyHi) * 0.20 +
(finalBiasRaw != 0 ? 1.0 : 0.0) * 0.15 +
(persistenceAgrees ? 1.0 : 0.0) * 0.10)
// FIX (built in from the start, not retrofitted): two-threshold hysteresis,
// not one shared cutoff. Strict to arm a fresh regime, distinctly looser to
// remain in it -- see the header note and quant-research-notes reference
// #6. A regime that drops below regimeHoldMin (or whose HTF bias itself
// flips to neutral) disarms and resets every trigger engine's pending state
// below, so a stale setup from the old regime can never carry into the new
// one.
var bool regimeArmed = false
if barstate.isconfirmed
if not regimeArmed and finalBiasRaw != 0 and regimeScore >= regimeEnterMin
regimeArmed := true
else if regimeArmed and (finalBiasRaw == 0 or regimeScore < regimeHoldMin)
regimeArmed := false
int finalBias = regimeArmed ? finalBiasRaw : 0
//=============================================================================
// 16. BASE INDICATORS
//=============================================================================
float atr = ta.atr(atrLen)
float emaFast = ta.ema(close, pullbackTrendEmaLen)
float emaFlip = ta.ema(close, flipEmaLen)
float bodySize = math.abs(close - open)
float candleRange = math.max(high - low, syminfo.mintick)
float upperWick = high - math.max(open, close)
float lowerWick = math.min(open, close) - low
float bodyPct = candleRange > 0 ? bodySize / candleRange : 0.0
float upperWickPct = candleRange > 0 ? upperWick / candleRange : 0.0
float lowerWickPct = candleRange > 0 ? lowerWick / candleRange : 0.0
bool bullCandle = close > open
bool bearCandle = close < open
//=============================================================================
// 17. TRIGGER 1 -- PULLBACK RECLAIM
//=============================================================================
bool bullPullback = finalBias == 1 and (low <= emaFast)
bool bearPullback = finalBias == -1 and (high >= emaFast)
bool bullPullbackRecent = ta.barssince(bullPullback) <= pullbackLookback
bool bearPullbackRecent = ta.barssince(bearPullback) <= pullbackLookback
bool pullbackLongSignal = regimeArmed and finalBias == 1 and bullPullbackRecent and close > emaFast and bullCandle and bodyPct >= pullbackMinBodyPct
bool pullbackShortSignal = regimeArmed and finalBias == -1 and bearPullbackRecent and close < emaFast and bearCandle and bodyPct >= pullbackMinBodyPct
//=============================================================================
// 18. TRIGGER 2 -- SECOND-FLIP RE-ENTRY
//=============================================================================
// Confirmed-bar-level approximation of MTF_Second_Flip_Continuation_v1_2.pine's
// fuller intrabar LTF reconstruction -- deliberately simplified for this
// combined script. A counter-trend bar (closes against finalBias, relative
// to emaFlip) followed by a rebound bar (closes back with finalBias) counts
// as one flip. A SECOND such flip arms the setup; price must then break the
// prior bar's extreme within flipConfirmWindow bars to confirm.
bool barIsBull = close > emaFlip
bool barIsBear = close < emaFlip
bool barCounterTrend = (finalBias == 1 and barIsBear) or (finalBias == -1 and barIsBull)
bool barAgreesWithBias = (finalBias == 1 and barIsBull) or (finalBias == -1 and barIsBear)
var int flipCount = 0
var bool flipWasCounter = false
var int lastFlipEventBar = na
var int flipRegimeBiasAtCount = 0
// Reset the flip count whenever the regime itself resets or flips direction
// -- a flip counted under the old regime/direction must never carry into a
// new one.
if not regimeArmed or finalBias != flipRegimeBiasAtCount
flipCount := 0
flipWasCounter := false
lastFlipEventBar := na
flipRegimeBiasAtCount := finalBias
if barstate.isconfirmed and regimeArmed
if barCounterTrend
flipWasCounter := true
else if barAgreesWithBias and flipWasCounter
flipCount += 1
flipWasCounter := false
lastFlipEventBar := bar_index
bool flipMemoryOk = not na(lastFlipEventBar) and bar_index - lastFlipEventBar <= flipMemoryBars
if not na(lastFlipEventBar) and bar_index - lastFlipEventBar > flipMemoryBars
flipCount := 0
bool flipArmedLong = regimeArmed and finalBias == 1 and flipCount >= 2 and flipMemoryOk
bool flipArmedShort = regimeArmed and finalBias == -1 and flipCount >= 2 and flipMemoryOk
// Pending break-confirmation memory, with the staleness-safe registration
// fix applied from the start (see MNQ_Liquidity_Sweep_Trend_Following_v1_3's
// section 19 fix earlier this session): a pending arm that has already
// expired as of THIS bar must not block a fresh arm from registering.
var int pendingFlipLongBar = na
var float pendingFlipLongLevel = na
var int pendingFlipShortBar = na
var float pendingFlipShortLevel = na
bool pendingFlipLongStale = not na(pendingFlipLongBar) and (bar_index - pendingFlipLongBar) > flipConfirmWindow
bool pendingFlipShortStale = not na(pendingFlipShortBar) and (bar_index - pendingFlipShortBar) > flipConfirmWindow
if flipArmedLong and (na(pendingFlipLongBar) or pendingFlipLongStale)
pendingFlipLongBar := bar_index
pendingFlipLongLevel := high[1]
if flipArmedShort and (na(pendingFlipShortBar) or pendingFlipShortStale)
pendingFlipShortBar := bar_index
pendingFlipShortLevel := low[1]
bool flipLongWindowOpen = not na(pendingFlipLongBar) and (bar_index - pendingFlipLongBar) >= 1 and (bar_index - pendingFlipLongBar) <= flipConfirmWindow
bool flipShortWindowOpen = not na(pendingFlipShortBar) and (bar_index - pendingFlipShortBar) >= 1 and (bar_index - pendingFlipShortBar) <= flipConfirmWindow
bool flipLongSignal = regimeArmed and finalBias == 1 and flipLongWindowOpen and close > pendingFlipLongLevel
bool flipShortSignal = regimeArmed and finalBias == -1 and flipShortWindowOpen and close < pendingFlipShortLevel
if flipLongSignal
pendingFlipLongBar := na
pendingFlipLongLevel := na
if flipShortSignal
pendingFlipShortBar := na
pendingFlipShortLevel := na
//=============================================================================
// 19. TRIGGER 3 -- LIQUIDITY SWEEP + RECLAIM
//=============================================================================
float pivotHigh = ta.pivothigh(high, sweepPivotLength, sweepPivotLength)
float pivotLow = ta.pivotlow(low, sweepPivotLength, sweepPivotLength)
var array<float> sweepHighLevels = array.new_float()
var array<int> sweepHighBars = array.new_int()
var array<float> sweepLowLevels = array.new_float()
var array<int> sweepLowBars = array.new_int()
if not na(pivotHigh)
array.push(sweepHighLevels, pivotHigh)
array.push(sweepHighBars, bar_index - sweepPivotLength)
if array.size(sweepHighLevels) > sweepStoredLevels
array.shift(sweepHighLevels)
array.shift(sweepHighBars)
if not na(pivotLow)
array.push(sweepLowLevels, pivotLow)
array.push(sweepLowBars, bar_index - sweepPivotLength)
if array.size(sweepLowLevels) > sweepStoredLevels
array.shift(sweepLowLevels)
array.shift(sweepLowBars)
float sweepMinDistance = not na(atr) ? atr * sweepMinDistanceAtr : na
float sweptHighLevel = na
int sweptHighIdx = na
int sweepHighCount = array.size(sweepHighLevels)
if sweepHighCount > 0
for i = sweepHighCount - 1 to 0
float level = array.get(sweepHighLevels, i)
int levelBar = array.get(sweepHighBars, i)
if levelBar < bar_index and high > level and not na(sweepMinDistance) and high - level >= sweepMinDistance
sweptHighLevel := level
sweptHighIdx := i
break
float sweptLowLevel = na
int sweptLowIdx = na
int sweepLowCount = array.size(sweepLowLevels)
if sweepLowCount > 0
for i = sweepLowCount - 1 to 0
float level = array.get(sweepLowLevels, i)
int levelBar = array.get(sweepLowBars, i)
if levelBar < bar_index and low < level and not na(sweepMinDistance) and level - low >= sweepMinDistance
sweptLowLevel := level
sweptLowIdx := i
break
bool bearishReclaim = not na(sweptHighLevel) and close < sweptHighLevel
bool bullishReclaim = not na(sweptLowLevel) and close > sweptLowLevel
bool validSellSweep = finalBias == -1 and bearishReclaim and upperWickPct >= sweepMinWickPct
bool validBuySweep = finalBias == 1 and bullishReclaim and lowerWickPct >= sweepMinWickPct
var int pendingSweepLongBar = na
var float pendingSweepLongLevel = na
var float pendingSweepLongStop = na
var int pendingSweepShortBar = na
var float pendingSweepShortLevel = na
var float pendingSweepShortStop = na
bool pendingSweepLongStale = not na(pendingSweepLongBar) and (bar_index - pendingSweepLongBar) > sweepConfirmWindow
bool pendingSweepShortStale = not na(pendingSweepShortBar) and (bar_index - pendingSweepShortBar) > sweepConfirmWindow
if validBuySweep and regimeArmed and (na(pendingSweepLongBar) or pendingSweepLongStale)
pendingSweepLongBar := bar_index
pendingSweepLongLevel := sweptLowLevel
pendingSweepLongStop := low
if validSellSweep and regimeArmed and (na(pendingSweepShortBar) or pendingSweepShortStale)
pendingSweepShortBar := bar_index
pendingSweepShortLevel := sweptHighLevel
pendingSweepShortStop := high
bool sweepLongWindowOpen = not na(pendingSweepLongBar) and (bar_index - pendingSweepLongBar) >= 1 and (bar_index - pendingSweepLongBar) <= sweepConfirmWindow
bool sweepShortWindowOpen = not na(pendingSweepShortBar) and (bar_index - pendingSweepShortBar) >= 1 and (bar_index - pendingSweepShortBar) <= sweepConfirmWindow
bool sweepLongSignal = regimeArmed and finalBias == 1 and sweepLongWindowOpen and close > pendingSweepLongLevel and bullCandle
bool sweepShortSignal = regimeArmed and finalBias == -1 and sweepShortWindowOpen and close < pendingSweepShortLevel and bearCandle
float sweepLongStopRef = pendingSweepLongStop
float sweepShortStopRef = pendingSweepShortStop
if sweepLongSignal
pendingSweepLongBar := na
pendingSweepLongLevel := na
if sweepShortSignal
pendingSweepShortBar := na
pendingSweepShortLevel := na
//=============================================================================
// 19B. TRIGGER 4 -- ADAPTIVE TREND FLOW (adapted from QuantAlgo)
//=============================================================================
// Entry mechanism adapted from "Adaptive Trend Flow [QuantAlgo]" (c) QuantAlgo,
// MPL 2.0 -- an adaptive fast/slow-EMA basis with stdev-scaled bands, and a
// SuperTrend-style flip state machine. The source indicator's flip signal
// alone has no bias or confirmation filter; one deliberate adaptation was
// made rather than importing it verbatim:
// Gated by finalBias/regimeArmed -- this strategy never takes a signal
// against its own regime gate (the "no counter-trend" rule every other
// trigger already follows), so a flow flip only fires as an entry when
// it agrees with the already-armed regime direction.
// The state machine itself (atfTrend/atfLevel below) is otherwise a
// deliberately EXACT structural port of the source's get_trend_state():
// it recomputes every bar, unconditionally, exactly like the source, with
// no internal barstate.isconfirmed gate. An earlier version of this
// adaptation wrapped the whole block in "if barstate.isconfirmed", which
// made zero difference to backtest results (historical bars are always
// confirmed) but silently broke live/replay visual parity with the source
// indicator -- during a still-forming bar, atfTrend/atfLevel would freeze
// instead of updating tick-by-tick like the source, so the dashboard's ATF
// TREND row and the "L"/"S" comparison against the source indicator on
// screen would lag a full bar behind. Section 23's commonEntryPass already
// requires barstate.isconfirmed before ANY strategy.entry() fires (the
// same single choke point Triggers 1 and 3 rely on, rather than each
// re-gating internally) -- so removing this trigger's own redundant gate
// costs nothing on order-execution safety and restores true bar-by-bar
// parity with the source, on the same checkpoint the other two ungated
// triggers already use.
// Variable names carry an atf/flow prefix throughout to avoid any collision
// with Trigger 2's flip*-prefixed second-flip engine -- these are two
// unrelated "flip" concepts that happen to share the word.
float atfTypical = hlc3
float atfFastEma = ta.ema(atfTypical, atfLength)
float atfSlowEma = ta.ema(atfTypical, atfLength * 2)
float atfBasis = (atfFastEma + atfSlowEma) / 2
float atfVol = ta.stdev(atfTypical, atfLength)
float atfSmoothVol = ta.ema(atfVol, atfSmoothLen)
float atfUpper = atfBasis + (atfSmoothVol * atfSensitivity)
float atfLower = atfBasis - (atfSmoothVol * atfSensitivity)
var int atfTrend = 0
var float atfLevel = na
// Two independent "if" statements, NOT "if/else if" -- this exactly
// mirrors the source's own structure, where the initialization check and
// the trend-continuation check are separate statements that both run on
// the same bar when priming for the first time. Confirmed harmless (the
// second check can never actually flip trend back on the priming bar,
// since lower < basis < upper by construction), but kept structurally
// identical to the source rather than collapsed into "else if", per the
// same-condition parity this trigger is meant to hold.
if na(atfLevel)
atfTrend := close > atfBasis ? 1 : -1
atfLevel := atfTrend == 1 ? atfLower : atfUpper
if atfTrend == 1
if close < atfLower
atfTrend := -1
atfLevel := atfUpper
else
atfLevel := atfLower
else
if close > atfUpper
atfTrend := 1
atfLevel := atfLower
else
atfLevel := atfUpper
// No inline isconfirmed gate here either, matching Triggers 1 and 3's
// convention -- the flip is a plain per-bar boolean; commonEntryPass
// (section 23) is the sole checkpoint that decides whether a bar's flip
// is eligible to actually submit an order.
bool atfFlipLong = atfTrend == 1 and atfTrend[1] == -1
bool atfFlipShort = atfTrend == -1 and atfTrend[1] == 1
bool flowLongSignal = regimeArmed and finalBias == 1 and atfFlipLong
bool flowShortSignal = regimeArmed and finalBias == -1 and atfFlipShort
//=============================================================================
// 20. TRIGGER COMBINATION AND TAGGING
//=============================================================================
// Any enabled trigger firing is a valid raw signal. Each strategy.entry's
// comment (and the alert message) tags which trigger fired, so Strategy
// Tester's List of Trades can be filtered/compared trigger by trigger --
// the point of building all four rather than picking one.
bool rawLongSignal = (useTriggerPullback and pullbackLongSignal) or (useTriggerFlip and flipLongSignal) or (useTriggerSweep and sweepLongSignal) or (useTriggerFlow and flowLongSignal)
bool rawShortSignal = (useTriggerPullback and pullbackShortSignal) or (useTriggerFlip and flipShortSignal) or (useTriggerSweep and sweepShortSignal) or (useTriggerFlow and flowShortSignal)
string longTriggerTag =
useTriggerSweep and sweepLongSignal ? "SWEEP" :
useTriggerFlow and flowLongSignal ? "FLOW" :
useTriggerFlip and flipLongSignal ? "FLIP" :
useTriggerPullback and pullbackLongSignal ? "PULLBACK" :
"NONE"
string shortTriggerTag =
useTriggerSweep and sweepShortSignal ? "SWEEP" :
useTriggerFlow and flowShortSignal ? "FLOW" :
useTriggerFlip and flipShortSignal ? "FLIP" :
useTriggerPullback and pullbackShortSignal ? "PULLBACK" :
"NONE"
float longStructuralRef =
useTriggerSweep and sweepLongSignal ? sweepLongStopRef :
useTriggerFlow and flowLongSignal ? atfLevel :
useTriggerFlip and flipLongSignal ? low[1] :
emaFast
float shortStructuralRef =
useTriggerSweep and sweepShortSignal ? sweepShortStopRef :
useTriggerFlow and flowShortSignal ? atfLevel :
useTriggerFlip and flipShortSignal ? high[1] :
emaFast
//=============================================================================
// 21. CANDIDATE RISK
//=============================================================================
float atrLongStop = not na(atr) ? close - atr * atrStopMultiplier : na
float atrShortStop = not na(atr) ? close + atr * atrStopMultiplier : na
float structuralLongStop = not na(longStructuralRef) ? longStructuralRef - atr * structuralStopBufferAtr : na
float structuralShortStop = not na(shortStructuralRef) ? shortStructuralRef + atr * structuralStopBufferAtr : na
float candidateLongStop = not na(structuralLongStop) ? math.min(atrLongStop, structuralLongStop) : atrLongStop
float candidateShortStop = not na(structuralShortStop) ? math.max(atrShortStop, structuralShortStop) : atrShortStop
float candidateLongRisk = not na(candidateLongStop) ? close - candidateLongStop : na
float candidateShortRisk = not na(candidateShortStop) ? candidateShortStop - close : na
bool longRiskPass = not na(candidateLongRisk) and candidateLongRisk > 0
bool shortRiskPass = not na(candidateShortRisk) and candidateShortRisk > 0
//=============================================================================
// 22. DAILY CONTROLS AND COOLDOWN
//=============================================================================
var int tradesToday = 0
var int lastSignalBar = na
var int lastExitBar = na
if newSessionDay and barstate.isnew
tradesToday := 0
bool tradeLimitPass = tradesToday < maxTradesPerDay
bool cooldownPass = (na(lastSignalBar) or bar_index - lastSignalBar > cooldownBars) and (na(lastExitBar) or bar_index - lastExitBar > cooldownBars)
bool flat = strategy.position_size == 0
//=============================================================================
// 23. FINAL ENTRY CONDITIONS
//=============================================================================
bool commonEntryPass = barstate.isconfirmed and entrySessionPass and flat and tradeLimitPass and cooldownPass and regimeArmed
bool longEntry = commonEntryPass and rawLongSignal and longRiskPass
bool shortEntry = commonEntryPass and rawShortSignal and shortRiskPass and not longEntry
//=============================================================================
// 24. SIGNAL-VOLATILITY DIAGNOSTIC (paper #1)
//=============================================================================
// b1/b2 track how often this strategy's own signal state flips, per
// Zoicaș-Ienciu & Pochea (quant-research-notes reference #1) -- built in
// from the start as a live diagnostic, not retrofitted after the fact.
var int sigState = 0
var int sigNBS = 0
var int sigNBN = 0
var int sigNSN = 0
var int sigTotal = 0
int newSigState = longEntry ? 1 : shortEntry ? -1 : flat ? 0 : sigState
if barstate.isconfirmed and newSigState != sigState
sigTotal += 1
if (newSigState == 1 and sigState == -1) or (newSigState == -1 and sigState == 1)
sigNBS += 1
else if (newSigState == 1 and sigState == 0) or (newSigState == 0 and sigState == 1)
sigNBN += 1
else if (newSigState == -1 and sigState == 0) or (newSigState == 0 and sigState == -1)
sigNSN += 1
sigState := newSigState
float b1SignalVol = sigTotal > 0 ? (sigNBS + sigNBN) / sigTotal * 100.0 : na
float b2SignalVol = sigTotal > 0 ? (sigNBS + sigNSN) / sigTotal * 100.0 : na
//=============================================================================
// 25. ORDERS
//=============================================================================
var float activeEntry = na
var float initialRisk = na
var float activeStop = na
var float activeTarget = na
var int entryBarIndex = na
var bool tradeInitialized = false
var bool breakEvenMoved = false
var float pendingStop = na
var string lastTriggerTag = "NONE"
if longEntry
pendingStop := candidateLongStop
lastSignalBar := bar_index
tradesToday += 1
lastTriggerTag := longTriggerTag
strategy.entry("Long", strategy.long, qty=contracts, comment="LONG " + longTriggerTag, alert_message="MNQ MTTC Bullish Signal (" + longTriggerTag + ")")
if shortEntry
pendingStop := candidateShortStop
lastSignalBar := bar_index
tradesToday += 1
lastTriggerTag := shortTriggerTag
strategy.entry("Short", strategy.short, qty=contracts, comment="SHORT " + shortTriggerTag, alert_message="MNQ MTTC Bearish Signal (" + shortTriggerTag + ")")
//=============================================================================
// 26. FILL INITIALIZATION
//=============================================================================
bool longFill = strategy.position_size > 0 and strategy.position_size[1] <= 0
bool shortFill = strategy.position_size < 0 and strategy.position_size[1] >= 0
if longFill and not tradeInitialized
activeEntry := strategy.position_avg_price
activeStop := pendingStop
initialRisk := activeEntry - activeStop
if not na(initialRisk) and initialRisk > 0
activeTarget := activeEntry + initialRisk * rrTarget
entryBarIndex := bar_index
tradeInitialized := true
breakEvenMoved := false
else
strategy.close("Long", comment="Invalid Risk", immediately=true)
if shortFill and not tradeInitialized
activeEntry := strategy.position_avg_price
activeStop := pendingStop
initialRisk := activeStop - activeEntry
if not na(initialRisk) and initialRisk > 0
activeTarget := activeEntry - initialRisk * rrTarget
entryBarIndex := bar_index
tradeInitialized := true
breakEvenMoved := false
else
strategy.close("Short", comment="Invalid Risk", immediately=true)
//=============================================================================
// 27. POSITION MANAGEMENT
//=============================================================================
bool managementEligible = strategy.position_size != 0 and tradeInitialized and not na(entryBarIndex) and bar_index > entryBarIndex
if strategy.position_size > 0 and managementEligible and useBreakEven and not breakEvenMoved and high >= activeEntry + initialRisk * breakEvenAtR
activeStop := math.max(activeStop, activeEntry)
breakEvenMoved := true
if strategy.position_size < 0 and managementEligible and useBreakEven and not breakEvenMoved and low <= activeEntry - initialRisk * breakEvenAtR
activeStop := math.min(activeStop, activeEntry)
breakEvenMoved := true
if strategy.position_size > 0 and tradeInitialized
strategy.exit("Long Exit", from_entry="Long", stop=activeStop, limit=activeTarget, alert_message="MNQ MTTC CLOSE LONG")
if strategy.position_size < 0 and tradeInitialized
strategy.exit("Short Exit", from_entry="Short", stop=activeStop, limit=activeTarget, alert_message="MNQ MTTC CLOSE SHORT")
if closeAtSessionEnd and finalSessionBar and strategy.position_size != 0
strategy.close_all(comment="Session Close", alert_message="MNQ MTTC CLOSE SESSION", immediately=true)
//=============================================================================
// 28. CLOSED-POSITION CLEANUP
//=============================================================================
bool positionJustClosed = strategy.position_size == 0 and strategy.position_size[1] != 0
if positionJustClosed
lastExitBar := bar_index
activeEntry := na
initialRisk := na
activeStop := na
activeTarget := na
entryBarIndex := na
tradeInitialized := false
breakEvenMoved := false
pendingStop := na
//=============================================================================
// 29. DASHBOARD
//=============================================================================
resolvedDashPos =
dashboardPos == "Top Left" ? position.top_left :
dashboardPos == "Bottom Right" ? position.bottom_right :
dashboardPos == "Bottom Left" ? position.bottom_left :
position.top_right
var table dash = table.new(resolvedDashPos, 2, 16, border_width=1, border_color=color.rgb(44, 57, 76))
f_row(int row, string leftText, string rightText, color valueColor) =>
table.cell(dash, 0, row, leftText, text_color=color.white, bgcolor=color.new(color.gray, 72), text_size=size.small, text_halign=text.align_left)
table.cell(dash, 1, row, rightText, text_color=color.white, bgcolor=color.new(valueColor, 55), text_size=size.small, text_halign=text.align_right)
if barstate.islast
table.clear(dash, 0, 0, 1, 15)
if showDashboard
string biasText = finalBiasRaw == 1 ? "BULL" : finalBiasRaw == -1 ? "BEAR" : "NEUTRAL"
color biasColor = finalBiasRaw == 1 ? C_BULL : finalBiasRaw == -1 ? C_BEAR : C_NEUTRAL
string regimeText = regimeArmed ? "ARMED" : "DISARMED"
color regimeColor = regimeArmed ? C_READY : C_WAIT
string posText = strategy.position_size > 0 ? "LONG" : strategy.position_size < 0 ? "SHORT" : "FLAT"
color posColor = strategy.position_size > 0 ? C_BULL : strategy.position_size < 0 ? C_BEAR : C_NEUTRAL
string triggersText = (useTriggerPullback ? "P" : "-") + (useTriggerFlip ? "F" : "-") + (useTriggerSweep ? "S" : "-") + (useTriggerFlow ? "A" : "-")
f_row(0, "MNQ MTTC", posText, posColor)
f_row(1, "BIAS", biasText, biasColor)
f_row(2, "REGIME SCORE", f_num(regimeScore) + " (" + f_num(regimeEnterMin) + "/" + f_num(regimeHoldMin) + ")", regimeColor)
f_row(3, "REGIME", regimeText, regimeColor)
f_row(4, "TRIGGERS ON", triggersText, C_NEUTRAL)
f_row(5, "PULLBACK", useTriggerPullback ? (bullPullbackRecent ? "BULL PB" : bearPullbackRecent ? "BEAR PB" : "WAIT") : "OFF", C_NEUTRAL)
f_row(6, "FLIP COUNT", str.tostring(flipCount) + "/2", flipCount >= 2 ? C_READY : C_NEUTRAL)
f_row(7, "SWEEP LONG/SHORT", (not na(pendingSweepLongBar) ? "L" : "-") + " / " + (not na(pendingSweepShortBar) ? "S" : "-"), C_NEUTRAL)
f_row(8, "ADX / CHOP", f_num(adxExec) + " / " + f_num(nz(chopValue)), C_NEUTRAL)
f_row(9, "EFFICIENCY", f_num(efficiencyRatio * 100), C_NEUTRAL)
f_row(10, "TRADES TODAY", str.tostring(tradesToday) + "/" + str.tostring(maxTradesPerDay), tradesToday < maxTradesPerDay ? C_READY : C_WAIT)
f_row(11, "COOLDOWN", cooldownPass ? "READY" : "WAIT", cooldownPass ? C_READY : C_WAIT)
f_row(12, "LAST TRIGGER", lastTriggerTag, C_NEUTRAL)
f_row(13, "SIGNAL VOL b1/b2", f_num(b1SignalVol) + "% / " + f_num(b2SignalVol) + "%", C_NEUTRAL)
f_row(14, "SL / TP", f_price(activeStop) + " / " + f_price(activeTarget), strategy.position_size != 0 ? C_READY : C_NEUTRAL)
f_row(15, "ATF TREND", useTriggerFlow ? (atfTrend == 1 ? "UP" : "DOWN") : "OFF", useTriggerFlow ? (atfTrend == 1 ? C_BULL : C_BEAR) : C_NEUTRAL)
//=============================================================================
// 30. VISUALS
//=============================================================================
plot(showEmas ? emaFast : na, "Pullback EMA", color=color.new(color.orange, 20))
plot(showEmas ? emaFlip : na, "Flip EMA", color=color.new(color.purple, 40))
plotshape(showEntryMarkers and longEntry, title="Long Entry", style=shape.triangleup, location=location.belowbar, color=C_BULL, size=size.small, text="L")
plotshape(showEntryMarkers and shortEntry, title="Short Entry", style=shape.triangledown, location=location.abovebar, color=C_BEAR, size=size.small, text="S")
plot(strategy.position_size != 0 ? activeStop : na, "Active Stop", color=C_STOP, linewidth=2, style=plot.style_linebr)
plot(strategy.position_size != 0 ? activeTarget : na, "Active Target", color=C_READY, linewidth=2, style=plot.style_linebr)
bgcolor(finalBiasRaw == 1 ? color.new(C_BULL, 95) : finalBiasRaw == -1 ? color.new(C_BEAR, 95) : na, title="HTF Bias")
//=============================================================================
// 31. ALERTS
//=============================================================================
alertcondition(longEntry, title="MNQ MTTC Bullish Signal", message="MNQ MTTC Bullish Signal | {{ticker}} | {{interval}}")
alertcondition(shortEntry, title="MNQ MTTC Bearish Signal", message="MNQ MTTC Bearish Signal | {{ticker}} | {{interval}}")
alertcondition(positionJustClosed, title="MNQ MTTC Position Closed", message="MNQ MTTC position closed | {{ticker}} | {{interval}}")
if longEntry
alert("MNQ MTTC Bullish Signal | " + longTriggerTag + " | " + syminfo.ticker + " @ " + f_price(close) + " | SL " + f_price(candidateLongStop), alert.freq_once_per_bar_close)
if shortEntry
alert("MNQ MTTC Bearish Signal | " + shortTriggerTag + " | " + syminfo.ticker + " @ " + f_price(close) + " | SL " + f_price(candidateShortStop), alert.freq_once_per_bar_close)
//=============================================================================
// 32. DATA WINDOW
//=============================================================================
plot(regimeScore, "Regime Score", display=display.data_window)
plot(float(finalBiasRaw), "Raw HTF Bias", display=display.data_window)
plot(regimeArmed ? 1.0 : 0.0, "Regime Armed", display=display.data_window)
plot(float(flipCount), "Flip Count", display=display.data_window)
plot(adxExec, "ADX", display=display.data_window)
plot(chopValue, "Choppiness", display=display.data_window)
plot(efficiencyRatio, "Efficiency Ratio", display=display.data_window)
plot(b1SignalVol, "Signal Volatility b1", display=display.data_window)
plot(b2SignalVol, "Signal Volatility b2", display=display.data_window)
plot(pullbackLongSignal ? 1.0 : 0.0, "Pullback Long Raw", display=display.data_window)
plot(flipLongSignal ? 1.0 : 0.0, "Flip Long Raw", display=display.data_window)
plot(sweepLongSignal ? 1.0 : 0.0, "Sweep Long Raw", display=display.data_window)
plot(flowLongSignal ? 1.0 : 0.0, "Flow Long Raw", display=display.data_window)
plot(flowShortSignal ? 1.0 : 0.0, "Flow Short Raw", display=display.data_window)
plot(float(atfTrend), "ATF Trend State", display=display.data_window)
Overview
The score blends higher-timeframe EMA bias, ADX, choppiness, efficiency ratio and persistence, with separate enter and hold thresholds. Four switchable triggers can open positions: pullback reclaim, second-flip re-entry, liquidity sweep with reclaim, and an adaptive trend-flow flip. Entries can be limited to a New York session window, with optional close at session end. It uses fixed contract sizing, no pyramiding, and plots on the price chart.
The inputs you can change from the gear icon on the chart. Defaults are the author's.
Setting
Type
Default
Variable
Trading Session
session
0930-1600
tradingSession
Session Timezone
string
America/New_York
sessionTimezone
Restrict Entries To Session Window
bool
true
restrictToSession
Close Position At Session End
bool
false
closeAtSessionEnd
Bias TF 1
timeframe
60
biasTF1
Bias TF 2
timeframe
240
biasTF2
Bias EMA Length
int
50
biasEmaLen
ADX Length
int
14
adxLen
ADX Norm Low (0 pts)
float
15.0
adxNormLo
ADX Norm High (full pts)
float
35.0
adxNormHi
Choppiness Length
int
14
chopLen
Choppiness Best (full pts)
float
38.2
chopBest
Show all 40 settings
Setting
Type
Default
Variable
Choppiness Worst (0 pts)
float
61.8
chopWorst
Efficiency Ratio Length
int
14
efficiencyLen
Efficiency Low (0 pts)
float
0.15
efficiencyLo
Efficiency High (full pts)
float
0.60
efficiencyHi
Persistence Bars
int
3
persistenceLen
Regime Enter Threshold (strict)
float
70.0
regimeEnterMin
Regime Hold Threshold (loose)
float
45.0
regimeHoldMin
Enable: Pullback Reclaim
bool
true
useTriggerPullback
Enable: Second-Flip Re-Entry
bool
true
useTriggerFlip
Enable: Liquidity Sweep + Reclaim
bool
true
useTriggerSweep
Enable: Adaptive Trend Flow
bool
true
useTriggerFlow
Pullback Trend EMA
int
21
pullbackTrendEmaLen
Pullback Lookback Bars
int
8
pullbackLookback
Minimum Reclaim Body %
float
0.45
pullbackMinBodyPct
Flip Reference EMA
int
21
flipEmaLen
Flip Memory, Bars
int
30
flipMemoryBars
Break Confirmation Window, Bars
int
4
flipConfirmWindow
Swing Pivot Length
int
5
sweepPivotLength
Stored Liquidity Levels
int
15
sweepStoredLevels
Minimum Sweep Distance / ATR
float
0.10
sweepMinDistanceAtr
Minimum Rejection Wick %
float
0.35
sweepMinWickPct
Reclaim Confirmation Window, Bars
int
2
sweepConfirmWindow
Main Length
int
10
atfLength
Smoothing Length
int
14
atfSmoothLen
Sensitivity
float
2.0
atfSensitivity
MNQ Contracts
int
1
contracts
ATR Length
int
14
atrLen
ATR Stop Multiplier
float
1.5
atrStopMultiplier
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.
Donald - Test Logic Futures is an overlay strategy designed for intraday futures trading. It combines kernel regression functions with exponential moving averages to evaluate price retracements and entry timing. Trades are filtered by session execution windows
This strategy plots up to four volume-weighted average price lines on the price chart: midnight, previous day, session, and a custom anchor such as session high and low, week, or month. It enters when price crosses two selected lines, using same-bar, position,
This strategy trades the three-candle strike pattern filtered by trend direction and time sessions. It calculates market regime using linear regression and exponential or smoothed moving averages to distinguish between ranging and trending conditions. Risk man
This strategy enters long or short on the price chart when price is on the correct side of a 200-period EMA, MACD agrees, RSI is not at the opposing extreme, ADX exceeds a threshold, volume beats a 20-bar average, and close breaks the recent high or low. A tim
This overlay strategy targets one-minute ATOM scalps. It tracks pivot highs and lows as resistance and support, compares a three-period EMA with a multi-stage smoothed close, and flags long or short when price crosses that curve in the matching direction. Dail
This strategy evaluates breakout and trend opportunities on the price chart using a weighted composite score of volume, trend, and candlestick structure. It tracks volume spikes, fast and slow EMAs, higher-timeframe EMA trend alignment, opening ranges, and ses