本文重點摘要
- 文章難度:★★★☆☆
- 簡介超級趨勢指標 ( SuperTrend Indicator ) 與平均趨向指標 ( Average Directional Index, ADX )。
- 介紹超級趨勢策略以及如何透過 ADX 指標優化超級趨勢策略。
- 透過 TQuant Lab 回測超級趨勢策略,觀察此策略賺取波段價差的效益。
前言
超級趨勢指標 ( SuperTrend Indicator ) 是一種技術分析工具,用於識別金融市場中的趨勢走向,幫助投資人判別波段的相對高點及低點,進而做出買賣決策,因此超級趨勢指標特別適合無法判別股價走向,或是常常太早退場、錯過波段漲幅的投資人。不過超級趨勢指標也有在盤整階段會失靈的缺點,所以本文我們將使用平均趨向指標 ( Average Directional Index, ADX 指標 ) 來優化超級趨勢策略。
ADX 指標是由 J. Welles Wilder 於 1978 年研發,代表價格趨勢強度的指標,ADX 指標介於 0~100,數值越大,即代表趨勢越強。因此我們將結合超級趨勢指標與 ADX 指標,有效判斷出趨勢與盤整區間,藉此建構超級趨勢策略,並利用 TQuant Lab 回測其績效,幫助投資人深入了解超級趨勢策略如何賺取波段收益。
超級趨勢指標 & ADX 指標
上圖為超級趨勢指標於價格曲線上的示意圖,我們可以看到超級趨勢指標能有效地判別出趨勢上漲的區間;但相對的,在盤整區間超級趨勢指標便會失靈,產生交易上的雜訊,因此本文我們將超級趨勢指標搭配可以為我們判斷趨勢強度的 ADX 指標,建構出超級趨勢策略。以下我們將分別介紹超級趨勢指標與 ADX 指標的計算公式,讓我們一窺這兩種指標的奧秘!
超級趨勢指標公式
雖然在以上的示意圖中,超級趨勢指標看似只由一條曲線組成,不過實際上超級趨勢指標擁有上軌與下軌——當收盤價突破上軌,代表價格突破壓力,即將形成上漲趨勢,此時下軌將成為新的支撐;反之,當收盤價跌破下軌,代表價格跌破支撐,即將形成下跌趨勢,此時上軌則成為新的壓力,因此我們看到的超級趨勢指標即為上漲趨勢中的支撐 ( 下軌 ) 與下跌趨勢中的壓力 ( 上軌 ) 所形成。
為了計算超級趨勢指標的上下軌,我們需要以下三個步驟:
Step1: 計算 ATR
ATR ( Average True Range, 真實波動幅度均值 ) 的計算基於 TR ( True Range, 真實波動幅度 )。TR 代表特定時間內的最大價格變動範圍,通常由以下三個差值中絕對值的最大值來決定:
- 當日最高價與最低價之差
- 前日收盤價與當日最高價之差
- 前日收盤價與當日最低價之差
將 TR 進行一段時間 ( window length ) 的移動平均,即可取得 ATR,一般為 14 日 ATR。
p.s. 更多關於 ATR 的應用可以參考:TQuant Lab 損失規避策略 — 真實波動幅度均值。
Step2: 計算基準上軌與下軌
基準上、下軌公式:
- Basic upper band = ( 最高價 + 最低價 ) / 2 + Multiplier × ATR
- Basic lower band = ( 最高價 + 最低價 ) / 2 - Multiplier × ATR
其中,Multiplier 是一個用來調整基準線距離的倍數,一般為 2 或 3。
Step3: 計算最終上軌與下軌
- 最終上軌:如果新的基準上軌低於前一個最終上軌,或者前一天的收盤價高於前一個最終上軌,則使用新的基準上軌。否則保持前一天的最終上軌不變。
- 最終下軌:如果新的基準下軌高於前一個最終下軌,或者前一天的收盤價低於前一個最終下軌,則使用新的基準下軌。否則保持前一天的最終下軌不變。
ADX 指標公式
ADX 指標的數值範圍在 0 到 100 之間,其數值的涵義如下:
- ADX < 25: 市場趨勢較弱,屬於盤整區間
- 25 < ADX < 50: 市場正在形成一定程度的趨勢
- ADX > 50: 市場已形成明顯的趨勢
ADX 指標的計算包含以下四個步驟:
Step1: 計算 ATR
同超級趨勢指標中 ATR 的計算方法。
Step2: 計算 +DM, -DM ( Directional Movement )
- +DM: 若 ( 今日高點 - 昨日高點 ) > ( 昨日低點 - 今日低點 ),則 +DM = max ( 今日高點 - 昨日高點, 0 ),否則 +DM = 0
- -DM: 若 ( 昨日低點 - 今日低點 ) > ( 今日高點 - 昨日高點 ),則 -DM = max ( 昨日低點 - 今日低點, 0 ),否則 -DM = 0
Step3: 計算 +DI, -DI ( Directional Indicator )
- +DI: 100 × ( +DM 的移動平均值 / ATR )
- -DI: 100 × ( -DM 的移動平均值 / ATR )
Step4: 計算 ADX
DX = 100 × ( |+DI - (-DI)| / |+DI + (-DI)| )
將 DX 進行一段時間 ( window length ) 的移動平均,即可取得 ADX。
以下,我們將透過 TQuant Lab 來生成超級趨勢策略所需的交易訊號。
超級趨勢策略
編輯環境與模組需求
本文使用 Windows 11 並以 Jupyter Lab 作為編輯器。
import os import numpy as np import pandas as pd # tej_key tej_key = 'your key' api_base = 'https://api.tej.com.tw' os.environ['TEJAPI_KEY'] = tej_key os.environ['TEJAPI_BASE'] = api_base
取得股票池
根據超級趨勢指標的特性,我們希望選取具有成長性且容易形成趨勢的股票,因此我們使用 get_universe 函式取得 2018 年底電子工業的上市股票清單,並透過 TEJ Tool API 篩選市值前 10 名的股票。
from zipline.sources.TEJ_Api_Data import get_universe pool = get_universe(start = '2018-12-28', end = '2018-12-28', mkt_bd_e = 'TSE', # Listed stock in Taiwan stktp_e = 'Common Stock', main_ind_c = 'M2300 電子工業' # Electronics Industry ) import TejToolAPI mktcap_data = TejToolAPI.get_history_data(start = '2018-12-28', end = '2018-12-28', ticker = pool, columns = ['Market_Cap_Dollars'] ) tickers = mktcap_data.nlargest(10, 'Market_Cap_Dollars')['coid'].tolist()
導入股票池價量資料
資料期間從 2019-01-01 至 2024-07-01,並導入上述 10 檔股票的價量資料與加權股價報酬指數 ( IR0001 ) 作為績效比較基準。
start = '2019-01-01' end = '2024-07-01' os.environ['mdate'] = start + ' ' + end os.environ['ticker'] = ' '.join(tickers) + ' ' + 'IR0001' !zipline ingest -b tquant
建立 CustomFactor 函式
有了價量資料,我們就能使用 CustomFactor 函式建構出我們所需的超級趨勢指標上下軌,以及 ADX 指標。此外,為了藉由超級趨勢指標最佳化地判斷出趨勢區間,減少短期的交易雜訊,我們將超級趨勢指標的 ATR 計算區間設為 50 日,並將計算基準上下軌的 Multiplier 設為 4;ADX 指標的計算區間則設為 14 日,以便及時判讀趨勢強弱。
詳細 CustomFactor 因子建構方式可參考 GitHub 原始碼:TQuant Lab 超級趨勢策略。
建立 Pipeline 函式
Pipeline() 提供使用者快速處理多檔標的的量化指標與價量資料的功能,於本次案例我們用以處理:
- 導入每日收盤價
- 計算超級趨勢指標的最終上下軌
- 計算 ADX 指標from zipline.data import bundles from zipline.pipeline import Pipeline from zipline.TQresearch.tej_pipeline import run_pipeline from zipline.pipeline.filters import StaticAssets bundle = bundles.load('tquant') benchmark_asset = bundle.asset_finder.lookup_symbol('IR0001',as_of_date = None) def make_pipeline(): close = TWEquityPricing.close.latest supertrend = Supertrend() adx = ADX() return Pipeline( columns={ 'close': close, 'final_upperband': supertrend.final_upperband, 'final_lowerband': supertrend.final_lowerband, 'ADX': adx.adx }, screen = ~StaticAssets([benchmark_asset]) ) pipeline_result = run_pipeline(make_pipeline(), start, end) pipeline_result
建立 Initialize 函式
initialize() 函式用於定義交易開始前的每日交易環境,與此例中我們設置:
- 流動性滑價
- 交易手續費
- 買入持有加權股價報酬指數 ( IR0001 ) 的報酬作為基準
- 將上述計算的 Pipeline 導入交易流程中
- 設定 context.has_order 記錄是否已買入from zipline.finance import slippage, commission from zipline.utils.calendar_utils import get_calendar from logbook import Logger, StderrHandler, INFO from zipline.api import * # Set up 'log' so we can see trading details when backtesting. log_handler = StderrHandler(format_string='[{record.time:%Y-%m-%d %H:%M:%S.%f}]: ' + '{record.level_name}: {record.func_name}: {record.message}', level=INFO) log_handler.push_application() log = Logger('Algorithm') def initialize(context): set_slippage(slippage.VolumeShareSlippage()) set_commission(commission.Custom_TW_Commission()) set_benchmark(symbol('IR0001')) attach_pipeline(make_pipeline(), 'mystrategy') context.has_ordered = {}
建立 Handle_data 函式
handle_data() 為構建交易策略的重要函式,會在回測開始後每天被呼叫,主要任務為設定交易策略、下單與紀錄交易資訊。
如文章開頭所述,我們希望透過 ADX 指標判別出夠強的趨勢再進行交易,以減少超級趨勢指標無法判讀盤整區間的劣勢,不過在建構買進訊號時,我們並不會避開盤整區間,原因是盤整區間可視為股市休息、能量累積的階段,不失為進場布局的好時機;反之,在建構賣出訊號時,我們才需要搭配 ADX 指標,確保進入下行趨勢再賣出持股,以免錯過先前的波段漲勢。
超級趨勢策略的進出場規則如下:
Long Entry:
收盤價突破最終上軌,代表價格突破壓力,即將形成上漲趨勢,依股票池數量等比例買入。
Short Entry:
收盤價跌破最終下軌,加上 ADX > 50,代表價格跌破支撐,形成下跌趨勢,將持股賣出。
def handle_data(context, data): out_dir = pipeline_output('mystrategy') for i in out_dir.index: sym = i.symbol price = out_dir.loc[i, 'close'] ADX = out_dir.loc[i, 'ADX'] final_upperband = out_dir.loc[i, 'final_upperband'] final_lowerband = out_dir.loc[i, 'final_lowerband'] cash_position = context.portfolio.cash stock_position = context.portfolio.positions[i].amount buy, sell = False, False if context.has_ordered.get(f'{i}') is None: context.has_ordered[f'{i}'] = False record( **{ f'price{sym}': price, f'buy{sym}': buy, f'sell{sym}': sell } ) if stock_position == 0: if (context.has_ordered[f'{i}'] == False) and (price > final_upperband): order_target_percent(i, 1/len(tickers)) buy = True context.has_ordered[f'{i}'] = True record(**{f'buy{sym}': buy}) elif stock_position > 0: if (context.has_ordered[f'{i}'] == True) and (price < final_lowerband) and (ADX > 50): order_target_percent(i, 0) sell = True context.has_ordered[f'{i}'] = False record(**{f'sell_{sym}': sell})
回測超級趨勢策略
使用 run_algorithm() 執行上述設定的超級趨勢策略,設置交易期間為 start_dt ( 2019-01-01 ) 到 end_dt ( 2024-07-01 ),所使用資料集為 tquant,初始資金為 10,000,000 元。其中輸出的 results 就是每日績效與交易的明細表。
start_dt = pd.Timestamp(start, tz = 'utc') end_dt = pd.Timestamp(end, tz = 'UTC') from zipline import run_algorithm results = run_algorithm( start = start_dt, end = end_dt, initialize = initialize, bundle = 'tquant', analyze = analyze, capital_base = 1e7, handle_data = handle_data ) results
利用 Pyfolio 進行績效評估
import pyfolio as pf returns, positions, transactions = pf.utils.extract_rets_pos_txn_from_zipline(results) benchmark_rets = results.benchmark_return # Creating a Full Tear Sheet pf.create_full_tear_sheet(returns=returns, positions=positions, transactions=transactions, benchmark_rets=benchmark_rets )
透過上表我們可以看到超級趨勢策略的年化報酬率達到 25.88%,年化波動度則約為相對較低的 13%。若進一步觀察績效指標,夏普比率為 1.84,索提諾比率則為 2.82,顯示超級趨勢策略能有效迴避下行風險,並在承受較低的風險下賺取超額報酬。觀察報酬曲線圖,雖然超級趨勢策略並沒有明顯超過大盤的績效,不過我們可以發現 2021 年初達到波段高點後的報酬趨於水平到 2022 年中,成功避免了 2022 熊市的大回檔,並且在 2023 年後也有不錯的回升趨勢,可見超級趨勢策略鎖住波段獲利、提前規避下行趨勢風險的特性。
在回檔比率圖中,可見最大的兩次回檔發生在 2020 年初的疫情恐慌以及 2022 年的熊市,不過相較於大盤兩次皆有約 30% 的回檔,超級趨勢策略的 16% 及 14 % 回檔已是相對較小的了。
個別股票超級趨勢策略表現
我們藉由 Pipeline 輸出的資料表,以及 run_algorithm() 產出的 results 交易明細表額外建立了一個函式 graph() 幫助我們了解個別股票於超級趨勢策略的表現。
graph() 建構方式可參考 GitHub 原始碼:TQuant Lab 超級趨勢策略。
上圖中紅點為進場點,綠點為出場點。可以看到超級趨勢策略在 2019 到 2020 年的上行趨勢中成功獲利,不過在 2021 年的盤整階段以及 2022 年的下行趨勢中卻有買在相對高點的失靈狀況,所幸我們透過 ADX 指標優化的賣點限縮了部分的跌幅,最後於 2023 年的買點也成功抱住波段獲利到 2024 年 7 月。
結論
本次策略由超級趨勢指標進行發想,而有鑑於超級趨勢指標於盤整階段的失靈現象,我們也使用 ADX 指標來優化策略,減少短期的交易雜訊。透過 Pyfolio 產出的績效分析圖表,我們觀察到超級趨勢策略有效規避下行趨勢的特性;另外我們也查看台積電在本策略的表現,結果發現策略確實有把握波段漲幅的效果。
需要提醒投資朋友的是,本文在策略建構上涉及股票池的選定以及指標計算的參數設定,不同股票池與參數皆可能對績效表現有所影響,對本策略有興趣的投資朋友可以嘗試不同的設定,建構最有效益的投資策略。
溫馨提醒,本次策略與標的僅供參考,不代表任何商品或投資上的建議。之後也會介紹使用 TEJ 資料庫來建構各式指標,並回測指標績效,所以歡迎對各種交易回測有興趣的讀者,選購 TQuant Lab 的相關方案,用高品質的資料庫,建構出適合自己的交易策略。
【TQuant Lab 回測系統】解決你的量化金融痛點
全方位提供交易回測所需工具
留言 0