Search code examples
pythonpandasmatplotlibfinance

Signal frontier analysis in pandas: VIX index


I have a very simple VIX (S&P500 1 month implied volatility index) "regime" code that does the following:

  1. Did vix go above 16.5? If yes, color chart red.
  2. Did vix go above 19.5? If yes, color chart green.
  3. Did vix go below 19.5? If yes, color chart blue.
  4. Did vix go below 16.5? If yes, color chart yellow.

In other words, the color does not just depend on the current state, but is set and held once the price passes above or below the boundaries above.

My code is attached below. Thank you very much.

import datetime as datetime
import pandas as pd
import numpy as np
import pandas_datareader.data as web
import matplotlib.pyplot as plt
import warnings

warnings.filterwarnings("ignore")
#%matplotlib inline

df = web.DataReader('^VIX', 'yahoo',datetime.datetime(2016  ,1, 1), datetime.datetime.today())
df = df.drop(df.columns[[0, 1, 2,3,5]], axis=1)
df1 = web.DataReader('spy', 'yahoo',datetime.datetime(2016  ,1, 1), datetime.datetime.today()) 
df1.rename(columns={'Adj Close': 'SPY'}, inplace=True)
df1 = df1.drop(df1.columns[[0, 1, 2,3,5]], axis=1)
df = pd.merge(df, df1, left_index=True, right_index=True)
df.reset_index(inplace=True)
plt.style.use('seaborn-white')
plt.rcParams["font.family"] = "Times"

plt.figure(figsize=(23,12))

ax1 = plt.subplot2grid((14,1), (0,0), rowspan=10, colspan=7)
plt.title('VIX Risk Off Indicator')
ax3 = ax1.twinx()
ax2 = plt.subplot2grid((14,1), (10,0), rowspan=4, colspan=7,sharex=ax1)
ax2.grid(False)

ax1.grid(False)
ax1.xaxis.set_visible(False)
ax1.legend()

df['16.5'] = np.where(np.logical_and(df['Adj Close'] >= 16.5,df['Adj Close'] <= 19.5),'yes','no')
df['19.5'] = np.where(np.logical_and(df['Adj Close'] >= 19.5,df['Adj Close'] >= 19.5),'yes','no')
df['l19.5'] = np.where(np.logical_and(df['Adj Close'] <= 19.5,df['Adj Close'] >= 16.5),'yes','no')

markers1 = [idx for idx,close in enumerate(df['16.5']) if close == 'yes']

for marker in markers1:
    ax1.axvline(marker, color='red',linewidth=1,alpha=.15)
markers1 = [idx for idx,close in enumerate(df['19.5']) if close == 'yes']

for marker in markers1:
    ax1.axvline(marker, color='green',linewidth=1,alpha=.5)    
markers1 = [idx for idx,close in enumerate(df['l19.5']) if close == 'yes']
for marker in markers1:
    ax1.axvline(marker, color='cyan',linewidth=1,alpha=.05)    


ax1.plot(df['SPY'],label='SPY', lw=1,color='black')

ax2.plot(df['Adj Close'],'black', label='VIX', lw=1)


ax2.grid(False)

ax2.legend()
pdffile = ('C://VIX.pdf')
plt.savefig(pdffile, format='pdf',transparent=False,bbox_inches='tight')
plt.show()
plt.close()
plt.close("all")       

Solution

  • Here's some code to get you started. In the future, it helps to pare down your examples to something smaller and isolate exactly what you're trying to do.

    The way I create regime states below is by using "triggers" rather than "states." The presence of a trigger is dependent upon the level of the VIX on day i but also on its level on day i - 1. You can these fill those trigger-points forwards until the next trigger appears.

    import pandas as pd
    import pandas_datareader as pdr
    import numpy as np
    import matplotlib.pyplot as plt
    
    vix = pdr.DataReader('VIXCLS', 'fred').dropna().squeeze()
    
    lower, upper = 16.5, 19.5
    
    # Each term inside parentheses is [False, True, ...]
    # Both terms must be True element-wise for a trigger to occur
    blue = (vix < upper) & (vix.shift() >= upper)
    yellow = (vix < lower) & (vix.shift() >= lower)
    green = (vix > upper) & (vix.shift() <= upper)
    red = (vix > lower) & (vix.shift() <= lower)
    
    mapping = {1: 'blue', 2: 'yellow', 3: 'green', 4: 'red'}
    
    indicator = pd.Series(np.where(blue, 1., np.where(yellow, 2.,
                          np.where(green, 3., np.where(red, 4., np.nan)))),
                          index=vix.index).ffill().map(mapping).dropna()
    
    vix = vix.reindex(indicator.index)
    plt.scatter(vix.index, vix, c=indicator, marker='*')
    plt.title('VIX regime')
    plt.ylabel('VIX')
    

    enter image description here

    Once you get the states, you could look into this example of plotting a multicolored line from the matplotlib docs. Good luck.