做空恐慌指数Python回测

1.VIX历史走势

import pandas as pd
import numpy as np

vixy_df = pd.read_csv('stock/VIXY.csv')
vix_df = pd.read_csv('stock/VIX.csv')

vix_df = vix_df.set_index('Date',False)
vix_df= vix_df[1:]
vix_df

import matplotlib.pyplot as plt
plt.figure(figsize=(15,8)) #创建绘图对象
plt.plot(pd.to_datetime(vix_df['Date']),vix_df['Adj Close'],"b",linewidth=1)   #在当前绘图对象绘图(X轴,Y轴,蓝色,线宽度)
# plt.plot(x,hs_profit_list,"r",linewidth=1)
plt.xlabel("Date") #X轴标签
plt.ylabel("Price")  #Y轴标签
plt.title("VIX") #图标题
plt.axhline(22, color="red", linestyle="--")
plt.axhline(35, color="red", linestyle="--")
plt.axhline(13, color="green", linestyle="--")
plt.show()  #显示图

做空恐慌指数Python回测_第1张图片
去雅虎financial 上下载VIX和VIXY的历史数据到stock目录下。
可以看到2011年后,VIX最高有涨到45多,35以上的也有4次,中等高度也有涨到超过22。低点的话13左右。

2. 简单条件当VIX 高于X的时候进行做空VIXY,低于Y的时候,平仓VIXY

VIX本身只有期货,所以我们来回测基于VIX的ETF,VIXY

import datetime
def MaxDrawdown(return_list):
    '''最大回撤率'''
    i = np.argmax((np.maximum.accumulate(return_list) - return_list) / np.maximum.accumulate(return_list))  # 结束位置
    if i == 0:
        return 0
    j = np.argmax(return_list[:i])  # 开始位置
    return (return_list[j] - return_list[i]) / (return_list[j])

all_date = list(vix_df.index.values)[1:]
def get_profit(short_vix_price=22.42, cover_vix_price=13.58, log=False):

    
#     percent_day_count = 12
#     is_high_average_day_count = 15
    is_short = False
#     start_hb_date = datetime.datetime.strptime(start_date, "%Y-%m-%d")
    profit = 1
    log_profit = 1
    win_profit = []
    loss_profit = []
    profit_list = []
    profit_date = []
    for date in all_date:
        date_index = list(vix_df.index.values).index(date)
        current_vix_price = vix_df['Adj Close'][date_index]
        is_high = current_vix_price >= short_vix_price
        if is_high and is_short is False:
            current_date_time = datetime.datetime.strptime(str(date)[0:10], "%Y-%m-%d")
#             day_count = (current_date_time - start_hb_date).days
            #算上空仓的货币基金收益
#             profit *= 1 + ((day_count / 365) * hb_percent)
            is_short = True
            short_price = vixy_df['Adj Close'][date_index]
            if log:
                print("short " + " date:" + str(date) + " price:" + str(short_price) + " vix:" + str(short_vix_price))
                
        if is_short and log:
            log_profit = log_profit * (( vixy_df['Adj Close'][date_index - 1] - vixy_df['Adj Close'][date_index]) / vixy_df['Adj Close'][date_index - 1] + 1)
        
        if is_short is True and current_vix_price <= cover_vix_price:
            is_short = False
#             start_hb_date = datetime.datetime.strptime(str(date)[0:10], "%Y-%m-%d")
            buy_price = vixy_df['Adj Close'][date_index]
            current_profit = (short_price - buy_price) /  short_price + 1
            profit *= current_profit
            #算上买卖成本
            profit *= 0.9985
            log_profit = profit
            if current_profit >=1:
                win_profit.append(current_profit - 1)
            else:
                loss_profit.append(current_profit - 1)
            if log:
                print("cover:VIXY "  + " date:" + str(date) + " price:" + str(buy_price) + " profit:" + str(profit))
        profit_list.append(log_profit)
        profit_date.append(date)


    if log:
        print('净值:' + str(profit))
        print('盈利次数:' + str(len(win_profit)))
        print('亏损次数:' + str(len(loss_profit)))
        winPercent = len(win_profit) /  float(len(win_profit) + len(loss_profit))
        print('胜率:' + str( winPercent) ) 
        averangeWinPercent = np.sum(win_profit) /  float(len(win_profit))
        print('平均每次盈利:' + str(averangeWinPercent ) ) 
        averageLossPerent = np.sum(loss_profit) /  float(len(loss_profit))
        print('平均每次亏损:' + str(averageLossPerent ) ) 
        kali = winPercent - (1 - winPercent) / (averangeWinPercent / abs(averageLossPerent));
        print('盈亏比:' + str(abs(averangeWinPercent / averageLossPerent)))
        print('凯利最佳仓位:' + str(kali))
        max_down = MaxDrawdown(profit_list)
        print('最大回撤:' + str(max_down))
    return profit, profit_list, profit_date

3.当VIX35做空VIXY,13平仓净值走势

x = profit_date
y = profit_list
plt.figure(figsize=(15,8)) #创建绘图对象
plt.plot(pd.to_datetime(x),y,"b",linewidth=1)   #在当前绘图对象绘图(X轴,Y轴,蓝色,线宽度)
# plt.plot(x,hs_profit_list,"r",linewidth=1)
plt.xlabel("Date") #X轴标签
plt.ylabel("Profit")  #Y轴标签
plt.title("Short VIXY") #图标题
plt.show()  #显示图

做空恐慌指数Python回测_第2张图片
净值:4.6848805430308555
盈利次数:4
亏损次数:0
胜率:1.0
平均每次盈利:0.49078186646488375
平均每次亏损:nan
盈亏比:nan
凯利最佳仓位:nan
最大回撤:0.6017801172984159

效果并不明显。

4.当VIX22做空VIXY,13平仓净值走势

做空恐慌指数Python回测_第3张图片
净值:7.786198365812795
盈利次数:7
亏损次数:0
胜率:1.0
平均每次盈利:0.3573116363119387
平均每次亏损:nan
盈亏比:nan
凯利最佳仓位:nan
最大回撤:0.717993653963472

5.暴利穷举2011年来历史较大值 13.8, 12.8

做空恐慌指数Python回测_第4张图片
净值:67.17964069219849
盈利次数:47
亏损次数:1
胜率:0.9791666666666666
平均每次盈利:0.10550110265455798
平均每次亏损:-0.20406508130081302
盈亏比:0.5169973323316323
凯利最佳仓位:0.9388698758894762
最大回撤:0.7179936539634723

6. 总结做空VIXY的策略

1.虽然理论上可以取得100%胜率,但是最大回撤惊人,所以不算是好策略。100%胜率的策略越要小心
2.做空的风险太高:1.证券商可以提早平仓不通知。2.做空还有利息没有算进去,最高20%也不是没有可能。3.证券商会提高保证金 4. 做空仓位上涨比做多股票会快速吞噬可用资金,可用计算下 5.做空的最大亏损有可能会超过100%
3.金融危机VIX最高有上涨到80,预计VIXY这种可能会上涨超过8倍

以上仅供学习,不要作为投资依据。

你可能感兴趣的:(量化投资)