Strategy · Pine Script v6 · On the chart

Index Futures Beat Buy and Hold

by PETERSAMUELOPS12· code credited to Gotrade

A leveraged trend-following strategy for index futures that uses 20, 50 and 200 period EMAs to decide between long, flat and optional short positions.

View on GitHub

GitHub stars1on the repository
Pine versionv6current
Lines of code247
Settings19inputs
LicenceNone statedfile: MPL-2.0
Last update5 months ago25 May 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

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

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

//@version=6
strategy("Index Futures – Beat Buy & Hold", overlay=true, fill_orders_on_standard_ohlc=true,
         default_qty_type=strategy.percent_of_equity, default_qty_value=100,
         initial_capital=10000, margin_long=10.0, margin_short=10.0,
         commission_type=strategy.commission.percent, commission_value=0.02,
         calc_on_every_tick=false)

// ═══════════════════════════════════════════════════════════════════════════════
// HOW THIS BEATS BUY & HOLD
// ─────────────────────────────────────────────────────────────────────────────
// 1. AVOIDS BEAR MARKETS  — exits longs (or goes short) when trend reverses
// 2. LEVERAGES UPTRENDS   — uses futures leverage during confirmed uptrends
// 3. EARNS IN DOWNTRENDS  — optional short side during bear phases
// 4. COMPOUNDS            — equity-based sizing grows with account
// 5. VOLATILITY SCALING   — cuts size during high-volatility periods
// ═══════════════════════════════════════════════════════════════════════════════

// ── Trend ─────────────────────────────────────────────────────────────────────
grpT = "Trend Settings"
emaFast    = input.int(20,   "Fast EMA",           minval=1,  group=grpT)
emaMid     = input.int(50,   "Mid EMA",            minval=1,  group=grpT)
emaSlow    = input.int(200,  "Slow EMA (trend)",   minval=1,  group=grpT)
exitFast   = input.bool(true,"Exit on fast/mid cross (tighter)", group=grpT,
               tooltip="ON = exit when 20 crosses 50. OFF = exit only when price crosses slow EMA.")

// ── Leverage & Sizing ─────────────────────────────────────────────────────────
grpL = "Leverage & Sizing"
baseLeverage    = input.float(5.0,  "Base leverage (uptrend)",      minval=1.0, maxval=50.0, step=0.5, group=grpL,
                    tooltip="Leverage applied in confirmed uptrend. 5x means 5% equity margin moves 5×.")
strongLeverage  = input.float(8.0,  "Strong-trend leverage bonus",  minval=1.0, maxval=50.0, step=0.5, group=grpL,
                    tooltip="Applied when fast EMA slope is steep (momentum accelerating).")
shortLeverage   = input.float(3.0,  "Short (bear) leverage",        minval=1.0, maxval=50.0, step=0.5, group=grpL)
volScaleDown    = input.bool(true,  "Reduce size in high volatility", group=grpL,
                    tooltip="Cuts leverage when ATR% is above the threshold — protects against choppy markets.")
volThreshPct    = input.float(1.5,  "High-vol ATR% threshold",      minval=0.1, step=0.1, group=grpL,
                    tooltip="ATR as % of price. Above this = high vol. Leverage is halved.")

// ── Risk ──────────────────────────────────────────────────────────────────────
grpR = "Risk Management"
riskPct         = input.float(2.0,  "Risk % per trade",             minval=0.1, step=0.1, group=grpR)
atrLen          = input.int(14,     "ATR period",                   minval=1,   group=grpR)
slAtr           = input.float(2.0,  "Stop loss (× ATR)",            minval=0.1, step=0.1, group=grpR)
useShorts       = input.bool(true,  "Enable short (bear market)",   group=grpR,
                    tooltip="Go short when below slow EMA. Profits from bear phases.")
maxDrawdownPct  = input.float(20.0, "Pause trading if drawdown > X%", minval=1.0, step=1.0, group=grpR,
                    tooltip="Halts new entries if equity has dropped X% from its peak. Prevents blowup.")

// ── Momentum Confirm ──────────────────────────────────────────────────────────
grpM = "Momentum Confirmation"
useRsi     = input.bool(true,  "RSI confirmation",    group=grpM)
rsiLen     = input.int(14,     "RSI period",          group=grpM, minval=2)
rsiLongMin = input.int(45,     "Long: RSI must be >", group=grpM, tooltip="Filters out weak/oversold trend entries.")
rsiShortMax= input.int(55,     "Short: RSI must be <",group=grpM)
useVolConf = input.bool(true,  "Volume confirmation (if available)", group=grpM,
               tooltip="Only enter if today's volume is above its 20-bar average.")

// ═══════════════════════════════════════════════════════════════════════════════
// INDICATORS
// ═══════════════════════════════════════════════════════════════════════════════
emaF    = ta.ema(close, emaFast)
emaM    = ta.ema(close, emaMid)
emaS    = ta.ema(close, emaSlow)
atr     = ta.atr(atrLen)
rsi     = ta.rsi(close, rsiLen)
volMA   = ta.sma(volume, 20)

// Trend states
uptrend   = close > emaS and emaF > emaM     // price above slow EMA + fast > mid
downtrend = close < emaS and emaF < emaM     // price below slow EMA + fast < mid

// Slope of fast EMA (momentum direction)
emaSlope     = emaF - emaF[5]
strongUptrend = uptrend and emaSlope > 0 and emaSlope > emaSlope[1]

// Volatility check
atrPct    = atr / close * 100
highVol   = volScaleDown and atrPct > volThreshPct

// Volume confirmation
volOk     = not useVolConf or volume > volMA

// ── Effective leverage after vol scaling ──────────────────────────────────────
effectiveLong  = highVol ? baseLeverage / 2 : (strongUptrend ? strongLeverage : baseLeverage)
effectiveShort = highVol ? shortLeverage / 2 : shortLeverage

// ── Drawdown guard ────────────────────────────────────────────────────────────
var float peakEquity = strategy.initial_capital
peakEquity := math.max(peakEquity, strategy.equity)
currentDD  = (peakEquity - strategy.equity) / peakEquity * 100
pauseTrading = currentDD > maxDrawdownPct

// ── RSI filters ───────────────────────────────────────────────────────────────
rsiOkLong  = not useRsi or rsi > rsiLongMin
rsiOkShort = not useRsi or rsi < rsiShortMax

// ═══════════════════════════════════════════════════════════════════════════════
// ENTRY SIGNALS
// ═══════════════════════════════════════════════════════════════════════════════
// Long: trend just turned up OR price recrosses above slow EMA
longEnter  = (ta.crossover(emaF, emaM) and close > emaS) or
             ta.crossover(close, emaS)
longSignal = longEnter and rsiOkLong and volOk and not pauseTrading

// Short: trend just turned down OR price recrosses below slow EMA
shortEnter  = (ta.crossunder(emaF, emaM) and close < emaS) or
              ta.crossunder(close, emaS)
shortSignal = shortEnter and rsiOkShort and volOk and useShorts and not pauseTrading

// ═══════════════════════════════════════════════════════════════════════════════
// POSITION & SIZING
// ═══════════════════════════════════════════════════════════════════════════════
inLong   = strategy.position_size > 0
inShort  = strategy.position_size < 0

// Risk-based qty: lose riskPct% of equity if SL hit
safeEquity = math.max(strategy.equity, strategy.initial_capital * 0.01)
stopDist   = atr * slAtr
riskAmt    = safeEquity * riskPct / 100
posQty     = riskAmt / stopDist   // in instrument units

// ── SL/TP stored on entry ─────────────────────────────────────────────────────
var float entryLongSL  = na
var float entryShortSL = na

// ═══════════════════════════════════════════════════════════════════════════════
// ORDERS
// ═══════════════════════════════════════════════════════════════════════════════
// ── Long entry ────────────────────────────────────────────────────────────────
if longSignal and not inLong
    if inShort
        strategy.close("Short", comment="↑ Flip")
    entryLongSL := close - stopDist
    strategy.entry("Long", strategy.long, qty=posQty * effectiveLong,
                   comment="▲ L×" + str.tostring(math.round(effectiveLong, 1)))

// ── Short entry ───────────────────────────────────────────────────────────────
if shortSignal and not inShort
    if inLong
        strategy.close("Long", comment="↓ Flip")
    entryShortSL := close + stopDist
    strategy.entry("Short", strategy.short, qty=posQty * effectiveShort,
                   comment="▼ S×" + str.tostring(math.round(effectiveShort, 1)))

// ── Long exits ────────────────────────────────────────────────────────────────
if inLong
    // Hard stop loss
    strategy.exit("Long SL", from_entry="Long", stop=entryLongSL, comment_loss="SL")
    // Trend reversal exit
    trendExitLong = exitFast ? ta.crossunder(emaF, emaM) : ta.crossunder(close, emaS)
    if trendExitLong
        strategy.close("Long", comment="TREND ↓")

// ── Short exits ───────────────────────────────────────────────────────────────
if inShort
    strategy.exit("Short SL", from_entry="Short", stop=entryShortSL, comment_loss="SL")
    trendExitShort = exitFast ? ta.crossover(emaF, emaM) : ta.crossover(close, emaS)
    if trendExitShort
        strategy.close("Short", comment="TREND ↑")

// ═══════════════════════════════════════════════════════════════════════════════
// PLOTS
// ═══════════════════════════════════════════════════════════════════════════════
plot(emaF,  "EMA Fast",  color=color.new(color.green,  20), linewidth=1)
plot(emaM,  "EMA Mid",   color=color.new(color.orange, 20), linewidth=1)
plot(emaS,  "EMA Slow",  color=color.new(color.blue,   10), linewidth=3)

plot(inLong  ? entryLongSL  : na, "Long SL",  color=color.red,   linewidth=1, style=plot.style_linebr)
plot(inShort ? entryShortSL : na, "Short SL", color=color.red,   linewidth=1, style=plot.style_linebr)

// Trend background
bgcolor(uptrend   ? color.new(color.green, 94) : na, title="Uptrend")
bgcolor(downtrend ? color.new(color.red,   94) : na, title="Downtrend")
bgcolor(pauseTrading ? color.new(color.orange, 88) : na, title="Paused (drawdown)")

plotshape(longSignal,  "Long Entry",  shape.triangleup,   location.belowbar, color.green, size=size.small)
plotshape(shortSignal, "Short Entry", shape.triangledown, location.abovebar, color.red,   size=size.small)

// ═══════════════════════════════════════════════════════════════════════════════
// DASHBOARD
// ═══════════════════════════════════════════════════════════════════════════════
var table dash = table.new(position.top_right, 2, 13,
     bgcolor=color.new(color.black, 55), border_width=1, border_color=color.new(color.gray, 60))

if barstate.islast
    posCol  = inLong ? color.lime : (inShort ? color.red : color.gray)
    netCol  = strategy.netprofit >= 0 ? color.lime : color.red
    pnlCol  = strategy.openprofit >= 0 ? color.lime : color.red
    ddColor = currentDD > maxDrawdownPct ? color.red : (currentDD > maxDrawdownPct * 0.7 ? color.orange : color.lime)
    na_str  = "–"

    table.cell(dash, 0, 0, "Beat Buy & Hold",    text_color=color.white, text_size=size.small, bgcolor=color.new(color.navy, 25))
    table.cell(dash, 1, 0, "",                   text_color=color.white, text_size=size.small, bgcolor=color.new(color.navy, 25))

    table.cell(dash, 0, 1, "Trend",     text_color=color.silver, text_size=size.small)
    table.cell(dash, 1, 1, uptrend ? "▲ UPTREND" : (downtrend ? "▼ DOWNTREND" : "── NEUTRAL"),
               text_color=uptrend ? color.lime : (downtrend ? color.red : color.gray), text_size=size.small)

    table.cell(dash, 0, 2, "Momentum",  text_color=color.silver, text_size=size.small)
    table.cell(dash, 1, 2, strongUptrend ? "⚡ STRONG UP" : (uptrend ? "↑ Normal" : "↓ Weak"),
               text_color=strongUptrend ? color.yellow : color.white, text_size=size.small)

    table.cell(dash, 0, 3, "Volatility", text_color=color.silver, text_size=size.small)
    table.cell(dash, 1, 3, str.tostring(math.round(atrPct, 2)) + "%" + (highVol ? " ⚠ HIGH" : " normal"),
               text_color=highVol ? color.orange : color.white, text_size=size.small)

    table.cell(dash, 0, 4, "RSI",        text_color=color.silver, text_size=size.small)
    table.cell(dash, 1, 4, str.tostring(math.round(rsi, 1)),
               text_color=rsi > 70 ? color.red : (rsi < 30 ? color.lime : color.white), text_size=size.small)

    table.cell(dash, 0, 5, "Position",   text_color=color.silver, text_size=size.small)
    table.cell(dash, 1, 5, inLong ? "▲ LONG " + str.tostring(math.round(strategy.position_size, 2)) :
               (inShort ? "▼ SHORT " + str.tostring(math.abs(math.round(strategy.position_size, 2))) : "FLAT"),
               text_color=posCol, text_size=size.small)

    table.cell(dash, 0, 6, "Leverage",   text_color=color.silver, text_size=size.small)
    curLev = inLong ? effectiveLong : (inShort ? effectiveShort : 0.0)
    table.cell(dash, 1, 6, inLong or inShort ? str.tostring(math.round(curLev, 1)) + "×" : na_str,
               text_color=color.yellow, text_size=size.small)

    table.cell(dash, 0, 7, "Stop Loss",  text_color=color.silver, text_size=size.small)
    slPrice = inLong ? entryLongSL : (inShort ? entryShortSL : na)
    table.cell(dash, 1, 7, not na(slPrice) ? str.tostring(math.round(slPrice, 2)) : na_str,
               text_color=color.orange, text_size=size.small)

    table.cell(dash, 0, 8, "Drawdown",   text_color=color.silver, text_size=size.small)
    table.cell(dash, 1, 8, str.tostring(math.round(currentDD, 1)) + "%" + (pauseTrading ? " PAUSED" : ""),
               text_color=ddColor, text_size=size.small)

    table.cell(dash, 0, 9, "Peak Equity", text_color=color.silver, text_size=size.small)
    table.cell(dash, 1, 9, "$" + str.tostring(math.round(peakEquity, 0)),
               text_color=color.lime, text_size=size.small)

    table.cell(dash, 0, 10, "Open P&L",  text_color=color.silver, text_size=size.small)
    table.cell(dash, 1, 10, "$" + str.tostring(math.round(strategy.openprofit, 2)),
               text_color=pnlCol, text_size=size.small)

    table.cell(dash, 0, 11, "Net Profit", text_color=color.silver, text_size=size.small)
    table.cell(dash, 1, 11, "$" + str.tostring(math.round(strategy.netprofit, 2)),
               text_color=netCol, text_size=size.small)

    winRate = strategy.closedtrades > 0 ? strategy.wintrades / strategy.closedtrades * 100 : 0.0
    table.cell(dash, 0, 12, "Win Rate",  text_color=color.silver, text_size=size.small)
    table.cell(dash, 1, 12, str.tostring(math.round(winRate, 1)) + "%  (" + str.tostring(strategy.closedtrades) + " trades)",
               text_color=winRate > 50 ? color.lime : color.orange, text_size=size.small)

Overview

Leverage is higher in confirmed uptrends and steeper trends, lower for shorts, and reduced when ATR as a percentage of price is high. RSI and volume confirmation, an ATR stop, risk percentage sizing and a pause after a drawdown limit apply. The name states a goal the script itself does not demonstrate.

Details

Published by

PETERSAMUELOPS12 on GitHub

Code credit

Gotrade, as written in the script's header

Draws

On the price chart

Markets

Indices

Timeframes

H4 and above

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
Fast EMAint20emaFast
Mid EMAint50emaMid
Slow EMA (trend)int200emaSlow
Exit on fast/mid cross (tighter)booltrueexitFast
Base leverage (uptrend)float5.0baseLeverage
Strong-trend leverage bonusfloat8.0strongLeverage
Short (bear) leveragefloat3.0shortLeverage
Reduce size in high volatilitybooltruevolScaleDown
High-vol ATR% thresholdfloat1.5volThreshPct
Risk % per tradefloat2.0riskPct
ATR periodint14atrLen
Stop loss (× ATR)float2.0slAtr
Show all 19 settings
SettingTypeDefaultVariable
Enable short (bear market)booltrueuseShorts
Pause trading if drawdown > X%float20.0maxDrawdownPct
RSI confirmationbooltrueuseRsi
RSI periodint14rsiLen
Long: RSI must be >int45rsiLongMin
Short: RSI must be <int55rsiShortMax
Volume confirmation (if available)booltrueuseVolConf
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

Doge SMA

by hackingthemarkets
474 stars

Doge SMA is a long-only moving-average crossover strategy drawn on the price chart. It calculates a fast and a slow simple moving average of close and enters a long position when the fast average crosses above the slow average, but only inside a user-defined s

Strategy v4 TrendMoving averages
Updated 4 years ago · None stated GitHub repository of Doge SMA

This strategy calculates and plots a fast Exponential Moving Average (EMA) and a slow EMA directly on the main price chart. It enters long trades when the fast EMA crosses above the slow EMA and exits when the fast EMA crosses below the slow EMA. Inputs allow

Strategy v6 TrendMoving averages
Updated yesterday · AGPL-3.0 GitHub repository of Forven S01508 — Simple EMA20/50 Cross
330 stars

2 EMA/SMA + RSI Strategy [Alorse] combines three configurable moving averages with a short-period Relative Strength Index filter. It plots fast, slow, and trend moving averages on the price chart. Long entries trigger when the fast moving average is above the

Strategy v4 TrendOscillators & momentum
Updated 2 months ago · None stated GitHub repository of 2 EMA/SMA + RSI Strategy [Alorse]

Acrypto - Weighted Strategy

by AlbertoCuadra
318 stars

This strategy plots on the price chart and opens long or short positions when a weighted score from MACD, Stochastic RSI, RSI, Supertrend and a moving-average crossover exceeds a user-set trigger. Each component has its own weight and candle delay. Entries can

Strategy v5 TrendOscillators & momentum
Updated 3 years ago · Custom licence GitHub repository of Acrypto - Weighted Strategy
257 stars

This strategy calculates dynamic support and resistance levels using pivot highs and lows alongside a custom smoothed trend filter and a 3-period EMA. It identifies entry opportunities when price breaks out relative to the trend filter and short-term EMA cross

Strategy v5 TrendSupport & resistance Repaints
Updated 6 weeks ago · None stated GitHub repository of 30s - ES 1m Strategy Candle Bar

EMA Crossover Strategy

by TradersPost
228 stars

EMA Crossover Strategy plots a fast and a slow exponential moving average on the price chart. It treats a confirmed fast-over-slow cross as a long condition and a confirmed cross under as a short condition. Position size is a percentage of equity. Optional per

Strategy v6 TrendMoving averages
Updated 3 months ago · None stated GitHub repository of EMA Crossover 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