此文章為VIP限定
美股該如何選股?如果你有實際開發過美股策略,會發現一件很奇怪的事,那就是台股有用的策略,在美股幾乎都失效。除了高效率市場的因素,我想還有一個關鍵假設,那就是選股池的影響性。
我們知道每個產業適用的指標不同,像本益比指標可能就不適合在獲利起伏很大的行業,例如原物料、營造,而在獲利穩定比較高的產業較具指標意義。
如果沒縮小選股池,針對特定產業找出指標,那就像在大海撈針,會對基本面選股有很大的影響美國是全球最大的資本市場,上市交易的標地很多,達上萬檔,細產業也分散到上百個,不像台股集中在製造業與電子業,就算台股沒分類,也很容易找到通用全市場的指標,但美股直接全市場選股,很容易因產業一致性的缺乏,導致許多雜訊出來,例如挑本益比低於10倍的股票,在A產業偏低,但在B產業是偏高,不可混為一談。
為解決選股池的問題,FinLab Package 在 0.4.5 的版本開發了美股選股池控制的功能,利用短短的程式碼,就能對美股做不同層級的分類,接下來會向大家介紹如何使用此功能,並找出本益成長比最適合用在哪些產業?
美股選股池分類
此功能的用途在當呼叫 data.get
或是 data.indicator
時,返回美股產業相關類股。
和台股不同的地方在美股因標的範圍較大,有4個篩選變數可以控制,預設都是全選。
細節請見美股選股池控制的功能。
參數說明
- market:證券種類,採取模糊比對。
若設定為 Common Stock ,則會篩選出美國國內上市企業與 ADR (海外存託憑證:外國公司在美國二次上市) 的普通股,不會選到一些流動性比較低的特別股。
若想排除 ADR,則可以設定為 Domestic Common Stock,就只會選到美國國內上市企業。 - sector:產業主板塊,可視為比較粗略的產業分類。像是美股有許多高科技公司很吸引人,若想選定標的在科技股,將此參數設定為 Technology 。
- industry:細產業,可視為比較細的產業分類,由於細產業很多,不方便一一列在文件上,我們可在美股企業基本資訊的資裡中找到資料,利用以下程式碼取得細產業索引:
set(data.get('us_tickers')['industry'])
。像是美股科技股中的軟體公司很吸引人,若想選定標的在軟體股,將此參數設定為 Software – Application 。 - exchange:交易所。不同的交易所有不同的主流標地及規範。偏愛科技股或新創的,可選NASDAQ。
紐約證券交易所(New York Stock Exchange,簡稱NYSE)和納斯達克交易所(NASDAQ)是美國主要的證券交易所,它們在以下幾個方面存在差異:
1.交易模式:紐約交易所採用傳統的“交易員制”模式,即交易員在交易所的交易廳內進行股票交易。而納斯達克交易所採用電子交易系統,投資者通過計算機網絡進行交易。
2.有吸引力的上市公司類型:紐約交易所主要是大型傳統企業,如跨國公司和傳統產業公司。納斯達克交易所則更有吸引力的科技、生物技術和高成長性公司。
3.上市要求:紐約證券交易所對上市公司的要求較為嚴格,包括市值、財務狀況、歷史業績等方面的要求。納斯達克交易較多成長型公司,其上市要求相對較低。
4.交易時間:紐約交易所的交易時間為周一至週五上午9:30至下午4:00(美國東部時間)。納斯達克交易所的交易時間也是周一至週五上午9:30至下午4:00 :00,但還提供了一些延長交易時間的選項。
5.許多市場地位:紐約交易所是世界上最大、最多的股票交易所之一,吸引了許多大型企業和國際投資者。納斯達克交易所在科技股領域具有越來越大的影響力,吸引了新興市場科技公司和高科技投資者。
使用範例
以下為幾個常用範例,幫助我們將資料限縮在特定範圍,限縮之後,就能針對本質較相近的股票做後續研究。
限定在美股普通股中的科技類股
with us_universe('Common Stock', ['Technology']):
close_subset = data.get('us_price:close')
print(close_subset)
date | AAOI | AAPL | .. | ABCO | NVDA |
---|---|---|---|---|---|
2017-01-03 | 39.65 | 38.3 | .. | 7.8 | 17.55 |
2017-01-04 | 39.85 | 38.85 | .. | 8.34 | 17.5 |
2017-01-05 | 39.25 | 38.1 | .. | 8.25 | 17.3 |
2017-01-06 | 39 | 37.85 | .. | 8.2 | 17.3 |
2017-01-09 | 38.2 | 37.2 | .. | 7.88 | 16.6 |
限定在美股特別股中的基礎原物料和能源類股
with data.us_universe('Preferred Stock', ['Basic Materials','Energy']):
close_subset = data.get('us_price:close')
print(close_subset)
date | AEUA | ALIN-PA | .. | ALIN-PB | ALIN-PE |
---|---|---|---|---|---|
2017-01-03 | 39.65 | 38.3 | .. | 7.8 | 17.55 |
2017-01-04 | 39.85 | 38.85 | .. | 8.34 | 17.5 |
2017-01-05 | 39.25 | 38.1 | .. | 8.25 | 17.3 |
2017-01-06 | 39 | 37.85 | .. | 8.2 | 17.3 |
2017-01-09 | 38.2 | 37.2 | .. | 7.88 | 16.6 |
限定在美股 NASDAQ 交易所普通股中的軟體類股
with data.us_universe('Common Stock', industry='Software', exchange='NASDAQ'):
close_subset = data.get('us_price:close')
print(close_subset)
date | ACIW | ACVA | .. | ZI | ZS |
---|---|---|---|---|---|
2017-01-03 | 39.65 | 38.3 | .. | 7.8 | 17.55 |
2017-01-04 | 39.85 | 38.85 | .. | 8.34 | 17.5 |
2017-01-05 | 39.25 | 38.1 | .. | 8.25 | 17.3 |
2017-01-06 | 39 | 37.85 | .. | 8.2 | 17.3 |
2017-01-09 | 38.2 | 37.2 | .. | 7.88 | 16.6 |
檢視有哪些細產業可選擇
print(set(data.get('us_tickers')['industry']))
{'Advertising Agencies',
'Aerospace & Defense',
'Agricultural Inputs',
'Airlines',
'Airports & Air Services',
'Aluminum',
...}
本益成長比最適合用在哪些產業?
全市場回測
我們來寫一個簡單的本益成長比(PEG)當範例,條件說明如下
- 本益比 > 0:公司近一年獲利要是正數
- 營業利益成長率 > 20:公司的獲利能力具一定水準,不是低利潤產業
- 營業利益成長率 > 營收成長率:本業獲利成長大於營收成長,代表公司的銷貨是重質不重量。
- 篩選出來後,用本益成長比做排序選出本益成長比最低的前10名,若您不了解本益成長比的定義,可參考這篇文章「進化後的本益比|本益成長比選股策略」。
- 每週再平衡。
- 停損為10%。
程式碼
from finlab import data
from finlab.backtest import sim
本益比 = data.get('us_daily_metrics_all:pe')
營收= data.get('us_fundamental_all:revenue')
營業利益 = data.get('us_fundamental_all:opinc')
def 成長率(s):
return ((s-s.shift(4)) / s.shift(4).abs()) * 100
營收成長率 = 成長率(營收)
營業利益成長率 = 成長率(營業利益)
peg = (本益比/營業利益成長率)
cond1 = 本益比 > 0
cond2 = 營業利益成長率 > 20
cond3 = 營業利益成長率 > 營收成長率
cond_all = cond1 & cond2 & cond3
position = peg*cond_all
position = position[position > 0].is_smallest(10)
report = sim(resample='W', position=position, fee_ratio=0, tax_ratio=0, stop_loss=0.1, name='美股本益成長比')
report.display()
回測結果
以這麼簡單的條件而言,發現效果相當不錯,接下來我們用選股池分類器來針對不同的板塊做回測。
板塊分組回測
將不同的板塊名稱輸入進選股池分類器,執行迴圈。並使用「回測組合比較報告」的功能來比較不同板塊的回測結果。
程式碼
from finlab import data
from finlab.backtest import sim
from finlab.optimize.combinations import ReportCollection
dataset = {}
for ind in ['Basic Materials','Communication Services','Consumer Cyclical','Consumer Defensive','Energy','Financial Services','Healthcare','Industrials','Real Estate','Technology','Utilities']:
with data.us_universe(sector=ind):
本益比 = data.get('us_daily_metrics:pe')
營收= data.get('us_fundamental:revenue')
營業利益 = data.get('us_fundamental:opinc')
def 成長率(s):
return ((s-s.shift(4)) / s.shift(4).abs()) * 100
營收成長率 = 成長率(營收)
營業利益成長率 = 成長率(營業利益)
peg = (本益比/營業利益成長率)
cond1 = 本益比 > 0
cond2 = 營業利益成長率 > 20
cond3 = 營業利益成長率 > 營收成長率
cond_all = cond1 & cond2 & cond3
position = peg*cond_all
position = position[position > 0].is_smallest(10)
report = sim(resample='W', position=position, fee_ratio=0, tax_ratio=0, stop_loss=0.1, name='美股本益成長比', upload=False)
dataset[ind] = report
indicators=['daily_mean','daily_sharpe','max_drawdown']
report_collection = ReportCollection(dataset)
# 策略分組指標報告
report_collection.plot_creturns().show()
report_collection.plot_stats('bar',indicators=indicators).show()
report_collection.plot_stats('heatmap',indicators=indicators)
回測結果
可以發現「科技股」的報酬率一支獨秀,報酬率的前3名板塊與後3名的差距非常大。
綜合評分以「報酬率、夏普率、最大回撤幅度」分級平均計算,前3名依序是「Consumer Cyclical、Financial Services、Technology」。
最終策略
將策略範圍的選股池限定在「Consumer Cyclical、Financial Services、Technology」這三個使用本益成長比策略表現較好的板塊,為什麼不要只限定在第一名的產業就好?原因在適當產業多元化,能避免過度集中在特定產業循環的風險,在產業逆風年,個股很難有表現,但如果有做產業分散,就比較有機會抵抗單一產業的逆風時刻。
程式碼
每個產業選10檔股票,再將這3個產業的選股結果合併。
from finlab import data
from finlab.backtest import sim
import pandas as pd
def sector_postion(sector):
with data.us_universe(sector=sector):
本益比 = data.get('us_daily_metrics:pe')
營收= data.get('us_fundamental:revenue')
營業利益 = data.get('us_fundamental:opinc')
def 成長率(s):
return ((s-s.shift(4)) / s.shift(4).abs()) * 100
營收成長率 = 成長率(營收)
營業利益成長率 = 成長率(營業利益)
peg = (本益比/營業利益成長率)
cond1 = 本益比 > 0
cond2 = 營業利益成長率 > 20
cond3 = 營業利益成長率 > 營收成長率
cond_all = cond1 & cond2 & cond3
position = peg*cond_all
position = position[position > 0].is_smallest(10)
return position
positions = pd.concat([sector_postion(sector) for sector in ['Consumer Cyclical','Financial Services','Technology']],axis=1)
report = sim(position=positions, resample='W', fee_ratio=0, tax_ratio=0, stop_loss=0.1, name='美股本益成長比', live_performance_start='2021-06-01')
回測結果
撋報酬率降低一些,但夏普率和最大回撤幅度與原先的結果相比則有明顯提升。
還在為優化策略所苦嗎?你絕對不能錯過 美股選股池控制 這個好用功能,趕緊來試試吧!