FinLab

事件研究法教學:用 Python 分析除權息對股價的影響

October 31, 2023

當台灣的上市公司宣布有關股票的特別消息,比如說要分紅或者調整股票的價值(這種情況我們稱之為除權或除息),這通常會對公司的股票價格造成一些波動。我們的研究就是要搞清楚,這些宣布到底對股票價格有什麼影響。

這篇文章中,我們將介紹 finlab package 嶄新超好用的工具,讓你一秒判斷除權息究竟要做多還是做空?首先,我們會從財務的大數據庫裡面搜集這些宣布的具體信息,包括宣布的時間、具體的生效日和股票的交易變動。這樣我們就能知道哪天發生了什麼事。

接下來,我們會整理這些信息,把它們按照時間和股票代號排列好,這個過程就像是把一堆散亂的資料整理成清晰的列表。

然後我們用一種叫做事件研究的方法,來計算這些特別宣布前後,股票的價格變動情況。我們會比較這個變動和一般市場的變動有什麼不同,從而評估這個宣布的影響力度。

簡而言之,我們的研究就是想要了解,當公司發出某些股票相關的重要消息時,投資人的反應是怎樣的,並且這對股票價格會有什麼樣的效果。

查看事件前後的異常報酬率

我們將用簡單的 Python 語法來分析:

  1. 從財務數據庫中提取除權息公告數據。
  2. 清洗和轉換數據,創建事件矩陣。
  3. 進行事件研究,計算異常收益率。
  4. 將結果以視覺化的方式呈現,分析事件對股價的影響。

只需要簡單的幾行,就能知道事件前後的異常報酬率了。舉例而言,如果想知道除權前後的異常報酬率,只需要執行下面的程式碼,就能輸出圖表了。

拿取財務資料

想像一下,你是一位探險家,你手中有一張藏寶圖,這張圖上標記著一系列的「X」,代表著可能埋藏著寶藏的地點。在這個比喻中,寶藏就是一個公司特定財務事件(如除權除息)對股票價格的潛在影響,而你要做的,就是跟隨這張地圖去探索這些「X」標記處是否真的有寶藏。

在我們的情境中,「X」標記是數據中的除權除息事件。我們的目標是要找出這些事件是否對股票價格造成了影響。

首先,我們利用一個像是魔法箱子的工具 —— finlab 數據庫,這個數據庫像是藏寶圖的起點。我們叫它出來(用一行程式碼),讓它顯示出最近的幾個「X」(也就是公司的除權除息事件)。

顯示程式碼
from finlab import data
 
data.get('dividend_announcement').head()

除權息公告數據集範例

  • finlab 庫導入 data 模組。
  • 調用 get 函數來檢索 dividend_announcement 數據集,這是一個包含公司除權息公告的數據集。
  • 顯示了包含多個欄位的 DataFrame,這些欄位包括股票代號、公告日期、基準日期、公司名稱、所屬期間、增資配股等信息。

然後,我們要確保我們的地圖是乾淨的,沒有重複的標記,也沒有模糊不清的部分(這就是去重和去除空值的程式碼部分)。我們還會重新繪製地圖,讓每個「X」都按照日期排好(轉換成一個新的表格)。

顯示程式碼
from finlab import data
 
event = data.get('dividend_announcement')\
    .drop_duplicates(subset=['stock_id', '除權交易日'])\
    .dropna(subset=['stock_id', '除權交易日'])\
    .pivot(index='除權交易日', columns='stock_id', values='市場別')\
    .rename_axis('date')\
    .notna()
 
event.head()
  • 這段程式碼進一步處理上述提取的數據。
  • .drop_duplicates() 移除重複的行。
  • .dropna() 刪除含有空值的行。
  • .pivot() 將數據重塑成一個以除權交易日為索引,股票代號為欄位的新 DataFrame。
  • .rename_axis('date') 更改索引名稱為 date
  • .notna() 將所有的 NaN 值轉換為布林值 False。

除權交易日事件矩陣

這樣就可以產生一張表格,True,對應到就是除權的股票和日期,我們可以用簡易的程式來驗證,來看除權息通常都是每年的夏天發生:

顯示程式碼
event.sum(axis=1).plot()

除權息事件時間分布圖

接下來我們可以透過很方便的函數來產生除權息後的五日、十日、二十日、六十日以後的報酬率:

顯示程式碼
from finlab.tools.event_study import create_factor_data
 
adj_close = data.get('etl:adj_close')
factor_data = create_factor_data(event, adj_close, event=event)
 
factor_data

除權息後各期報酬率數據

但如此還是有點不清楚,有沒有方法能來統計呢?接下來我們可以透過 event_study 來視覺化事件發生後的報酬率:

顯示程式碼
from finlab.tools import event_study
 
benchmark = data.get('benchmark_return:發行量加權股價報酬指數')
 
r = event_study.event_study(factor_data, benchmark, adj_close.ffill())
 
r.head()

事件研究異常報酬率結果

這樣就產生出一張表格,其中 y 軸是每一次除權息,x 軸是除權息的前後幾天的報酬率。我們可以用簡易的方式來將報酬率繪製出來:

顯示程式碼
r.mul(100).mean().plot.bar(use_index=False)
ax = r.mean().mul(100).cumsum().plot(use_index=False)

除權息事件前後異常報酬率與累計報酬率圖表:Y軸是報酬百分比,X軸是天數,第零天為事件發生日。直條圖為扣除大盤的報酬率,線段為累計報酬率。

Y軸是報酬百分比,X軸是天,第零天為事件發生日。直條圖為扣除大盤的報酬率,線段為累計報酬率。

執行完上面的程式後,就能把數據視覺化呈現出來,運用起來相當方便。更甚者,FinLab 已經提供完整的資料集了,不用自己再用爬蟲去慢慢爬資料了!

想建立自己的策略?

用自然語言描述你的選股想法,AI 自動驗證、回測、給你答案

免費開始