{"id":1854,"date":"2023-09-05T14:00:00","date_gmt":"2023-09-05T14:00:00","guid":{"rendered":"https:\/\/www.tejwin.com\/en\/insights\/macd-tquant\/"},"modified":"2023-09-05T14:00:00","modified_gmt":"2023-09-05T14:00:00","slug":"macd-tquant","status":"publish","type":"insight","link":"https:\/\/www.tejwin.com\/en\/insights\/macd-tquant\/","title":{"rendered":"TQuant Lab\u00a0MACD Trading Strategy"},"content":{"rendered":"<figure class=\"wp-block-image aligncenter\"><img loading=\"lazy\" decoding=\"async\" alt=\"TQuant Lab\u00a0MACD\u4ea4\u6613\u7b56\u7565\" class=\"wp-image-19343\" height=\"1063\" src=\"https:\/\/www.tejwin.com\/en\/wp-content\/uploads\/2026\/08\/image-29.jpeg\" width=\"1600\"\/><figcaption class=\"wp-element-caption\">Photo by <a href=\"https:\/\/unsplash.com\/@erdaest?utm_source=medium&amp;utm_medium=referral\" rel=\"noreferrer noopener\" target=\"_blank\">Erda Estremera<\/a> on\u00a0<a href=\"https:\/\/unsplash.com?utm_source=medium&amp;utm_medium=referral\" rel=\"noreferrer noopener\" target=\"_blank\">Unsplash<\/a><\/figcaption><\/figure>\n<h2 class=\"wp-block-heading\"><strong>Highlight<\/strong><\/h2>\n<ul class=\"wp-block-list\">\n<li>Article Difficulty\uff1a\u2605\u2605\u2606\u2606\u2606<\/li>\n<li>Using TQuant Lab to design MACD Trading Strategy  <\/li>\n<li>Using TQuant Lab to generate performance reports and visualizes charts<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\"><strong>Preface<\/strong><\/h2>\n<p class=\"wp-block-paragraph\">MACD, which stands for Moving Average Convergence Divergence, is a commonly used tool in technical analysis for measuring the trend changes and momentum of an asset.<\/p>\n<p class=\"wp-block-paragraph\">MACD consists of two main components:<\/p>\n<ol class=\"wp-block-list\">\n<li>Short-Term Moving Average Line: This is a shorter moving average line typically calculated over a shorter time period, such as a 12-day moving average.<\/li>\n<li>Long-Term Moving Average Line: This is a longer moving average line calculated over a longer time period, such as a 26-day moving average.<\/li>\n<\/ol>\n<p class=\"wp-block-paragraph\">The calculation steps for MACD are as follows:<\/p>\n<ul class=\"wp-block-list\">\n<li>Calculate the moving averages for the fast line and slow line.<\/li>\n<li>Subtract the slow line from the fast line to obtain the difference, which is the fast line.<\/li>\n<li>Calculate the moving average of these differences, resulting in the MACD indicator itself, also known as the slow line.<\/li>\n<\/ul>\n<p class=\"wp-block-paragraph\">MACD values can be positive, negative, or zero, and their relative positions and changes provide insights into the asset\u2019s price trends.<\/p>\n<p class=\"wp-block-paragraph\">Key MACD signals include:<\/p>\n<ul class=\"wp-block-list\">\n<li>Golden Cross: When the fast line crosses above the slow line, it is typically considered a signal of an upward trend, potentially indicating a price increase.<\/li>\n<li>Death Cross: When the fast line crosses below the slow line, it is generally seen as a signal of a downward trend, possibly indicating a price decrease.<\/li>\n<\/ul>\n<p class=\"wp-block-paragraph\">Additionally, the MACD histogram represents the difference between the fast line and slow line, with the height of the bars indicating the magnitude of this difference.<\/p>\n<h2 class=\"wp-block-heading\"><strong>Editing Environment and Module Requirements<\/strong><\/h2>\n<p class=\"wp-block-paragraph\">This article uses the Mac operating system and Jupyter Notebook as the editor.<br \/>Before delving into the main content, let\u2019s start by providing the domain and key. Following that, we will proceed with data importation. In this practical implementation, we will use TSMC (stock code: 2330) as an example, setting the time range from December 30, 2018, to May 26, 2023.<\/p>\n<pre class=\"wp-block-code\"><code><code>import os<br\/>import pandas as pd<br\/>import numpy as np<br\/><br\/>os.environ['TEJAPI_BASE'] = 'https:\/\/api.tej.com.tw'<br\/>os.environ['TEJAPI_KEY'] = 'your_key'<br\/>os.environ['mdate'] = '20181230 20230526'<br\/>os.environ['ticker'] = '2330'<br\/><br\/># \u4f7f\u7528 ingest \u5c07\u80a1\u50f9\u8cc7\u6599\u5c0e\u5165\u66ab\u5b58\uff0c\u4e26\u4e14\u547d\u540d\u8a72\u80a1\u7968\u7d44\u5408 (bundle) \u70ba tquant<br\/>!zipline ingest -b tquant<br\/><br\/>import talib<br\/>from zipline.api import order_target, record, symbol<br\/>from zipline.finance import commission, slippage<br\/>import matplotlib.pyplot as plt<\/code><\/code><\/pre>\n<h2 class=\"wp-block-heading\">Create the initialize function<\/h2>\n<p class=\"wp-block-paragraph\">Firstly, let\u2019s establish the initialize function, which is used to define the trading environment before the commencement of trading. In this example, we set:<\/p>\n<ul class=\"wp-block-list\">\n<li>Stock code<\/li>\n<li>Number of shares held<\/li>\n<li>Position holding status<\/li>\n<li>Transaction fees<\/li>\n<li>Liquidity slippage<\/li>\n<\/ul>\n<pre class=\"wp-block-code\"><code><code>def initialize(context):<br\/>context.sym = symbol('2330')<br\/>context.i = 0<br\/>context.invested = False<br\/>context.set_commission(commission.PerDollar(cost=0.00285))<br\/>context.set_slippage(slippage.VolumeShareSlippage())<\/code><\/code><\/pre>\n<h2 class=\"wp-block-heading\">Create the handle_data function<\/h2>\n<p class=\"wp-block-paragraph\">The handle_data function is used to process the daily trading strategy or actions. In this context:<\/p>\n<ul class=\"wp-block-list\">\n<li>Condition 1: When the fast line crosses above the slow line, and the MACD histogram changes from negative to positive, it is considered a buy signal.<\/li>\n<li>Condition 2: When the fast line falls below the slow line, the MACD histogram changes from positive to negative, and there is a non-zero position holding, it is considered a sell signal.<\/li>\n<\/ul>\n<p class=\"wp-block-paragraph\">We use talib to calculate the moving averages, setting the short-term window period to 12 days, the long-term window period to 26 days, and the MACD line\u2019s window period to 9 days.<\/p>\n<p class=\"wp-block-paragraph\">In addition to the default output information, we also want to record additional information during the execution of the trading strategy, such as the closing price, fast line index, slow line index, buy signal status, sell signal status, etc. Therefore, in the \u2018record\u2019 section, we add output fields accordingly.<\/p>\n<pre class=\"wp-block-code\"><code><code>def handle_data(context, data):<br\/>trailing_window = data.history(context.sym, 'price', 35, '1d')#35 = 26 + 9<br\/>if trailing_window.isnull().values.any():<br\/>return<br\/><br\/>short_ema = talib.EMA(trailing_window.values, timeperiod = 12)<br\/>long_ema = talib.EMA(trailing_window.values, timeperiod = 26)<br\/>dif = short_ema - long_ema<br\/>MACD = talib.EMA(dif, timeperiod = 9)<br\/>bar = dif - MACD<br\/>buy = False<br\/>sell = False<br\/><br\/># Trading logic<br\/>#condition1<br\/>if (dif[-2] &lt; MACD[-2]) and (dif[-1] &gt; MACD[-1]) and (bar[-2] &lt; 0) and (bar[-1] &gt; 0):<br\/><br\/>order_target(context.sym, 1000)<br\/>context.invested = True<br\/>buy = True<br\/><br\/>#condition2<br\/>elif (dif[-2] &gt; MACD[-2]) and (dif[-1] &lt; MACD[-1]) and (bar[-2] &gt; 0) and (bar[-1] &lt; 0) and context.invested:<br\/>order_target(context.sym, 0)<br\/>context.invested = False<br\/>sell = True<br\/><br\/># Save values for later inspection<br\/>record(TSMC = data.current(symbol('2330'), 'close'),<br\/>dif = dif[-1],<br\/>MACD = MACD[-1],<br\/>bar = bar[-1],<br\/>buy = buy,<br\/>sell = sell)<\/code><\/code><\/pre>\n<h2 class=\"wp-block-heading\">Create the analyze Function<\/h2>\n<p class=\"wp-block-paragraph\">In the analyze function, utilize <strong>matplotlib.pyplot <\/strong>to draw the portfolio value line chart and MACD indicator chart. We plan to generate two charts. The first one is the portfolio value line chart, responsible for recording the trend of the portfolio value. The second one is the MACD indicator chart, tasked with documenting the trends of the fast line, slow line, MACD histogram, and marking buy and sell points.<\/p>\n<pre class=\"wp-block-code\"><code><code># Note: this function can be removed if running<br\/># this algorithm on quantopian.com<br\/>def analyze(context=None, results=None):<br\/>import matplotlib.pyplot as plt<br\/>import logbook<br\/>logbook.StderrHandler().push_application()<br\/>log = logbook.Logger('Algorithm')<br\/><br\/>fig = plt.figure()<br\/>ax1 = fig.add_subplot(211)<br\/>results.portfolio_value.plot(ax=ax1)<br\/>ax1.set_ylabel('Portfolio value (TWD)')<br\/>ax2 = fig.add_subplot(212)<br\/>ax2.set_ylabel('MACD')<br\/># If data has been record()ed, then plot it.<br\/># Otherwise, log the fact that no data has been recorded.<br\/>if 'dif' in results and 'MACD' in results:<br\/>results[['dif', 'MACD']].plot(ax=ax2)<br\/>ax2.plot(<br\/>results.index[results[\"buy\"] == True],<br\/>results.loc[results[\"buy\"] == True, 'MACD'],<br\/>'^',<br\/>markersize=10,<br\/>color='m',<br\/>)<br\/>ax2.plot(<br\/>results.index[results[\"sell\"] == True],<br\/>results.loc[results[\"sell\"] == True, 'MACD'],<br\/>'v',<br\/>markersize=10,<br\/>color='k',<br\/>)<br\/>ax3 = ax2.twinx()<br\/>colors = [\"red\" if i &gt; 0 else \"green\" for i in results['bar']]<br\/>ax3.bar(results.index, results['bar'], color=colors, alpha=0.5, width=0.4, label='MACD Bar')<br\/><br\/>lines, labels = ax2.get_legend_handles_labels()<br\/>bars, bar_labels = ax3.get_legend_handles_labels()<br\/>ax2.legend(lines + bars, labels + bar_labels, loc='upper right')<br\/><br\/>plt.gcf().set_size_inches(18, 8)<br\/>else:<br\/>msg = 'TSMC - dif and MACD data not captured using record().'<br\/>ax2.annotate(msg, xy=(0.1, 0.5))<br\/>log.info(msg)<br\/>plt.show()<\/code><\/code><\/pre>\n<h2 class=\"wp-block-heading\">Execute MACD Trading Strategy<\/h2>\n<p class=\"wp-block-paragraph\">Utilize the \u2018run_algorithm\u2019 function to execute the compiled trading strategy. Set the trading period from December 30, 2018, to May 26, 2023, with an initial capital of 100,000 CNY. Employ the \u2018tquant\u2019 dataset. The output variable \u2018results\u2019 will represent the daily performance and details of the trades.<\/p>\n<pre class=\"wp-block-code\"><code><code>from zipline import run_algorithm<br\/><br\/>start_date = pd.Timestamp('2018-12-30',tz='utc')<br\/>end_date = pd.Timestamp('2023-05-26',tz='utc')<br\/>results = run_algorithm(start= start_date,<br\/>end=end_date,<br\/>initialize=initialize,<br\/>capital_base=1e6,<br\/>analyze=analyze,<br\/>handle_data=handle_data,<br\/>data_frequency='daily',<br\/>bundle='tquant'<br\/>)<\/code><\/code><\/pre>\n<figure class=\"wp-block-image aligncenter caption-align-center\"><img loading=\"lazy\" decoding=\"async\" alt=\"Trading Strategy Performance Report\" class=\"wp-image-19339\" height=\"453\" src=\"https:\/\/www.tejwin.com\/en\/wp-content\/uploads\/2026\/08\/image-369.png\" width=\"1088\"\/><figcaption class=\"wp-element-caption\">Trading Strategy Performance Report<\/figcaption><\/figure>\n<h2 class=\"wp-block-heading\">Report<\/h2>\n<figure class=\"wp-block-image aligncenter caption-align-center\"><img loading=\"lazy\" decoding=\"async\" alt=\"Trading Strategy Performance Report\" class=\"wp-image-19341\" height=\"616\" src=\"https:\/\/www.tejwin.com\/en\/wp-content\/uploads\/2026\/08\/image-370.png\" width=\"801\"\/><figcaption class=\"wp-element-caption\">Trading Strategy Performance Report<\/figcaption><\/figure>\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n<p class=\"wp-block-paragraph\">Based on the above report, we can observe that the portfolio value increased by approximately thirty percent. Through the MACD indicator chart, we gain a clear understanding of the timing of each trading action and trend performance. With TQuant Lab, we can significantly reduce code complexity, implementing complex backtesting systems with minimal code. However, it\u2019s important to note that while MACD is a popular technical analysis tool, it is not absolutely reliable, and using it in isolation may generate false signals. Typically, technical analysts combine MACD with other indicators and analysis methods for more accurate judgments.<\/p>\n<p class=\"wp-block-paragraph\">However, it is crucial to reiterate that the targets mentioned in this article are for illustrative purposes only and do not represent recommendations or advice on any financial products. Additionally, the outcomes generated by the language model do not guarantee absolute correctness and require further confirmation. Therefore, readers interested in topics such as strategy construction, performance backtesting, and research evidence are encouraged to explore solutions available in <a class=\"ek-link\" href=\"https:\/\/eshop.tej.com.tw\/E-Shop\/index\" rel=\"noreferrer noopener\" target=\"_blank\">TEJ E Shop<\/a>, which provides comprehensive databases for various tests.<\/p>\n<h2 class=\"wp-block-heading\"><strong>Source Code<\/strong><\/h2>\n<ul class=\"wp-block-list\">\n<li><a class=\"ek-link\" href=\"https:\/\/gist.github.com\/tej87681088\/aac61698c312a70fce778b903911464a\" rel=\"noopener\" target=\"_blank\">Github<\/a><\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">Extended Reading<\/h3>\n<ul class=\"wp-block-list\">\n<li><a class=\"ek-link\" href=\"\/en\/insight\/analysis-of-the-chip-concentration\/\">Analysis of the chip concentration<\/a><\/li>\n<li><a class=\"ek-link\" href=\"https:\/\/www.tejwin.com\/wp-admin\/post.php?post=17017&amp;action=edit&amp;lang=en\">Herding indicators<\/a><\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">Related Links<\/h3>\n<ul class=\"wp-block-list\">\n<li><a class=\"ek-link\" href=\"https:\/\/api.tej.com.tw\/index.html\" rel=\"noopener\" target=\"_blank\">TEJ API <\/a>HomePage<\/li>\n<li><a class=\"ek-link\" href=\"https:\/\/eshop.tej.com.tw\/E-Shop\/Edata_intro\" rel=\"noopener\" target=\"_blank\">TEJ E-Shop<\/a> Database Purchase<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>MACD, which stands for Moving Average Convergence Divergence, is a commonly used tool in technical analysis for measuring the trend changes and momentum of an asset.<\/p>\n","protected":false},"featured_media":1853,"template":"","tags":[50,52],"insight_category":[16],"class_list":["post-1854","insight","type-insight","status-publish","has-post-thumbnail","hentry","tag-market-data","tag-quantitative-analysis","insight_category-quant-data-science"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/insight\/1854","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/insight"}],"about":[{"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/types\/insight"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/media\/1853"}],"wp:attachment":[{"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/media?parent=1854"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/tags?post=1854"},{"taxonomy":"insight_category","embeddable":true,"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/insight_category?post=1854"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}