‹ All setups

Indicator setup · 5-minute gold · QQE Mod + EMA 50

QQE Mod

RSI flips bullish while price keeps falling and bearish right before it rallies. QQE Mod smooths two RSI calculations and only colors the histogram when they agree. Let the EMA 50 pick the side, trade the color change on a strong candle that has closed, stop beyond the last swing, and take 2R only when there's room to get there.

8 / 5RSI length / smoothing
EMA 50picks the side
1 : 2risk to reward

6 / 6

Watch one buy, start to finish

1

Let the EMA 50 pick the side

  • Price above the EMA 50: only look for buys.
  • Price below the EMA 50: only look for sells.
  • Price crossing back and forth, going sideways, or signals fighting each other: wait for something clearer.

QQE Mod on its own changes color too often. The EMA 50 shows the broader direction, so only the color changes that go with it count.

2

Wait for the color change

  • Above the EMA 50, wait for the histogram to go from red to blue.
  • Below the EMA 50, wait for it to go from blue to red.
  • Gray bars in between are normal. The signal is the bar where the color shows up.

Blue and red only appear when both of the indicator's RSI calculations agree. A pullback that turns it red, then a turn back to blue, is momentum shifting back with the trend.

3

Check the candle

  • For a buy: a strong bullish candle with a long body that closes near its high.
  • For a sell: a strong bearish candle with a long body that closes near its low.
  • A setup near a support area (a resistance area for a sell) adds context.

The color says momentum turned. The candle shows buyers (or sellers) actually pushing price. And it only counts once it has closed.

4

Enter at the next open

  • Wait for the signal candle to close.
  • Enter at the open of the next candle.
  • Never before the close: an open candle can still change, and so can the histogram.

Entering on a closed candle means the signal you saw is the signal that printed.

5

Stop beyond the last swing

  • Buy: below the most recent swing low.
  • Sell: above the most recent swing high.
  • If that distance is too big for your risk limit, skip the trade. Don't move the stop closer to make it fit.

The swing is where the setup is proven wrong, and it gives the trade room to move.

6

Target 2R, if there's room

  • The target is twice the stop distance: a 2-unit stop means a target 4 units away.
  • Before entering, find the next resistance (for a buy) or support (for a sell).
  • If it sits between the entry and the target, skip it, even when everything else agrees.

Price can stall or bounce at that level before it reaches the target. Then the reward doesn't justify the risk.

The settings

From the video. Test them on historical charts before risking real money; they aren't proven best for every market.

QQE Mod

The version by Mihkel00 on TradingView, or the combined script at the bottom of this page (it already has these settings). Primary RSI Length 8, RSI Smoothing 5. Leave everything else at its default.

EMA 50

Add an exponential moving average, set the length to 50 and pick a color you can see easily.

The chart

Gold on a 5-minute chart. It can be tested on other markets, but different markets behave differently.

What the colors mean

The histogram is the smoothed RSI minus 50. Its color says whether the two calculations agree.

Blue

Both calculations agree: bullish momentum. Red to blue is a shift toward bullish.

Red

Both agree: bearish momentum. Blue to red is a shift toward bearish.

Gray, or nothing

They don't agree, or the RSI is near 50. No signal either way.

The sell side is the mirror

Below the EMA 50, look for sells only: QQE Mod goes from blue to red on a strong bearish candle that closes near its low, enter at the next open, stop above the most recent swing high, 2R below. And the same room check, upside down: is there support just under the entry?

Both charts are illustrative, and the histograms are computed from their bars with the indicator's own math. On the right the indicators agree and the candle is strong, but there's a support zone just under the entry. Even in a downtrend, support can slow the drop, stop it, or cause a bounce before the target.

Room to the target

The last check before every entry. Put in the entry, the stop and the next level in the way, and see whether the 2R target comes first. The presets are the walkthrough and the video's two skipped trades.

A color change isn't a trade

Plenty of color changes fail. The histogram turns blue, the move doesn't last, and price can't continue higher. Trade every color change and you take a lot of weak signals.

The EMA 50, the candle and the room check are the filter.

No indicator gets rid of false signals. Test this on historical charts and in a demo account before risking real money.

Three times to stay out

The mistake to avoid is taking every signal without looking at the market around it.

Price keeps crossing the EMA 50

Above it, below it, above it again. The market is moving sideways and the direction isn't clear.

Wait until price stays on one side.

QQE Mod keeps flipping

Blue, red, blue. Trade every change and you get in again and again with no trend. And don't chase a very large candle that's already far from the EMA 50: you're late, with less room left.

Wait for a clean change with the trend.

The candle hasn't closed

An open candle can still change, and the histogram can change with it. Blue halfway through the candle isn't a signal.

Decide after the close, enter on the next open.

The indicator

One script for the whole setup (Pine Script v6): QQE Mod in its own pane, the EMA 50 on the price chart, and BUY and SELL labels when every rule on this page lines up. It marks and alerts. It does not place trades.

qqe-mod-ema50.pine · Pine Script v6
Download
//@version=6
// QQE MOD + EMA 50 — The Trade Method (thetrademethod.com/setups/qqe-mod.html)
// One indicator for the whole setup:
//   • QQE Mod in its own pane (same math as the QQE MOD script, primary RSI length 8)
//   • the EMA 50 drawn on the price chart
//   • BUY when price is above the EMA 50 and QQE Mod turns from red to blue on a strong
//     candle that has closed; SELL is the mirror image below the EMA 50
//   • stop beyond the last swing, 2R target, and a room check against the nearest swing
//     high (buy) or swing low (sell) between the entry and the target
//   • stay-out filters: EMA chop, chasing far from the EMA, unclosed candles
// It marks and alerts. It does not place trades.

indicator("QQE MOD + EMA 50", shorttitle="QQE + EMA 50", overlay=false, max_lines_count=300, max_labels_count=300)

// === PRIMARY QQE SETTINGS ===
group_primary = "Primary QQE Settings"
rsiLengthPrimary = input.int(8, title="RSI Length", minval=1, group=group_primary)
rsiSmoothingPrimary = input.int(5, title="RSI Smoothing", minval=1, group=group_primary)
qqeFactorPrimary = input.float(3.0, title="QQE Factor", group=group_primary)
sourcePrimary = input.source(close, title="RSI Source", group=group_primary)

// === SECONDARY QQE SETTINGS ===
group_secondary = "Secondary QQE Settings"
rsiLengthSecondary = input.int(6, title="RSI Length", minval=1, group=group_secondary)
rsiSmoothingSecondary = input.int(5, title="RSI Smoothing", minval=1, group=group_secondary)
qqeFactorSecondary = input.float(1.61, title="QQE Factor", group=group_secondary)
thresholdSecondary = input.float(3.0, title="Threshold", group=group_secondary)
sourceSecondary = input.source(close, title="RSI Source", group=group_secondary)

// === BOLLINGER BANDS SETTINGS ===
group_bollinger = "Bollinger Bands Settings"
bollingerLength = input.int(50, minval=1, title="Length", group=group_bollinger)
bollingerMultiplier = input.float(0.35, step=0.1, minval=0.001, maxval=5, title="Multiplier", group=group_bollinger)

// === EMA ===
group_ema = "EMA (on the price chart)"
emaLength = input.int(50, minval=1, title="EMA Length", group=group_ema)
emaColor = input.color(color.new(#ff9f0a, 0), title="EMA Color", group=group_ema)

// === SIGNAL RULES ===
group_sig = "Signal Rules"
colorWithin = input.int(10, minval=1, title="Opposite color within (bars)", group=group_sig, tooltip="Buy: the histogram must have been red within this many bars before it turns blue. Sell: blue before red.")
useCandle = input.bool(true, title="Require a strong candle", group=group_sig)
minBody = input.float(0.6, minval=0.0, maxval=1.0, step=0.05, title="Min body (% of range)", group=group_sig, tooltip="0.6 = the body is at least 60% of the candle's high-to-low range.")
closeNear = input.float(0.25, minval=0.0, maxval=1.0, step=0.05, title="Close within top/bottom (% of range)", group=group_sig, tooltip="Buy: close in the top 25% of the range. Sell: close in the bottom 25%.")

// === STOP, TARGET, ROOM ===
group_risk = "Stop, Target, Room"
swingLeft = input.int(3, minval=1, title="Swing pivot: bars left", group=group_risk)
swingRight = input.int(2, minval=1, title="Swing pivot: bars right", group=group_risk)
stopBuffer = input.float(0.0, minval=0.0, title="Stop buffer (price)", group=group_risk, tooltip="Extra distance beyond the swing, in price. Gold example: 0.50.")
rrTarget = input.float(2.0, minval=0.1, step=0.5, title="Target (R)", group=group_risk)
maxRisk = input.float(0.0, minval=0.0, title="Max stop distance (price, 0 = off)", group=group_risk, tooltip="Skip the trade when the stop is further than this from the entry.")
useRoom = input.bool(true, title="Skip when a level sits before the target", group=group_risk, tooltip="Buy: the nearest earlier swing high above the entry. Sell: the nearest earlier swing low below it.")
levelMemory = input.int(30, minval=1, maxval=200, title="Swing levels to remember", group=group_risk)

// === STAY-OUT FILTERS ===
group_out = "Stay-Out Filters"
useChop = input.bool(true, title="Skip when price keeps crossing the EMA", group=group_out)
chopBars = input.int(20, minval=2, title="Chop: look back (bars)", group=group_out)
chopMax = input.int(3, minval=0, title="Chop: max EMA crosses", group=group_out)
useChase = input.bool(true, title="Skip when too far from the EMA (chasing)", group=group_out)
chaseAtr = input.float(2.5, minval=0.1, step=0.1, title="Chase: max distance (ATRs)", group=group_out)

// === DISPLAY ===
group_disp = "Display"
showLevels = input.bool(true, title="Draw entry, stop and target", group=group_disp)
levelBars = input.int(20, minval=1, maxval=400, title="Level length (bars)", group=group_disp)
showSkips = input.bool(true, title="Mark skipped signals (no room)", group=group_disp)

// === FUNCTIONS ===
calculateQQE(rsiLength, smoothingFactor, qqeFactor, source) =>
    wildersLength = rsiLength * 2 - 1
    rsi = ta.rsi(source, rsiLength)
    smoothedRsi = ta.ema(rsi, smoothingFactor)
    atrRsi = math.abs(smoothedRsi[1] - smoothedRsi)
    smoothedAtrRsi = ta.ema(atrRsi, wildersLength)
    dynamicAtrRsi = smoothedAtrRsi * qqeFactor

    longBand = 0.0
    shortBand = 0.0
    trendDirection = 0

    newShortBand = smoothedRsi + dynamicAtrRsi
    newLongBand = smoothedRsi - dynamicAtrRsi
    longBand := smoothedRsi[1] > longBand[1] and smoothedRsi > longBand[1] ? math.max(longBand[1], newLongBand) : newLongBand
    shortBand := smoothedRsi[1] < shortBand[1] and smoothedRsi < shortBand[1] ? math.min(shortBand[1], newShortBand) : newShortBand
    longBandCross = ta.cross(longBand[1], smoothedRsi)

    if ta.cross(smoothedRsi, shortBand[1])
        trendDirection := 1
    else if longBandCross
        trendDirection := -1
    else
        trendDirection := trendDirection[1]

    qqeTrendLine = trendDirection == 1 ? longBand : shortBand
    [qqeTrendLine, smoothedRsi]

// nearest remembered level above (dir = 1) or below (dir = -1) a price
nearestLevel(array<float> levels, float price, int dir) =>
    float best = na
    if array.size(levels) > 0
        for i = 0 to array.size(levels) - 1
            lv = array.get(levels, i)
            if dir == 1 and lv > price and (na(best) or lv < best)
                best := lv
            if dir == -1 and lv < price and (na(best) or lv > best)
                best := lv
    best

// === QQE MOD ===
[primaryQQETrendLine, primaryRSI] = calculateQQE(rsiLengthPrimary, rsiSmoothingPrimary, qqeFactorPrimary, sourcePrimary)
[secondaryQQETrendLine, secondaryRSI] = calculateQQE(rsiLengthSecondary, rsiSmoothingSecondary, qqeFactorSecondary, sourceSecondary)

bollingerBasis = ta.sma(primaryQQETrendLine - 50, bollingerLength)
bollingerDeviation = bollingerMultiplier * ta.stdev(primaryQQETrendLine - 50, bollingerLength)
bollingerUpper = bollingerBasis + bollingerDeviation
bollingerLower = bollingerBasis - bollingerDeviation

qqeBlue = secondaryRSI - 50 > thresholdSecondary and primaryRSI - 50 > bollingerUpper
qqeRed = secondaryRSI - 50 < -thresholdSecondary and primaryRSI - 50 < bollingerLower

rsiColorSecondary = math.abs(secondaryRSI - 50) > thresholdSecondary ? color.new(#707070, 20) : na

// === EMA 50 AND FILTERS ===
ema50 = ta.ema(close, emaLength)
atr14 = ta.atr(14)
emaCrosses = math.sum(ta.cross(close, ema50) ? 1 : 0, chopBars)
chopOk = not useChop or emaCrosses <= chopMax
chaseOk = not useChase or math.abs(close - ema50) <= chaseAtr * atr14

// === COLOR CHANGES ===
barsSinceRed = ta.barssince(qqeRed)
barsSinceBlue = ta.barssince(qqeBlue)
turnBlue = qqeBlue and not qqeBlue[1] and barsSinceRed[1] < colorWithin
turnRed = qqeRed and not qqeRed[1] and barsSinceBlue[1] < colorWithin

// === THE CANDLE ===
candleRange = high - low
bodyPct = candleRange > 0 ? math.abs(close - open) / candleRange : 0.0
bullCandle = not useCandle or (close > open and bodyPct >= minBody and (high - close) / candleRange <= closeNear)
bearCandle = not useCandle or (close < open and bodyPct >= minBody and (close - low) / candleRange <= closeNear)

// === SWINGS: the stop, and the levels for the room check ===
var float lastSwingLow = na
var float lastSwingHigh = na
var array<float> swingHighs = array.new<float>()
var array<float> swingLows = array.new<float>()
pl = ta.pivotlow(low, swingLeft, swingRight)
ph = ta.pivothigh(high, swingLeft, swingRight)
if not na(pl)
    lastSwingLow := pl
    array.push(swingLows, pl)
    if array.size(swingLows) > levelMemory
        array.shift(swingLows)
if not na(ph)
    lastSwingHigh := ph
    array.push(swingHighs, ph)
    if array.size(swingHighs) > levelMemory
        array.shift(swingHighs)

// the swing must sit beyond this candle, or it can't hold a stop
buyStop = math.min(nz(lastSwingLow, low), low) - stopBuffer
sellStop = math.max(nz(lastSwingHigh, high), high) + stopBuffer
buyRisk = close - buyStop
sellRisk = sellStop - close
buyTarget = close + rrTarget * buyRisk
sellTarget = close - rrTarget * sellRisk
buyLevel = nearestLevel(swingHighs, close, 1)
sellLevel = nearestLevel(swingLows, close, -1)
buyRoom = not useRoom or na(buyLevel) or buyLevel >= buyTarget
sellRoom = not useRoom or na(sellLevel) or sellLevel <= sellTarget
buyRiskOk = buyRisk > 0 and (maxRisk == 0 or buyRisk <= maxRisk)
sellRiskOk = sellRisk > 0 and (maxRisk == 0 or sellRisk <= maxRisk)

// === SIGNALS (only on a closed candle) ===
buySetup = barstate.isconfirmed and close > ema50 and turnBlue and bullCandle and chopOk and chaseOk and buyRiskOk
sellSetup = barstate.isconfirmed and close < ema50 and turnRed and bearCandle and chopOk and chaseOk and sellRiskOk
buySignal = buySetup and buyRoom
sellSignal = sellSetup and sellRoom
buySkip = buySetup and not buyRoom
sellSkip = sellSetup and not sellRoom

// === PANE: QQE MOD ===
plot(secondaryQQETrendLine - 50, title="Secondary QQE Trend Line", color=color.white, linewidth=2)
plot(secondaryRSI - 50, color=rsiColorSecondary, title="Secondary RSI Histogram", style=plot.style_columns)
plot(qqeBlue ? secondaryRSI - 50 : na, title="QQE Up Signal", style=plot.style_columns, color=#00c3ff)
plot(qqeRed ? secondaryRSI - 50 : na, title="QQE Down Signal", style=plot.style_columns, color=#ff0062)
hline(0, title="Zero Line", color=color.white, linestyle=hline.style_dotted)

// === PRICE CHART: EMA 50 and the signals ===
plot(ema50, title="EMA 50", color=emaColor, linewidth=2, force_overlay=true)
plotshape(buySignal, title="Buy", style=shape.labelup, location=location.belowbar, color=color.new(#30d158, 0), textcolor=color.black, text="BUY", size=size.small, force_overlay=true)
plotshape(sellSignal, title="Sell", style=shape.labeldown, location=location.abovebar, color=color.new(#ff453a, 0), textcolor=color.white, text="SELL", size=size.small, force_overlay=true)
plotshape(showSkips and buySkip, title="Buy skipped (no room)", style=shape.xcross, location=location.belowbar, color=color.new(#8e8e93, 0), text="no room", textcolor=color.new(#8e8e93, 0), size=size.tiny, force_overlay=true)
plotshape(showSkips and sellSkip, title="Sell skipped (no room)", style=shape.xcross, location=location.abovebar, color=color.new(#8e8e93, 0), text="no room", textcolor=color.new(#8e8e93, 0), size=size.tiny, force_overlay=true)

// entry (next open, drawn at this close), stop and target
if showLevels and (buySignal or sellSignal)
    isBuy = buySignal
    stopPx = isBuy ? buyStop : sellStop
    tgtPx = isBuy ? buyTarget : sellTarget
    x2 = bar_index + levelBars
    line.new(bar_index, close, x2, close, color=color.new(color.white, 0), width=1, force_overlay=true)
    line.new(bar_index, stopPx, x2, stopPx, color=color.new(#ff453a, 0), width=2, force_overlay=true)
    line.new(bar_index, tgtPx, x2, tgtPx, color=color.new(#30d158, 0), width=2, force_overlay=true)
    label.new(x2, stopPx, "Stop " + str.tostring(stopPx, format.mintick), style=label.style_label_left, color=color.new(#ff453a, 0), textcolor=color.black, size=size.tiny, force_overlay=true)
    label.new(x2, tgtPx, str.tostring(rrTarget) + "R " + str.tostring(tgtPx, format.mintick), style=label.style_label_left, color=color.new(#30d158, 0), textcolor=color.black, size=size.tiny, force_overlay=true)

// === ALERTS ===
alertcondition(buySignal, title="QQE + EMA 50 Buy", message="QQE Mod turned blue above the EMA 50 on a strong closed candle: buy the next open.")
alertcondition(sellSignal, title="QQE + EMA 50 Sell", message="QQE Mod turned red below the EMA 50 on a strong closed candle: sell the next open.")
alertcondition(buySkip or sellSkip, title="QQE + EMA 50 Skipped (no room)", message="QQE + EMA 50 signal skipped: a level sits before the target.")
if buySignal
    alert("BUY " + syminfo.ticker + " · entry ~" + str.tostring(close, format.mintick) + " · stop " + str.tostring(buyStop, format.mintick) + " · target " + str.tostring(buyTarget, format.mintick), alert.freq_once_per_bar_close)
if sellSignal
    alert("SELL " + syminfo.ticker + " · entry ~" + str.tostring(close, format.mintick) + " · stop " + str.tostring(sellStop, format.mintick) + " · target " + str.tostring(sellTarget, format.mintick), alert.freq_once_per_bar_close)

Watch the video

The full walkthrough: setting up QQE Mod and the EMA 50 on a 5-minute gold chart, a buy, a sell, two trades skipped for lack of room, and the three times to stay out.

Open on YouTube ›

The trend picks the side. The color picks the moment.

QQE Mod alone gives too many signals. Taken only in the EMA 50's direction, on a strong candle that has closed, with the stop at the last swing and room for 2R, most of the weak ones drop out.

  • Above the EMA 50, red to blue. Below it, blue to red. Crossing it, nothing.
  • Wait for the close, enter on the next open, stop beyond the swing.
  • No room before the next level, no trade.

Based on a video walkthrough of QQE Mod (Mihkel00's TradingView indicator) with an EMA 50 on 5-minute gold, and the Pine Script code above. The walkthrough, the stepper chart, the sell charts and the stay-out loops are illustrative, not real prices; the histograms on the walkthrough, stepper and sell charts are calculated from those made-up bars with the same math as the code.