SuperTrend
SuperTrend
- Category: Trend — Overlay Indicator
- Default Parameters: period=10, multiplier=3
- Output: A single trend line (above or below price)
- Applicable Markets: Stocks, Futures, Forex, Cryptocurrencies
I. What is SuperTrend
SuperTrend is a trend-following indicator based on ATR (Average True Range). It draws a single line on the price chart: when the market is in an uptrend, the line appears below the price (typically green); when the market is in a downtrend, it appears above the price (typically red).
SuperTrend draws design inspiration from the combination of Parabolic SAR and ATR channels. Unlike SAR, SuperTrend uses ATR to adapt to market volatility, avoiding the issue of SAR clinging too tightly to price near the end of a trend due to an excessively large acceleration factor. Its core concept is:
- Use the price midpoint as the baseline
- Offset by in both directions to form upper and lower bands
- Dynamically switch trend direction based on the price’s relationship with the bands
With minimal parameters, clear logic, and unambiguous signals, SuperTrend is extremely popular in quantitative and intraday trading, especially among the Indian stock market’s intraday trading community.
SuperTrend is essentially a smart-switching version of ATR channels. A standard ATR channel (like Keltner Channel) displays both upper and lower bands simultaneously, while SuperTrend shows only one based on the trend direction, making the signal more intuitive.
II. Mathematical Principles and Calculation
Prerequisite: ATR
First, calculate ATR (Average True Range). True Range (TR) is defined as:
Or using RMA/Wilder smoothing:
Basic Upper and Lower Bands
Final Bands (Anti-Rollback)
The core rule for the final upper band is: it can only decrease, never increase (tightening the stop in a downtrend).
The rule for the final lower band is the opposite: it can only increase, never decrease (raising the stop in an uptrend).
SuperTrend Value
Trend Determination Rules
- If —> Switch to uptrend (bullish)
- If —> Switch to downtrend (bearish)
- Otherwise —> Maintain the previous trend direction
Calculation Steps
- Calculate True Range and ATR(period) for each bar
- Compute basic upper and lower bands using
- Apply the anti-rollback rules to obtain the final bands
- Compare the closing price with the final bands to determine trend direction
- Select the upper or lower band as the SuperTrend value based on trend direction
III. Python Implementation
import numpy as np
import pandas as pd
def supertrend(df: pd.DataFrame,
period: int = 10,
multiplier: float = 3.0) -> pd.DataFrame:
"""
Calculate the SuperTrend indicator.
Parameters
----------
df : DataFrame, must contain 'high', 'low', 'close' columns
period : ATR period, default 10
multiplier : ATR multiplier, default 3.0
Returns
----------
DataFrame with 'supertrend', 'trend', 'upper_band', 'lower_band' columns
trend: 1 indicates uptrend (bullish), -1 indicates downtrend (bearish)
"""
high = df['high'].values
low = df['low'].values
close = df['close'].values
n = len(df)
# ---------- Calculate ATR ----------
tr = np.zeros(n)
tr[0] = high[0] - low[0]
for i in range(1, n):
tr[i] = max(high[i] - low[i],
abs(high[i] - close[i - 1]),
abs(low[i] - close[i - 1]))
# Use RMA (Wilder smoothing) for ATR
atr = np.zeros(n)
atr[:period] = np.nan
atr[period - 1] = np.mean(tr[:period])
for i in range(period, n):
atr[i] = (atr[i - 1] * (period - 1) + tr[i]) / period
# ---------- Basic upper and lower bands ----------
hl2 = (high + low) / 2
basic_upper = hl2 + multiplier * atr
basic_lower = hl2 - multiplier * atr
# ---------- Final upper and lower bands ----------
final_upper = np.full(n, np.nan)
final_lower = np.full(n, np.nan)
supertrend_val = np.full(n, np.nan)
trend = np.zeros(n, dtype=int)
# Initialization
final_upper[period - 1] = basic_upper[period - 1]
final_lower[period - 1] = basic_lower[period - 1]
trend[period - 1] = 1 # Assume initial uptrend
for i in range(period, n):
# Final upper band: only allowed to decrease or reset on breakout
if basic_upper[i] < final_upper[i - 1] or close[i - 1] > final_upper[i - 1]:
final_upper[i] = basic_upper[i]
else:
final_upper[i] = final_upper[i - 1]
# Final lower band: only allowed to increase or reset on breakdown
if basic_lower[i] > final_lower[i - 1] or close[i - 1] < final_lower[i - 1]:
final_lower[i] = basic_lower[i]
else:
final_lower[i] = final_lower[i - 1]
# Determine trend direction
if trend[i - 1] == 1:
# Previous period was uptrend
if close[i] < final_lower[i]:
trend[i] = -1 # Switch to downtrend
else:
trend[i] = 1 # Maintain uptrend
else:
# Previous period was downtrend
if close[i] > final_upper[i]:
trend[i] = 1 # Switch to uptrend
else:
trend[i] = -1 # Maintain downtrend
# SuperTrend value
if trend[i] == 1:
supertrend_val[i] = final_lower[i]
else:
supertrend_val[i] = final_upper[i]
result = pd.DataFrame({
'supertrend': supertrend_val,
'trend': trend,
'upper_band': final_upper,
'lower_band': final_lower,
'atr': atr
}, index=df.index)
return result
# ========== Usage Example ==========
if __name__ == "__main__":
np.random.seed(42)
n = 120
dates = pd.date_range('2024-01-01', periods=n, freq='B')
# Simulate OHLCV data (with trend)
trend_component = np.linspace(0, 15, n) + 5 * np.sin(np.linspace(0, 4 * np.pi, n))
noise = np.cumsum(np.random.randn(n) * 0.4)
price = 100 + trend_component + noise
df = pd.DataFrame({
'open': price + np.random.uniform(-0.5, 0.5, n),
'high': price + np.abs(np.random.randn(n)) * 1.5,
'low': price - np.abs(np.random.randn(n)) * 1.5,
'close': price + np.random.uniform(-0.3, 0.3, n),
'volume': np.random.randint(1000, 5000, n)
}, index=dates)
st = supertrend(df, period=10, multiplier=3.0)
merged = df.join(st)
print("SuperTrend data for the last 15 periods:")
print(merged[['close', 'supertrend', 'trend', 'atr']].tail(15).to_string())
# Count buy/sell signals
signals = merged['trend'].diff()
buy_signals = (signals == 2).sum() # -1 -> 1
sell_signals = (signals == -2).sum() # 1 -> -1
print(f"\nNumber of buy signals: {buy_signals}")
print(f"Number of sell signals: {sell_signals}")
- A larger
multiplierplaces the SuperTrend line further from price, yielding fewer but more reliable signals - A smaller
multipliergenerates more frequent signals but also more false ones - Common parameter combinations: (10, 3), (10, 2), (7, 3), (14, 2)
- Optimize through backtesting based on the asset’s volatility characteristics
IV. Problems the Indicator Solves
1. Trend Direction Identification
SuperTrend provides a binary trend state:
- Green line below price —> Uptrend, consider holding long or staying out
- Red line above price —> Downtrend, consider holding short or staying out
2. Clear Buy/Sell Signals
| Signal | Condition | Action |
|---|---|---|
| Buy | Trend changes from -1 to 1 (close breaks above upper band) | Open long position |
| Sell | Trend changes from 1 to -1 (close breaks below lower band) | Close long or open short |
3. Dynamic Stop-Loss Level
The SuperTrend line itself serves as the suggested stop-loss. In an uptrend, the lower band (green line) continuously rises without retreating, naturally forming an ascending stop-loss level.
4. Volatility Adaptation
Because it is based on ATR, SuperTrend automatically widens the band during high-volatility periods and narrows it during low-volatility periods, avoiding the mismatch of fixed stop-loss distances across different volatility environments.
SuperTrend performs excellently in trending markets but produces frequent false signals during extended sideways consolidation. Consider combining it with ADX or other trend strength indicators to filter signals.
V. Advantages, Disadvantages, and Use Cases
Advantages
- Minimal parameters: Only 2 parameters, small tuning space, less prone to overfitting
- Clear signals: Color/position changes directly indicate buy or sell, no subjective judgment needed
- Volatility adaptive: ATR foundation enables reasonable performance across different volatility environments
- Anti-rollback mechanism: Final bands only move in the favorable direction, never retreating to widen the stop
- Computationally efficient: Simple algorithm, suitable for real-time calculations and high-frequency backtesting
Disadvantages
- Many false signals in ranging markets: Repeated reversals in sideways ranges produce consecutive small losses
- Lagging: Signals are delayed at the beginning of trend reversals, missing part of the move
- Cannot measure trend strength: Only provides direction, does not quantify trend intensity
- Gap sensitivity: Large gaps can instantly change the trend determination
Use Cases
| Scenario | Suitability | Notes |
|---|---|---|
| One-directional trending markets | High | Reliable signals with effective trailing stops |
| Intraday trading (5min/15min) | High | Suitable for intraday swing trading |
| Daily trend trading | High | Effectively filters daily timeframe noise |
| Narrow range consolidation | Low | Frequent reversals cause consecutive losses |
| Extreme events (black swans) | Low | ATR may not adapt quickly enough to sudden volatility |
Comparison with Similar Indicators
| Dimension | SuperTrend | Parabolic SAR | Moving Average | Ichimoku |
|---|---|---|---|---|
| Number of Parameters | 2 | 2 | 1 | 4 |
| Volatility Adaptation | Yes (ATR) | Yes (AF acceleration) | No | No |
| Stop-Loss Function | Built-in | Built-in | Requires additional design | Cloud provides reference |
| Signal Frequency | Medium | Relatively high | Relatively low | Medium |
| Ranging Market Performance | Poor | Poor | Medium | Poor |
| Visual Complexity | Simple | Simple | Simple | Complex |
- Combine with ADX: Enable SuperTrend signals when ADX > 25, pause trading when ADX < 20
- Multi-timeframe analysis: Confirm trend direction on higher timeframes, use SuperTrend on lower timeframes for entry
- Use multiple parameter sets (e.g., observe multiplier=2 and multiplier=3 simultaneously), enter when both signals agree
- Include slippage and commissions in backtesting, as reversal signals can be frequent