This article describes a trend-following trading strategy implemented in Backtrader that uses the SuperTrend indicator to identify trend changes, requiring a confirmation candle before entering trades. The strategy employs trailing stops to manage risk and capture profits during sustained trends.
The SuperTrend Confirmation Trading Strategy integrates the following components:
Below is the complete Backtrader code for the strategy, including the custom SuperTrend indicator:
import backtrader as bt
class SuperTrend(bt.Indicator):
"""
SuperTrend Indicator
"""
= dict(subplot=False)
plotinfo = ('supertrend',)
lines = (('period', 10), ('multiplier', 3.0),)
params
def __init__(self):
# ATR and Median Price are needed for the calculation
self.atr = bt.indicators.AverageTrueRange(period=self.p.period)
self.median_price = (self.data.high + self.data.low) / 2.0
# This will be calculated in the next() method
self.basic_upper_band = self.median_price + (self.p.multiplier * self.atr)
self.basic_lower_band = self.median_price - (self.p.multiplier * self.atr)
def next(self):
# On the first bar, the SuperTrend is set to the close price
if len(self) == 1:
self.lines.supertrend[0] = self.data.close[0]
return
= self.lines.supertrend[-1]
prev_st = self.data.close[-1]
prev_close
# --- Calculate the current SuperTrend value ---
if prev_close > prev_st: # If the previous trend was UP
# The new ST is the max of the previous ST and the current lower band
self.lines.supertrend[0] = max(self.basic_lower_band[0], prev_st)
else: # If the previous trend was DOWN
# The new ST is the min of the previous ST and the current upper band
self.lines.supertrend[0] = min(self.basic_upper_band[0], prev_st)
# --- Check for a flip in the trend ---
= self.data.close[0]
current_close if current_close > self.lines.supertrend[0]: # If price is now above the ST line
# We are in an uptrend, so the ST line should be based on the lower band
self.lines.supertrend[0] = self.basic_lower_band[0]
elif current_close < self.lines.supertrend[0]: # If price is now below the ST line
# We are in a downtrend, so the ST line should be based on the upper band
self.lines.supertrend[0] = self.basic_upper_band[0]
class SuperTrendConfirmationStrategy(bt.Strategy):
"""
Trades SuperTrend flips only after a confirmation candle.
1. Waits for the SuperTrend indicator to flip direction.
2. Waits for the next candle to close, confirming the new trend.
3. Exits with a trailing stop-loss.
"""
= (
params 'st_period', 7),
('st_multiplier', 2.0),
('trail_percent', 0.02),
(
)
def __init__(self):
self.order = None
self.st = SuperTrend(self.datas[0], period=self.p.st_period, multiplier=self.p.st_multiplier)
# State variables to manage the confirmation logic
self.waiting_for_buy_confirmation = False
self.waiting_for_sell_confirmation = False
def notify_order(self, order):
if order.status in [order.Submitted, order.Accepted]:
return
if order.status in [order.Completed]:
if order.isbuy():
self.sell(exectype=bt.Order.StopTrail, trailpercent=self.p.trail_percent)
elif order.issell():
self.buy(exectype=bt.Order.StopTrail, trailpercent=self.p.trail_percent)
self.order = None
def next(self):
if self.order:
return
= self.data.close[0] > self.st.supertrend[0]
is_uptrend = self.data.close[-1] > self.st.supertrend[-1]
was_uptrend
# --- Confirmation Logic ---
# If we were waiting for a buy confirmation...
if self.waiting_for_buy_confirmation:
self.waiting_for_buy_confirmation = False # Reset flag
if is_uptrend and not self.position: # Check confirmation
self.order = self.buy()
return
# If we were waiting for a sell confirmation...
if self.waiting_for_sell_confirmation:
self.waiting_for_sell_confirmation = False # Reset flag
if not is_uptrend and not self.position: # Check confirmation
self.order = self.sell()
return
# --- Flip Detection Logic ---
# A flip from downtrend to uptrend occurred on the previous bar
if is_uptrend and not was_uptrend:
# Only set the flag if not already waiting for a sell confirmation
if not self.waiting_for_sell_confirmation:
self.waiting_for_buy_confirmation = True
# A flip from uptrend to downtrend occurred on the previous bar
if not is_uptrend and was_uptrend:
# Only set the flag if not already waiting for a buy confirmation
if not self.waiting_for_buy_confirmation:
self.waiting_for_sell_confirmation = True
The custom SuperTrend indicator dynamically tracks trend direction using price and volatility:
Components:
Logic (next
):
The strategy trades trend flips after a confirmation candle, with trailing stops for risk management:
Trading Logic (next
):
Order Management
(notify_order
):
st_period
,
st_multiplier
, or trail_percent
to optimize
for specific assets or market conditions.This strategy is designed for trending markets where the SuperTrend indicator can effectively capture sustained directional moves, suitable for assets like forex, stocks, or cryptocurrencies, and can be backtested to evaluate its effectiveness across various timeframes and assets.