Strategy · Pine Script v6 · On the chart

Trend Following Strategy v6 Signal Cooldown

by rosijay17-cmd

A Donchian-style trend strategy that enters on a breakout of a 55-bar channel and exits on a 20-bar channel break, with a 200-period EMA as the regime filter.

View on GitHub

GitHub stars1on the repository
Pine versionv6current
Lines of code1,173
Settings26inputs
LicenceGPL-3.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 strategy, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart. The trades and results appear in the Strategy Tester tab; adjust the settings with the gear icon.

Source Code

1,173 lines of Pine Script v6 from Trend_Following_Strategy_v6_Signal_Cooldown_FIX.pine, published under GPL-3.0. Keep the author's credit and licence lines when you reuse it.

Trend_Following_Strategy_v6_Signal_Cooldown_FIX.pine
//@version=6
// FIX ("the same issue happening"): the cooldown logic itself is sound in
// this version -- it starts the clock the moment a signal is ACCEPTED
// (lastAcceptedSignalBar), not tied to strategy.closedtrades at all, so
// it's immune to the exact bug class that hit the MNQ Regime strategy
// earlier in this session. But this kept the ORIGINAL strategy.percent_of_
// equity sizing (10% of a $10,000 account) from the pre-fix version, and
// if this is being tested on MNQ (as the prior version of this script
// was), that sizing produces a ZERO-quantity order every time: 10% of
// $10,000 is $1,000, and MNQ's notional value per contract (price * $2/
// point) runs roughly $59,000 at the levels seen elsewhere in this
// session -- $1,000 / $59,000 rounds down to 0 contracts, since futures
// can't hold a fraction of a contract. A zero-quantity strategy.entry()
// is effectively a no-op: tradesThisSession and the L/S triangles still
// fire because they only read this script's own boolean conditions, but
// no real position ever opens -- same end symptom as the margin-rejection
// bug in the MNQ Regime strategy (a counted "trade" that never actually
// existed), just a different mechanism (rounds to zero instead of getting
// rejected for margin).
//
// Switched to a fixed 1-contract size, matching the fix already applied
// to the MNQ Regime strategy. If this is NOT being run on MNQ, or if 1
// contract isn't the intended size, this is the number to adjust --
// nothing else in the cooldown/session logic needs to change for that.
strategy(
     title = "Trend Following Strategy v6 - Signal Cooldown FIX",
     shorttitle = "TF v6 CD FIX",
     overlay = true,
     pyramiding = 0,
     initial_capital = 10000,
     default_qty_type = strategy.fixed,
     default_qty_value = 1,
     commission_type = strategy.commission.percent,
     commission_value = 0.05,
     slippage = 1
     )

// =============================================================================
// 01 — TREND INPUTS
// =============================================================================

string trendGroup = "01 — Trend"

int entryLengthInput = input.int(
     55,
     "Donchian Entry Length",
     minval = 2,
     group = trendGroup
     )

int exitLengthInput = input.int(
     20,
     "Donchian Exit Length",
     minval = 2,
     group = trendGroup
     )

int emaLengthInput = input.int(
     200,
     "Regime EMA Length",
     minval = 1,
     group = trendGroup
     )

bool requireFreshBreakoutInput = input.bool(
     true,
     "Require Fresh Breakout",
     tooltip = "When enabled, price must newly cross the Donchian breakout level.",
     group = trendGroup
     )

// =============================================================================
// 02 — TREND STRENGTH
// =============================================================================

string filterGroup = "02 — Trend Strength"

bool useAdxInput = input.bool(
     true,
     "Use ADX / DMI Filter",
     group = filterGroup
     )

int diLengthInput = input.int(
     14,
     "DI Length",
     minval = 1,
     group = filterGroup
     )

int adxSmoothingInput = input.int(
     14,
     "ADX Smoothing",
     minval = 1,
     group = filterGroup
     )

float adxMinimumInput = input.float(
     20.0,
     "Minimum ADX",
     minval = 0,
     step = 0.5,
     group = filterGroup
     )

// =============================================================================
// 03 — RISK MANAGEMENT
// =============================================================================

string riskGroup = "03 — Risk Management"

int atrLengthInput = input.int(
     14,
     "ATR Length",
     minval = 1,
     group = riskGroup
     )

float atrMultiplierInput = input.float(
     3.0,
     "ATR Stop Multiplier",
     minval = 0.1,
     step = 0.1,
     group = riskGroup
     )

// =============================================================================
// 04 — SESSION TRADE LIMIT
// =============================================================================

string sessionLimitGroup = "04 — Session Trade Limit"

string sessionInput = input.session(
     "0000-0000",
     "Trading Session",
     tooltip = "0000-0000 = full-day session.",
     group = sessionLimitGroup
     )

int maxTradesPerSessionInput = input.int(
     8,
     "Max Trades Per Session",
     minval = 1,
     tooltip = "Maximum number of accepted entry signals during one session.",
     group = sessionLimitGroup
     )

// =============================================================================
// 05 — COOLDOWN
// =============================================================================

string cooldownGroup = "05 — Cooldown"

bool useCooldownInput = input.bool(
     true,
     "Use Signal Cooldown",
     tooltip = "Cooldown begins immediately when an entry signal is accepted.",
     group = cooldownGroup
     )

int cooldownBarsInput = input.int(
     5,
     "Cooldown Bars",
     minval = 0,
     maxval = 500,
     tooltip = "Minimum number of chart bars between accepted entry signals. On a 5-minute chart, 5 bars = 25 minutes.",
     group = cooldownGroup
     )

// =============================================================================
// 06 — TRADE DIRECTION
// =============================================================================

string directionGroup = "06 — Direction"

string tradeDirectionInput = input.string(
     "Both",
     "Trade Direction",
     options = [
         "Both",
         "Long only",
         "Short only"
         ],
     group = directionGroup
     )

// =============================================================================
// 07 — VISUALS
// =============================================================================

string visualGroup = "07 — Visuals"

bool showChannelsInput = input.bool(
     true,
     "Show Donchian Channels",
     group = visualGroup
     )

bool showStopsInput = input.bool(
     true,
     "Show ATR Trailing Stop",
     group = visualGroup
     )

bool showBlockedBackgroundInput = input.bool(
     true,
     "Highlight Blocked Bars",
     group = visualGroup
     )

bool showSignalsInput = input.bool(
     true,
     "Show Entry Signals",
     group = visualGroup
     )

bool colorBarsInput = input.bool(
     false,
     "Color Bars By Trend",
     group = visualGroup
     )

bool showDashboardInput = input.bool(
     true,
     "Show Dashboard",
     group = visualGroup
     )

// =============================================================================
// 08 — S/R LEVELS
// =============================================================================
//
// Brought over from the LuxAlgo "Support and Resistance Levels with
// Breaks" indicator -- LEVELS ONLY (its pivot-based step-lines). Nothing
// else from that script: no volume oscillator, no break/wick shapes, no
// alertconditions, no entry logic. This strategy's own Donchian + ADX +
// cooldown entry/exit/dashboard logic is completely untouched -- these
// two step-lines are purely an additional visual reference, same as the
// existing Donchian channel plots below.
// =============================================================================

string srGroup = "08 — S/R Levels"

bool showSrLevelsInput = input.bool(
     true,
     "Show Support/Resistance Levels",
     group = srGroup
     )

int srLeftBarsInput = input.int(
     15,
     "Left Bars",
     minval = 1,
     group = srGroup
     )

int srRightBarsInput = input.int(
     15,
     "Right Bars",
     minval = 1,
     group = srGroup
     )

color srResistanceColorInput = input.color(
     color.red,
     "Resistance Color",
     group = srGroup
     )

color srSupportColorInput = input.color(
     color.blue,
     "Support Color",
     group = srGroup
     )

// =============================================================================
// TREND CALCULATIONS
// =============================================================================

float regimeEma = ta.ema(
     close,
     emaLengthInput
     )

// Use previous completed bars for Donchian levels.

float entryHigh = ta.highest(
     high,
     entryLengthInput
     )[1]

float entryLow = ta.lowest(
     low,
     entryLengthInput
     )[1]

float exitHigh = ta.highest(
     high,
     exitLengthInput
     )[1]

float exitLow = ta.lowest(
     low,
     exitLengthInput
     )[1]

// =============================================================================
// S/R PIVOT LEVELS
//
// 100% parity with the original LuxAlgo indicator's math -- pivothigh(
// leftBars, rightBars)/pivotlow(leftBars, rightBars) with no explicit
// source implicitly read high/low, matching ta.pivothigh/ta.pivotlow's
// 2-arg overload used here. fixnan() stays bare -- unlike pivothigh/
// pivotlow/ema/crossover/crossunder, it never moved into the ta.
// namespace in Pine v6.
// =============================================================================

float srPivotHighRaw = ta.pivothigh(srLeftBarsInput, srRightBarsInput)
float srPivotLowRaw = ta.pivotlow(srLeftBarsInput, srRightBarsInput)
float srHighUsePivot = fixnan(srPivotHighRaw[1])
float srLowUsePivot = fixnan(srPivotLowRaw[1])

plot(
     showSrLevelsInput ? srHighUsePivot : na,
     title = "S/R Resistance",
     color = ta.change(srHighUsePivot) != 0 ? na : srResistanceColorInput,
     linewidth = 3,
     offset = -(srRightBarsInput + 1)
     )

plot(
     showSrLevelsInput ? srLowUsePivot : na,
     title = "S/R Support",
     color = ta.change(srLowUsePivot) != 0 ? na : srSupportColorInput,
     linewidth = 3,
     offset = -(srRightBarsInput + 1)
     )

// =============================================================================
// ATR
// =============================================================================

float atrValue = ta.atr(
     atrLengthInput
     )

// =============================================================================
// DMI / ADX
// =============================================================================

[plusDi, minusDi, adx] = ta.dmi(
     diLengthInput,
     adxSmoothingInput
     )

// =============================================================================
// REGIME
// =============================================================================

bool bullishRegime =
     close > regimeEma

bool bearishRegime =
     close < regimeEma

// =============================================================================
// DIRECTION PERMISSIONS
// =============================================================================

bool allowLong =
     tradeDirectionInput != "Short only"

bool allowShort =
     tradeDirectionInput != "Long only"

// =============================================================================
// ADX / DMI
// =============================================================================

bool longStrengthOk =
     not useAdxInput or
     (
         adx >= adxMinimumInput and
         plusDi > minusDi
     )

bool shortStrengthOk =
     not useAdxInput or
     (
         adx >= adxMinimumInput and
         minusDi > plusDi
     )

// =============================================================================
// BREAKOUT CONDITIONS
// =============================================================================

bool longBeyondChannel =
     not na(entryHigh) and
     close > entryHigh

bool shortBeyondChannel =
     not na(entryLow) and
     close < entryLow

bool freshLongBreakout =
     not na(entryHigh) and
     not na(entryHigh[1]) and
     close > entryHigh and
     close[1] <= entryHigh[1]

bool freshShortBreakout =
     not na(entryLow) and
     not na(entryLow[1]) and
     close < entryLow and
     close[1] >= entryLow[1]

bool longBreakout =
     requireFreshBreakoutInput
         ? freshLongBreakout
         : longBeyondChannel

bool shortBreakout =
     requireFreshBreakoutInput
         ? freshShortBreakout
         : shortBeyondChannel

// =============================================================================
// SESSION DETECTION
// =============================================================================

int sessionTime =
     time(
         timeframe.period,
         sessionInput + ":1234567"
         )

bool inSession =
     not na(sessionTime)

bool newDay =
     ta.change(time("D")) != 0

bool previousBarInSession =
     bar_index > 0
         ? inSession[1]
         : false

bool newSession =
     inSession and
     (
         newDay or
         not previousBarInSession
     )

// =============================================================================
// SESSION TRADE COUNTER
// =============================================================================

var int tradesThisSession = 0

if newSession
    tradesThisSession := 0

bool sessionLimitReached =
     tradesThisSession >= maxTradesPerSessionInput

bool sessionLimitOK =
     inSession and
     not sessionLimitReached

// =============================================================================
// SIGNAL COOLDOWN
// =============================================================================
//
// IMPORTANT:
//
// The old version waited for strategy.closedtrades.
// That is why the dashboard stayed:
//
// BARS LEFT = n/a
//
// while entry signals continued.
//
// This version starts cooldown immediately when an ENTRY SIGNAL is accepted.
// =============================================================================

var int lastAcceptedSignalBar = na

int barsSinceLastSignal =
     na(lastAcceptedSignalBar)
         ? 1000000
         : bar_index - lastAcceptedSignalBar

bool cooldownActive =
     useCooldownInput and
     cooldownBarsInput > 0 and
     not na(lastAcceptedSignalBar) and
     barsSinceLastSignal < cooldownBarsInput

bool cooldownOK =
     not cooldownActive

int cooldownBarsLeft =
     not useCooldownInput or
     cooldownBarsInput == 0 or
     na(lastAcceptedSignalBar)
         ? 0
         : math.max(
             cooldownBarsInput - barsSinceLastSignal,
             0
             )

// =============================================================================
// MASTER ENTRY PERMISSION
// =============================================================================

bool flat =
     strategy.position_size == 0

bool entryPermission =
     flat and
     inSession and
     not sessionLimitReached and
     cooldownOK

// =============================================================================
// RAW SETUPS
// =============================================================================
//
// These represent the market conditions BEFORE cooldown/session blocking.
// Useful for dashboard diagnostics.
// =============================================================================

bool rawLongSetup =
     allowLong and
     bullishRegime and
     longStrengthOk and
     longBreakout

bool rawShortSetup =
     allowShort and
     bearishRegime and
     shortStrengthOk and
     shortBreakout

// =============================================================================
// FINAL ENTRY SIGNALS
// =============================================================================

bool longSignal =
     entryPermission and
     rawLongSetup

bool shortSignal =
     entryPermission and
     rawShortSetup

// =============================================================================
// STOPS
// =============================================================================

var float longStop = na
var float shortStop = na

// =============================================================================
// LONG ENTRY
// =============================================================================

if longSignal

    // Start cooldown IMMEDIATELY.
    lastAcceptedSignalBar := bar_index

    // Count only accepted entry signals.
    tradesThisSession += 1

    longStop :=
         close -
         atrValue * atrMultiplierInput

    shortStop := na

    strategy.entry(
         id = "Long",
         direction = strategy.long,
         comment = "Long Breakout",
         alert_message = "BULL | LONG ENTRY | DONCHIAN BREAKOUT | {{ticker}} {{interval}} @ {{close}}"
         )

    strategy.exit(
         id = "Long ATR Exit",
         from_entry = "Long",
         stop = longStop,
         comment = "Long ATR Stop",
         alert_message = "LONG EXIT | DONCHIAN BREAKOUT | {{ticker}} {{interval}} @ {{close}}"
         )

// =============================================================================
// SHORT ENTRY
// =============================================================================

if shortSignal

    // Start cooldown IMMEDIATELY.
    lastAcceptedSignalBar := bar_index

    // Count only accepted entry signals.
    tradesThisSession += 1

    shortStop :=
         close +
         atrValue * atrMultiplierInput

    longStop := na

    strategy.entry(
         id = "Short",
         direction = strategy.short,
         comment = "Short Breakout",
         alert_message = "BEAR | SHORT ENTRY | DONCHIAN BREAKOUT | {{ticker}} {{interval}} @ {{close}}"
         )

    strategy.exit(
         id = "Short ATR Exit",
         from_entry = "Short",
         stop = shortStop,
         comment = "Short ATR Stop",
         alert_message = "SHORT EXIT | DONCHIAN BREAKOUT | {{ticker}} {{interval}} @ {{close}}"
         )

// =============================================================================
// LONG MANAGEMENT
// =============================================================================

if strategy.position_size > 0

    float longCandidateStop =
         close -
         atrValue * atrMultiplierInput

    longStop :=
         math.max(
             nz(
                 longStop,
                 strategy.position_avg_price -
                 atrValue * atrMultiplierInput
                 ),
             longCandidateStop
             )

    strategy.exit(
         id = "Long ATR Exit",
         from_entry = "Long",
         stop = longStop,
         comment = "Long ATR Stop",
         alert_message = "LONG EXIT | DONCHIAN BREAKOUT | {{ticker}} {{interval}} @ {{close}}"
         )

    if not na(exitLow) and close < exitLow

        strategy.close(
             id = "Long",
             comment = "Long Channel Exit",
             alert_message = "LONG EXIT | DONCHIAN BREAKOUT | {{ticker}} {{interval}} @ {{close}}"
             )

// =============================================================================
// SHORT MANAGEMENT
// =============================================================================

if strategy.position_size < 0

    float shortCandidateStop =
         close +
         atrValue * atrMultiplierInput

    shortStop :=
         math.min(
             nz(
                 shortStop,
                 strategy.position_avg_price +
                 atrValue * atrMultiplierInput
                 ),
             shortCandidateStop
             )

    strategy.exit(
         id = "Short ATR Exit",
         from_entry = "Short",
         stop = shortStop,
         comment = "Short ATR Stop",
         alert_message = "SHORT EXIT | DONCHIAN BREAKOUT | {{ticker}} {{interval}} @ {{close}}"
         )

    if not na(exitHigh) and close > exitHigh

        strategy.close(
             id = "Short",
             comment = "Short Channel Exit",
             alert_message = "SHORT EXIT | DONCHIAN BREAKOUT | {{ticker}} {{interval}} @ {{close}}"
             )

// =============================================================================
// RESET STOPS WHEN FLAT
// =============================================================================

if strategy.position_size == 0

    if not longSignal
        longStop := na

    if not shortSignal
        shortStop := na

// =============================================================================
// BROKER-VERIFIED EXIT DETECTION
//-----------------------------------------------------------------------------
// Walks strategy.closedtrades with its own cursor, same pattern already used
// in the P0 Delta + DBR CP merged strategy -- this catches EVERY exit that
// actually happened at the broker (ATR stop hit intrabar, or the channel
// close), not just the two script-side branches that call strategy.exit()/
// strategy.close() above. Feeds the "Long Trend Exit"/"Short Trend Exit"
// alertconditions below.
// =============================================================================

var int tfProcessedClosedTrades = 0

bool longTrendClosed = false
bool shortTrendClosed = false

while tfProcessedClosedTrades < strategy.closedtrades
    int closedIdx = tfProcessedClosedTrades
    string thisClosedId = strategy.closedtrades.entry_id(closedIdx)

    if thisClosedId == "Long"
        longTrendClosed := true
    else if thisClosedId == "Short"
        shortTrendClosed := true

    tfProcessedClosedTrades += 1

// =============================================================================
// EMA
// =============================================================================

plot(
     regimeEma,
     title = "Regime EMA",
     color = color.orange,
     linewidth = 2
     )

// =============================================================================
// DONCHIAN ENTRY CHANNEL
// =============================================================================

plot(
     showChannelsInput
         ? entryHigh
         : na,
     "Long Entry Channel",
     color = color.new(color.green, 45)
     )

plot(
     showChannelsInput
         ? entryLow
         : na,
     "Short Entry Channel",
     color = color.new(color.red, 45)
     )

// =============================================================================
// DONCHIAN EXIT CHANNEL
// =============================================================================

plot(
     showChannelsInput
         ? exitHigh
         : na,
     "Short Exit Channel",
     color = color.new(color.green, 70)
     )

plot(
     showChannelsInput
         ? exitLow
         : na,
     "Long Exit Channel",
     color = color.new(color.red, 70)
     )

// =============================================================================
// ATR STOPS
// =============================================================================

plot(
     showStopsInput and strategy.position_size > 0
         ? longStop
         : na,
     "Long ATR Stop",
     color = color.red,
     linewidth = 2,
     style = plot.style_linebr
     )

plot(
     showStopsInput and strategy.position_size < 0
         ? shortStop
         : na,
     "Short ATR Stop",
     color = color.red,
     linewidth = 2,
     style = plot.style_linebr
     )

// =============================================================================
// BACKGROUND
// =============================================================================
//
// Orange = session limit reached / outside session
// Blue   = cooldown active
// =============================================================================

color blockedBackground = na

if showBlockedBackgroundInput and strategy.position_size == 0

    if not inSession or sessionLimitReached

        blockedBackground :=
             color.new(
                 color.orange,
                 85
                 )

    else if cooldownActive

        blockedBackground :=
             color.new(
                 color.blue,
                 88
                 )

bgcolor(
     blockedBackground,
     title = "Entry Blocked"
     )

// =============================================================================
// BAR COLORS
// =============================================================================

color regimeColor =
     bullishRegime
         ? color.new(color.green, 65)
         : bearishRegime
             ? color.new(color.red, 65)
             : na

barcolor(
     colorBarsInput
         ? regimeColor
         : na
     )

// =============================================================================
// ACCEPTED ENTRY SIGNALS
// =============================================================================
//
// These triangles ONLY appear when the trade is actually permitted.
//
// Therefore cooldown-blocked raw setups DO NOT produce triangles.
// =============================================================================

plotshape(
     showSignalsInput and longSignal,
     title = "Accepted Long Signal",
     style = shape.triangleup,
     location = location.belowbar,
     color = color.lime,
     size = size.small,
     text = "L"
     )

plotshape(
     showSignalsInput and shortSignal,
     title = "Accepted Short Signal",
     style = shape.triangledown,
     location = location.abovebar,
     color = color.red,
     size = size.small,
     text = "S"
     )

// =============================================================================
// DASHBOARD
// =============================================================================

var table dashboard =
     table.new(
         position.top_right,
         2,
         9,
         border_width = 1
         )

f_cell(_col, _row, _text, _color) =>

    table.cell(
         dashboard,
         _col,
         _row,
         _text,
         bgcolor = _color,
         text_color = color.white,
         text_size = size.small
         )

if showDashboardInput and barstate.islast

    // Recalculate cooldown display AFTER any signal on the current bar
    // because lastAcceptedSignalBar may have just changed.

    int liveBarsSinceSignal =
         na(lastAcceptedSignalBar)
             ? 1000000
             : bar_index - lastAcceptedSignalBar

    int liveCooldownLeft =
         not useCooldownInput or
         cooldownBarsInput == 0 or
         na(lastAcceptedSignalBar)
             ? 0
             : math.max(
                 cooldownBarsInput - liveBarsSinceSignal,
                 0
                 )

    bool liveCooldownActive =
         useCooldownInput and
         cooldownBarsInput > 0 and
         not na(lastAcceptedSignalBar) and
         liveBarsSinceSignal < cooldownBarsInput

    string cooldownText =
         not useCooldownInput
             ? "OFF"
             : na(lastAcceptedSignalBar)
                 ? "READY"
                 : str.tostring(liveCooldownLeft)

    // -------------------------------------------------------------------------
    // SESSION
    // -------------------------------------------------------------------------

    f_cell(
         0,
         0,
         "IN SESSION",
         color.gray
         )

    f_cell(
         1,
         0,
         inSession ? "YES" : "NO",
         inSession
             ? color.new(color.green, 30)
             : color.new(color.red, 30)
         )

    // -------------------------------------------------------------------------
    // TRADES
    // -------------------------------------------------------------------------

    f_cell(
         0,
         1,
         "TRADES THIS SESSION",
         color.gray
         )

    f_cell(
         1,
         1,
         str.tostring(tradesThisSession),
         color.gray
         )

    // -------------------------------------------------------------------------
    // MAX
    // -------------------------------------------------------------------------

    f_cell(
         0,
         2,
         "MAX PER SESSION",
         color.gray
         )

    f_cell(
         1,
         2,
         str.tostring(maxTradesPerSessionInput),
         color.gray
         )

    // -------------------------------------------------------------------------
    // LIMIT
    // -------------------------------------------------------------------------

    f_cell(
         0,
         3,
         "LIMIT REACHED",
         color.gray
         )

    f_cell(
         1,
         3,
         sessionLimitReached ? "YES" : "NO",
         sessionLimitReached
             ? color.new(color.red, 25)
             : color.new(color.green, 30)
         )

    // -------------------------------------------------------------------------
    // COOLDOWN
    // -------------------------------------------------------------------------

    f_cell(
         0,
         4,
         "COOLDOWN",
         color.gray
         )

    f_cell(
         1,
         4,
         useCooldownInput ? "ON" : "OFF",
         useCooldownInput
             ? color.new(color.blue, 20)
             : color.gray
         )

    // -------------------------------------------------------------------------
    // BARS LEFT
    // -------------------------------------------------------------------------

    f_cell(
         0,
         5,
         "BARS LEFT",
         color.gray
         )

    f_cell(
         1,
         5,
         cooldownText,
         liveCooldownActive
             ? color.new(color.red, 25)
             : color.new(color.green, 30)
         )

    // -------------------------------------------------------------------------
    // RAW LONG SETUP
    // -------------------------------------------------------------------------

    f_cell(
         0,
         6,
         "LONG SETUP",
         color.gray
         )

    f_cell(
         1,
         6,
         rawLongSetup ? "YES" : "NO",
         rawLongSetup
             ? color.new(color.green, 30)
             : color.new(color.red, 40)
         )

    // -------------------------------------------------------------------------
    // RAW SHORT SETUP
    // -------------------------------------------------------------------------

    f_cell(
         0,
         7,
         "SHORT SETUP",
         color.gray
         )

    f_cell(
         1,
         7,
         rawShortSetup ? "YES" : "NO",
         rawShortSetup
             ? color.new(color.green, 30)
             : color.new(color.red, 40)
         )

    // -------------------------------------------------------------------------
    // ENTRY PERMISSION
    // -------------------------------------------------------------------------

    f_cell(
         0,
         8,
         "ENTRY ALLOWED",
         color.gray
         )

    f_cell(
         1,
         8,
         entryPermission ? "YES" : "NO",
         entryPermission
             ? color.new(color.green, 30)
             : color.new(color.red, 30)
         )

// =============================================================================
// ALERTS
// =============================================================================
//
// A TradingView alert is bound to the exact contract symbol it was created
// on -- that's why the alert went dead after the September contract expired,
// not a bug in this script. No Pine code fixes that; it's how alerts bind on
// the platform. Chart and alert off the CONTINUOUS ticker (e.g. MNQ1!/NQ1!)
// instead of a dated contract (MNQU2026, MNQZ2026, ...) so the alert keeps
// firing across every roll instead of going silent again next quarter.
// =============================================================================

alertcondition(
     longSignal,
     "Long Trend Entry",
     "BULL | LONG ENTRY | DONCHIAN BREAKOUT | {{ticker}} {{interval}} @ {{close}}"
     )

alertcondition(
     shortSignal,
     "Short Trend Entry",
     "BEAR | SHORT ENTRY | DONCHIAN BREAKOUT | {{ticker}} {{interval}} @ {{close}}"
     )

alertcondition(
     longTrendClosed,
     "Long Trend Exit",
     "LONG EXIT | DONCHIAN BREAKOUT | {{ticker}} {{interval}} @ {{close}}"
     )

alertcondition(
     shortTrendClosed,
     "Short Trend Exit",
     "SHORT EXIT | DONCHIAN BREAKOUT | {{ticker}} {{interval}} @ {{close}}"
     )

// Detailed dynamic alerts (BULL/BEAR entries, LONG/SHORT exits, real prices):
// Create Alert -> this strategy -> Any alert() function call
// Message -> {{strategy.order.alert_message}}
//
// Or pick one specific signal type (only fires for that one):
// Create Alert -> this strategy -> "Long Trend Entry" / "Short Trend Entry" /
// "Long Trend Exit" / "Short Trend Exit" -- Message auto-fills, no
// placeholder needed.

Overview

Entries can require a fresh breakout and an ADX and DMI strength check. An ATR trailing stop is drawn, and a cooldown in bars blocks new signals after one is accepted. A session limit caps trades per session and direction can be restricted. Fixed one-contract sizing is used. Donchian channels, stops, signals, support and resistance levels and a dashboard draw on the chart.

Details

Published by

rosijay17-cmd on GitHub

Draws

On the price chart

Category

Trend, Breakout

Markets

Any symbol

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
Donchian Entry Lengthint55entryLengthInput
Donchian Exit Lengthint20exitLengthInput
Regime EMA Lengthint200emaLengthInput
Require Fresh BreakoutbooltruerequireFreshBreakoutInput
Use ADX / DMI FilterbooltrueuseAdxInput
DI Lengthint14diLengthInput
ADX Smoothingint14adxSmoothingInput
Minimum ADXfloat20.0adxMinimumInput
ATR Lengthint14atrLengthInput
ATR Stop Multiplierfloat3.0atrMultiplierInput
Trading Sessionsession0000-0000sessionInput
Max Trades Per Sessionint8maxTradesPerSessionInput
Show all 26 settings
SettingTypeDefaultVariable
Use Signal CooldownbooltrueuseCooldownInput
Cooldown Barsint5cooldownBarsInput
Trade DirectionstringBothtradeDirectionInput
Show Donchian ChannelsbooltrueshowChannelsInput
Show ATR Trailing StopbooltrueshowStopsInput
Highlight Blocked BarsbooltrueshowBlockedBackgroundInput
Show Entry SignalsbooltrueshowSignalsInput
Color Bars By TrendboolfalsecolorBarsInput
Show DashboardbooltrueshowDashboardInput
Show Support/Resistance LevelsbooltrueshowSrLevelsInput
Left Barsint15srLeftBarsInput
Right Barsint15srRightBarsInput
Resistance Colorcolorcolor.redsrResistanceColorInput
Support Colorcolorcolor.bluesrSupportColorInput
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

This trend-following strategy executes a classic Donchian channel breakout system designed to cross-validate backtest results against external framework benchmarks. It triggers a long entry when the closing price breaks above the highest high of the prior entr

Strategy v6 BreakoutTrend
Updated yesterday · AGPL-3.0 GitHub repository of Forven S01509 - Simple Donchian 20/10 Breakout
257 stars

This strategy plots running pivot highs as red R circles and pivot lows as blue S circles directly on the price chart. It computes an EMA 3 and a Cto trend line from close prices, then generates long signals on upward EMA-Cto crossovers combined with price pos

Strategy v6 TrendMoving averages Repaints
Updated 6 weeks ago · None stated GitHub repository of Best Chart 1m Strategy Candle Bar

12/26-IT Strategy

by hasnocool
106 stars

This strategy executes trades based on crossovers between a 12-period and a 26-period exponential moving average (EMA). Long positions can be filtered by pivot resistance breakouts and RSI boundary ranges. For trade management, it provides two configurable par

Strategy v5 TrendMoving averages
Updated 2 years ago · GPL-3.0 GitHub repository of 12/26-IT Strategy

均线突破交易系统

by tangly1024
76 stars

This strategy trades long breakouts of a fast and a slow moving average on the price chart. It opens a long position when price crosses above either average, using a percentage of equity as size. It reduces the position by a set share when the high reaches the

Strategy v5 TrendMoving averages
Updated 5 months ago · None stated GitHub repository of 均线突破交易系统
53 stars

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

Strategy v6 TrendOscillators & momentum
Updated 2 months ago · MPL-2.0 GitHub repository of BTCUSD 5M Optimized Strategy

More Trend scripts

Related on ForexR

Trade Your Charts With a Regulated Broker

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

Compare brokers