Table of Contents
現金增資是上市櫃公司常見的籌資方式,目的為擴大資本支出、償還相關債務以及改善財務結構等,但有不少文獻指出,這種借錢的舉動會向市場發出負面的訊號,公司股價因此時常在宣告現金增資時應聲下跌。
而事件研究法即是研究公司重大事件(購併、增資、股票回購…)或是金融市場事件(制度改革、政策、總經…),對於公司價值影響的一種統計方法。一般而言,主要依循以下步驟進行 : 事件日確定、定義估計期間與事件發生期間、計算異常報酬率、統計檢驗。因此本週我們透過 TEJ API的資料庫,來觀察現金增資宣告是否真的會對台灣上市公司價值造成影響吧!
本文使用 Windows OS 並以 Jupyter Notebook 作為編輯器
import tejapi import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import LinearRegression from scipy import stats tejapi.ApiConfig.api_key = 'Your Key' tejapi.ApiConfig.ignoretz = True
Note: sklearn.linear_model用於迴歸分析;scipy用於統計檢定
tse_stocks
列表security = tejapi.get('TWN/ANPRCSTD', mkt = 'TSE', stypenm = '普通股', opts = {'columns':['coid','mdate','stypenm','mkt']}, paginate = True, chinese_column_name = True) tse_stocks = security['證券碼'].tolist()
events = tejapi.get('TWN/ASTK1', x_mt_date = {'gte':'2019-01-01', 'lte':'2021-08-01'}, opts = {'columns':['coid','cash','x_mt_date']}, paginate = True, chinese_column_name = True)
本文以股東會決議日為事件發生日,並選取 2019~2021年8月之間的事件
cash = events[events['現金增資(仟股)']>0].reset_index(drop=True)
除了現金增資外,亦包含盈餘、公積增資等事件,而本文以現金增資為主
tse_cash = cash[cash['公司'].isin(tse_stocks)].reset_index(drop=True)
利用上市公司代碼tse_stocks
與 isin()
,篩選出 cash
表格有涵蓋上市公司代碼的資料
估計期間 (T0 ~ T1):設 -260期 ~ -10期,此期間的報酬與 Fama & French 5因子投組報酬跑迴歸,得到公司各因子的估計係數,其將用於計算事件期間的預期報酬
事件日 (0): 股東會決議日,因其為市場接收到現金增資事件的最早時點
事件期間 (T2 ~ T3):設 -5期 ~ +5期,計算此期間實際報酬與 Fama & French 模型所預測出的報酬差異,得到異常報酬
因涵蓋 140 起現金增資宣告事件,故以迴圈的方式進行每個事件的運算,並儲存最後結果至 final
變數,而過程中會排除報酬率資料缺漏、初次上市事件。以下擷取迴圈部分程式碼的重點內容加以解釋,並圖示第一筆資料 ( stock = ‘1314’, date = ‘2019–05–24’ ) 處理情況幫助理解每個迴圈的運作。其餘資料處理部分則詳見文章下方的完整程式碼
return_set = tejapi.get('TWN/APRCD', coid = stock, mdate = {'gte': date + pd.Timedelta(days = -450), 'lte': date + pd.Timedelta(days = 25)}, opts = {'columns' : ['coid', 'mdate','roi']}, paginate = True, chinese_column_name = True)
利用每起事件的公司 stock
、日期 date
,撈取事件日前後的報酬率,這邊取 -450 ~ 25 天是為了確保擁有完整估計期間 (251交易日)、事件期間 (11交易日)的報酬率
event_index = return_set[return_set['年月日'] == date].index.values.astype(int)[0]
首先找出事件日的索引值,轉成數字後儲存到 event_index
,以此為基準切割成估計期間、事件期間報酬
estimate_window = return_set[event_index - 260 - 1: event_index - 10].reset_index(drop=True) event_window = return_set[event_index - 5: event_index + 5 + 1].reset_index(drop=True)
#估計起始日期(-260) estimate_start = estimate_window.loc[0, '年月日'] #事件結束日期(+5) event_end = event_window.loc[5*2, '年月日']
分別找出估計期間的起始日期、事件期間的結束日期,並儲存到對應變數。再以此為根據,直接撈出 – 260期 ~ 5期,這段期間的每日市場風險溢酬、規模溢酬、淨值市價比溢酬、盈利能力因子、投資因子投組報酬資料,Y9999
代表以所有上市公司、簡單報酬率計算以上因子投組報酬
fama_french = tejapi.get('TWN/AFACTO1D', coid = 'Y9999', mdate = {'gte':estimate_start, 'lte': event_end}, opts = {'columns': ['coid', 'mdate','mrp','smbn','bp','op','inv']}, paginate = True, chinese_column_name = True)
ols_data = estimate_window.merge(fama_french, on = '年月日') x = ols_data.loc[:,['市場風險溢酬', '規模溢酬(5因子)','淨值市價比溢酬','盈利能力因子','投資因子']].values y = ols_data['報酬率%'].values.reshape(-1,1) model = LinearRegression() model.fit(x,y)
將估計期間報酬率與 Fame-French 因子報酬合併,並形成帶入迴歸模型所需的二維陣列應變數(公司報酬率) 與自變數 (因子報酬),最後再帶入模型
predict_data = event_window.merge(fama_french, on = '年月日') event_x = predict_data.loc[:,['市場風險溢酬','規模溢酬(5因子)','淨值市價比溢酬','盈利能力因子','投資因子']].values
將事件期間報酬率與 Fame & French 因子報酬合併,並將這段期間的因子投組報酬儲存,其將用於計算預期報酬的自變數,因此將其置入已有估計係數的模型 model.predict()
算出預期報酬,接著即可算出異常報酬率、累計異常報酬率。這邊最後加上相對天數欄位,將用於最後所有事件的分群計算。
event_window['預期報酬率'] = model.predict(event_x) event_window['異常報酬率'] = event_window['報酬率%'] - event_window['預期報酬率'] event_window['累計異常報酬率'] = event_window['異常報酬率'].cumsum() event_window['相對天數'] = [i for i in range(-5, 5 + 1)]
每個事件 (迴圈) 重複以上基本步驟,並將最後將結果都附加在 final
表格,以下為 final
最終結果
sorted_data = final.groupby(by = '相對天數').mean().reset_index()
plt.plot(sorted_data['相對天數'], sorted_data['異常報酬率'], label = 'Average Abnormal Retrun') plt.plot(sorted_data['相對天數'], sorted_data['累計異常報酬率'], label = 'Cumulative Abnormal Return') plt.xlabel('Event Day') plt.title('Event Study') plt.xticks(np.arange(-5, 5+1 , 1)) plt.legend() plt.show()
可以看到,在宣告現金增資日後的幾天,出現明顯地異常負報酬,但到了第三天後,異常報酬恢復到 0 左右,可能代表市場已經消化這個資訊
ttest = pd.DataFrame() for day in range(-5,5+1): sample = final[final['相對天數'] == day]['異常報酬率'].values t, p_value = stats.ttest_1samp(sample, 0) if p_value <= 0.01: significance = '***' elif 0.01 < p_value <= 0.05: significance = '**' elif 0.05 < p_value <= 0.1: significance = '*' else: significance = '' ttest = ttest.append(pd.DataFrame(np.array([day,t,p_value, significance]).reshape((1,4)), columns = ['相對天數','T檢定值', 'P-value','顯著水準'],)).reset_index(drop=True)
ttest = ttest.set_index('相對天數')
利用 stats.ttest_lsamp()
進行T檢定,檢驗每個相對日的異常報酬是否顯著異於 0。最後再根據 P 值自行加上顯著性星星,最後整理成 ttest
表格
此時可以推論,在現金增資宣告日的後1、2日,公司的價值顯著受到影響,推測是因為公司通常於盤後宣告重大決議,因此股價於次日交易日開始反應
經過這一連串的操作,相信讀者對於事件研究有了進一步的認識!過程中有許多假設可以自行調整、或是參考對應領域的文獻,例如估計期間、事件期間與異常報酬的計算方式,而這當中運用到的資料,都能從 TEJ API 資料庫快速撈取下來,直接省略事前資料爬取、清理、計算等繁瑣步驟。若讀者有興趣驗證其他經濟事件對公司的影響,推薦到 TEJ E Shop,選購最符合自身需求的方案!
電子報訂閱