Home >  > 利用python测试volatility策略

利用python测试volatility策略

0

一、Strategy:

hold S&P 500 ETF when volatility is low, when vol is high be in cash.

二、知识点
1.从雅虎获取历史行情,并转化成df。
2.plot展示(原来的代码没有显示Figure,后来加了plt.show()才显示。

三、代码:

import pandas as pd
import matplotlib.pyplot as plt

def load_equities_web(symbol, date_from):
    import pandas_datareader.data as web
    raw_data = web.DataReader(symbol, 'yahoo', pd.to_datetime(date_from), pd.datetime.now())
    data = raw_data.stack(dropna=False)['Adj Close'].to_frame().reset_index().rename(columns = {'Symbols':'symbol', 'Date':'date', 'Adj Close':'value'}).sort_values(by = ['symbol', 'date'])
    return pd.pivot_table(data, columns = 'symbol', index = 'date', values ='value')


prices = load_equities_web(['SPY', '^GSPC', '^VIX'], date_from = '2000-01-01')

def backtest_strategy(prices, symbol_trade, symbol_volatility, volatility_threshold, capital, symbol_benchmark):
    
    
    df_init   = (prices[symbol_trade]*0).to_frame().assign(cash = 0)
    df_update = (prices[symbol_trade]*0).to_frame().assign(cash = 0)
    df_end    = (prices[symbol_trade]*0).to_frame().assign(cash = 0)
    
    df_init.iloc[0, df_init.columns.get_loc('cash')] = capital
    df_end.iloc[0, df_end.columns.get_loc('cash')]   = capital
    
    calendar = pd.Series(prices.index).iloc[1:]
    
    
    for date in calendar:
        prev_date = df_init.index[df_init.index<date][-1]
        
        df_init.loc[date, :] = df_end.loc[prev_date, :]
        
        port_value = df_init.loc[date, symbol_trade] * prices.loc[date, symbol_trade] + df_init.loc[date, 'cash']
        
        if prices.loc[date, symbol_volatility] > volatility_threshold: # volatility is high -> be fully in cash
            df_end.loc[date, symbol_trade] = 0
            df_end.loc[date, 'cash']       = port_value
        else: # volatility is low -> be in market position
            df_end.loc[date, symbol_trade] = port_value/prices.loc[date, symbol_trade]
            df_end.loc[date, 'cash'] = 0
        df_update.loc[date] = df_end.loc[date] - df_init.loc[date]
    
    portval = (df_end*prices.assign(cash = 1)[[symbol_trade, 'cash']]).sum(axis = 1).to_frame().rename(columns = {0:'strategy'})
    portval['benchmark'] = prices[symbol_benchmark]
    portval = portval/portval.iloc[0].values
    
    return portval
    

res = backtest_strategy(prices = prices, symbol_trade = 'SPY', symbol_volatility = '^VIX', volatility_threshold = 20, capital = 10000, symbol_benchmark = '^GSPC')
print(res)
res.plot()
plt.show()

四、成果展示

本文暂无标签

发表评论

*

*