Strategy · Pine Script v6 · On the chart

Trend Following Strategy - Triangle Entries

by rosijay17-cmd

A trend-following strategy that marks entries with triangles.

View on GitHub

Repaints

GitHub stars1on the repository
Pine versionv6current
Lines of code1,274
Settings40inputs
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,274 lines of Pine Script v6 from Trend_Following_Strategy_Triangle_Entries_v1.pine, published under GPL-3.0. Keep the author's credit and licence lines when you reuse it.

Trend_Following_Strategy_Triangle_Entries_v1.pine
//@version=6
//@strategy_alert_message {{strategy.order.alert_message}} | Fill={{strategy.order.price}}

strategy(
    "Trend Following Strategy - Triangle Entries v1",
    overlay = true,
    pyramiding = 0,
    process_orders_on_close = true,
    calc_on_order_fills = true,
    calc_on_every_tick = false,
    max_labels_count = 500
)

//=============================================================================
// INPUT GROUPS
//=============================================================================

const string GROUP_GENERAL = "01 — General"
const string GROUP_TREND   = "02 — Trend Engine"
const string GROUP_ENTRY   = "03 — Entry"
const string GROUP_RISK    = "04 — Risk Management"
const string GROUP_SESSION = "05 — Session"
const string GROUP_ALERT   = "06 — Alerts"
const string GROUP_VISUAL  = "07 — Visuals"

//=============================================================================
// GENERAL
//=============================================================================

bool allowLongInput = input.bool(
    true,
    "Enable Longs",
    group = GROUP_GENERAL
)

bool allowShortInput = input.bool(
    true,
    "Enable Shorts",
    group = GROUP_GENERAL
)

float quantityInput = input.float(
    1.0,
    "Order Quantity",
    minval = 0.01,
    step = 0.01,
    group = GROUP_GENERAL
)

int maxTradesPerDayInput = input.int(
    4,
    "Maximum Trades Per Day",
    minval = 1,
    maxval = 20,
    group = GROUP_GENERAL
)

//=============================================================================
// TREND ENGINE
//=============================================================================

int fastEmaLengthInput = input.int(
    20,
    "Fast EMA",
    minval = 2,
    group = GROUP_TREND
)

int slowEmaLengthInput = input.int(
    50,
    "Slow EMA",
    minval = 3,
    group = GROUP_TREND
)

int slopeLookbackInput = input.int(
    5,
    "Slow EMA Slope Lookback",
    minval = 1,
    group = GROUP_TREND
)

float minimumSlopeAtrInput = input.float(
    0.10,
    "Minimum Trend Slope / ATR",
    minval = 0.0,
    step = 0.01,
    tooltip = "Higher values require a stronger EMA trend.",
    group = GROUP_TREND
)

bool useAdxInput = input.bool(
    true,
    "Use ADX Trend Strength",
    group = GROUP_TREND
)

int diLengthInput = input.int(
    14,
    "DI Length",
    minval = 2,
    group = GROUP_TREND
)

int adxSmoothingInput = input.int(
    14,
    "ADX Smoothing",
    minval = 2,
    group = GROUP_TREND
)

float minimumAdxInput = input.float(
    20.0,
    "Minimum ADX",
    minval = 1.0,
    step = 0.5,
    group = GROUP_TREND
)

//=============================================================================
// HIGHER TIMEFRAME TREND
//=============================================================================

bool useHTFInput = input.bool(
    true,
    "Use Higher Timeframe Trend",
    group = GROUP_TREND
)

// FIX: default was "60" (1H), which errors out (RE10142) on any chart
// timeframe of 1H or above. "D" stays valid regardless of which
// intraday timeframe this gets applied to; still fully overridable.
string htfInput = input.timeframe(
    "D",
    "Higher Timeframe",
    group = GROUP_TREND
)

int htfFastLengthInput = input.int(
    20,
    "HTF Fast EMA",
    minval = 2,
    group = GROUP_TREND
)

int htfSlowLengthInput = input.int(
    50,
    "HTF Slow EMA",
    minval = 3,
    group = GROUP_TREND
)

//=============================================================================
// ENTRY
//=============================================================================

string entryModeInput = input.string(
    "Pullback Continuation",
    "Entry Mode",
    options = [
        "Pullback Continuation",
        "Breakout"
    ],
    group = GROUP_ENTRY
)

//-----------------------------------------------------------------------------
// Pullback
//-----------------------------------------------------------------------------

float pullbackToleranceAtrInput = input.float(
    0.20,
    "Pullback EMA Tolerance — ATR",
    minval = 0.0,
    step = 0.05,
    tooltip = "How close price must come to the fast EMA.",
    group = GROUP_ENTRY
)

string pullbackConfirmationInput = input.string(
    "Break Previous Bar",
    "Pullback Confirmation",
    options = [
        "Bull/Bear Candle",
        "Break Previous Bar"
    ],
    group = GROUP_ENTRY
)

//-----------------------------------------------------------------------------
// Breakout
//-----------------------------------------------------------------------------

int breakoutLookbackInput = input.int(
    10,
    "Breakout Lookback",
    minval = 2,
    group = GROUP_ENTRY
)

float breakoutBufferAtrInput = input.float(
    0.05,
    "Breakout Buffer — ATR",
    minval = 0.0,
    step = 0.01,
    group = GROUP_ENTRY
)

//-----------------------------------------------------------------------------
// Extra confirmation
//-----------------------------------------------------------------------------

bool requireVolumeInput = input.bool(
    false,
    "Require Above-Average Volume",
    group = GROUP_ENTRY
)

int volumeLengthInput = input.int(
    20,
    "Volume Average Length",
    minval = 2,
    group = GROUP_ENTRY
)

float volumeMultiplierInput = input.float(
    1.0,
    "Volume Multiplier",
    minval = 0.1,
    step = 0.1,
    group = GROUP_ENTRY
)

//=============================================================================
// RISK MANAGEMENT
//=============================================================================

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

string stopMethodInput = input.string(
    "Wider of ATR / Structure",
    "Stop Method",
    options = [
        "ATR",
        "Structure",
        "Wider of ATR / Structure"
    ],
    group = GROUP_RISK
)

float stopAtrInput = input.float(
    1.5,
    "ATR Stop Multiplier",
    minval = 0.1,
    step = 0.1,
    group = GROUP_RISK
)

int structureLookbackInput = input.int(
    7,
    "Structure Lookback",
    minval = 2,
    group = GROUP_RISK
)

float structureBufferAtrInput = input.float(
    0.10,
    "Structure Buffer — ATR",
    minval = 0.0,
    step = 0.05,
    group = GROUP_RISK
)

float rewardRiskInput = input.float(
    2.0,
    "Target — R",
    minval = 0.25,
    step = 0.25,
    group = GROUP_RISK
)

//-----------------------------------------------------------------------------
// Break-even
//-----------------------------------------------------------------------------

bool breakEvenInput = input.bool(
    true,
    "Move Stop To Break-Even",
    group = GROUP_RISK
)

float breakEvenTriggerInput = input.float(
    1.0,
    "Break-Even Trigger — R",
    minval = 0.25,
    step = 0.25,
    group = GROUP_RISK
)

int breakEvenOffsetTicksInput = input.int(
    0,
    "Break-Even Offset — Ticks",
    minval = 0,
    group = GROUP_RISK
)

//-----------------------------------------------------------------------------
// Trailing
//-----------------------------------------------------------------------------

bool trailingInput = input.bool(
    false,
    "Enable ATR Trailing Stop",
    group = GROUP_RISK
)

float trailingStartRInput = input.float(
    1.5,
    "Start Trailing At — R",
    minval = 0.25,
    step = 0.25,
    group = GROUP_RISK
)

float trailingAtrInput = input.float(
    1.25,
    "Trailing Distance — ATR",
    minval = 0.1,
    step = 0.05,
    group = GROUP_RISK
)

//=============================================================================
// SESSION
//=============================================================================

bool useSessionInput = input.bool(
    true,
    "Use Trading Session",
    group = GROUP_SESSION
)

string tradeSessionInput = input.session(
    "0930-1555",
    "Trading Session",
    group = GROUP_SESSION
)

string flatSessionInput = input.session(
    "1555-1600",
    "Force Flat Window",
    group = GROUP_SESSION
)

string daysInput = input.string(
    "23456",
    "Trading Days",
    tooltip = "23456 = Monday through Friday.",
    group = GROUP_SESSION
)

string timezoneInput = input.string(
    "America/New_York",
    "Time Zone",
    group = GROUP_SESSION
)

bool forceFlatInput = input.bool(
    true,
    "Close At End Of Session",
    group = GROUP_SESSION
)

//=============================================================================
// ALERTS
//=============================================================================

bool alertExitsInput = input.bool(
    false,
    "Send Exit Alerts",
    tooltip = "OFF = directional entry alerts only.",
    group = GROUP_ALERT
)

//=============================================================================
// VISUALS
//=============================================================================

bool showTrianglesInput = input.bool(
    true,
    "Show Entry Triangles",
    group = GROUP_VISUAL
)

string triangleSizeInput = input.string(
    "Small",
    "Triangle Size",
    options = [
        "Tiny",
        "Small",
        "Normal"
    ],
    group = GROUP_VISUAL
)

bool showEmaInput = input.bool(
    true,
    "Show EMAs",
    group = GROUP_VISUAL
)

bool showTrendBackgroundInput = input.bool(
    false,
    "Trend Background",
    group = GROUP_VISUAL
)

bool showTradeLevelsInput = input.bool(
    true,
    "Show Entry / Stop / Target",
    group = GROUP_VISUAL
)

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

//=============================================================================
// VALIDATION
//=============================================================================

if useSessionInput and not timeframe.isintraday
    runtime.error("Session filtering requires an intraday chart.")

if useHTFInput and timeframe.in_seconds(htfInput) <= timeframe.in_seconds(timeframe.period)
    runtime.error("Higher timeframe must be greater than chart timeframe.")

//=============================================================================
// SESSION
//=============================================================================

string tradeSession = tradeSessionInput + ":" + daysInput
string flatSession = flatSessionInput + ":" + daysInput

bool inTradeSession = not na(
    time(
        timeframe.period,
        tradeSession,
        timezoneInput
    )
)

bool inFlatSession = not na(
    time(
        timeframe.period,
        flatSession,
        timezoneInput
    )
)

bool sessionOK = not useSessionInput or inTradeSession

//=============================================================================
// CORE INDICATORS
//=============================================================================

float fastEMA = ta.ema(
    close,
    fastEmaLengthInput
)

float slowEMA = ta.ema(
    close,
    slowEmaLengthInput
)

float atr = ta.atr(
    atrLengthInput
)

[plusDI, minusDI, adx] = ta.dmi(
    diLengthInput,
    adxSmoothingInput
)

float volumeAverage = ta.sma(
    volume,
    volumeLengthInput
)

//=============================================================================
// EMA SLOPE
//=============================================================================
// FIX (syntax error CE10156, "end of line without line continuation"):
// same class of error already fixed in the previous two scripts this
// session -- multi-line expressions outside brackets used 4-space or
// 8-space continuation indents, both multiples of 4, which Pine reserves
// for if/for/function block nesting. Every broken statement below is
// collapsed onto a single line instead of re-indented. Bracket-delimited
// multi-line calls and the multi-line "if" conditions that already used
// a safe 3-space continuation are untouched.

float slowSlope = slowEMA - slowEMA[slopeLookbackInput]

float normalizedSlope = not na(atr) and atr > 0 ? slowSlope / atr : 0.0

//=============================================================================
// CONFIRMED HTF VALUES
//=============================================================================

[htfClose, htfFastEMA, htfSlowEMA] = request.security(
    syminfo.tickerid,
    htfInput,
    [
        close[1],
        ta.ema(close, htfFastLengthInput)[1],
        ta.ema(close, htfSlowLengthInput)[1]
    ],
    lookahead = barmerge.lookahead_on
)

bool htfBull = htfFastEMA > htfSlowEMA and htfClose > htfFastEMA

bool htfBear = htfFastEMA < htfSlowEMA and htfClose < htfFastEMA

//=============================================================================
// LOCAL TREND
//=============================================================================

bool adxLongOK = not useAdxInput or (adx >= minimumAdxInput and plusDI > minusDI)

bool adxShortOK = not useAdxInput or (adx >= minimumAdxInput and minusDI > plusDI)

bool localBullTrend = fastEMA > slowEMA and close > slowEMA and normalizedSlope >= minimumSlopeAtrInput and adxLongOK

bool localBearTrend = fastEMA < slowEMA and close < slowEMA and normalizedSlope <= -minimumSlopeAtrInput and adxShortOK

bool bullTrend = localBullTrend and (not useHTFInput or htfBull)

bool bearTrend = localBearTrend and (not useHTFInput or htfBear)

//=============================================================================
// VOLUME FILTER
//=============================================================================

bool volumeOK = not requireVolumeInput or volume >= volumeAverage * volumeMultiplierInput

//=============================================================================
// PULLBACK ENTRY
//=============================================================================

float pullbackTolerance = atr * pullbackToleranceAtrInput

bool longPullbackTouch = bullTrend and low <= fastEMA + pullbackTolerance and low >= slowEMA - pullbackTolerance

bool shortPullbackTouch = bearTrend and high >= fastEMA - pullbackTolerance and high <= slowEMA + pullbackTolerance

bool longBullCandle = close > open and close > fastEMA

bool shortBearCandle = close < open and close < fastEMA

bool longPreviousBarBreak = close > high[1] and close > fastEMA

bool shortPreviousBarBreak = close < low[1] and close < fastEMA

bool longPullbackConfirmation = pullbackConfirmationInput == "Bull/Bear Candle" ? longBullCandle : longPreviousBarBreak

bool shortPullbackConfirmation = pullbackConfirmationInput == "Bull/Bear Candle" ? shortBearCandle : shortPreviousBarBreak

//=============================================================================
// PULLBACK MEMORY
//
// A pullback can occur first and confirmation can happen a few bars later.
//=============================================================================

var bool longPullbackArmed = false
var bool shortPullbackArmed = false

var int longPullbackBar = na
var int shortPullbackBar = na

int pullbackExpirationBars = 5

if longPullbackTouch
    longPullbackArmed := true
    longPullbackBar := bar_index

    shortPullbackArmed := false
    shortPullbackBar := na

if shortPullbackTouch
    shortPullbackArmed := true
    shortPullbackBar := bar_index

    longPullbackArmed := false
    longPullbackBar := na

//-----------------------------------------------------------------------------
// Invalidate when trend is lost
//-----------------------------------------------------------------------------

if longPullbackArmed and not bullTrend
    longPullbackArmed := false
    longPullbackBar := na

if shortPullbackArmed and not bearTrend
    shortPullbackArmed := false
    shortPullbackBar := na

//-----------------------------------------------------------------------------
// Expire
//-----------------------------------------------------------------------------

if longPullbackArmed and not na(longPullbackBar)
    if bar_index - longPullbackBar > pullbackExpirationBars
        longPullbackArmed := false
        longPullbackBar := na

if shortPullbackArmed and not na(shortPullbackBar)
    if bar_index - shortPullbackBar > pullbackExpirationBars
        shortPullbackArmed := false
        shortPullbackBar := na

//=============================================================================
// BREAKOUT ENTRY
//=============================================================================

float priorHigh = ta.highest(high, breakoutLookbackInput)[1]

float priorLow = ta.lowest(low, breakoutLookbackInput)[1]

float breakoutBuffer = atr * breakoutBufferAtrInput

float longBreakoutLevel = priorHigh + breakoutBuffer

float shortBreakoutLevel = priorLow - breakoutBuffer

bool longBreakout = bullTrend and close > longBreakoutLevel and close[1] <= longBreakoutLevel

bool shortBreakout = bearTrend and close < shortBreakoutLevel and close[1] >= shortBreakoutLevel

//=============================================================================
// DAILY TRADE COUNT
//=============================================================================

bool newDay = timeframe.change("D")

var int tradesToday = 0

if newDay
    tradesToday := 0

    longPullbackArmed := false
    shortPullbackArmed := false

    longPullbackBar := na
    shortPullbackBar := na

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

bool canEnter = barstate.isconfirmed and sessionOK and strategy.position_size == 0 and tradesToday < maxTradesPerDayInput and volumeOK

//=============================================================================
// SELECT ENTRY MODEL
//=============================================================================
// FIX (separate from the syntax error above -- a real logic bug):
// the original used bare "longEntrySignal =" / "shortEntrySignal ="
// inside these if/else branches. In Pine, "=" on a name that already
// exists in an outer scope does NOT reassign it -- it declares a NEW
// variable shadowed to that block only. The outer longEntrySignal/
// shortEntrySignal (declared above, used below in the conflict check and
// the actual strategy.entry() calls) would have stayed permanently
// false, since the shadowed copies vanish when the if/else block ends.
// That alone would have produced zero entries even with the syntax fixed
// silently and separately from any threshold/filter tuning. Changed both
// to ":=", which is the correct outer-scope reassignment operator.

bool longEntrySignal = false
bool shortEntrySignal = false

if entryModeInput == "Pullback Continuation"

    longEntrySignal := canEnter and allowLongInput and bullTrend and longPullbackArmed and longPullbackConfirmation

    shortEntrySignal := canEnter and allowShortInput and bearTrend and shortPullbackArmed and shortPullbackConfirmation

else

    longEntrySignal := canEnter and allowLongInput and bullTrend and longBreakout

    shortEntrySignal := canEnter and allowShortInput and bearTrend and shortBreakout

//=============================================================================
// PREVENT SAME BAR CONFLICT
//=============================================================================

if longEntrySignal and shortEntrySignal
    longEntrySignal := false
    shortEntrySignal := false

//=============================================================================
// ALERT FUNCTIONS
//=============================================================================

f_entryAlert(
    string direction,
    string setup
) =>

    "TREND ENTRY " + direction + " | Symbol=" + syminfo.tickerid + " | TF=" + timeframe.period + " | Setup=" + setup + " | Signal=" + str.tostring(close, format.mintick)


f_exitAlert(
    string direction,
    float stopPrice,
    float targetPrice
) =>

    "TREND EXIT " + direction + " | Symbol=" + syminfo.tickerid + " | Stop=" + str.tostring(stopPrice, format.mintick) + " | Target=" + str.tostring(targetPrice, format.mintick)

//=============================================================================
// PENDING RISK INFORMATION
//=============================================================================

var float pendingATR = na
var float pendingStructureStop = na

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

if longEntrySignal

    pendingATR := atr

    pendingStructureStop := ta.lowest(low, structureLookbackInput) - atr * structureBufferAtrInput

    strategy.entry(
        id = "Long",
        direction = strategy.long,
        qty = quantityInput,
        comment = "BUY TREND",
        alert_message = f_entryAlert(
            "LONG",
            entryModeInput
        )
    )

    longPullbackArmed := false
    longPullbackBar := na

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

else if shortEntrySignal

    pendingATR := atr

    pendingStructureStop := ta.highest(high, structureLookbackInput) + atr * structureBufferAtrInput

    strategy.entry(
        id = "Short",
        direction = strategy.short,
        qty = quantityInput,
        comment = "SELL TREND",
        alert_message = f_entryAlert(
            "SHORT",
            entryModeInput
        )
    )

    shortPullbackArmed := false
    shortPullbackBar := na

//=============================================================================
// TRIANGLE ENTRY SIGNALS
//=============================================================================

plotshape(
    showTrianglesInput and
    longEntrySignal and
    triangleSizeInput == "Tiny",
    title = "Long Triangle Tiny",
    style = shape.triangleup,
    location = location.belowbar,
    color = color.lime,
    size = size.tiny
)

plotshape(
    showTrianglesInput and
    longEntrySignal and
    triangleSizeInput == "Small",
    title = "Long Triangle Small",
    style = shape.triangleup,
    location = location.belowbar,
    color = color.lime,
    size = size.small
)

plotshape(
    showTrianglesInput and
    longEntrySignal and
    triangleSizeInput == "Normal",
    title = "Long Triangle Normal",
    style = shape.triangleup,
    location = location.belowbar,
    color = color.lime,
    size = size.normal
)

plotshape(
    showTrianglesInput and
    shortEntrySignal and
    triangleSizeInput == "Tiny",
    title = "Short Triangle Tiny",
    style = shape.triangledown,
    location = location.abovebar,
    color = color.red,
    size = size.tiny
)

plotshape(
    showTrianglesInput and
    shortEntrySignal and
    triangleSizeInput == "Small",
    title = "Short Triangle Small",
    style = shape.triangledown,
    location = location.abovebar,
    color = color.red,
    size = size.small
)

plotshape(
    showTrianglesInput and
    shortEntrySignal and
    triangleSizeInput == "Normal",
    title = "Short Triangle Normal",
    style = shape.triangledown,
    location = location.abovebar,
    color = color.red,
    size = size.normal
)

//=============================================================================
// ACTIVE TRADE
//=============================================================================

var float activeEntry = na
var float activeStop = na
var float activeTarget = na
var float initialRisk = na

varip int lastHandledEntryBar = na

bool newLongFill = strategy.position_size > 0 and strategy.position_size[1] <= 0 and (na(lastHandledEntryBar) or lastHandledEntryBar != bar_index)

bool newShortFill = strategy.position_size < 0 and strategy.position_size[1] >= 0 and (na(lastHandledEntryBar) or lastHandledEntryBar != bar_index)

//=============================================================================
// LONG FILL
//=============================================================================

if newLongFill

    lastHandledEntryBar := bar_index
    tradesToday += 1

    activeEntry := strategy.position_avg_price

    float entryATR = na(pendingATR) ? atr : pendingATR

    float atrStop = activeEntry - entryATR * stopAtrInput

    float structureStop = pendingStructureStop

    if na(structureStop) or structureStop >= activeEntry
        structureStop := atrStop

    if stopMethodInput == "ATR"

        activeStop := atrStop

    else if stopMethodInput == "Structure"

        activeStop := structureStop

    else

        activeStop := math.min(atrStop, structureStop)

    activeStop := math.min(activeStop, activeEntry - syminfo.mintick)

    initialRisk := activeEntry - activeStop

    activeTarget := activeEntry + initialRisk * rewardRiskInput

//=============================================================================
// SHORT FILL
//=============================================================================

if newShortFill

    lastHandledEntryBar := bar_index
    tradesToday += 1

    activeEntry := strategy.position_avg_price

    float entryATR = na(pendingATR) ? atr : pendingATR

    float atrStop = activeEntry + entryATR * stopAtrInput

    float structureStop = pendingStructureStop

    if na(structureStop) or structureStop <= activeEntry
        structureStop := atrStop

    if stopMethodInput == "ATR"

        activeStop := atrStop

    else if stopMethodInput == "Structure"

        activeStop := structureStop

    else

        activeStop := math.max(atrStop, structureStop)

    activeStop := math.max(activeStop, activeEntry + syminfo.mintick)

    initialRisk := activeStop - activeEntry

    activeTarget := activeEntry - initialRisk * rewardRiskInput

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

if strategy.position_size > 0 and
   not na(activeEntry) and
   not na(initialRisk)

    //-------------------------------------------------------------
    // Break-even
    //-------------------------------------------------------------

    if breakEvenInput and
       high >= activeEntry + initialRisk * breakEvenTriggerInput

        float breakEvenStop = activeEntry + breakEvenOffsetTicksInput * syminfo.mintick

        activeStop := math.max(activeStop, breakEvenStop)

    //-------------------------------------------------------------
    // Trailing
    //-------------------------------------------------------------

    if trailingInput and
       high >= activeEntry + initialRisk * trailingStartRInput

        float trailingCandidate = close - atr * trailingAtrInput

        activeStop := math.max(activeStop, trailingCandidate)

    strategy.exit(
        id = "Long Exit",
        from_entry = "Long",
        stop = activeStop,
        limit = activeTarget,
        alert_message = f_exitAlert(
            "LONG",
            activeStop,
            activeTarget
        ),
        disable_alert = not alertExitsInput
    )

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

if strategy.position_size < 0 and
   not na(activeEntry) and
   not na(initialRisk)

    //-------------------------------------------------------------
    // Break-even
    //-------------------------------------------------------------

    if breakEvenInput and
       low <= activeEntry - initialRisk * breakEvenTriggerInput

        float breakEvenStop = activeEntry - breakEvenOffsetTicksInput * syminfo.mintick

        activeStop := math.min(activeStop, breakEvenStop)

    //-------------------------------------------------------------
    // Trailing
    //-------------------------------------------------------------

    if trailingInput and
       low <= activeEntry - initialRisk * trailingStartRInput

        float trailingCandidate = close + atr * trailingAtrInput

        activeStop := math.min(activeStop, trailingCandidate)

    strategy.exit(
        id = "Short Exit",
        from_entry = "Short",
        stop = activeStop,
        limit = activeTarget,
        alert_message = f_exitAlert(
            "SHORT",
            activeStop,
            activeTarget
        ),
        disable_alert = not alertExitsInput
    )

//=============================================================================
// FORCE FLAT
//=============================================================================

if forceFlatInput and
   inFlatSession and
   strategy.position_size != 0

    string exitDirection = strategy.position_size > 0 ? "LONG" : "SHORT"

    strategy.close_all(
        comment = "END OF SESSION",
        alert_message =
            "TREND EOD EXIT " +
            exitDirection +
            " | Symbol=" +
            syminfo.tickerid,
        disable_alert = not alertExitsInput
    )

//=============================================================================
// RESET TRADE LEVELS
//=============================================================================

if strategy.position_size == 0 and
   not newLongFill and
   not newShortFill

    activeEntry := na
    activeStop := na
    activeTarget := na
    initialRisk := na

//=============================================================================
// VISUALS
//=============================================================================

plot(
    showEmaInput
    ? fastEMA
    : na,
    "Fast EMA",
    color = color.aqua,
    linewidth = 2
)

plot(
    showEmaInput
    ? slowEMA
    : na,
    "Slow EMA",
    color = color.orange,
    linewidth = 2
)

//-----------------------------------------------------------------------------
// Trend background
//-----------------------------------------------------------------------------

color trendBackground = bullTrend ? color.new(color.green, 92) : bearTrend ? color.new(color.red, 92) : color.new(color.gray, 96)

bgcolor(
    showTrendBackgroundInput
    ? trendBackground
    : na,
    title = "Trend Background"
)

//-----------------------------------------------------------------------------
// Trade levels
//-----------------------------------------------------------------------------

plot(
    showTradeLevelsInput and
    strategy.position_size != 0
    ? activeEntry
    : na,
    "Entry",
    color = color.blue,
    linewidth = 2,
    style = plot.style_linebr
)

plot(
    showTradeLevelsInput and
    strategy.position_size != 0
    ? activeStop
    : na,
    "Stop",
    color = color.red,
    linewidth = 2,
    style = plot.style_linebr
)

plot(
    showTradeLevelsInput and
    strategy.position_size != 0
    ? activeTarget
    : na,
    "Target",
    color = color.green,
    linewidth = 2,
    style = plot.style_linebr
)

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

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

if barstate.islast

    string trendText = bullTrend ? "BULLISH" : bearTrend ? "BEARISH" : "NEUTRAL"

    string htfText = not useHTFInput ? "OFF" : htfBull ? "BULLISH" : htfBear ? "BEARISH" : "NEUTRAL"

    string statusText = strategy.position_size > 0 ? "LONG" : strategy.position_size < 0 ? "SHORT" : sessionOK ? "WAITING" : "OUT OF SESSION"

    if showDashboardInput

        table.cell(
            dashboard,
            0,
            0,
            "TREND",
            bgcolor = color.black,
            text_color = color.white
        )

        table.cell(
            dashboard,
            1,
            0,
            trendText,
            text_color = color.white
        )

        table.cell(
            dashboard,
            0,
            1,
            "HTF",
            bgcolor = color.black,
            text_color = color.white
        )

        table.cell(
            dashboard,
            1,
            1,
            htfText,
            text_color = color.white
        )

        table.cell(
            dashboard,
            0,
            2,
            "ENTRY",
            bgcolor = color.black,
            text_color = color.white
        )

        table.cell(
            dashboard,
            1,
            2,
            entryModeInput,
            text_color = color.white
        )

        table.cell(
            dashboard,
            0,
            3,
            "ADX",
            bgcolor = color.black,
            text_color = color.white
        )

        table.cell(
            dashboard,
            1,
            3,
            str.tostring(
                adx,
                "#.0"
            ),
            text_color = color.white
        )

        table.cell(
            dashboard,
            0,
            4,
            "TRADES",
            bgcolor = color.black,
            text_color = color.white
        )

        table.cell(
            dashboard,
            1,
            4,
            str.tostring(tradesToday) +
            " / " +
            str.tostring(maxTradesPerDayInput),
            text_color = color.white
        )

        table.cell(
            dashboard,
            0,
            5,
            "STATUS",
            bgcolor = color.black,
            text_color = color.white
        )

        table.cell(
            dashboard,
            1,
            5,
            statusText,
            text_color = color.white
        )

    else

        table.clear(
            dashboard,
            0,
            0,
            1,
            5
        )

Overview

Trend needs a fast and slow EMA stack with a minimum slope, an optional ADX filter and an optional higher-timeframe EMA check defaulting to daily. Two entry modes are offered: a pullback continuation to the EMA that confirms by breaking the previous bar, and a breakout over a recent lookback with an ATR buffer and optional above-average volume. The stop is the wider of an ATR multiple or recent structure, the target is a reward-to-risk multiple, and a daily trade cap applies.

Details

Published by

rosijay17-cmd on GitHub

Draws

On the price chart

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

  • Signals can change on the live bar or after it closes (repainting)

Settings

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

SettingTypeDefaultVariable
Enable LongsbooltrueallowLongInput
Enable ShortsbooltrueallowShortInput
Order Quantityfloat1.0quantityInput
Maximum Trades Per Dayint4maxTradesPerDayInput
Fast EMAint20fastEmaLengthInput
Slow EMAint50slowEmaLengthInput
Slow EMA Slope Lookbackint5slopeLookbackInput
Minimum Trend Slope / ATRfloat0.10minimumSlopeAtrInput
Use ADX Trend StrengthbooltrueuseAdxInput
DI Lengthint14diLengthInput
ADX Smoothingint14adxSmoothingInput
Minimum ADXfloat20.0minimumAdxInput
Show all 40 settings
SettingTypeDefaultVariable
Use Higher Timeframe TrendbooltrueuseHTFInput
Higher TimeframetimeframeDhtfInput
HTF Fast EMAint20htfFastLengthInput
HTF Slow EMAint50htfSlowLengthInput
Entry ModestringPullback ContinuationentryModeInput
Pullback EMA Tolerance — ATRfloat0.20pullbackToleranceAtrInput
Pullback ConfirmationstringBreak Previous BarpullbackConfirmationInput
Breakout Lookbackint10breakoutLookbackInput
Breakout Buffer — ATRfloat0.05breakoutBufferAtrInput
Require Above-Average VolumeboolfalserequireVolumeInput
Volume Average Lengthint20volumeLengthInput
Volume Multiplierfloat1.0volumeMultiplierInput
ATR Lengthint14atrLengthInput
Stop MethodstringWider of ATR / StructurestopMethodInput
ATR Stop Multiplierfloat1.5stopAtrInput
Structure Lookbackint7structureLookbackInput
Structure Buffer — ATRfloat0.10structureBufferAtrInput
Target — Rfloat2.0rewardRiskInput
Move Stop To Break-EvenbooltruebreakEvenInput
Break-Even Trigger — Rfloat1.0breakEvenTriggerInput
Break-Even Offset — Ticksint0breakEvenOffsetTicksInput
Enable ATR Trailing StopboolfalsetrailingInput
Start Trailing At — Rfloat1.5trailingStartRInput
Trailing Distance — ATRfloat1.25trailingAtrInput
Use Trading SessionbooltrueuseSessionInput
Trading Sessionsession0930-1555tradeSessionInput
Force Flat Windowsession1555-1600flatSessionInput
Trading Daysstring23456daysInput
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

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 均线突破交易系统
43 stars

This strategy executes trades on short-term cryptocurrency charts using a combination of pivot support and resistance levels and a multi-pole smoothed trend filter. Entries trigger when price crosses the smoothed trend line and confirms above or below a short-

Strategy v5 TrendBreakout Repaints
Updated 2 years ago · None stated GitHub repository of SOL 1m - Strategy Candle Bar

ADA4H Optuna Strategy

by skywalker0803r
42 stars

This strategy trades longs and shorts on the price chart. Long entries require a close above the prior Donchian high, a close above a long-term SMA, and RSI above a threshold, with size set as a percentage of equity. Long exits use a stop at the prior Donchian

Strategy v5 TrendOscillators & momentum
Updated 2 months ago · None stated GitHub repository of ADA4H Optuna Strategy
16 stars

This strategy plots Donchian channels, trailing stops, and profit targets directly on the price chart. It enters breakout trades using a 55-bar Donchian channel and sizes positions according to an ATR-based risk percentage per unit. The system adds units as pr

Strategy v6 TrendBreakout
Updated 12 months ago · None stated GitHub repository of Seykota Alt 10: Profit Targets

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