跳至主要內容
FinLab

VIX 美股大跌投資法:用 Python 實作回測恐慌指數抄底策略

美股最近跌的慘慘慘,又到了聖誕假期,剛好又休市。我們當然趁現在來研究美股大跌時,要如何來投資,才是最佳的選擇呀!今天要介紹 VIX,以及查看 VIX 如何幫助我們做美股長期投資。

VIX 美股大跌投資法 Python 實作教學封面

線上程式碼直接跑免安裝

什麼是VIX

首先,究竟是什麼是 VIX 呢?VIX 是一個預估 12 個月的波動程度,假如市場上的不確定因素越高,代表將來的股價會有非常高的不確定性,則 VIX 越高,假如市場普遍穩定,則 VIX 就會比較低。通常 VIX 大概會在 15 附近,當大家極度恐慌時(例如恐怖攻擊、金融海嘯等),VIX 會急速跳動到 30~50,然後再緩和下來。

嚴謹的數學公式以連結的方式讓大家參考

於是有人就說可以參考 VIX 非常高的時候,當作是買點進行買入。 今天我們就用 python 來試試看是否有用?

獲取歷史資料

取得歷史資料的方式非常簡單,可以到「芝加哥期交所」官網來下載 S&P500歷史資料,還有VIX歷史資料,將下載下來的 csv 檔放在資料夾中,就可以開始今天的實驗了!

目錄

今天的教學主要分成以下幾個步驟

  1. 利用 pandas 匯入 csv 檔資料
  2. 計算 S&P500 的年報酬率,並繪圖
  3. 回測並檢討
  4. 稍微修改買入條件,並比較效果如何

假如第一次接觸 python 的朋友,可以參考python安裝教學,安裝好之後就可以一起來玩囉!

接下來我們就來玩玩這些資料吧

1. 利用pandas匯入歷史資料

首先,我們可以使用 pd.read_csv() 這個函示來匯入歷史資料如下:

顯示程式碼
%matplotlib inline
import pandas as pd
 
vix = pd.read_csv("vixcurrent.csv", header=1, index_col='Date', parse_dates=['Date'])
vixc = vix['VIX Close']

VIX 歷史資料走勢圖

其中,header=1 是指從第一行是 column 的名稱。index_col 是將指定的 column 轉換成 index,最後,parse_dates 是將指定的 column 轉換成 datetime 的格式。

再來,也是用類似的方法將 SPX 的指數給拿出來:

顯示程式碼
b = pd.read_excel("dailypricehistory.xls", header=4)['SPXSM']
b.index = pd.to_datetime(b.index, errors="coerce")
b = b.reindex(vixc.index)
b = b.dropna()
b.plot()

SP500 大盤指數歷史走勢圖

不過我們使用了一些額外的 code,來稍微處理一下大盤指數,其中 b.dropna() 是將冗餘的資料去掉,另外,使用 b.reindex() 是因為,我們希望 vixc 跟 b 的長度是一樣的,每一天的 index 是對齊的。

大盤歷史績效分析

接下來我們希望可以分析美股 SP500 的年報酬指數,我們可以這樣寫:

顯示程式碼
(b.dropna()[-1]/b[0]) ** (250/len(b))

其實公式就是:

年化報酬率計算公式

但由於我們要算年報酬,還要進一步修改,ndays 就是所有的歷史報酬天數,其中的 250 是一年的交易日估算。

從下圖可以看出,大盤的平均年報酬率大概是 6% 左右。

大盤平均年報酬率計算結果

VIX大於40,買入一年大盤能賺錢嗎?

接下來,我們來看當 VIX 大於 40 的當天,買入大盤並持有 250 天,會發生什麼事情呢:

顯示程式碼
# vix 大於 th 時,進行買入
th = 40
# 持有 days 天
days = 250
 
# 當天是否買入
buy = (vixc > th)
 
# 確保最近三十天並沒有buy發生,才是需要買入的訊號
buy &= (buy.shift().rolling(30).mean() == 0)
 

最後一行值得一提,因為其實 VIX 大於 40 後,有時候會常常飆高,但其實我們是希望 VIX 突然飆高的第一天,而不是變低後 39,然後又飆高到 40 以上,這種訊號不是我們需要的,所以利用上方的最後一行代碼進行過濾。

繪圖

將買點給畫出來:

顯示程式碼
b.plot()
buy.astype(float).plot(secondary_y=True)

VIX 大於 40 的買入訊號標示於大盤走勢圖

報酬率計算

接下來我們就來計算,當我們使用這個邏輯進行買賣時,效果如何:

顯示程式碼
# 當天收盤價
price_begin = b[buy]
 
# 隔250天後 的收盤價
price_end = b.shift(-days)[buy]
 
# 報酬率計算
ret = (price_end/price_begin)

VIX 大於 40 買入持有 250 天的報酬率結果

我們可以發現報酬率滿不錯的,唯一一次沒有賺錢,是在 2008 年金融海嘯那次,我們可以將報酬率畫出來,方便大家理解

持有250天的報酬率

接下來我們可以將這四次持有 250 天的大盤報酬曲線畫出來,橫軸為時間,會得到很有趣的結果:

顯示程式碼
import matplotlib.pyplot as plt
 
def normalize(s):
    return s / s[0]
 
for d in ret.index.dropna():
    plt.plot(normalize(b.loc[d:].head(250).values))

四次買點持有 250 天的大盤報酬曲線比較圖

這張圖中藍色的為金融海嘯,所以當買入時,還跌了一段,還是賠了 40% 的資產,非常的恐怖…。可見這種方法還是不能亂用。

另外更有趣的是,紅色跟藍色的大盤趨勢非常像,而綠色跟橘色也很類似,感覺大盤的變化隨時間是有規律的。

優化策略

接下來,我想要進行一個小修改,因為 VIX 是市場恐慌的程度,VIX 高代表市場可能過於悲觀,但是不代表悲觀已經結束了,所以 2008 年的 VIX 才會噴到將近 50 左右的位置,所以我們不應該在 VIX 噴發時投資,應該要等它降溫時,投資會比較好,所以新的策略邏輯如下:

  1. VIX 近120天超過40
  2. VIX 當天降到了30
顯示程式碼
th = 40
days = 250
 
buy = (
    ((vixc > th).rolling(120).sum() > 0) &
    (vixc < 30)
)
 
buy &= (buy.shift().rolling(30).mean() == 0)
 
price_begin = b[buy]
price_end = b.shift(-days)[buy]
ret = (price_end/price_begin)#.groupby(price_begin.index.year).first()
ret

優化後策略買入持有 250 天的報酬率結果

我們發現,這四次的買點都是有獲利的,且大於平均年報酬率(6%),說明了這可能是比較好的投資方法。然而取樣的點非常少,才 4 次,所以也有可能只是運氣好而已,過去不等於未來,投資風險就請大家自行斟酌囉!

相信大家可以用類似的方式,找到更好的投資方式喔!快來試試看吧~

優化後策略四次買點持有 250 天的大盤報酬曲線圖

想建立自己的策略?

用自然語言描述你的選股想法,AI 自動驗證、回測、給你答案

免費開始