前言
吉姆.史萊特(Jim Slater)是英國知名的成長型投資大師,曾替週日電訊報 (Sunday Telegraph) 撰寫投資組合推薦專欄,於 1963至1965年間獲取約 68.9 % 報酬率,與此同時,英國股市僅上漲 3.6%,吉姆.史萊特因此聲名大噪。其最著名的莫過於以「祖魯原則」為依據的投資方法,主張在投資市場向必須學習祖魯族一樣,集中火力在自己選定的利基專門領域,這樣才能發揮優勢。吉姆.史萊特則特別注重中小型公司長期獲利的成長及相對強度,並以本益比/成長率比值(PEG)等作為評價的重要標準,如以下所示 :
- 過去四年每股盈餘持續成長大於15%
- 本益比/成長率比值(PEG)小於1.2、預估本益比低於20倍
- 流動性高、借貸低、現金流量高、過去5年每年皆有獲利
- 公司有競爭優勢,如能主導市場的強勢品牌
- 有轉機或有題材:如新產品或新管理階層
- 市場資本小、股價相對強度高、管理階層持股比重高
編輯環境及模組需求
本文使用 Windows OS 並以 Jupyter Notebook 作為編輯器
import pandas as pd
import numpy as np
import tejapi
import matplotlib.pyplot as plt
tejapi.ApiConfig.api_key = "Your Key"
tejapi.ApiConfig.ignoretz = True
本文重點概要
量化指標
由於吉姆.史萊特的選股條件,部分包含一些主觀判斷的因素,在參考目前台灣市場環境後,整合出以下客觀、可量化的指標作為篩選條件
基本面條件
條件一: 公司總市值 < 市場平均總市值
條件二: 過去五年稅後淨利皆為正
條件三: 過去三年稅後淨利成長率皆 >= 15%
條件四: 預估稅後淨利成長率 >= 15%
條件五: 近五年平均營運現金流量 > 近五年平均稅後淨利
條件六: 近年營運現金流量 > 近年稅後淨利
條件七: 近年營業利益率 >= 10%
條件八: 近年可運用資本報酬率 >= 10%
條件九: 最近一季負債/淨值比 < 50%
條件十: 最近董監事持股比例 >= 20% 或是 最新一期董監事持股比例增加
交易面條件
條件十一: 預估本益比 <= 20
條件十二: 預估本益比/預估稅後盈餘成長率比值 <= 1.2
條件十三: 超額報酬(月) > 0
資料庫使用
投資策略實作
選股條件: 至少符合 9項以上基本面條件,而交易面條件皆須滿足
投組持有期間: 為了避免前視偏誤,參考證券分析之開山始祖一班傑明.葛拉漢的投資心法的做法,以Q4財報公佈日(統一設隔年3/31)開始持有一年。例如2004年完整財務數據,將於2005/03/31公佈,故當期投組持有期間為 2005/03/31 ~ 2006/03/31
投組報酬率: 投組完整持有一年的報酬率,並考慮交易成本
Step 1. 取得所有上市股票代碼
security = tejapi.get('TWN/ANPRCSTD',
paginate = True,
chinese_column_name = True)
stock_list = security[(security['上市別'] == 'TSE') & (security['證券種類名稱'] == '普通股')]['證券碼'].tolist()
Step 2. 撈取篩選所需資料,同時建立條件欄位,滿足時為 1,反之為 0
每次迴圈為一檔股票的處理,由於資料量龐大,運行的時間約 40分。處理的流程大致為將資料調整成相同頻率 (年化)、利用 np.where()
建立條件滿足欄位,最後在合併源自於不同資料庫的資料,並將結果儲存在 data
。另外在篩選、疊加、排序或刪除資料時,索引會因此被打亂,所以習慣加上 reset_index(drop=True)
。以下為 data
最終結果
data_cp = data.copy()
為了避免修改到原資料而需重新撈取,以備份檔進行操作。
#計算市場平均總市值
avg_mv = data_cp.groupby(by = '財報年月')['季底普通股市值'].mean()
#將計算出市場平均總市值,以財報年月配對到原資料,形成新的一欄
data_cp['市場平均總市值'] = data_cp['財報年月'].map(avg_mv)
#條件一: 公司總市值 < 市場平均總市值
data_cp['條件1'] = np.where(data_cp['季底普通股市值'] < data_cp['市場平均總市值'], 1, 0)
擁有所有公司市值資訊後,即可建立條件一。這邊使用 map()
將索引為財報年月的 avg_mv
與 data_cp
的財報年月欄配對,並將值投射到新欄位
#整理出之後需要的欄位
data_cp = data_cp[['公司代碼','財報年月','季底普通股市值','預估稅後淨利成長率','條件1','條件2','條件3','條件4','條件5','條件6','條件7','條件8','條件9','條件10']]
data_cp['分數'] = data_cp['條件1'] + data_cp['條件2'] + data_cp['條件3'] + data_cp['條件4'] + data_cp['條件5'] + data_cp['條件6'] + data_cp['條件7'] + data_cp['條件8'] + data_cp['條件9'] + data_cp['條件10']
#取大於9分的股票
data_cp = data_cp[data_cp['分數'] >= 9].sort_values(by = '財報年月').reset_index(drop=True)
Step 3. 撈取交易面資料篩選、年報酬資料計算每年投組報酬率
這邊以年份進行迴圈,並於迴圈內進行交易面條件篩選、投組報酬率的計算。其中撈取本益比的資料期間為建構投組的前一整年,例如當財報日期為 2020–12–01時,將於2021–03–31 (120日後)建構投組,因此考慮建構前一整年 (2020–03–31 ~ 2021–03–31)的本益比;而此投組會持有至約 2022–03–31,以成分股該日的年報酬率作為投組報酬的計算。但因尚未持滿一年,故計算投組報酬時會排除以 2020年財務數據為篩選依據的投組
Panel
Return
Step 4. 累計報酬視覺化 (詳見完整程式碼)
Step 5. 績效表格 (詳見完整程式碼)
Step 6. 以2020財報數據建構的投組之成份股 (詳見完整程式碼)
結論
由於本篇撈取的資料量較大,涵蓋了上市公司多年度的財務、籌碼與交易面數據,所以建議可先由少數公司、較短期間測試,或是自行調整量化指標的標準,若短期績效不錯,可再拉長時間區間進行回測檢驗。除了資料時間長度,資料的品質與多樣化程度更是不能忽略,因此推薦讀者於TEJ EShop選購各類型的資料庫,嘗試以量化方式實踐不同投資大師的投資哲學吧!
本文僅供參考之用,因以目前上市公司為主,故或有倖存者偏差疑慮、部分計算也較為簡略。因此本文不構成要約、招攬或邀請、誘使、任何不論種類或形式之申述或訂立任何建議及推薦,讀者務請運用個人獨立思考能力,自行作出投資決定,如因相關建議招致損失,概與作者無涉。
完整程式碼
延伸閱讀
相關連結