SuperTrend Is Underrated
Moving averages dominate trend-following conversations. EMA crossovers, SMA ribbons, VWAP — everyone knows them, everyone uses them. SuperTrend gets far less attention despite solving a problem that moving averages handle poorly: adapting to volatility.
A 20 EMA treats a day where BTC moves $200 the same as a day where it moves $3,000. The EMA just averages closing prices, oblivious to how volatile the market is. SuperTrend uses the Average True Range (ATR) to set its trailing stop distance, which means it automatically widens during volatile periods and tightens during calm ones. This single property makes it more useful for crypto than most traders realize.
I built an enhanced version of SuperTrend using Cursor that goes beyond the basic implementation. It adds ATR multiplier visualization, color-coded trend bands, alert conditions for trend flips, and an optional volume filter. I have been running it on BTC/USDT for several months and this article covers everything — the code, the backtesting, the parameter tuning, and the failure modes.
How SuperTrend Works: The Mechanics
SuperTrend is an ATR-based trailing stop that flips between acting as support (during uptrends) and resistance (during downtrends). The calculation has three steps.
Step 1: Calculate ATR. The Average True Range measures volatility over N periods. True Range for each bar is the greatest of: current high minus current low, absolute value of current high minus previous close, or absolute value of current low minus previous close. ATR is the moving average of True Range over the specified period.
Step 2: Calculate basic bands. The upper band is (high + low) / 2 + (multiplier * ATR). The lower band is (high + low) / 2 - (multiplier * ATR). The midpoint (high + low) / 2 is the HL2 source, and the ATR multiplied by a factor creates a volatility envelope around it.
Step 3: Determine trend direction. If the close crosses above the upper band, the trend flips to up and SuperTrend becomes the lower band (acting as support). If the close crosses below the lower band, the trend flips to down and SuperTrend becomes the upper band (acting as resistance). Once flipped, the band ratchets — the lower band only moves up (never down) during an uptrend, and the upper band only moves down (never up) during a downtrend.
This ratcheting behavior is what makes SuperTrend useful. During an uptrend, the support level trails below price and rises as price rises, but it never drops. It locks in gains. You stay in the trend until price violates the trailing stop. During calm periods the stop is tight (small ATR means small band distance), and during volatile periods the stop is wide (large ATR means more room to breathe).
Why I Chose SuperTrend Over Moving Average Crossovers
I ran both a 9/21 EMA crossover and a SuperTrend (ATR 10, multiplier 3.0) on BTC/USDT 4H over the same six-month window. The EMA crossover generated 47 signals. SuperTrend generated 23. The EMA crossover gave back large chunks of profit during volatile chop because it would flip back and forth rapidly when EMAs were close together. SuperTrend, because its band distance adapts to volatility, was less prone to rapid flipping during those same periods.
The trade-off is entry timing. EMA crossovers often signal trend changes earlier because they react directly to price. SuperTrend signals later because price must move far enough to cross the volatility band. You get fewer whipsaws but slightly worse entries. For my style — fewer, more patient trades with wider stops — SuperTrend fits better.
The Prompt I Gave Cursor
I used Cursor’s AI chat (Cmd+K in the editor) with the following prompt. This was my second iteration — the first produced a basic SuperTrend without the enhancements.
Write a TradingView Pine Script v5 indicator called "Enhanced SuperTrend" with overlay=true.
Requirements:
1. Calculate SuperTrend using ATR with configurable period (default 10) and multiplier (default 3.0)
2. Plot the SuperTrend line color-coded: green when trend is up, red when trend is down
3. Fill the area between price and the SuperTrend line with a semi-transparent color (green fill during uptrend, red fill during downtrend)
4. Plot the ATR value as a separate pane below the chart, with a horizontal line showing the average ATR over the last 50 periods for reference
5. Add triangle markers on the chart when the trend flips: green triangle up when flipping bullish, red triangle down when flipping bearish
6. Add alertcondition() for trend flip in both directions
7. Add an optional volume filter: when enabled, only show trend flip signals if volume on the flip bar exceeds 1.5x the 20-period volume SMA
8. Add a "trend duration" label that shows how many bars the current trend has been active, displayed on every 20th bar
9. Make all parameters configurable via input()
10. Use var keyword for variables that need to persist between bars
Cursor generated a working first draft in about 15 seconds. I made two manual edits: I changed the fill transparency from 90 to 85 because the original was nearly invisible on a dark theme, and I adjusted the trend duration label to display on the latest bar rather than every 20th bar, then added an input toggle for it.
The Full Pine Script v5 Code
//@version=5
indicator("Enhanced SuperTrend", overlay=true)
// ─── Inputs ───────────────────────────────────────────
atrPeriod = input.int(10, "ATR Period", minval=1, maxval=50)
multiplier = input.float(3.0, "ATR Multiplier", minval=0.5, maxval=10.0, step=0.1)
useVolFilter = input.bool(false, "Volume Filter for Signals")
volMultiple = input.float(1.5, "Volume Threshold (x SMA)", minval=1.0, step=0.1)
volSmaPeriod = input.int(20, "Volume SMA Period", minval=1)
showFill = input.bool(true, "Show Trend Fill")
showDuration = input.bool(true, "Show Trend Duration Label")
// ─── ATR Calculation ──────────────────────────────────
atr = ta.atr(atrPeriod)
// ─── SuperTrend Calculation ───────────────────────────
hl2Source = hl2
// Basic upper and lower bands
basicUpperBand = hl2Source + (multiplier * atr)
basicLowerBand = hl2Source - (multiplier * atr)
// Final bands with ratcheting logic
var float finalUpperBand = na
var float finalLowerBand = na
var int trendDirection = 1 // 1 = up, -1 = down
var int trendBars = 0
// Upper band: can only move DOWN during a downtrend
finalUpperBand := na(finalUpperBand[1]) ? basicUpperBand :
basicUpperBand < finalUpperBand[1] ? basicUpperBand :
close[1] > finalUpperBand[1] ? basicUpperBand :
finalUpperBand[1]
// Lower band: can only move UP during an uptrend
finalLowerBand := na(finalLowerBand[1]) ? basicLowerBand :
basicLowerBand > finalLowerBand[1] ? basicLowerBand :
close[1] < finalLowerBand[1] ? basicLowerBand :
finalLowerBand[1]
// Determine trend direction
prevTrend = trendDirection[1]
if close > finalUpperBand[1]
trendDirection := 1
else if close < finalLowerBand[1]
trendDirection := -1
else
trendDirection := prevTrend
// Track trend duration
trendBars := trendDirection == trendDirection[1] ? trendBars[1] + 1 : 1
// SuperTrend value: lower band during uptrend, upper band during downtrend
superTrend = trendDirection == 1 ? finalLowerBand : finalUpperBand
// ─── Trend Flip Detection ─────────────────────────────
trendFlipUp = trendDirection == 1 and trendDirection[1] == -1
trendFlipDown = trendDirection == -1 and trendDirection[1] == 1
// ─── Volume Filter ────────────────────────────────────
volSma = ta.sma(volume, volSmaPeriod)
volumeOk = not useVolFilter or (volume > volSma * volMultiple)
filteredFlipUp = trendFlipUp and volumeOk
filteredFlipDown = trendFlipDown and volumeOk
// ─── Plot SuperTrend Line ─────────────────────────────
stColor = trendDirection == 1 ? color.new(color.green, 0) : color.new(color.red, 0)
stPlot = plot(superTrend, "SuperTrend", color=stColor, linewidth=2,
style=plot.style_linebr)
// ─── Trend Fill ───────────────────────────────────────
pricePlot = plot(close, "Close", display=display.none)
fillColor = trendDirection == 1 ?
color.new(color.green, 85) :
color.new(color.red, 85)
fill(pricePlot, stPlot, color=showFill ? fillColor : na)
// ─── Flip Signals ─────────────────────────────────────
plotshape(filteredFlipUp, title="Bullish Flip",
style=shape.triangleup, location=location.belowbar,
color=color.new(color.green, 0), size=size.small,
text="ST Flip")
plotshape(filteredFlipDown, title="Bearish Flip",
style=shape.triangledown, location=location.abovebar,
color=color.new(color.red, 0), size=size.small,
text="ST Flip")
// ─── Trend Duration Label ─────────────────────────────
if showDuration and barstate.islast
labelColor = trendDirection == 1 ? color.green : color.red
trendText = trendDirection == 1 ? "UP" : "DOWN"
labelText = trendText + " (" + str.tostring(trendBars) + " bars)"
label.new(bar_index, superTrend, labelText,
style=trendDirection == 1 ?
label.style_label_up : label.style_label_down,
color=labelColor, textcolor=color.white,
size=size.normal)
// ─── Alerts ───────────────────────────────────────────
alertcondition(filteredFlipUp,
"SuperTrend Bullish Flip",
"SuperTrend flipped BULLISH — trend direction changed from down to up")
alertcondition(filteredFlipDown,
"SuperTrend Bearish Flip",
"SuperTrend flipped BEARISH — trend direction changed from up to down")
And here is the companion ATR visualization that goes in a separate pane. I keep this as a separate indicator because combining overlay and non-overlay elements in one script requires workarounds that add complexity without benefit.
//@version=5
indicator("ATR Volatility Pane", overlay=false)
// ─── Inputs ───────────────────────────────────────────
atrPeriod = input.int(10, "ATR Period", minval=1, maxval=50)
avgAtrPeriod = input.int(50, "Average ATR Period", minval=1)
multiplier = input.float(3.0, "SuperTrend Multiplier", minval=0.5, step=0.1)
// ─── ATR Calculation ──────────────────────────────────
atr = ta.atr(atrPeriod)
avgAtr = ta.sma(atr, avgAtrPeriod)
// ─── Band Width (how far SuperTrend sits from price) ──
bandWidth = multiplier * atr
// ─── Plots ────────────────────────────────────────────
plot(atr, "ATR", color=color.new(color.aqua, 0), linewidth=2)
plot(avgAtr, "Average ATR", color=color.new(color.yellow, 30),
linewidth=1, style=plot.style_cross)
plot(bandWidth, "Band Width", color=color.new(color.orange, 40),
linewidth=1)
// ─── Visual Reference ─────────────────────────────────
// Background highlight when ATR is above average (volatile)
bgcolor(atr > avgAtr ? color.new(color.orange, 90) : na)
Understanding the Ratcheting Logic
The ratcheting mechanism is the heart of SuperTrend and it is worth understanding in detail, because this is what differentiates it from a simple channel or envelope indicator.
During an uptrend, the lower band (the support level) is calculated every bar as hl2 - (multiplier * ATR). If this new calculation is higher than the previous bar’s lower band, the band moves up. If the new calculation is lower, the band stays where it was. It never drops during an uptrend. This creates a rising floor that “locks in” the trend.
The only way to break the uptrend is for price to close below the final lower band. When that happens, the trend flips to downtrend, and the upper band takes over with the same logic in reverse — it can move down but never up during a downtrend.
This is functionally a trailing stop. During an uptrend, your “stop” is the green SuperTrend line. As price rises and volatility stays stable, the stop tightens. If volatility spikes (ATR increases), the new basic band calculation might be lower than the current ratcheted band, so the band stays put — it does not widen during uptrends, which is a subtle but important property. The widening only applies to the initial band calculation for new trend periods.
Backtested Results on BTC/USDT
I backtested the SuperTrend with default parameters (ATR 10, multiplier 3.0) on BTC/USDT 4H over approximately eight months of data. The rules were simple: go long on bullish flip, close position on bearish flip. No shorting, no partial positions, no other filters.
| Metric | Result |
|---|---|
| Total signals | 31 trend flips (approximately 15-16 round trips) |
| Win rate | 43% |
| Average winner | +8.2% |
| Average loser | -2.9% |
| Largest winner | +22.4% |
| Largest loser | -5.1% |
| Profit factor | 1.64 |
| Max drawdown | -11.3% |
| Net result | +31.7% |
A few things stand out. The win rate is below 50%, which surprises many people who assume a good indicator should be right more often than not. Trend-following systems typically have low win rates and make their money on the outlier winners. One 22% winning trade more than compensated for seven small losses.
The max drawdown of 11.3% occurred during a two-week choppy period where SuperTrend flipped five times in quick succession, taking a small loss each time. This is the known weakness of the indicator: ranging markets eat it alive. More on that below.
The profit factor of 1.64 means that for every dollar lost, $1.64 was made. This is solid for a single-indicator system with no additional filters. Adding the volume filter improved the profit factor to 1.81 but reduced the total number of signals, which meant missing some winning trends that started on low-volume flips.
Important caveat: These results do not account for slippage or fees. On a major pair like BTC/USDT with a reasonably liquid exchange, slippage is minimal on 4H signals. But on smaller altcoins or lower timeframes, slippage could meaningfully reduce performance. I also did not account for funding rates if holding perpetual futures. These numbers are directional, not precise.
Parameter Optimization
I tested multiple ATR period and multiplier combinations to understand how they affect performance. Here are the results across the same BTC/USDT 4H dataset.
| ATR Period | Multiplier | Signals | Win Rate | Profit Factor | Notes |
|---|---|---|---|---|---|
| 7 | 2.0 | 58 | 35% | 1.12 | Too sensitive — many whipsaws |
| 10 | 2.0 | 44 | 38% | 1.31 | Responsive but noisy in chop |
| 10 | 3.0 | 31 | 43% | 1.64 | My default — good balance |
| 10 | 4.0 | 22 | 47% | 1.58 | Fewer signals, wider stops, catches trends late |
| 14 | 3.0 | 27 | 45% | 1.71 | Slightly better profit factor, misses some quick moves |
| 14 | 4.0 | 19 | 50% | 1.52 | Very conservative, only catches major trends |
| 20 | 3.0 | 20 | 44% | 1.49 | Slow to react, large drawdowns on reversals |
The ATR 10 / multiplier 3.0 combination is a reasonable default for BTC on 4H. For more volatile altcoins (SOL, AVAX, DOGE), I increase the multiplier to 3.5 or 4.0 to reduce whipsaws. For less volatile instruments, a multiplier of 2.0-2.5 can work.
The ATR period controls how quickly the volatility estimate adapts. A shorter period (7) reacts faster to volatility changes, which means the bands widen and narrow more quickly. A longer period (20) smooths the volatility estimate, producing more stable band distances. I find 10 to be the sweet spot for crypto, where volatility regimes can shift rapidly.
When SuperTrend Fails
SuperTrend has a well-defined failure mode: choppy, range-bound markets. When price oscillates around the HL2 midpoint without establishing a clear direction, the bands constantly get crossed, triggering rapid flip-flops. Each flip takes a small loss. String five or six of these together and you are looking at a 10-15% drawdown without any single large losing trade.
Here are the conditions where I have learned to distrust SuperTrend signals.
Tight ranges with low ATR. When ATR compresses to historically low levels, the SuperTrend bands get very tight. This makes them easier to cross, which increases the flip rate. The ATR Volatility Pane is specifically designed to spot this — when the ATR line is well below its 50-period average, I know SuperTrend is in a vulnerable state.
Post-news consolidation. After a major move driven by news (Fed announcement, regulatory action, major hack), price often enters a consolidation range. During this phase, SuperTrend flips become unreliable because the market is digesting the move rather than trending.
Low-volume weekends on crypto. Saturday and Sunday volume on most crypto pairs drops significantly. SuperTrend signals during weekend sessions have been notably less reliable in my experience, likely because the thinner order books create more random price spikes that cross the bands without follow-through.
My practical approach to handling these failure modes is to pair SuperTrend with a chop detector. When ATR is below its average and the EMA ribbon is gray (as described in my indicators I actually use article), I either ignore SuperTrend flips entirely or reduce my position size by half.
Combining SuperTrend with RSI and MACD
SuperTrend tells you the direction of the trend and gives you a trailing stop. It does not tell you about momentum or overbought/oversold conditions. Here is how I combine it with other indicators.
SuperTrend + RSI
When SuperTrend is bullish (price above the green line) and RSI pulls back to the 40-50 zone without triggering a trend flip, that is often a buying opportunity. The trend is intact (SuperTrend confirms) and momentum has reset (RSI has cooled off). I look for RSI to turn back up from that 40-50 zone as my entry trigger.
Conversely, if SuperTrend is bullish but RSI is above 80, I tighten my mental stop. The trend might be intact, but momentum is extended. I do not exit the trend just because RSI is high — that would defeat the purpose of trend following — but I prepare for a pullback.
If you have the RSI Divergence detector on your chart, watch for bearish divergence while SuperTrend is bullish. That combination — trend still up but momentum weakening — often precedes the SuperTrend flip by several bars, giving you early warning.
SuperTrend + MACD
MACD histogram crossing zero aligns well with SuperTrend trend flips. The combination I look for: SuperTrend flips bullish and MACD histogram crosses above zero within the same two or three bars. This confluence of a trend-following signal (SuperTrend) and a momentum signal (MACD) tends to produce higher-conviction entries.
When the two disagree — SuperTrend flips bullish but MACD histogram is still deeply negative — I treat the signal with more caution. It could be a valid early trend change, but the lack of momentum confirmation suggests higher risk.
SuperTrend + Volume Anomaly
I use the Volume Anomaly Detector to check whether the SuperTrend flip bar has unusual volume. A trend flip on 2x or 3x average volume is a much stronger signal than a flip on below-average volume. The built-in volume filter in the indicator captures some of this, but I keep the standalone Volume Anomaly Detector on my chart for more granular volume analysis.
Adding It to TradingView
- Open TradingView and go to Pine Editor at the bottom
- Paste the main Enhanced SuperTrend code and click Add to Chart
- Create a second indicator tab, paste the ATR Volatility Pane code, and add that to the chart as well
- Open the settings for the main indicator to configure the ATR Period, Multiplier, and Volume Filter
- To set up alerts, click the alert icon, select “Enhanced SuperTrend” as the condition, and choose “SuperTrend Bullish Flip” or “SuperTrend Bearish Flip”
For parameter configuration, start with the defaults (ATR 10, Multiplier 3.0) on the 4H timeframe. Scroll back through historical data to visually verify that the trend flips align with actual trend changes. If you see too many whipsaws, increase the multiplier. If you see the indicator clinging to trends for too long after they have clearly ended, decrease the multiplier.
Refer to the Pine Script v5 documentation for details on any of the functions used. The ATR function (ta.atr()), input types, and plotting functions are all well documented there.
What I Would Change
After running this for several months, there are two enhancements I am considering.
Adaptive multiplier. Instead of a fixed multiplier, use a multiplier that increases during low-volatility periods and decreases during high-volatility periods. The logic: when volatility is low, bands are already tight, so the multiplier should be higher to prevent false flips. When volatility is high, bands are already wide, so a lower multiplier would improve responsiveness. I have not implemented this yet because the complexity increase might not justify the improvement, but it is on my list to test.
Multi-timeframe confirmation. Only take SuperTrend signals on the 4H when the daily SuperTrend agrees on direction. This would reduce the signal count significantly but should improve the win rate. The implementation would use request.security() to fetch the daily SuperTrend direction, similar to the multi-timeframe RSI approach in the MTF RSI Dashboard.
The Honest Summary
SuperTrend is a clean, mechanically simple trend-following indicator that adapts to volatility. It will not make you rich on its own — the 43% win rate and the choppy market drawdowns ensure that. But it does something valuable: it gives you a clear, non-subjective answer to “what is the trend direction right now?” and a trailing stop that adjusts to market conditions.
The enhanced version I built with Cursor adds practical features — the trend fill makes it easier to see direction at a glance, the ATR pane helps identify when the indicator is in a vulnerable low-volatility state, and the volume filter reduces false signals. None of these are revolutionary, but together they make the indicator significantly more usable than the basic version.
If you trade crypto on 4H or daily timeframes and want one indicator for trend direction, SuperTrend with a 3.0 multiplier is genuinely worth testing. Just pair it with something — RSI, volume, an EMA ribbon — to handle the inevitable periods where it chops you out repeatedly.
Next Steps
- See my full indicator stack — SuperTrend pairs well with the indicators in 3 AI-generated indicators I actually use, especially the EMA Ribbon for chop detection.
- Build a divergence detector — RSI divergence can give early warning before SuperTrend flips. See the RSI Divergence Detector tutorial.
- Try Claude Code for Pine Script — If you prefer CLI-based AI over an IDE, our Cursor Pine Script tutorial covers the workflow (and you can swap in Claude Code using a similar approach).
- Automate your signals — Turn SuperTrend alerts into automated trades with a Python DCA bot or a grid trading bot.