About this guide: I'm Lawrence, the writer behind supa.is. Between February and May 2026 I've published 150+ articles on supa.is across crypto and brokerage tooling β including 20+ TradingView-specific guides (recent examples: TradingView Free vs Paid 2026, TradingView Alert Not Triggering? 12 Fixes, Pine Script v5 to v6 Migration). The most-repeated reader question across that TradingView archive is exactly how to build a robust, backtestable SuperTrend strategy from scratch, which is why I'm publishing this standardized guide instead of answering one-off.
The SuperTrend indicator is one of the most effective trend-following tools in a trader's arsenal β and building your own version in Pine Script gives you complete control over the logic, signals, and risk management. This guide explores how to construct a custom SuperTrend strategy indicator from scratch in Pine Script v6, breaking down the underlying math, backtesting mechanics, and filtering logic that the built-in indicator simply cannot provide.
I use TradingView daily for my USDJPY momentum trading, and the SuperTrend concept underpins a lot of how I think about trend direction. The default built-in SuperTrend is fine for quick checks, but a custom implementation lets you add filters, alerts, and multi-timeframe confirmation that the built-in version simply can't do.
What Is the SuperTrend Indicator?
The SuperTrend is an ATR-based (Average True Range) trend-following indicator that plots a dynamic line above or below price. When price is above the line, the trend is bullish. When price is below, the trend is bearish. Flip points generate buy and sell signals.
The math is straightforward:
- Upper Band = (High + Low) / 2 + Multiplier Γ ATR
- Lower Band = (High + Low) / 2 β Multiplier Γ ATR
- If the close is above the upper band, the trend flips bullish (SuperTrend = lower band)
- If the close is below the lower band, the trend flips bearish (SuperTrend = upper band)
| Parameter | Default | Effect |
|---|---|---|
| ATR Period | 10 | Number of bars used to calculate volatility. Higher = smoother, fewer signals |
| Multiplier | 3.0 | How far the bands sit from the midpoint. Higher = wider bands, fewer false signals |
Why Build a Custom SuperTrend Instead of Using the Built-In?
TradingView includes a built-in ta.supertrend() function and a default SuperTrend indicator. So why bother writing your own?
strategy() script gives you net profit, win rate, max drawdown, profit factor, and trade-by-trade results in TradingView's Strategy Tester.
3. Alert automation. Custom scripts let you create alerts that fire on your exact conditions, which you can pipe to webhooks for automated execution.
4. Multi-timeframe confirmation. You can request the SuperTrend value from a higher timeframe and only take signals that align with the bigger picture β something the built-in indicator doesn't support natively.
5. Visual customization. Add buy/sell labels, background coloring, dashboard panels, or combine SuperTrend with other indicators in a single script (important for free-tier users who are limited to 3 indicators per chart on TradingView, as of 2026-04).
Concept 1: Basic SuperTrend Indicator in Pine Script v6
Let's start with a clean SuperTrend indicator. This version uses TradingView's built-in ta.supertrend() function for the core calculation, then adds visual signals on top.
//@version=6
indicator("Custom SuperTrend", overlay=true)
// βββ INPUTS ββββββββββββββββββββββββββββββββββββββββ
atrPeriod = input.int(10, "ATR Period", minval=1)
multiplier = input.float(3.0, "Multiplier", minval=0.1, step=0.1)
// βββ SUPERTREND CALCULATION ββββββββββββββββββββββββ
[supertrend, direction] = ta.supertrend(multiplier, atrPeriod)
// direction: -1 = bullish (price above), +1 = bearish (price below)
isBullish = direction < 0
isBearish = direction > 0
// βββ PLOT ββββββββββββββββββββββββββββββββββββββββββ
plot(supertrend, "SuperTrend",
color=isBullish ? color.green : color.red,
linewidth=2, style=plot.style_linebr)
// βββ BUY / SELL SIGNALS ββββββββββββββββββββββββββββ
buySignal = isBullish and not isBullish[1]
sellSignal = isBearish and not isBearish[1]
plotshape(buySignal, "Buy", shape.triangleup,
location.belowbar, color.green, size=size.small)
plotshape(sellSignal, "Sell", shape.triangledown,
location.abovebar, color.red, size=size.small)
// βββ BACKGROUND ββββββββββββββββββββββββββββββββββββ
bgcolor(isBullish ? color.new(color.green, 93) : color.new(color.red, 93))
What this does:
- Plots the SuperTrend line in green during uptrends, red during downtrends
- Shows triangle markers at the exact bar where the trend flips
- Adds a subtle background tint so you can see trend zones at a glance
Concept 2: Converting to a Backtestable Strategy
To turn this into a strategy() so you can see actual backtest performance numbers in TradingView's Strategy Tester, the logic shifts from plot() to strategy.entry() and strategy.close().
//@version=6
strategy("SuperTrend Strategy", overlay=true,
default_qty_type=strategy.percent_of_equity,
default_qty_value=100,
initial_capital=10000,
commission_type=strategy.commission.percent,
commission_value=0.1)
// βββ INPUTS ββββββββββββββββββββββββββββββββββββββββ
atrPeriod = input.int(10, "ATR Period", minval=1)
multiplier = input.float(3.0, "Multiplier", minval=0.1, step=0.1)
// βββ SUPERTREND CALCULATION ββββββββββββββββββββββββ
[supertrend, direction] = ta.supertrend(multiplier, atrPeriod)
isBullish = direction < 0
isBearish = direction > 0
buySignal = isBullish and not isBullish[1]
sellSignal = isBearish and not isBearish[1]
// βββ STRATEGY ENTRIES ββββββββββββββββββββββββββββββ
if buySignal
strategy.entry("Long", strategy.long)
if sellSignal
strategy.close("Long")
// βββ PLOT ββββββββββββββββββββββββββββββββββββββββββ
plot(supertrend, "SuperTrend",
color=isBullish ? color.green : color.red,
linewidth=2, style=plot.style_linebr)
plotshape(buySignal, "Buy", shape.triangleup,
location.belowbar, color.green, size=size.small)
plotshape(sellSignal, "Sell", shape.triangledown,
location.abovebar, color.red, size=size.small)
After adding this to your chart, the Strategy Tester tab at the bottom of TradingView will display performance metrics. Pay attention to:
- Net Profit β total P&L including commissions
- Profit Factor β gross profit Γ· gross loss (above 1.5 is solid)
- Max Drawdown β the worst peak-to-trough decline
- Win Rate β percentage of profitable trades
commission_value=0.1 line above adds a realistic 0.1% per trade (as of 2026-04). Always include commission β it's the difference between a profitable backtest and a real-world loss.
Tip: The Strategy Tester is available on all TradingView plans, but the number of bars it processes differs by plan. Essential and above give you more historical data for longer backtests.
Concept 3: Adding an RSI Filter to Reduce False Signals
SuperTrend whipsaws hard in sideways markets. Adding an RSI filter cuts the noise: only take long entries when RSI confirms momentum is actually behind the move.
//@version=6
strategy("SuperTrend + RSI Filter", overlay=true,
default_qty_type=strategy.percent_of_equity,
default_qty_value=100,
initial_capital=10000,
commission_type=strategy.commission.percent,
commission_value=0.1)
// βββ INPUTS ββββββββββββββββββββββββββββββββββββββββ
atrPeriod = input.int(10, "ATR Period", minval=1)
multiplier = input.float(3.0, "Multiplier", minval=0.1, step=0.1)
rsiLength = input.int(14, "RSI Length", minval=1)
rsiLongMin = input.int(50, "RSI Min for Long", minval=1, maxval=100)
rsiShortMax = input.int(50, "RSI Max for Short", minval=1, maxval=100)
// βββ CALCULATIONS ββββββββββββββββββββββββββββββββββ
[supertrend, direction] = ta.supertrend(multiplier, atrPeriod)
rsi = ta.rsi(close, rsiLength)
isBullish = direction < 0
isBearish = direction > 0
buySignal = isBullish and not isBullish[1] and rsi > rsiLongMin
sellSignal = isBearish and not isBearish[1] and rsi < rsiShortMax
// βββ STRATEGY ENTRIES ββββββββββββββββββββββββββββββ
if buySignal
strategy.entry("Long", strategy.long)
if sellSignal
strategy.close("Long")
strategy.entry("Short", strategy.short)
// Exit short on next buy signal
if isBullish and not isBullish[1]
strategy.close("Short")
// βββ PLOTS βββββββββββββββββββββββββββββββββββββββββ
plot(supertrend, "SuperTrend",
color=isBullish ? color.green : color.red,
linewidth=2, style=plot.style_linebr)
plotshape(buySignal, "Buy", shape.triangleup,
location.belowbar, color.green, size=size.small)
plotshape(sellSignal, "Sell", shape.triangledown,
location.abovebar, color.red, size=size.small)
// βββ RSI PANEL (optional) ββββββββββββββββββββββββββ
// Uncomment these lines to see RSI in a separate panel:
// plot(rsi, "RSI", color.purple)
// hline(rsiLongMin, "RSI Filter Level", color.gray)
What the RSI filter does:
- A buy signal only fires if RSI is above 50, confirming upward momentum
- A sell signal only fires if RSI is below 50, confirming downward momentum
- This cuts out many low-conviction flip signals in choppy markets
Concept 4: Multi-Timeframe SuperTrend Confirmation
The best upgrade to any trend indicator is a higher-timeframe filter. Only trade with the bigger trend: if the daily SuperTrend is bullish, only take long signals on the 4-hour chart.
//@version=6
strategy("SuperTrend MTF Strategy", overlay=true,
default_qty_type=strategy.percent_of_equity,
default_qty_value=100,
initial_capital=10000,
commission_type=strategy.commission.percent,
commission_value=0.1)
// βββ INPUTS ββββββββββββββββββββββββββββββββββββββββ
atrPeriod = input.int(10, "ATR Period", minval=1)
multiplier = input.float(3.0, "Multiplier", minval=0.1, step=0.1)
htfInput = input.timeframe("D", "Higher Timeframe")
// βββ CURRENT TIMEFRAME SUPERTREND ββββββββββββββββββ
[supertrend, direction] = ta.supertrend(multiplier, atrPeriod)
isBullish = direction < 0
isBearish = direction > 0
// βββ HIGHER TIMEFRAME SUPERTREND βββββββββββββββββββ
htfDirection = request.security(syminfo.tickerid, htfInput,
ta.supertrend(multiplier, atrPeriod)[1])
// [1] prevents lookahead bias β uses the CONFIRMED bar value
htfBullish = htfDirection < 0
// βββ FILTERED SIGNALS ββββββββββββββββββββββββββββββ
buySignal = isBullish and not isBullish[1] and htfBullish
sellSignal = isBearish and not isBearish[1] and not htfBullish
if buySignal
strategy.entry("Long", strategy.long)
if sellSignal
strategy.close("Long")
// βββ PLOTS βββββββββββββββββββββββββββββββββββββββββ
plot(supertrend, "SuperTrend",
color=isBullish ? color.green : color.red,
linewidth=2, style=plot.style_linebr)
plotshape(buySignal, "Buy (MTF Confirmed)", shape.triangleup,
location.belowbar, color.green, size=size.normal)
plotshape(sellSignal, "Sell", shape.triangledown,
location.abovebar, color.red, size=size.small)
// HTF trend background
bgcolor(htfBullish ? color.new(color.green, 95) : color.new(color.red, 95))
Important: The [1] offset on the request.security() call is critical. Without it, you get lookahead bias β the strategy would "cheat" by using higher-timeframe data that wasn't available yet in real time. Always offset by 1 bar for confirmed data.
The subtle green/red background shows the higher-timeframe trend direction at a glance. Large green triangles mark buy signals that have multi-timeframe confluence β these are the highest-conviction setups.
Note: Multi-timeframe data requests require TradingView Essential or higher. Free plan users are limited in their request.security() calls.
Concept 5: Adding Stop Loss and Take Profit
Every strategy needs risk management. Here's how to add a percentage-based stop loss and take profit:
//@version=6
strategy("SuperTrend + Risk Management", overlay=true,
default_qty_type=strategy.percent_of_equity,
default_qty_value=100,
initial_capital=10000,
commission_type=strategy.commission.percent,
commission_value=0.1)
// βββ INPUTS ββββββββββββββββββββββββββββββββββββββββ
atrPeriod = input.int(10, "ATR Period", minval=1)
multiplier = input.float(3.0, "Multiplier", minval=0.1, step=0.1)
slPercent = input.float(2.0, "Stop Loss %", minval=0.1, step=0.1)
tpPercent = input.float(4.0, "Take Profit %", minval=0.1, step=0.1)
useTrailSL = input.bool(false, "Use Trailing Stop")
trailPercent = input.float(1.5, "Trail %", minval=0.1, step=0.1)
// βββ SUPERTREND ββββββββββββββββββββββββββββββββββββ
[supertrend, direction] = ta.supertrend(multiplier, atrPeriod)
isBullish = direction < 0
isBearish = direction > 0
buySignal = isBullish and not isBullish[1]
sellSignal = isBearish and not isBearish[1]
// βββ ENTRIES WITH SL/TP ββββββββββββββββββββββββββββ
if buySignal
strategy.entry("Long", strategy.long)
if useTrailSL
strategy.exit("Trail", "Long",
trail_points=close * trailPercent / 100 / syminfo.mintick,
trail_offset=close * trailPercent / 100 / syminfo.mintick)
else
strategy.exit("SL/TP", "Long",
stop=close * (1 - slPercent / 100),
limit=close * (1 + tpPercent / 100))
if sellSignal
strategy.close("Long")
// βββ PLOTS βββββββββββββββββββββββββββββββββββββββββ
plot(supertrend, "SuperTrend",
color=isBullish ? color.green : color.red,
linewidth=2, style=plot.style_linebr)
plotshape(buySignal, "Buy", shape.triangleup,
location.belowbar, color.green, size=size.small)
plotshape(sellSignal, "Sell", shape.triangledown,
location.abovebar, color.red, size=size.small)
Risk management options in this script:
- Fixed SL/TP: Default 2% stop loss and 4% take profit gives a 1:2 risk-reward ratio
- Trailing Stop: Toggle on to use a trailing stop instead β the stop follows price up but never moves down
- SuperTrend Exit: The
sellSignalclose acts as an additional exit β if the trend reverses before SL/TP is hit, you exit on the trend flip
Concept 6: Full Production Strategy β Complete Code
Here's the complete strategy combining everything: SuperTrend + RSI filter + multi-timeframe confirmation + risk management + a dashboard panel.
//@version=6
strategy("SuperTrend Pro Strategy", overlay=true,
default_qty_type=strategy.percent_of_equity,
default_qty_value=100,
initial_capital=10000,
commission_type=strategy.commission.percent,
commission_value=0.1,
max_bars_back=5000)
// βββββββββββββββββββββββββββββββββββββββββββββββββββ
// INPUTS
// βββββββββββββββββββββββββββββββββββββββββββββββββββ
grpST = "SuperTrend Settings"
atrPeriod = input.int(10, "ATR Period", minval=1, group=grpST)
multiplier = input.float(3.0, "Multiplier", minval=0.1, step=0.1, group=grpST)
grpFilter = "Filters"
useRSI = input.bool(true, "Use RSI Filter", group=grpFilter)
rsiLength = input.int(14, "RSI Length", minval=1, group=grpFilter)
rsiMin = input.int(50, "RSI Min for Long", group=grpFilter)
useMTF = input.bool(false, "Use Multi-Timeframe Filter", group=grpFilter)
htfInput = input.timeframe("D", "Higher Timeframe", group=grpFilter)
grpRisk = "Risk Management"
slPercent = input.float(2.0, "Stop Loss %", minval=0.1, step=0.1, group=grpRisk)
tpPercent = input.float(4.0, "Take Profit %", minval=0.1, step=0.1, group=grpRisk)
allowShort = input.bool(false, "Allow Short Trades", group=grpRisk)
Risk Warning
Risk Warning: Crypto trading involves substantial risk of loss. Never invest more than you can afford to lose. This is not financial advice.
FAQ
What is the best SuperTrend setting?
The default 10-period ATR with a 3.0 multiplier works well for most markets. For faster, noisier markets like crypto, you might increase the ATR period to 14 and the multiplier to 4.0 to reduce whipsaws.Can I use SuperTrend on the free TradingView plan?
Yes, but the free plan limits you to 3 indicators per chart. Combining SuperTrend with RSI and other tools requires a paid plan, or writing a single custom script that includes all the logic.Why does my SuperTrend strategy backtest poorly?
SuperTrend is a trend-following indicator. It performs poorly in choppy, sideways markets. Always add a filter (like RSI or multi-timeframe confirmation) to avoid taking signals during consolidation.How do I avoid lookahead bias in multi-timeframe SuperTrend?
Always use[1] at the end of your request.security() call. This ensures you are using the confirmed value of the higher timeframe, not the current, unconfirmed bar.