
Table of Contents
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.
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.
md (fast line).md using a Simple Moving Average to obtain the signal line, sb (slow line).md crosses above the slow line sb.md crosses below the slow line sb.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.
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.
Import the necessary Python packages for this strategy, including pandas, numpy, talib, and core components from the Zipline framework.
To implement the Impulse MACD strategy, we need to define two essential helper functions:
initialize Function: Strategy InitializationIn the initialize function, we define all the one-time settings required before the backtest begins. These include:
ma_len, sig_len) and the multiplier for ATR-based stop-loss (atr_multiplier).continuous_future object representing the futures contract to be traded.schedule_function to arrange daily execution of the main trading logic (daily_trade) and post-market checks for futures contract rolling (roll_futures).daily_trade Function: Daily Trading and Risk ManagementThis function is called on each trading day and serves as the core logic of the strategy. The main steps are as follows:
Fetch the latest historical price data and call the calculate_indicators function to compute the md, sb, and atr values.
Generate a buy signal or sell signal based on the golden cross or death cross between md (fast line) and sb (slow line).
_get_tx_chain_stateWhen 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.
StopOrder.roll_futures Function: Futures Contract RolloverThis 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:
Set the parameters for the backtest, including the start and end dates, initial 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.
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 return, annualized return, Sharpe ratio, maximum drawdown, and more. The results are then printed for easy comparison.






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