上一集我們介紹了Sharpe ratio,可以用來衡量風險跟報酬的指標(也就是報酬 / 風險),這集我們就利用Sharpe ratio來進行台股的模擬買賣,假裝我們這20年來,都使用sharpe ratio的策略,可以得到多少獲利呢?

為何Sharpe ratio幾乎都小於一
上次有人問我,夏普指標小於一,代表風險(分母)大於獲利(分子),而為什麼市面上所有的指數,其sharpe ratio都小於一,難道股票都不能賺錢嗎?
這只是代表,在股市中,我們為了要獲利,往往需要承受很大的風險!但不代表長期投資下來是不能獲利的。我們必須要找到sharpe ratio比較高的策略,才能使風險降低,獲利升高。
利用Python研發一個策略
首先,我們得準備台股的歷史紀錄,還有台股的夏普指標,假如之前沒有跟上,可以到上一個單元複習一下喔!:
close['TSEC weighted index'].plot()
sharpe['TSEC weighted index'].plot(secondary_y=True)

可以發現,當sharpe ratio比較低時,台股也都是在比較低點,
可以發現,當sharpe ratio比較高時,台股也都是在比較高點,
當sharpe ratio 轉折時,通常也是台股會轉折的時候
利用這個觀察,我們就可以來編寫一個策略:
- 當sharpe ratio往上轉折時,則買入
- 當sharpe ratio往下轉折時,則賣出
利用Python快速編寫
為了找出轉折點,我們必須做一點資料處理:
- 時間序列的平滑
- 時間序列的斜率
- 找出斜率由正到負,或由負到正的訊號
為了使用python寫出上述的策略,我們要先將夏普值平滑一下,不然雜訊太多了:
sr = sharpe['TSEC weighted index'].dropna()
d = 60
srsma = sr.rolling(d).mean()
sr.plot()
srsma.plot()

來色的線是我們就將sharpe ratio做移動窗格的平均,可以發現平均之後,時間序列比較平滑,這樣子我們找轉折點比較方便,所謂的轉折點,就是斜率由正到負,或由負到正的瞬間,所以我們要先找出夏普曲線的斜率。
夏普曲線的斜率
斜率非常簡單,可以使用diff
這個功能:
srsma = sr.rolling(d).mean()
srsmadiff = srsma.diff()
srsma.plot()
srsmadiff.plot(secondary_y=True)

可以發現上圖中,橘色的為sharpe ratio,藍色的為斜率,當橘色線由上而下轉折時,藍色的線會快速向下穿越0,有了這個特性,我們就可以來找轉折點了!
找轉折點
接下來我們可以來找轉折點了,就是斜率由正到負,或由負到正的瞬間。
buy = (srsmadiff > 0) & (srsmadiff.shift() < 0)
sell = (srsmadiff < 0) & (srsmadiff.shift() > 0)
(buy * 1).plot()
(sell * -1).plot()

找出持有的時段
那我們就可以來看一下,假如天都用一樣的方式來產生這些訊號,當 buy
訊號為True
時,買入,而當sell=True
時空手,如此執行20年的持有加權指數的時段:
import numpy as np
hold = pd.Series(np.nan, index=buy.index)
hold[buy] = 1
hold[sell] = -1
hold.ffill(inplace=True)
hold.plot()

交易頻率似乎有點高,不過沒關係,我們之後還會再做調整
接來是回測
回測
今天我們先簡單算一算,不考慮手續費,但是真實情況是必須考慮的喔!請謹記在心
twii = adjclose['TSEC weighted index'][buy.index]
pct_change = twii.pct_change()
pct_ratio = (pct_change.shift(-1)+1) # 今天到明天的價格變化
pct_ratio.fillna(1)[hold == 1].cumprod().plot()
這段程式碼,有點複雜,當中的pct_change
是一個每天獲利上下 x%。
而pct_ratio
代表買入之後每天的變化(不漲不跌是1,大於1則漲,小於1則跌)
我們希望將「持有」時間段的pct_ratio
全部都乘起來,代表獲利。

可以發現,這個策略效果並不是很好,不過別擔心
下個單元,我們使用參數最佳化,從5000種組合中,找出最好的策略!