產業資料庫重要嗎?如果你想讓選股技巧更上一層樓,勢必會進階到產業分析。
投資標的的優劣評價,除了自己跟自己比,例如近期財報是否較過去改善,另一個判斷企業競爭力的評價方式,就是跟同業比,好壞都是比較而來的,選對比較基準才讓評價有意義。
除了同業個股比較,產業資料庫的另一個主要應用在找出族群趨勢,如果一個產業的企業的營收或股價趨勢都向上,那代表該產業蒸蒸日上,有產業景氣良好的基本面護體,更能增加投資判斷把握度與可解釋性,排除單一個股炒作的個別性,更進階的應用甚至可延伸到概念股落後補漲效應。
這一切的應用的基礎都建構在「產業資料庫」的分類,這篇教學文章將說明FinLab的「產業題材資料庫」的簡單應用,並教你如何用 Python 與 Pandas 基礎語法去「客製化」自己的產業分類,讓產業資料庫更豐富。
產業資料
FinLab 的細產業主題資料來源主要取自「產業價值鍊資訊平台」,少部分為自定義分類。從 FinLab資料庫 只要一行程式碼就能下載全部的細產業資訊,讓你輕鬆以此基礎做後續應用。要注意的是此份資料僅限 VIP 使用。
產業價值鍊資訊平台 會將主產業再分拆上下游的細產業,讓你更精細的去比較,否則證交所一般分類光半導體就近百檔,比較效果相對籠統。
每家公司所屬產業的資訊放在 catergory 內,category 欄位的型態是文字格式,所有產業分類會放入 List 後再包成文字型態,從該資料得知公司分別有哪些產業的標籤。
例如1101台泥的產業序列裡有主產業的水泥,也有細產業「水泥:水泥成品」、「水泥:水泥熟料」(格式為「主產業:細產業 or 主產業」)。
簡單查詢應用
如果我們想查詢哪些公司屬於水泥產業?我們可以運用pandas內的 Series.str.contains,讓我們快速分類出產業名單,如下範例,只要「category」欄位內含「水泥」兩字,就會被納入範圍。
from finlab import data
from finlab.backtest import sim
# 取出產業題材
themes = data.get('security_industry_themes')
# 選出產業包含「水泥」的公司
ind1 = themes[themes['category'].str.contains('水泥')]
contains 語法支援 or 的運用,如果我們今天想選出產業包含「水泥」或「建材營造」的公司,可以使用以下語句,使用’|’的符號做邏輯運算串連:
ind2 = themes[themes['category'].str.contains('水泥|建材營造')]
簡單回測範例
「想挑出水泥產業中,本益比低於水泥產業本益比中位數之個股當投資組合」
實作很簡單,用前述contains篩選的stock_id,套入本益比資料做欄位圈選,就能限定資料範圍,再運用 median(axis=1)
,計算每日產業本益比中位數,axis=1的用途在取每一期(橫列)的中位數。
from finlab import data
from finlab.backtest import sim
# 取出產業題材
themes = data.get('security_industry_themes')
# 選出產業包含「水泥」公司
ind = themes[themes['category'].str.contains('水泥')]
pe = data.get('price_earning_ratio:本益比')
ind_pe = pe[list(ind['stock_id'])]
# 計算每日產業本益比中位數,axis=1的用途在取每一期(橫列)的中位數
ind_pe_med = ind_pe.median(axis=1)
# 選出本益比小於同業本益比中位數且本益比小於25的公司
position = (ind_pe < ind_pe_med) & (ind_pe < 25)
# 回測
report = sim(position, upload=False)
report.display()
自定義產業分類
有時我們發現產業價值鏈資訊平台的分類仍不能滿足需求,像是他缺少概念股的標籤資料,學會Python 的好處在我們可以任意擴展資料,去自定義新增的分類。
使用開發好的 create_new_industry_themes 的函式去創建新的產業分類,其中 additional_themes 變數控制新增標籤,格式為[([目標群],[標籤群]),...]
。
例如以下範例對’6684′, ‘6756’, ‘3014’ 新增 ‘元宇宙:祖克柏概念股’ 的標籤,對’1342′, ‘1584’新增’航太週邊:空中巴士概念股’的標籤,對’2342′, ‘3317’, ‘4923’, ‘5299’, ‘6287’ 增加兩個標籤’半導體:基礎元件’, ‘通訊產業:通訊元件’。
def add_sub_group(dataframe, stock_list: list, theme_list: list):
try:
dataframe.loc[stock_list]['category'] = dataframe.loc[stock_list]['category'].apply(
lambda s: s.extend(theme_list))
except KeyError:
print('stock_list not in index.')
return dataframe
def process_sub_group_list(sub_group_list):
sub_group_list.extend(list(set({i[:i.index(':')] for i in sub_group_list if ':' in i})))
return sorted(list(set(sub_group_list)))
def create_new_industry_themes(additional_themes):
df = data.get('security_industry_themes')
df = df.set_index(['stock_id', 'name'])
df['category'] = df['category'].apply(lambda s: eval(s))
if additional_themes:
for stock_list, theme_list in additional_themes:
df = add_sub_group(df, stock_list, theme_list)
df['category'] = df['category'].apply(lambda s: process_sub_group_list(s))
df = df.astype(str)
df = df.reset_index()
return df
additional_themes = [
(['6684', '6756', '3014'], ['元宇宙:祖克柏概念股']),
(['1342', '1584'], ['航太週邊:空中巴士概念股']),
(['2342', '3317', '4923', '5299', '6287'], ['半導體:基礎元件', '通訊產業:通訊元件']),
]
new_themes = create_new_industry_themes(additional_themes)
# 檢查6684 是否成功新增標籤
new_themes[new_themes['stock_id']=='6684']['category'].values
執行完含式後,會發現 new_themes 已有新增資料~之後就可以用自定義後的 new_themes 做產業分析囉!
小結
colab程式範例
學會基礎的產業資料的資料處理技巧後,就可以進行許多分析與策略開發,像是「產業面選股策略|同業本益比比較法」就是延伸的應用喔!
如果有自己的產業分類標籤可以加入,那就會進化成個人獨有的資料,可能創造出不易被模仿的策略或產業觀察指標。