# Import Libraries
import math
import numpy as np
import talib as ta
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels import regression
import statsmodels.api as sm
from quantopian.interactive.data.quandl import yahoo_index_vix as vix
from pandas.core.generic import NDFrame
# import data operations
import odo as odo
from odo import odo
# For use in your algorithms via the pipeline API
from quantopian.pipeline.data.quandl import yahoo_index_vix
# For use in Quantopian Research, exploring interactively
from quantopian.interactive.data.quandl import yahoo_index_vix
def linreg(X,Y):
# Running the linear regression
X = sm.add_constant(X)
model = regression.linear_model.OLS(Y, X).fit()
a = model.params[0]
b = model.params[1]
X = X[:, 1]
# Return summary of the regression and plot results
X2 = np.linspace(X.min(), X.max(), 10000)
Y_hat = X2 * b + a
#plt.scatter(X, Y, alpha=0.3) # Plot the raw data
plt.plot(X2, Y_hat, alpha=0.9); # Add the regression line, colored in red
plt.title('VIX after Bottom (Linear Regression)')
return b
#return model.summary()
vix_df = odo(vix, pd.DataFrame)
vix_df.index = vix_df.asof_date
symbol = "SPY"
start = "2004-01-01"
end = "2017-01-20"
prices = get_pricing(symbol, start_date=start, end_date=end, fields='close_price')
prices.index.tz = None
sym_date=list()
sym_prices=list()
sym_vixstartdate=list()
vixinc = dict()
vixdec = dict()
totals = dict()
vixper = dict()
previous=[30]
after=[0,1]
reg = [15]
rsi = ta.RSI(np.array(prices), timeperiod=14)
# define a bottom: no close price lower than bottom in the previous x days and next y days.
for y in after:
for s in previous:
for q in reg:
vixincrease=0
vixdecrease=0
for i in range(len(prices.index)-q):
for j in range(s+1):
if prices[i] < prices[i-j-1]:
continue
else: break
if j == s:
for k in range(y+1):
if prices[i] < prices[i+k+1]:
continue
else: break
if k == y:
sym_prices.append(prices[i])
sym_date.append(prices.index[i])
sym_vixstartdate.append(prices.index[i+y])
b=linreg(range(q),vix_df.close.loc[prices.index[i+y:i+y+q]])
plt.xlabel('Days')
plt.ylabel('VIX')
plt.text(1, 90,'(Bottom: no close price lower than bottom in the previous ' + str(previous) +\
' days and next ' + str(y) + ' day)')
if b>0:
vixincrease=vixincrease+1
else:
vixdecrease=vixdecrease+1
plt.axis([None, None, 0, 100])
vixinc[(s,y,q)] = vixincrease
vixdec[(s,y,q)] = vixdecrease
totals[(s,y,q)] = vixinc[(s,y,q)]+vixdec[(s,y,q)]
vixper = {(s,y,q): float(vixdec[(s,y,q)])/totals[(s,y,q)] for (s,y,q) in totals}
sym_bottom_data = {
'price': sym_prices,
'date': sym_date,
'vixstartdate': sym_vixstartdate
}
print 'percentage:', vixper, 'totals:', totals
# MACD Calculation
macd, macdsignal, macdhist = ta.MACD(prices, 12, 26, 9)
trigger = macd - macdsignal
# When the trigger is positive, or becomes positives, it was a bottom. Likewise, when it goes from positive to
# negative, it represents a top.
symbol='SPY'
start = "2004-01-01"
end = "2017-01-20"
stock_spy = get_pricing(symbol, start_date=start, end_date=end, fields=['high', 'low', 'close_price'])
# Vix Fix calculated for the SPY
WVF = (stock_spy['high'].rolling(28).max() - stock_spy['low'])/stock_spy['high'].rolling(28).max()*100
# Bollinger Bands
vfup, vfmid, vflow = ta.BBANDS(np.array(WVF),timeperiod=28,nbdevup=2, nbdevdn=2, matype=0)
plt.plot(vfup)
plt.plot(vfmid)
plt.plot(vflow)
plt.title('Williams Vix Fix and Bollinger Bands')
plt.xlabel('days')
plt.ylabel('Levels')
plt.grid(False);
When the WVF crosses the upper band, then it is time to sell the volatility, as it means the stock has reached lower bottom. On the contrary, when the WVF crosses the lower band, then it is time to buy as it means it market top, as it decreases the VIX will begin increasing.
http://www.nasdaq.com/article/the-award-winning-research-thats-led-to-a-100-win-rate-cm464581 This article shows how by adding a moving average to the WVF the signals improve. by adding the MA, the market action tells when the volatility had reached a short-term peak, allowing to balance the potential risks and rewards of option selling. The MA works in the same way the MACD works for any stock.
#Define the variables
fast = 12
slow = 26
signal = 9
#macd = ta.MACD(WVF, fastperiod = fast, slowperiod=slow, signalperiod=signal)
#plt.plot(macd);
shortma = pd.rolling_mean(WVF, fast)
longma = pd.rolling_mean(WVF, slow)
macd = shortma - longma
macdr = macd.pct_change()[1:]
signal = pd.rolling_mean(macd, signal)
trigger = macd - signal
rtrigger = trigger.pct_change()[1:];
Moving forward, everytime the entry criteria is met, that is, when the price at time t is the lowest in the time period [t-30:t], I will take a time series for 30 days and test every day for an exit signal to come (i.e. RSI>70). Once this happens, the time series will be crop to the time when the signal comes and run a regression on that time. Should no signal come, the biggest regression day-length will be 30 days.
vix_df = odo(vix, pd.DataFrame)
vix_df.index = vix_df.asof_date
symbol = "SPY"
start = "2004-01-01"
end = "2017-01-20"
prices = get_pricing(symbol, start_date=start, end_date=end, fields='close_price')
prices.index.tz = None
sym_date=list()
sym_prices=list()
sym_vixstartdate=list()
vixinc = dict()
vixdec = dict()
totals = dict()
vixper = dict()
selldays = dict()
previous=[30]
after=[0]
# define a bottom: no close price lower than bottom in the previous x days and next y days.
for y in after:
for s in previous:
R=np.array([0,]*30)
#R = list() # Vector for the RSI Index
vixincrease = 0
vixdecrease = 0
days = 0
for i in range(len(prices.index)-30):
for j in range(s+1):
if prices[i] < prices[i-j-1]:
continue
else: break
if j == s:
for k in range(y+1):
if prices[i] < prices[i+k+1]:
continue
else: break
if k == y:
sym_prices.append(prices[i])
sym_date.append(prices.index[i])
sym_vixstartdate.append(prices.index[i+y])
R=rsi[i+y+1:i+y+30+1] # RSI vector
# Count the number of days until the sell signal comes
RSI = []
for r in R:
if r < 70:
r = 1
else: break
RSI.append(r)
days = sum(RSI) + 1
selldays[(s,y)] = days
b=linreg(range(15),vix_df.close.loc[prices.index[i+y:i+y+15]])
plt.xlabel('Days')
plt.ylabel('VIX')
plt.grid(False)
plt.text(1, 90,'(Bottom: no close price lower than bottom in the previous ' + str(previous) +\
' days and next ' + str(y) + ' day)')
if b>0:
vixincrease=vixincrease+1
else:
vixdecrease=vixdecrease+1
plt.axis([None, None, 0, 100])
vixinc[(s,y)] = vixincrease
vixdec[(s,y)] = vixdecrease
totals[(s,y)] = vixinc[(s,y)]+vixdec[(s,y)]
vixper = {(s,y): float(vixdec[(s,y)])/totals[(s,y)] for (s,y) in totals}
sym_bottom_data = {
'price': sym_prices,
'date': sym_date,
'vixstartdate': sym_vixstartdate
}
print 'percentage:', vixper, 'totals:', totals, 'Signal days:', selldays
#print days
#print selldays
print days
print R
len(R)
vix_df = odo(vix, pd.DataFrame)
vix_df.index = vix_df.asof_date
spy_df = odo(prices, pd.DataFrame)
symbol = "SPY"
start = "2004-01-01"
end = "2017-01-20"
prices = get_pricing(symbol, start_date=start, end_date=end, fields='close_price')
prices.index.tz = None
sym_date=list()
sym_prices=list()
sym_vixstartdate=list()
vixincrease=0
vixdecrease=0
previous=30
after=0
reg = [30]
rsi = ta.RSI(np.array(prices), timeperiod=14)
rsi_df = odo(rsi, pd.DataFrame)
for n in reg:
A=np.array([0,]*n)
B=np.array([0,]*n) # Vector for the SPY Prices to calculate the different indicators
R=np.array([0,]*n) # Vector for the RSI Index
# define a bottom: no close price lower than bottom in the previous x days and next y days.
for i in range(n,len(prices.index)-n):
for j in range(previous+1):
if prices[i] < prices[i-j-1]:
continue
else: break
if j == previous:
for k in range(after+1):
if prices[i] < prices[i+k+1]:
continue
else: break
if k == after:
sym_prices.append(prices[i])
sym_date.append(prices.index[i])
sym_vixstartdate.append(prices.index[i+after])
A=np.vstack([A,np.array(vix_df.close.loc[prices.index[i+after+1:i+after+n+1]])]) # VIX
B=np.vstack([B,np.array(prices[prices.index[i+after+1:i+after+n+1]])]) # SPY Prices
R=np.vstack([R,np.array(rsi[i+after+1:i+after+n+1])]) # RSI vector
# Count the number of days until the sell signal comes
Rlist = R.tolist()
RSI = []
for r in Rlist:
if r < 70:
r = 1
else: break
RSI.append(r)
days = sum(RSI) + 1
sym_bottom_data = {
'price': sym_prices,
'date': sym_date,
'vixstartdate': sym_vixstartdate
}
sym_bottom_frame_data = pd.DataFrame(sym_bottom_data)
Alist = R.tolist()
days = np.array(range(30))
lisst = []
for i in Alist:
if i[24]<200 and i[25]<200 and i[26]<200 and i[27]<200 and i[28]<200 and i[27]<200:
lisst.append(i)
listo = []
for i in np.array(lisst):
n = i/i[0]
listo.append(n)
deflist = zip(*Alist)
plt.plot(deflist)
plt.grid(False)
plt.xlabel('Days')
plt.ylabel('VIX')
plt.title('VIX behaviour after bottom');
B = sum(listo[1:])/len(listo[1:])
plt.plot(B, color='red')
plt.grid(False)
plt.xlabel('Days')
plt.ylabel('VIX')
plt.title('VIX mean behaviour');