← Back to Home
SuperTrend Confirmation Trading Strategy with Trailing Stops

SuperTrend Confirmation Trading Strategy with Trailing Stops

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.

Strategy Overview

The SuperTrend Confirmation Trading Strategy integrates the following components:

Code Implementation

Below is the complete Backtrader code for the strategy, including the custom SuperTrend indicator:

import backtrader as bt

class SuperTrend(bt.Indicator):
    """
    SuperTrend Indicator
    """
    plotinfo = dict(subplot=False)
    lines = ('supertrend',)
    params = (('period', 10), ('multiplier', 3.0),)

    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

        prev_st = self.lines.supertrend[-1]
        prev_close = self.data.close[-1]

        # --- 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 ---
        current_close = self.data.close[0]
        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
            
        is_uptrend = self.data.close[0] > self.st.supertrend[0]
        was_uptrend = self.data.close[-1] > self.st.supertrend[-1]

        # --- 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

Strategy Explanation

1. SuperTrend Indicator

The custom SuperTrend indicator dynamically tracks trend direction using price and volatility:

2. SuperTrendConfirmationStrategy

The strategy trades trend flips after a confirmation candle, with trailing stops for risk management:

Key Features

Pasted image 20250717005554.png
Pasted image 20250717005603.png

Potential Improvements

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.