Table of Contents
RSI是判斷股市當中買賣雙方力道強弱的動量技術指標,綜合考量上漲下跌的幅度和天數,評估市場買賣超的情形,決定進出場的策略。RSI指標的計算流程如下:
RSI指標的判斷依據如下:
RSI的指標鈍化問題:由於 RSI是將漲、跌分開來處理,因此若市場在短期內皆為漲勢,則會使跌幅的參考數據過於稀少,導致 RSI指標判斷失真,反之亦然。鈍化的情形尤其容易發生在高低檔階段,而本文也嘗試以綜合 RSI區間及長短天期 RSI交叉的方式降低鈍化影響。
本文使用 MacOS 並以 Jupyter Notebook 作為編輯器
# 基本套件
import pandas as pd
import numpy as np
import copy
# 視覺化套件
import plotly.graph_objects as go
import plotly.express as px
# TEJ API
import tejapi
tejapi.ApiConfig.api_key = 'Your Key'
tejapi.ApiConfig.ignoretz = True
Step 1. 股價資料撈取
stock_data = tejapi.get('TWN/APRCD',
coid= '2324', # 仁寶
mdate={'gte': '2020-01-01', 'lte':'2021-12-14'},
opts={'columns': ['coid', 'mdate', 'open_d', 'close_d']},
chinese_column_name=True,
paginate=True)
本文以仁寶(2324)從2020年初至今(2021–12–14)的資料範圍作為示範,藉此了解筆記型電腦代工廠商在疫情下的股價波動,以及如何使用RSI,決定進出場時機。
Step 2. 計算14日RSI、7日RSI
# 計算隔日價差以及分類每日漲跌
stock_data['隔日差價'] = stock_data['收盤價(元)'].diff()
stock_data['上漲'] = stock_data['隔日差價'].clip(lower = 0)
stock_data['下跌'] = (-1) * stock_data['隔日差價'].clip( upper = 0)
# 14日RSI指標
stock_data['14日上漲均值'] = stock_data['上漲'].ewm(com = 14, adjust = False).mean()
stock_data['14日下跌均值'] = stock_data['下跌'].ewm(com = 14, adjust = False).mean()
stock_data['14日相對強弱值'] = stock_data['14日上漲均值'] / stock_data['14日下跌均值']
stock_data['14日相對強弱指標'] = stock_data['14日相對強弱值'].apply(lambda rs : rs/(1+rs)*100)
# 7日RSI指標
stock_data['7日上漲均值'] = stock_data['上漲'].ewm(com = 7, adjust = False).mean()
stock_data['7日下跌均值'] = stock_data['下跌'].ewm(com = 7, adjust = False).mean()
stock_data['7日相對強弱值'] = stock_data['7日上漲均值'] / stock_data['7日下跌均值']
stock_data['7日相對強弱指標'] = stock_data['7日相對強弱值'].apply(lambda rs : rs/(1+rs)*100)
Step 3. RSI指標走勢圖 & 買賣超區間(30,70)(詳見完整程式碼)
透過比較RSI長短天期走勢以及買賣超區間,找到黃金交叉以及死亡交叉。需注意的是高檔階段仍有較嚴重的鈍化問題,但仍要在第一次死亡交叉時就出場,畢竟在實際投資的時候,無法絕對精準得預測未來。
Step 4. 找出買賣訊號與視覺化買賣點(詳見完整程式碼)
賣超階段:RSI < 30,準備買入;此外,降低RSI在低檔的鈍化影響,增加一項需要7日RSI向上突破14日RSI的條件,作為價格將要反轉的黃金交叉依據。
買超階段:RSI > 70,準備賣出;此外,降低RSI在高檔的鈍化影響,增加一項需要7日RSI向下突破14日RSI的條件,作為價格將要反轉死亡交叉依據。
signal = []
trade = 0
# 交易訊號只發生在買賣超階段與黃金交叉或死亡交叉同時發生的情境下
for i in range(len(stock_data)):
if stock_data.loc[i, '14日相對強弱指標'] <= 30 and stock_data.loc[i-1, '14日相對強弱指標'] > stock_data.loc[i-1, '7日相對強弱指標'] and stock_data.loc[i, '14日相對強弱指標'] <= stock_data.loc[i, '7日相對強弱指標'] and trade == 0:
signal.append(1000)
trade = trade + 1
elif stock_data.loc[i, '14日相對強弱指標'] >= 70 and stock_data.loc[i-1, '14日相對強弱指標'] < stock_data.loc[i-1, '7日相對強弱指標'] and stock_data.loc[i, '14日相對強弱指標'] >= stock_data.loc[i, '7日相對強弱指標'] and trade == 1:
signal.append(-1000)
trade = trade - 1
else:
signal.append(0)
stock_data['買賣股數'] = signal
在MACD指標回測實戰裡,我們有詳細介紹考慮手續費、現金部位計算報酬率的方式,因為流程固定,本文以下方函數包裝。
def target_return(data, principal):
#計算成本
data['手續費'] = data['開盤價(元)']* abs(data['買賣股數'])*0.001425
data['手續費'] = np.where((data['手續費']>0)&(data['手續費'] <20), 20, data['手續費'])
data['證交稅'] = np.where(data['買賣股數']<0, data['開盤價(元)']* abs(data['買賣股數'])*0.003, 0)
data['摩擦成本'] = (data['手續費'] + data['證交稅']).apply(np.floor)
#計算資產價值
data['股票價值'] = data['買賣股數'].cumsum() * data['收盤價(元)']
data['現金價值'] = principal - data['摩擦成本'] + (data['開盤價(元)']* -data['買賣股數']).cumsum()
data['資產價值'] = data['股票價值'] + data['現金價值']
#計算報酬率
data['當日價值變動(%)'] = (data['資產價值']/data['資產價值'].shift(1) - 1)*100
data['累計報酬(%)'] = (data['資產價值']/principal - 1)*100
return data
本文單純考量一般股票買賣,並無考慮融券融資情形,所以沒有計算保證金的流程,只要將買賣股數的資料整理好,並決定期初的現金部位,即可算出交易成本以及報酬率。本文選擇投入20000元。
RSI_return = target_return(data = stock_data, principal = 20000)
加入買入持有策略以及大盤績效,作為此次RSI交易策略的比較基準。
・買入持有策略
bh_data = copy.deepcopy(stock_data)
bh_data['買賣股數'] = 0
bh_data.loc[0, '買賣股數'] = 1000
bh_data.loc[len(bh_data)-1, '買賣股數'] = -1000
# 去除RSI指標策略才會用到的參數
bh_data = bh_data.drop(['隔日差價', '上漲', '下跌', '14日上漲均值', '14日下跌均值', '14日相對強弱值', '14日相對強弱指標','7日上漲均值', '7日下跌均值', '7日相對強弱值', '7日相對強弱指標'], axis = 1)
bh_return = target_return(data=bh_data, principal = 20000)
・大盤績效
market = tejapi.get('TWN/APRCD',
coid = 'Y9997',
mdate = {'gte':'2020-01-01', 'lte':'2021-12-14'},
opts = {'columns':['coid','mdate', 'close_d','roi']},
chinese_column_name = True)
market['累計報酬(%)'] = (market['報酬率%'].apply(lambda x:0.01*x +1).cumprod() - 1)*100
以市場指數報酬(Y9997)代表市場的表現,並計算出累計報酬率。
Step 1. 累計報酬比較(詳見完整程式碼)
從累計報酬率知道RSI策略交易在疫情爆發後的低檔階段進場,並且在市場賣超電子股前的高檔階段出場(因大宗商品上漲而市場轉投入傳產股),此外,也剛好避開台灣疫情徹底失守對股市的影響,可是在這之間還是有一些相對高低檔的波段,因為交易訊號的觸發標準較嚴格,而沒有抓準。
Step 2. 累計報酬比較(詳見完整程式碼)
透過績效比較可以發現運用RSI的交易策略,在報酬率或波動度上的表現都優於買入持有,代表RSI是有機會找到適當的進出場時機,提高投資效益;此外,跟大盤績效的比較,RSI策略沒有突出的報酬率,但是在波動度上則更加穩定,這是因為避開2020年初的全球股災以及2021年台灣本土疫情失守的空頭階段,讓RSI策略的夏普值優於大盤績效。
藉由上述內容,讀者應該可以發現RSI在高低檔的鈍化情形相當嚴重,所以本文加入長短天期交叉的條件,使RSI策略更有穩健性,當然也相對犧牲更多的交易機會,這是個別投資人需要自己去衡量的結果,畢竟技術指標的運用因人而異,所以歡迎對各種交易回測有興趣的讀者,選購TEJ E-Shop的相關方案,用高品質的資料庫,建構出適合自己的交易策略。
電子報訂閱