台股研究室實作風險因子Beta|單因子選股|風險因子Beta|Ep.1

  • Post author:
  • Reading time:6 mins read
台股研究室
圖片來源:博客來

市面上論述量化交易的中文著作不多,講台股的更少,葉怡成教授去年出版的「台股研究室」是鳳毛麟角的大作,以各種選股因子與模型回測最近12年的台灣股市,
全面檢視台股投資的方法。涵蓋價值因子、獲利因子、風險因子、規模因子、慣性因子,分析全面,回測與分析的注意事項也有點到,針對單因子和多因子策略作探討,比較可惜的是該書無提供相關代碼,這點Finlab課程的內容剛好可以補上,利用Python課程的技巧親身實作葉教授的分析,驗證的同時,更能內化書中的內容,改良成屬於自己的策略。這一系列會從單因子開始實作。

風險因子理論基礎

參考台股研究室Ch.10 & 維基百科

“””

在投資學上,風險指的是報酬率的不確定性,總風險由非系統風險和系統性風險組成。

非系統風險為特定公司發生的風險,例如罷工、火災、經理人背信等等,可透過多元化投資組合抵銷。

系統風險發生於企業外部,無法被多元化投資組合抵銷,也稱作市場風險,系統風險的大小可用\beta  (beta)系數衡量。表示一段時間內股票或投資組合的漲跌比率相對於市場的漲跌比率的比值。例如beta=1.3,則代表市場漲跌1%,投資組合的漲跌期望值為1.3%,與市場走勢同步,波動較市場大。若beta=-0.5%則代表市場漲跌1%,投資組合的漲跌期望值為-0.5%,與市場走勢異步,波動較市場小。

beta係數利用回歸的方法計算,可簡單歸類:
beta係數絕對值等於1即證券的價格與市場一同變動。
beta係數絕對值高於1即證券價格比總體市場更波動。
beta係數絕對值低於1即證券價格的波動比市場為低。
如果beta =0表示沒有風險。

其他相關理論內容可自行參考書籍或網站資料

“””

投資組合Beta實作

完整程式碼連結置底。

帶入投資組合標的與權重、還原股價、benchmark資料即可做成,這邊使用發行量加權報酬指數,使用python內建的統計套件“from scipy import stats”的linregress(線性回歸)計算出beta和alpha,

tickers = ['1101', '2330', '6261', '6263', '9939']
weights = [0.1,0.2,0.25,0.25,0.2]

def get_alpha_beta(tickers:list,weights:list,start_date=None,end_date=None,limit=None,price_data=None,benchmark_ret=None,plot=False):
    if price_data is None:
        price_data =data.get_adj()
    price_data = price_data[tickers]
    if start_date:
        price_data = price_data[price_data.index >= start_date]
    if end_date:
        price_data = price_data[price_data.index <= end_date]
    if limit:
        price_data = price_data.iloc[-limit:]
    ret_data = price_data.replace(0,np.nan).fillna(method='ffill').pct_change()[1:]
    port_ret = (ret_data * weights).sum(axis = 1)
    if benchmark_ret is None:
        benchmark_ret=data.get('benchmark_return:發行量加權股價報酬指數').pct_change()[1:].loc[port_ret.index].iloc[:,-1]
    if plot:
        df=pd.concat([benchmark_ret, port_ret], axis=1)
        df.columns=['benchmark','port']
        sns.regplot(x='benchmark',y='port',data=df)
        plt.xlabel("Benchmark Returns")
        plt.ylabel("Portfolio Returns")
        plt.title("Portfolio Returns vs Benchmark Returns")
        plt.show()
    beta, alpha = stats.linregress(benchmark_ret.values,port_ret.values)[:2]
    return beta, alpha

get_alpha_beta(tickers,weights,'2020-1-1','2021-4-30',plot=True)

beta port
  

Beta 選股策略

台股研究室採用T+2季做為財報消息公布後的進場點,Q1-Q4分別在同年
7月、同年11月、隔年1月、隔年4月的1日進場,避免先視偏差,採取比較延遲進場的保守作法,實務上一般人也很難跟消息跟很緊,這樣的設定是合理的。

選股與回測策略條件如下

1. beta以進場日前200天計算。

2. 每回合持有一季,不帶入稅費計算,主要看分組趨勢。

3. 參考台股研究室,beta分10組,分組的數值由大到小,第1組為beta最大前10%,第10組為beta最小的10%,以此類推。分組回測主要是方便觀察單因子是否為單調線性,若是,策略效果較顯著,若為曲折線型,則參考度較小。

程式細節:
使用pandas的rank與cut分組,cut比較少在使用,執得認識一下。
https://pandas.pydata.org/docs/reference/api/pandas.cut.html

beta_cal_range=200
now = datetime.now().strftime("%Y-%m-%d")
dates=pd.date_range(start='2008-1-1', end=now , freq='3MS')

df_set=[]
for date in dates:
    print(f'process {date}')
    price_data =data.get_adj()
    port_ret = price_data[price_data.index < date].replace(0,np.nan).fillna(method='ffill').pct_change()[1:].iloc[-beta_cal_range:].dropna(axis=1)
    benchmark_ret=data.get('benchmark_return:發行量加權股價報酬指數').pct_change()[1:].loc[port_ret.index].iloc[:,-1]
    df=pd.DataFrame([{'stock_id':i,'beta':stats.linregress(benchmark_ret.values,port_ret[i])[0] } for i in port_ret.columns])
    df['date']=date
    df['beta_rank']=df['beta'].rank(pct=True)
    labels=[str(i) for i in range(10,0,-1)]
    df['label']=pd.cut(df['beta_rank'],bins=[i/10 for i in range(0,11,1)], labels=labels)
    df_set.append(df)

df_all=pd.concat(df_set)

label_group=df_all.copy()
label_group=label_group.set_index(['stock_id','date'])
add_profit_prediction(label_group)
label_group=label_group.groupby(['date','label'])[['beta','return']].mean()
label_group=label_group.dropna()
label_group=label_group.reset_index()
label_group['cumprod_return']=label_group.groupby(['label'])[['return']].cumprod()
label_group

回測結果

newplot
各季大部分分組呈現左高右低,beta小的組別在多頭沒那麼強勢時,風險比beta大的組別好,尤其是金融海嘯的空頭時期。近期多頭強勢,beta大的吃香。
newplot 1
newplot 2
beta越大的組別(label小的)下一季的股票波動很大,且大跌次數多。beta越小的組別(label大的)下一季的股票波動較小,跌次數少,上漲仍會吃到,雖然抗跌抗漲,但抗漲的幅度沒想像中大,抗跌的好處蓋過抗漲。
newplot 3
長期獲利累積下來,beta小的組別9、10表現很好,累積報酬率明顯大過beta大的組別,回撤率小,穩穩向上。
newplot 4 1
beta小的組別明顯選出來的標的以小型股(冷門股)居多,lebel.10股本中位數為60000張,lebel.9股本中位數為60000張。股本趨勢隨beta越大上升。對資金較大的人,流動性需要考慮。

結論

實作出來的結果與葉教授書中圖片的結果相似,單因子策略有效。證實冒著較高的風險,不一定報酬較高,反而冒著較低的波動風險,長期能獲得較好的績效。相關結果的解釋可參閱書中內容。

beta大的台股投組放中長期小心閃尿啊,瘋狗流愛抓高beta的,停損要設好,長期凹下場不好。中長期投組可納入風險因子當作篩選因子,低波動進場,放著好安心。

beta單因子策略即始劃分10組,用最小beta的投資仍有百檔標的,需要進一步搭配其他因子減少標的和優化,考量流動性問題,將第9組一併納入可減少部分流動性風險。

colab程式連結

供各位先進參考

Ben

Python 軟體工程師與量化策略研究員。 鑽研資料工程、網頁後端、資料視覺化、量化交易策略開發。 投資主力在台股市場,量化策略為主、質化分析為輔,追求人機攜做最佳化。逐步將觸角延伸到總經、美股、加密貨幣,朝更全方位的交易人邁進。