← Back to Home
Heikin-Ashi Trend-Following Trading Strategy with Trailing Stops

Heikin-Ashi Trend-Following Trading Strategy with Trailing Stops

This article describes a trend-following trading strategy implemented in Backtrader that uses Heikin-Ashi candles to identify strong trends. The strategy enters trades after a sequence of trend-confirming candles and employs trailing stops to manage risk and capture profits.

Strategy Overview

The Heikin-Ashi Trend-Following Trading Strategy integrates the following components:

Code Implementation

Below is the complete Backtrader code for the strategy, including the custom Heikin-Ashi indicator:

import backtrader as bt

# Custom Heikin-Ashi Indicator
class HeikinAshi(bt.Indicator):
    lines = ('ha_open', 'ha_high', 'ha_low', 'ha_close',)
    plotinfo = dict(subplot=False) # Plot on the main chart

    def __init__(self):
        # Heikin-Ashi Close
        self.lines.ha_close = (self.data.open + self.data.high + self.data.low + self.data.close) / 4.0

    def next(self):
        # Heikin-Ashi Open
        # On the first bar, the HA open is the average of the regular open and close
        self.lines.ha_open[0] = (self.lines.ha_open[-1] + self.lines.ha_close[-1]) / 2.0 if len(self) > 1 else (self.data.open[0] + self.data.close[0]) / 2.0
        
        # Heikin-Ashi High and Low
        self.lines.ha_high[0] = max(self.data.high[0], self.lines.ha_open[0], self.lines.ha_close[0])
        self.lines.ha_low[0] = min(self.data.low[0], self.lines.ha_open[0], self.lines.ha_close[0])

class HeikinAshiTrendStrategy(bt.Strategy):
    """
    A trend-following strategy that uses the pattern of Heikin-Ashi candles
    to identify and trade strong trends.
    1. Uses a custom Heikin-Ashi indicator to smooth price.
    2. Enters on a sequence of strong trend-confirming candles.
    3. Exit is managed with a trailing stop-loss.
    """
    params = (
        ('consecutive_candles', 3), # Number of strong HA candles needed for entry
        ('trail_percent', 0.02),   # Trailing stop
    )

    def __init__(self):
        self.order = None
        # Instantiate our custom Heikin-Ashi indicator
        self.ha = HeikinAshi(self.datas[0])

    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):
        # Make sure we have enough bars to check the sequence
        if len(self) < self.p.consecutive_candles:
            return

        if self.order:
            return

        # --- Entry Logic ---
        if not self.position:
            # --- Check for a BUY Signal ---
            is_buy_signal = True
            # Loop backwards from the current candle (i=0) to check the sequence
            for i in range(self.p.consecutive_candles):
                # Perform the check on the historical data inside the loop
                is_green_past = self.ha.ha_close[-i] > self.ha.ha_open[-i]
                has_no_lower_wick_past = self.ha.ha_open[-i] == self.ha.ha_low[-i]
                
                if not (is_green_past and has_no_lower_wick_past):
                    is_buy_signal = False
                    break  # If one candle fails, the sequence is broken

            if is_buy_signal:
                self.order = self.buy()
                return  # Exit to avoid checking for a sell signal on the same bar

            # --- Check for a SELL Signal ---
            is_sell_signal = True
            # Loop backwards to check the sequence
            for i in range(self.p.consecutive_candles):
                # Perform the check on the historical data inside the loop
                is_red_past = self.ha.ha_close[-i] < self.ha.ha_open[-i]
                has_no_upper_wick_past = self.ha.ha_open[-i] == self.ha.ha_high[-i]
                
                if not (is_red_past and has_no_upper_wick_past):
                    is_sell_signal = False
                    break  # If one candle fails, the sequence is broken
            
            if is_sell_signal:
                self.order = self.sell()

Strategy Explanation

1. HeikinAshi Indicator

The custom Heikin-Ashi indicator smooths price action to highlight trends:

2. HeikinAshiTrendStrategy

The strategy uses Heikin-Ashi candles to identify strong trends and manage trades:

Key Features

Pasted image 20250716231844.png
Pasted image 20250716231851.png

Potential Improvements

This strategy is designed for trending markets where Heikin-Ashi candles can effectively identify sustained directional moves, suitable for assets like forex, stocks, or cryptocurrencies, and can be backtested to evaluate its effectiveness across various timeframes and assets.