Impulse MACD Futures Trading Strategy

Photo by rc.xyz NFT gallery on Unsplash

Introduction

LazyBear is a highly influential indicator developer on the internationally renowned trading platform, TradingView. He has created a large number of popular custom technical indicators, and his open-source code has inspired countless quantitative traders and technical analysis enthusiasts around the world. LazyBear’s indicators often focus on reducing the lag of traditional indicators and incorporate unique market observations to better capture trends and momentum.

One of his representative works, the “Impulse MACD,” is adopted here. This indicator is not a traditional Moving Average Convergence Divergence (MACD), but rather a significantly improved version. It uses a zero-lag Double Exponential Moving Average (DEMA) to respond more quickly to price changes and combines a smoothed high-low price channel (SMMA) to determine market “impulse.”

The core idea is that trading signals are more valuable only when price momentum aligns with the trend direction. This helps to filter out some of the noise typically found in ranging markets.

Investment Instrument and Backtesting Period

This study focuses exclusively on the Taiwan Stock Index Futures (TX) as the sole trading instrument. The analysis and backtesting are based on daily high, low, and closing price data. Since the indicators used in the strategy—such as DEMA and SMMA—require a historical “warm-up” period to initialize properly, with the longest calculation window set to 30 days, sufficient prior data is necessary before the actual backtest can begin.

To ensure the stability and reliability of all generated trading signals, the backtesting period is set from January 1, 2019, to September 12, 2025. This timeframe provides ample historical context for accurate indicator initialization and ensures the rigor and validity of the testing results.

Core Logic

1. Indicator System

  • Calculate the average of High, Low, and Close prices (HLC/3).
  • Apply a zero-lag Double Exponential Moving Average (DEMA) to capture price movements more responsively.
  • Use the relationship between price and a Smoothed Moving Average (SMMA) channel built from high and low prices to derive the main momentum indicator, md (fast line).
  • Smooth the md using a Simple Moving Average to obtain the signal line, sb (slow line).

2. Entry Siganl

  • buy signal is generated when the fast line md crosses above the slow line sb.
  • sell signal is generated when the fast line md crosses below the slow line sb.

3.Exit & Risk Management

  • Implement a trailing stop-loss mechanism based on the Average True Range (ATR).
  • The stop-loss level adjusts dynamically as the price moves in favor of the open position, aiming to lock in profits while maintaining strict control over downside risk.

4. Contract Rolling

Before the futures contract reaches expiration, the strategy automatically closes the expiring position and opens an identical position in the next front-month contract, ensuring continuity and accuracy throughout the backtest period.

1、 Environment Setup and Required Packages

1.1 Data Import

First, we need to configure the TEJ API key to access the data source. Then, using environment variables, we specify the required instruments for backtesting—Taiwan Stock Index Futures (TX) and the market index (IR0001)—as well as the desired data period.

Finally, we use the zipline ingest command to import this data into Zipline’s local database, preparing it for use in the backtesting process.

1.2 Import Required Packages

Import the necessary Python packages for this strategy, including pandasnumpytalib, and core components from the Zipline framework.

2、 Indicator Calculation Functions

To implement the Impulse MACD strategy, we need to define two essential helper functions:

  • _smma: Calculates the Smoothed Moving Average (SMMA), which serves as the foundation for the subsequent indicator logic.
  • calculate_indicators: This function integrates all indicator calculations, including HLC/3, ATR, SMMA of the high-low price channel, and finally the fast line md and the slow line sb. It forms the core of the strategy’s signal generation.

3、Building the Zipline Trading Strategy

3.1 initialize Function: Strategy Initialization

In the initialize function, we define all the one-time settings required before the backtest begins. These include:

  • Strategy Parameters: Set the time periods needed for indicator calculations (ma_lensig_len) and the multiplier for ATR-based stop-loss (atr_multiplier).
  • Asset Definition: Define the continuous_future object representing the futures contract to be traded.
  • Transaction Costs: Configure commission and slippage models to make the backtest results more realistic and closer to live trading conditions.
  • Benchmark Setting: Set the Taiwan Weighted Index Total Return (IR001) as the benchmark for performance comparison.
  • Scheduling: Use schedule_function to arrange daily execution of the main trading logic (daily_trade) and post-market checks for futures contract rolling (roll_futures).

3.2 daily_trade Function: Daily Trading and Risk Management

This function is called on each trading day and serves as the core logic of the strategy. The main steps are as follows:

Data Retrieval and Indicator Calculation

Fetch the latest historical price data and call the calculate_indicators function to compute the mdsb, and atr values.

Signal Generation

Generate a buy signal or sell signal based on the golden cross or death cross between md (fast line) and sb (slow line).

Position Management and the Role of _get_tx_chain_state

When working with futures, it’s not sufficient to simply check whether the current continuous contract (context.future) exists in context.portfolio.positions.

This is because during a contract rollover, the actual position may still be held in the expiring contract, while context.future already points to the new front-month contract.

A simple position check might mistakenly assume there is no open position, resulting in a new order being placed. This can lead to multiple open positions across different contract months (i.e., unintended overexposure).

To avoid this, the helper function _get_tx_chain_state iterates through all open positions and checks whether the asset’s root_symbol is 'TX'. This allows the strategy to accurately determine the total number of contracts held across the entire TX futures chain (root_qty), preventing duplicate entries during rollover periods.

Trailing Stop-Loss Logic

  • No Open Position:
    If no position is currently held, enter a new long or short position based on the generated signal.
  • Open Position Exists:
    If a position is currently open, activate the ATR-based trailing stop-loss mechanism.
    The stop-loss level only moves in the direction favorable to the position (to protect profits) and is implemented using Zipline’s StopOrder.
    If the stop level needs adjustment, the existing stop order is canceled and replaced with an updated stop order at the new level.

3.3 roll_futures Function: Futures Contract Rollover

This function is executed after the market closes each day to check whether the currently held futures contract is approaching expiration (within 5 days). If so, it will automatically:

  • Close the position in the expiring contract
  • Open a new position with the same quantity in the next-month contract
  • Place an initial trailing stop-loss order for the new position

4. Running the Backtest

Set the parameters for the backtest, including the start and end datesinitial capital, and other relevant settings. Then, call the run_algorithm function to launch the entire backtesting process. The results will be stored in the results object.

5、Strategy Performance Analysis

5.1 Calculating Key Performance Indicators (KPIs)

After the backtest is completed, we extract data from the results object to calculate key performance metrics for both the strategy and the market benchmark. These include cumulative returnannualized returnSharpe ratiomaximum drawdown, and more. The results are then printed for easy comparison.


【TQuant Lab Backtesting System】Solving Your Quantitative Finance Pain Points


GitHub Source Code

Click to View on GitHub

Further Reading

Related Links

Back
Processing...