教學
技術指標
本頁內容7
data.indicator() 支援 TA-Lib 與 pandas_ta 上百種技術指標,一行就算出數千檔股票、長年期的結果,可用於個股分析與機器學習。結果和 data.get() 一樣是「日期 × 股票」的表,可以直接拿來寫選股條件。
安裝 TA-Lib
!pip install ta-lib參考 官方安裝教學,支援 Windows、MacOS、Linux。
更多參數與函式請參考 TA-Lib 官方文件。
計算所有股票的 RSI
把指標名稱和參數交給 data.indicator(),例如 RSI(timeperiod=14):
from finlab import data
data.indicator('RSI', timeperiod=14)
from finlab import data
data.set_market('us')
rsi = data.indicator('RSI', timeperiod=14)
rsi[['AAPL', 'MSFT', 'NVDA']].tail()- 會計算目前市場的所有股票,每一列是日期、每一欄是股票代號。
- 前 14 天因資料不足可能為
NaN。 - 預設用未還原股價計算;
adjust_price=True改用還原股價,resample='W'改用週 K。
計算兩條線的指標:KD
data.indicator('STOCH') 計算 KD 值,會回傳兩個 DataFrame(K、D):
from finlab import data
k, d = data.indicator('STOCH')
k
from finlab import data
data.set_market('us')
k, d = data.indicator('STOCH')
k挑出 K 值大於 D 值的股票
(k > d).iloc[-1] 取最近一日的結果,是一個以股票代號為索引的布林 Series:
(k > d).iloc[-1]0015 False
0050 True
0051 False
0052 True
0053 True
...
9951 True
9955 False
9958 False
9960 True
9962 True
Name: 2021-07-13 00:00:00, Length: 2269, dtype: bool只要 K 大於 D 的股票代號:
signal = (k > d).iloc[-1]
signal[signal].index # 最近一日 K 大於 D 的股票代號用 pandas_ta 算更多指標
pandas_ta 也能計算多種技術指標,安裝方式與指標列表請見官方文件:
pip install pandas-ta一樣透過 data.indicator() 使用,例如 supertrend:
from finlab import data
values = data.indicator('supertrend')若 TA-Lib 沒有對應的函式,會改用 pandas_ta 計算(可能較慢)。
用 Pandas 自製指標
不依賴 TA-Lib,直接用 Pandas 運算建立自訂指標。
動能、乖離率與營收成長
from finlab import data
close = data.get('price:收盤價')
volume = data.get('price:成交股數')
rev = data.get('monthly_revenue:當月營收')
# 動能指標:N 日報酬率
momentum_20 = close / close.shift(20) - 1
# 均線乖離率
ma60 = close.average(60)
bias = (close - ma60) / ma60
# 量價背離:股價創高但成交量萎縮
price_high = close == close.rolling(60).max()
volume_low = volume < volume.average(20)
divergence = price_high & volume_low
# 月營收成長率
rev_yoy = rev / rev.shift(12) - 1 # 年增率
rev_mom = rev / rev.shift(1) - 1 # 月增率
rev_3m = rev.average(3) / rev.average(12) - 1 # 3 月均值 vs 12 月均值from finlab import data
data.set_market('us')
close = data.get('price:adj_close')
volume = data.get('price:volume')
revenue = data.get('us_income_statement:revenue') # 季資料
# 動能指標:N 日報酬率
momentum_20 = close / close.shift(20) - 1
# 均線乖離率
ma60 = close.average(60)
bias = (close - ma60) / ma60
# 量價背離:股價創高但成交量萎縮
price_high = close == close.rolling(60).max()
volume_low = volume < volume.average(20)
divergence = price_high & volume_low
# 季營收成長率
rev_yoy = revenue / revenue.shift(4) - 1 # 年增率
rev_qoq = revenue / revenue.shift(1) - 1 # 季增率
rev_trend = (
revenue.rolling(2).mean() / revenue.rolling(4).mean() - 1
) # 近 2 季均值 vs 近 4 季均值合成多因子分數(.cs)
.cs 在每個日期跨所有股票計算。先把每個因子標準化,再等權加總:
pe = data.get('price_earning_ratio:本益比')
roe = data.get('fundamental_features:ROE稅後')
# 多因子合成:先標準化再等權加總
score = roe.cs.zscore() + (-pe).cs.zscore() # ROE 越高越好,PE 越低越好
# 選出綜合評分前 10%
position = score.cs.rank() > 0.9eps = data.get('us_income_statement:eps_diluted')
net_income = data.get('us_income_statement:net_income')
equity = data.get('us_balance_sheet:total_stockholders_equity')
raw_close = data.get('price:close') # 估值用未還原股價
pe = raw_close / eps.rolling(4).sum() # 近四季本益比
roe = net_income / equity[equity > 0] # 季 ROE,只算股東權益為正的公司
# 多因子合成:先標準化再等權加總
score = roe.cs.zscore() + (-pe).cs.zscore() # ROE 越高越好,PE 越低越好
# 選出綜合評分前 10%
position = score.cs.rank() > 0.9產業中性化(.sector)
直接用 ROE 選股,會偏重 ROE 本來就高的產業。改在產業內標準化,選出「在各自產業中表現突出」的股票:
# 問題:直接用 ROE 選股會偏重高 ROE 產業(如半導體)
# 解法:產業內標準化,選出「在各自產業中表現突出」的股票
roe_neutral = roe.sector.zscore() # 產業中性化
rev_neutral = rev_yoy.sector.zscore() # 營收成長也做中性化
# 合成因子
score = roe_neutral + rev_neutral
position = score.cs.rank() > 0.8
# 也可以直接用產業內排名
position = roe.sector.rank() > 0.7 # 各產業 ROE 前 30%美股要傳入「股票代號 → 產業」的對照;不傳時,.sector 用的是台股產業分類。
# 問題:直接用 ROE 選股會偏重高 ROE 產業(如科技業)
# 解法:產業內標準化,選出「在各自產業中表現突出」的股票
profile = data.get('us_company_profile')
sectors = dict(zip(profile['symbol'], profile['sector']))
roe_neutral = roe.sector(sectors).zscore() # 產業中性化
rev_neutral = rev_yoy.sector(sectors).zscore() # 營收成長也做中性化
# 合成因子
score = roe_neutral + rev_neutral
position = score.cs.rank() > 0.8
# 也可以直接用產業內排名
position = roe.sector(sectors).rank() > 0.7 # 各產業 ROE 前 30%設定權重並回測(.weight)
選好股票後,用 .weight 決定每檔的權重,再交給 sim() 回測:
from finlab.backtest import sim
position = score.cs.rank() > 0.8
# 精細權重:反波動率 + 產業上限 + 換手率限制
weights = (
position.weight.inverse_volatility(window=60)
.weight.cap_industry(max_weight=0.3)
.rebalance('QE') # 只留換股日,換手率才是每次換股之間的
.weight.limit_turnover(max_turnover=0.3)
)
report = sim(weights, resample='Q')不傳 price 時,inverse_volatility() 讀的是台股股價,所以美股要傳 price=close。weight.cap_industry() 是依台股產業設上限,只適用台股。
from finlab.backtest import sim
position = score.cs.rank() > 0.8
# 精細權重:反波動率 + 換手率限制
weights = (
position.weight.inverse_volatility(window=60, price=close)
.rebalance('QE') # 只留換股日,換手率才是每次換股之間的
.weight.limit_turnover(max_turnover=0.3)
)
report = sim(weights, resample='Q').cs、.sector、.weight 的所有方法詳見 finlab.dataframe 參考文件。
下一步
- 技術指標選股 用技術指標寫出一個完整的選股策略。
- 寫選股條件 排名取前幾名、多個條件取交集、設定進出場。
- 歷史回測 換股頻率、停損停利、手續費與交易紀錄。
- finlab.dataframe .cs、.sector、.weight 與其他 FinlabDataFrame 方法。
這一頁有幫到你嗎?