使用 Python 和 finlab 庫優化台灣股市投資策略

引言:投資於台灣股市的機會

對於專注於台灣股市的投資者來說,元大高股息ETF(代號:0056)提供了投資於台灣高股息股票的機會。這種ETF旨在追蹤高股息指數,並尋求穩定的股息回報與資本增值機會。本文將介紹如何使用Python的finlab庫進行策略分析和回測,以揭示此ETF的優勢和潛在弱點,並制定更精確的投資策略。

一、0056.TW ETF的投資吸引力與挑戰

投資吸引力

作為一個以高股息股票為目標的ETF,0056 提供了相對穩定的收益來源,非常適合尋求收入型投資的人群。其低波動性也使得風險較低的投資者將其視為一個吸引人的選擇。

潛在挑戰

  1. 選股範圍限制:由於ETF設計上的限制,需要選擇流動性較高的股票,因此無法覆蓋所有高股息股票,這限制了投資者的選擇範圍。
  2. 高股息股票的風險:高現金股息的股票未必能保證股價的長期表現。從統計數據來看,這類股票往往表現較差,缺乏有效的抗風險能力。

二、比較 0056.TW 與策略性投資的表現

從2010年開始的數據顯示,0056 ETF的增長軌跡相對平穩,而策略的增長曲線則顯示出更加顯著的上升趨勢。這表明,使用策略性投資可以在長期內明顯優於直接投資0056.TW ETF。

image
0056 與新的策略比較

三、使用 Python 和 finlab 庫實施投資策略

數據獲取

使用finlab庫可以輕鬆獲取多種金融數據,例如股票的收盤價數據,這對進行金融分析和量化交易至關重要。

撰寫策略條件

在實行量化交易策略時,清楚定義策略條件極為重要。以下是使用 Python 和 finlab 庫來撰寫策略條件的具體方法,幫助更好地理解和實施這些策略:

1. 現金股息的年化股息率計算

股息率是衡量股票分紅能力的重要指標,年化股息率則進一步反映了股票在一年內為投資者帶來的潛在回報。計算方式如下:

  • 數據提取:首先,從 finlab 數據庫中提取股票的收盤價和股利公告數據。
  • 股息率計算:將公司宣布的現金股息除以其在股息宣布日的收盤價,得到股息收益率。接著,將這些股息收益率滾動累加,計算出一定時間(例如520天)內的年化股息率。

2. 動態平均比較以識別趨勢

動態平均比較是用來判斷股票是否保持上升趨勢的方法,通過以下步驟實施:

  • 移動平均計算:計算股票的多個移動平均值,例如10天、30天、50天等。這些平均值幫助平滑日常價格波動,提供更清晰的趨勢指示。
  • 趨勢分析:判斷股票的當前收盤價是否持續高於這些移動平均值。如果股票的收盤價穩定高於大部分或所有的移動平均值,則認為股票處於上升趨勢。

3. 風險評估通過最小回撤分析

回撤是衡量股票在某段時間內最大損失的指標,對於評估股票的風險承受能力至關重要:

  • 回撤計算:計算每個交易日的收盤價相對於之前最高價的跌幅百分比,以此來評估股票的最大損失。
  • 風險分析:透過500天的滾動窗口分析股票的最小回撤。這樣可以觀察到股票在不同市場條件下的最壞表現。股票的抗跌能力越強,其在市場低迷時期的表現通常越穩健。

這些策略條件組合在一起,形成一個全面的量化交易策略,不僅分析股票的收益表現,也評估其對市場下行風險的抵抗力。這種方法為尋求在保持增長性的同時管理市場風險的投資者提供了重要的決策支援工具。

整合策略與執行回測

結合收盤價格、股息公告和其他金融指標,選出潛力最大的20支股票進行投資。使用finlab的回測工具來驗證策略在歷史數據上的表現。

結語:加強投資決策

通過使用finlab Python庫實施的策略,投資者可以基於數據驅動的方法來優化投資決策。本文的技術分析和策略介紹,不僅加深了對ETF和股市投資的理解,也展示了如何透過科技提高投資回報。

# 引入 finlab 套件,給量化分析加點料!
from finlab import data
from finlab.backtest import sim
from finlab.dataframe import FinlabDataFrame

# 拿到股票的收盤價,這是我們的金融日常
close = data.get('price:收盤價')

# 獲取董事會公告的數據,因為我們關心的是股東會得到多少紅包
df = data.get('board_dividend_announcement')
dates = df['股東會日期'].fillna(df['董事會決議(擬議)股利分派日'])

# 讓我們確保每個股票只得到它應得的一份股利,不多也不少
cash_dividend = data.get('board_dividend_announcement')\
    .drop_duplicates(['stock_id', '股東配發之現金(股利)總金額(元)'], keep='first')\
    .groupby([df.stock_id, dates])\
    .first()['盈餘分配之現金股利(元/股)']\
    .dropna().reset_index()\
    .pivot(index='股東會日期', columns='stock_id', values='盈餘分配之現金股利(元/股)')

# 計算年化股息,因為我們希望看到的是長期表現,不是昙花一現
cash_dividend_annual = (cash_dividend / close).rolling(520, min_periods=1).sum()

# 建立一個神秘的等級系統,來找出那些超越平凡的股票
rank = sum([close > close.average(i) for i in range(10, 150, 20)])

# 成交股數也是關鍵,沒人關注的股票可能只有我們的表哥會買
volume = data.get('price:成交股數')

# 回撤告訴我們,股票在壞日子里跌得有多深
drawdown = close / close.cummax()

# 這裡我們選出了最強的20隻股票,因為在股市裡只有最強者才能生存
pos = FinlabDataFrame(cash_dividend_annual)[
     (rank.rank(axis=1, pct=True) > 0.7)
     & (drawdown.rolling(500, min_periods=200).min().rank(axis=1, pct=True) > 0.7)
     & (volume > 50_000)
].is_largest(20)

# 讓我們看看這些股票過去的表現如何,是否真的值得投資
r = sim(pos, resample='Q', upload=False)
r.display()
image 2
image 3

從這份比較來看,策略和0056 ETF之間的表現差異相當明顯。整體而言,這個策略遠遠超過了0056 ETF,實現了1134.93%的總回報,而ETF只有290.64%。這表示策略的年複合成長率(CAGR)達到了20.00%,是0056的兩倍多,達到10.39%。

風險調整後的表現也更亮眼,策略的夏普比率為1.49,遠高於ETF的0.84;索提諾比率也是2.24,比ETF的1.30來得高。儘管策略的最大回撤略高於ETF(-30.59%對比-25.86%),但它的卡爾瑪比率(0.65比0.40)顯示在不利條件下恢復得更好。

此外,無論是月度還是年度回報,這個策略也都表現得更加穩定,充分展現了其抓住市場動向的高效能力。這樣的比較突顯了策略在追求強勁增長和在市場波動中保持韌性方面的雙重優勢,對於尋求穩健成長的投資者來說,無疑是個吸引人的選擇。

FinLab - 韓承佑

嗨大家好,我是韓承佑,FinLab創辦人,畢業於巴黎薩克雷大學資工博士,目前擔任臺灣量化交易協會 學術顧問、台北商業大學 創新育成中心 創業技術顧問與上市科技公司 量化交易顧問。當初,我喜歡寫程式、無意間因為軟體比賽接觸Fintech,從此開始了財經跟程式的學習之路。我們成立 FinLab 量化投資部落格,用自己研發的軟體,對台灣股市做大量快速的實驗。希望可以在量化投資的路上,當大家的「武器製造商」!