Analyzing Historical VSTOXX Data

A Sample notebook based on the EurEX Tutorial

The data sets are for the periods from 31.12.1986 and 04.01.1999, respectively, to 28.12.2012. Prepared data sets can be downloaded her: EURO STOXX 50 data: es.txt VSTOXX data: vs.txt The meanings of the abbreviations in the EURO STOXX 50 file es.txt are as follows: SX5P: STOXX Europe 50 prices in EUR SX5E: EURO STOXX 50 prices in EUR SXXP: STOXX Europe 600 prices in EUR SXXE: EURO STOXX ESG Leaders 50 prices in EUR SXXF: STOXX Europe 600 ex UK prices in EUR SXXA: STOXX Europe 600 ex Eurozone prices in EUR DK5F: STOXX Nordic 30 prices in EUR DKXF: STOXX Nordic prices in EUR In the VSTOXX file, the meanings are vs.txt V2TX: VSTOXX-values V6I1: Sub-Index 1 month V6I2: Sub-Index 2 months V6I3: Sub-Index 3 months V6I4: Sub-Index 6 months V6I5: Sub-Index 9 months V6I6: Sub-Index 12 months V6I7: Sub-Index 18 months V6I8: Sub-Index 24 months

Data Munging

Load, clean and transform our data.


In [10]:
from pylab import *
from pandas import *
es = read_csv('/resources/es.txt', sep=';', index_col=0, parse_dates=True, dayfirst=True)
vs = read_csv('/resources/vs.txt', sep=',', index_col=0, parse_dates=True, dayfirst=True)

In [11]:
es.describe()


Out[11]:
SX5P SX5E SXXP SXXE SXXF SXXA DK5F DKXF DEL
count 6707.000000 6707.000000 6707.000000 6707.000000 6707.000000 6707.000000 6707.000000 6707.000000 0
mean 2291.899274 2403.464984 212.768260 222.327155 238.596119 201.298986 3958.073328 272.399155 NaN
std 1138.860688 1219.650999 93.983572 103.606716 113.135815 84.456273 2573.524155 156.103534 NaN
min 626.090000 615.900000 66.690000 68.550000 68.390000 64.550000 536.870000 55.250000 NaN
25% 1129.585000 1140.685000 111.660000 120.650000 119.775000 111.695000 1222.490000 118.455000 NaN
50% 2427.500000 2468.450000 225.280000 225.780000 250.300000 215.530000 4043.590000 270.970000 NaN
75% 3145.875000 3304.345000 284.215000 298.920000 323.280000 273.010000 6262.395000 384.995000 NaN
max 5183.240000 5464.430000 405.500000 466.240000 477.410000 359.720000 9449.200000 776.820000 NaN

8 rows × 9 columns


In [12]:
# Remove the "DEL" column.
del es['DEL']
es.head()


Out[12]:
SX5P SX5E SXXP SXXE SXXF SXXA DK5F DKXF
Date
1986-12-31 775.00 900.82 82.76 98.58 98.06 69.06 645.26 65.56
1987-01-01 775.00 900.82 82.76 98.58 98.06 69.06 645.26 65.56
1987-01-02 770.89 891.78 82.57 97.80 97.43 69.37 647.62 65.81
1987-01-05 771.89 898.33 82.82 98.60 98.19 69.16 649.94 65.82
1987-01-06 775.92 902.32 83.28 99.19 98.83 69.50 652.49 66.06

5 rows × 8 columns


In [13]:
vs.describe()


Out[13]:
V2TX V6I1 V6I2 V6I3 V6I4 V6I5 V6I6 V6I7 V6I8
count 3568.000000 3190.000000 3568.000000 3532.000000 3568.000000 3568.000000 3557.000000 3568.000000 3561.000000
mean 26.256777 27.409339 26.206614 25.597214 26.744512 26.685291 26.133793 26.609877 25.707989
std 10.159910 11.758534 9.916886 9.126218 8.315138 7.482762 6.870516 6.467140 5.778371
min 11.600000 0.000000 11.680000 11.630000 12.600000 13.240000 11.930000 14.640000 12.320000
25% 19.800000 19.805000 19.970000 19.430000 21.550000 22.085000 21.420000 22.377500 21.420000
50% 24.390000 24.875000 24.430000 24.140000 25.665000 25.735000 25.370000 25.920000 24.890000
75% 29.305000 31.075000 29.150000 28.772500 30.082500 30.270000 30.190000 30.522500 29.430000
max 87.510000 115.710000 83.380000 73.080000 64.460000 56.810000 49.730000 52.900000 44.680000

8 rows × 9 columns


In [14]:
vs.head()


Out[14]:
V2TX V6I1 V6I2 V6I3 V6I4 V6I5 V6I6 V6I7 V6I8
Date
1999-01-04 18.20 21.25 17.56 31.22 33.31 33.73 33.22 31.85 23.82
1999-01-05 29.69 36.64 28.43 32.69 33.73 33.17 32.85 32.29 25.05
1999-01-06 25.17 25.41 25.14 32.22 32.65 31.97 32.93 33.29 26.01
1999-01-07 32.52 35.44 32.20 36.13 34.51 33.11 33.28 33.73 26.22
1999-01-08 33.23 35.88 33.00 36.08 36.40 33.47 33.48 33.92 26.37

5 rows × 9 columns

Establish Content of Interest

Create a new dataset that contains EURO STOXX 50 prices in EUR (SX5E) from es.txt and the VSTOXX (V2TX) values from vs.txt since 01 Jan 2000.


In [15]:
data = DataFrame({'EUROSTOXX' : es['SX5E'][es.index > datetime(1999, 12, 31)],
                  'VSTOXX' : vs['V2TX'][vs.index > datetime(1999, 12, 31)]})
data.describe()


Out[15]:
EUROSTOXX VSTOXX
count 3332.00000 3314.000000
mean 3256.72934 26.206014
std 848.55381 10.441883
min 1809.98000 11.600000
25% 2583.36750 19.322500
50% 2950.87000 24.170000
75% 3809.30500 29.320000
max 5464.43000 87.510000

8 rows × 2 columns


In [16]:
data.head()


Out[16]:
EUROSTOXX VSTOXX
Date
2000-01-03 4849.22 30.98
2000-01-04 4657.83 33.22
2000-01-05 4541.75 32.59
2000-01-06 4500.69 31.18
2000-01-07 4648.27 27.44

5 rows × 2 columns

Installation of HDF5

Install the following:

pip install h5py

In [17]:
!pip install h5py


Requirement already satisfied (use --upgrade to upgrade): h5py in /home/notebook/ka_env/lib/python2.7/site-packages
Cleaning up...

Create HDF5 Database


In [18]:
h5 = HDFStore('data.h5')
h5['es'] = es
h5['vs'] = vs
h5['data'] = data
h5


Out[18]:
<class 'pandas.io.pytables.HDFStore'>
File path: data.h5
/data            frame        (shape->[3333,2])
/es              frame        (shape->[6707,8])
/vs              frame        (shape->[3568,9])

In [19]:
h5.close()

Data Analysis

Use the Data Frame data.h5 to explore the correlation between EURO STOXX 50 and VSTOXX. There is a number of empirical studies that show that the volatility indexes are in general strongly negatively correlated with stock indexes.

Open HDF5 Datastore


In [20]:
h5 = HDFStore('data.h5', 'a')
es = h5['es']
vs = h5['vs']
data = h5['data']
h5.close()

In [21]:
data.head()


Out[21]:
EUROSTOXX VSTOXX
Date
2000-01-03 4849.22 30.98
2000-01-04 4657.83 33.22
2000-01-05 4541.75 32.59
2000-01-06 4500.69 31.18
2000-01-07 4648.27 27.44

5 rows × 2 columns


In [22]:
%matplotlib inline

Plot the EURO STOXX 50 and VSTOXX indexes


In [23]:
data.plot(subplots=True, figsize=(9, 4), color='blue', grid=True)


Out[23]:
array([<matplotlib.axes.AxesSubplot object at 0x7fd3aed78050>,
       <matplotlib.axes.AxesSubplot object at 0x7fd3aed63b50>], dtype=object)

Observation: The two indexes seem to be highly negatively correlated. When the EURO STOXX 50 goes up, the VSTOXX comes down and vice versa. Something sometimes called the leverage effect.

Computation of Changes

To calculate and visualize the absolute changes, we plot a histogram which shows the absolute differences and their absolute frequencies.


In [24]:
data.diff().hist(color='b', alpha=.5, bins=100)


Out[24]:
array([[<matplotlib.axes.AxesSubplot object at 0x7fd3aebc5d90>,
        <matplotlib.axes.AxesSubplot object at 0x7fd3aeaef790>]], dtype=object)

The figure shows the absolute returns of both indexes on daily basis.

Observation: The daily percentage changes might also be of interest. We can compute and plot them as well.


In [25]:
data.pct_change().head()


Out[25]:
EUROSTOXX VSTOXX
Date
2000-01-03 NaN NaN
2000-01-04 -0.039468 0.072305
2000-01-05 -0.024921 -0.018964
2000-01-06 -0.009041 -0.043265
2000-01-07 0.032791 -0.119949

5 rows × 2 columns


In [26]:
data.pct_change().hist(color='b', alpha=.5, bins=100)


Out[26]:
array([[<matplotlib.axes.AxesSubplot object at 0x7fd3aeb13310>,
        <matplotlib.axes.AxesSubplot object at 0x7fd3ae52c0d0>]], dtype=object)

Calculation of Log-Returns

In financial applications, one is often interested in daily log-returns. We will calculate them and store them in the Data Frame data. To this end, we generate two now columns using the shift method. Then we plot the results.


In [27]:
data['esr'] = log(data['EUROSTOXX'] / data['EUROSTOXX'].shift(1))
data['vsr'] = log(data['VSTOXX'] / data['VSTOXX'].shift(1))
data.head()


Out[27]:
EUROSTOXX VSTOXX esr vsr
Date
2000-01-03 4849.22 30.98 NaN NaN
2000-01-04 4657.83 33.22 -0.040268 0.069810
2000-01-05 4541.75 32.59 -0.025237 -0.019147
2000-01-06 4500.69 31.18 -0.009082 -0.044229
2000-01-07 4648.27 27.44 0.032264 -0.127775

5 rows × 4 columns


In [28]:
data[['esr', 'vsr']].plot(subplots=True, figsize=(9, 4), color='blue', grid=True)


Out[28]:
array([<matplotlib.axes.AxesSubplot object at 0x7fd3ae08ccd0>,
       <matplotlib.axes.AxesSubplot object at 0x7fd3ae011bd0>], dtype=object)

Correlation between EURO STOXX 50 and VSTOXX

There are (at least) two possible ways to calculate the correlation between both log-returns. On the one hand, we can generate a correlation matrix as output (which would be preferred for more than two time series). On the other hand, we can compute the correlation directly between the two time series of interest:


In [29]:
data[['esr','vsr']].corr()


Out[29]:
esr vsr
esr 1.00000 -0.75278
vsr -0.75278 1.00000

2 rows × 2 columns


In [30]:
data['esr'].corr(data['vsr'])


Out[30]:
-0.75277950362156976

Observation: The log-returns of both indexes are highly negatively correlated. Again support for the leverage effect which implies that with dropping index levels risk increases. Also, if index levels rise, risks come down in general.


In [30]: