Implied Volatilities and Model Calibration

This setion of the documentation illustrates how to calculate implied volatilities and how to calibrate a model to VSTOXX volatility index call option quotes. The example implements the calibration for a total of one month worth of data.


In [1]:
import numpy as np
import pandas as pd

VSTOXX Futures & Options Data

We start by loading VSTOXX data from a pandas HDFStore into DataFrame objects (source: Eurex, cf. http://www.eurexchange.com/advanced-services/).


In [2]:
h5 = pd.HDFStore('./data/vstoxx_march_2014.h5', 'r')
vstoxx_index = h5['vstoxx_index'] 
vstoxx_futures = h5['vstoxx_futures'] 
vstoxx_options = h5['vstoxx_options']
h5.close()

VSTOXX index for the first quarter of 2014.


In [3]:
%matplotlib inline
vstoxx_index['V2TX'].plot()


Out[3]:
<matplotlib.axes._subplots.AxesSubplot at 0x108caac50>

The VSTOXX futures data (8 futures maturities/quotes per day).


In [4]:
vstoxx_futures.info()


<class 'pandas.core.frame.DataFrame'>
Int64Index: 504 entries, 0 to 503
Data columns (total 5 columns):
DATE         504 non-null datetime64[ns]
EXP_YEAR     504 non-null int64
EXP_MONTH    504 non-null int64
PRICE        504 non-null float64
MATURITY     504 non-null datetime64[ns]
dtypes: datetime64[ns](2), float64(1), int64(2)
memory usage: 23.6 KB

In [5]:
vstoxx_futures.tail()


Out[5]:
DATE EXP_YEAR EXP_MONTH PRICE MATURITY
499 2014-03-31 2014 7 20.40 2014-07-18
500 2014-03-31 2014 8 20.70 2014-08-15
501 2014-03-31 2014 9 20.95 2014-09-19
502 2014-03-31 2014 10 21.05 2014-10-17
503 2014-03-31 2014 11 21.25 2014-11-21

The VSTOXX options data. This data set is quite large due to the large number of European put and call options on the VSTOXX.


In [6]:
vstoxx_options.info()


<class 'pandas.core.frame.DataFrame'>
Int64Index: 46960 entries, 0 to 46959
Data columns (total 7 columns):
DATE         46960 non-null datetime64[ns]
EXP_YEAR     46960 non-null int64
EXP_MONTH    46960 non-null int64
TYPE         46960 non-null object
STRIKE       46960 non-null float64
PRICE        46960 non-null float64
MATURITY     46960 non-null datetime64[ns]
dtypes: datetime64[ns](2), float64(2), int64(2), object(1)
memory usage: 2.9+ MB

In [7]:
vstoxx_options.tail()


Out[7]:
DATE EXP_YEAR EXP_MONTH TYPE STRIKE PRICE MATURITY
46955 2014-03-31 2014 11 P 85 63.65 2014-11-21
46956 2014-03-31 2014 11 P 90 68.65 2014-11-21
46957 2014-03-31 2014 11 P 95 73.65 2014-11-21
46958 2014-03-31 2014 11 P 100 78.65 2014-11-21
46959 2014-03-31 2014 11 P 105 83.65 2014-11-21

As a helper function we need a function to calculate all relevant third Fridays for all relevant maturity months of the data sets.


In [8]:
import datetime as dt
import calendar

def third_friday(date):
    day = 21 - (calendar.weekday(date.year, date.month, 1) + 2) % 7
    return dt.datetime(date.year, date.month, day)

In [9]:
third_fridays = {}
for month in set(vstoxx_futures['EXP_MONTH']):
    third_fridays[month] = third_friday(dt.datetime(2014, month, 1))

In [10]:
third_fridays


Out[10]:
{1: datetime.datetime(2014, 1, 17, 0, 0),
 2: datetime.datetime(2014, 2, 21, 0, 0),
 3: datetime.datetime(2014, 3, 21, 0, 0),
 4: datetime.datetime(2014, 4, 18, 0, 0),
 5: datetime.datetime(2014, 5, 16, 0, 0),
 6: datetime.datetime(2014, 6, 20, 0, 0),
 7: datetime.datetime(2014, 7, 18, 0, 0),
 8: datetime.datetime(2014, 8, 15, 0, 0),
 9: datetime.datetime(2014, 9, 19, 0, 0),
 10: datetime.datetime(2014, 10, 17, 0, 0),
 11: datetime.datetime(2014, 11, 21, 0, 0)}

Implied Volatilities from Market Quotes

Often calibration efforts are undertaken to replicate the market implied volatilities or the so-called volatility surface as good as possible. With DX Analytics and the BSM_european_option class, you can efficiently calculate (i.e. numerically estimate) implied volatilities. For the example, we use the VSTOXX futures and call options data from 31. March 2014.


In [11]:
from dx import *

Some definitions, the pre-selection of option data and the pre-definition of the market environment needed.


In [12]:
V0 = 17.6639  # VSTOXX level on 31.03.2014
futures_data = vstoxx_futures[vstoxx_futures.DATE == '2014/3/31'].copy()
options_data = vstoxx_options[(vstoxx_options.DATE == '2014/3/31')
                              & (vstoxx_options.TYPE == 'C')].copy()
me = market_environment('me', dt.datetime(2014, 3, 31))
me.add_constant('initial_value', 17.6639)  # index on 31.03.2014
me.add_constant('volatility', 2.0)  # for initialization
me.add_curve('discount_curve', constant_short_rate('r', 0.01))  # assumption
options_data['IMP_VOL'] = 0.0  # initialization new iv column

The following loop now calculates the implied volatilities for all those options whose strike lies within the defined tolerance level.


In [13]:
%%time
tol = 0.3  # tolerance level for moneyness
for option in options_data.index:
    # iterating over all option quotes
    forward = futures_data[futures_data['MATURITY'] == \
                options_data.loc[option]['MATURITY']]['PRICE'].values
                # picking the right futures value
    if (forward * (1 - tol) < options_data.loc[option]['STRIKE']
                             < forward * (1 + tol)):
        # only for options with moneyness within tolerance
        call = options_data.loc[option]
        me.add_constant('strike', call['STRIKE'])
        me.add_constant('maturity', call['MATURITY'])
        call_option = BSM_european_option('call', me)
        options_data.loc[option, 'IMP_VOL'] = \
            call_option.imp_vol(call['PRICE'], 'call', volatility_est=0.6)


CPU times: user 695 ms, sys: 7.31 ms, total: 702 ms
Wall time: 699 ms

A selection of the results.


In [14]:
options_data[60:70]


Out[14]:
DATE EXP_YEAR EXP_MONTH TYPE STRIKE PRICE MATURITY IMP_VOL
46230 2014-03-31 2014 5 C 12 7.55 2014-05-16 0.000000
46231 2014-03-31 2014 5 C 13 6.55 2014-05-16 0.000000
46232 2014-03-31 2014 5 C 14 5.55 2014-05-16 1.541568
46233 2014-03-31 2014 5 C 15 4.55 2014-05-16 1.321803
46234 2014-03-31 2014 5 C 16 3.65 2014-05-16 1.153001
46235 2014-03-31 2014 5 C 17 2.90 2014-05-16 1.042549
46236 2014-03-31 2014 5 C 18 2.35 2014-05-16 0.997178
46237 2014-03-31 2014 5 C 19 1.90 2014-05-16 0.969301
46238 2014-03-31 2014 5 C 20 1.55 2014-05-16 0.958777
46239 2014-03-31 2014 5 C 21 1.30 2014-05-16 0.968430

And the complete results visualized.


In [15]:
import matplotlib.pyplot as plt
%matplotlib inline
plot_data = options_data[options_data.IMP_VOL > 0]
plt.figure(figsize=(8, 6))
for maturity in sorted(set(options_data['MATURITY'])):
    data = plot_data.isin({'MATURITY': [maturity,]})
    data = plot_data[plot_data.MATURITY == maturity]
      # select data for this maturity
    plt.plot(data['STRIKE'], data['IMP_VOL'],
             label=maturity.date(), lw=1.5)
    plt.plot(data['STRIKE'], data['IMP_VOL'], 'r.')
plt.grid() 
plt.xlabel('strike')
plt.ylabel('implied volatility of volatility')
plt.legend()
plt.show()


Market Modeling

This sub-section now implements the model calibration based on selected options data. In particular, we choose, for a given pricing date, the following options data:

  • for a single maturity only
  • call options only
  • for a certain moneyness of the options

Relevant Market Data

The following following returns the relevant market data per calibration date:


In [16]:
tol = 0.2
def get_option_selection(pricing_date, maturity, tol=tol):
    ''' Function selects relevant options data. '''
    forward = vstoxx_futures[(vstoxx_futures.DATE == pricing_date)
                & (vstoxx_futures.MATURITY == maturity)]['PRICE'].values[0]
    option_selection = \
        vstoxx_options[(vstoxx_options.DATE == pricing_date)
                     & (vstoxx_options.MATURITY == maturity)
                     & (vstoxx_options.TYPE == 'C')
                     & (vstoxx_options.STRIKE > (1 - tol) * forward)
                     & (vstoxx_options.STRIKE < (1 + tol) * forward)]
    return option_selection, forward

Options Modeling

Given the options and their respective quotes to which to calibrate the model, the function get_option_models returns the DX Analytics option models for all relevant options. As risk factor model we use the square_root_diffusion class.


In [17]:
def get_option_models(pricing_date, maturity, option_selection):
    ''' Models and returns traded options for given option_selection object. '''
    me_vstoxx = market_environment('me_vstoxx', pricing_date)
    initial_value = vstoxx_index['V2TX'][pricing_date]
    me_vstoxx.add_constant('initial_value', initial_value)
    me_vstoxx.add_constant('final_date', maturity)
    me_vstoxx.add_constant('currency', 'EUR')
    me_vstoxx.add_constant('frequency', 'W')
    me_vstoxx.add_constant('paths', 10000)
    csr = constant_short_rate('csr', 0.01)
      # somewhat arbitrarily chosen here
    me_vstoxx.add_curve('discount_curve', csr)
    
    # parameters to be calibrated later
    me_vstoxx.add_constant('kappa', 1.0)
    me_vstoxx.add_constant('theta', 1.2 * initial_value)
    me_vstoxx.add_constant('volatility', 1.0)
    
    vstoxx_model = square_root_diffusion('vstoxx_model', me_vstoxx)
      # square-root diffusion for volatility modeling
      # mean-reverting, positive process
    
    # option parameters and payoff
    me_vstoxx.add_constant('maturity', maturity)
    payoff_func = 'np.maximum(maturity_value - strike, 0)'
    
    option_models = {}
    for option in option_selection.index:
        strike = option_selection['STRIKE'].ix[option]
        me_vstoxx.add_constant('strike', strike)
        option_models[option] = \
                            valuation_mcs_european_single(
                                    'eur_call_%d' % strike,
                                    vstoxx_model,
                                    me_vstoxx,
                                    payoff_func)
    return vstoxx_model, option_models

The function calculate_model_values estimates and returns model value estimates for all relevant options given a parameter set for the square_root_diffusion risk factor model.


In [18]:
def calculate_model_values(p0):
    ''' Returns all relevant option values.
    
    Parameters
    ===========
    p0 : tuple/list
        tuple of kappa, theta, volatility
    
    Returns
    =======
    model_values : dict
        dictionary with model values
    '''
    kappa, theta, volatility = p0
    vstoxx_model.update(kappa=kappa,
                        theta=theta,
                        volatility=volatility)
    model_values = {}
    for option in option_models:
       model_values[option] = \
         option_models[option].present_value(fixed_seed=True)
    return model_values

Calibration Functions

Mean-Squared Error Calculation

The calibration of the pricing model is based on the minimization of the mean-squared error (MSE) of the model values vs. the market quotes. The MSE calculation is implemented by the function mean_squared_error which also penalizes economically implausible parameter values.


In [19]:
i = 0
def mean_squared_error(p0):
    ''' Returns the mean-squared error given
    the model and market values.
    
    Parameters
    ===========
    p0 : tuple/list
        tuple of kappa, theta, volatility
    
    Returns
    =======
    MSE : float
        mean-squared error
    '''
    if p0[0] < 0 or p0[1] < 5. or p0[2] < 0 or p0[2] > 10.:
        return 100
    global i, option_selection, vstoxx_model, option_models, first, last
    pd = dt.datetime.strftime(
            option_selection['DATE'].iloc[0].to_pydatetime(),
            '%d-%b-%Y')
    mat = dt.datetime.strftime(
            option_selection['MATURITY'].iloc[0].to_pydatetime(),
            '%d-%b-%Y')
    model_values = calculate_model_values(p0)
    option_diffs = {}
    for option in model_values:
        option_diffs[option] = (model_values[option]
                              - option_selection['PRICE'].loc[option])
    MSE = np.sum(np.array(option_diffs.values()) ** 2) / len(option_diffs)
    if i % 150 == 0:
        # output every 0th and 100th iteration
        if i == 0:
            print '%12s %13s %4s  %6s  %6s  %6s --> %6s' % \
                 ('pricing_date', 'maturity_date', 'i', 'kappa',
                  'theta', 'vola', 'MSE')
        print '%12s %13s %4d  %6.3f  %6.3f  %6.3f  --> %6.3f' % \
                (pd, mat, i, p0[0], p0[1], p0[2], MSE)
    i += 1
    return MSE

Implementing the Calibration Procedure

The function get_parameter_series calibrates the model to the market data for every date contained in the pricing_date_list object for all maturities contained in the maturity_list object.


In [20]:
import scipy.optimize as spo
def get_parameter_series(pricing_date_list, maturity_list):
    global i, option_selection, vstoxx_model, option_models, first, last
    # collects optimization results for later use (eg. visualization)
    parameters = pd.DataFrame()
    for maturity in maturity_list:
        first = True
        for pricing_date in pricing_date_list:
            option_selection, forward = \
                    get_option_selection(pricing_date, maturity)
            vstoxx_model, option_models = \
                    get_option_models(pricing_date, maturity, option_selection)
            if first is True:
                # use brute force for the first run
                i = 0
                opt = spo.brute(mean_squared_error,
                    ((0.5, 2.51, 1.),   # range for kappa
                     (10., 20.1, 5.),   # range for theta
                     (0.5, 10.51, 5.0)),  # range for volatility
                     finish=None)
            i = 0
            opt = spo.fmin(mean_squared_error, opt,
                 maxiter=200, maxfun=350, xtol=0.0000001, ftol=0.0000001)
            parameters = parameters.append(
                     pd.DataFrame(
                     {'pricing_date' : pricing_date,
                      'maturity' : maturity,
                      'initial_value' : vstoxx_model.initial_value,
                      'kappa' : opt[0],
                      'theta' : opt[1],
                      'sigma' : opt[2],
                      'MSE' : mean_squared_error(opt)}, index=[0,]),
                     ignore_index=True)
            first = False
            last = opt
    return parameters

The Calibration Itself

This completes the set of necessary function to implement such a larger calibration effort. The following code defines the dates for which a calibration shall be conducted and for which maturities the calibration is required.


In [21]:
%%time
pricing_date_list = pd.date_range('2014/3/1', '2014/3/31', freq='B')
maturity_list = [third_fridays[7]]
parameters = get_parameter_series(pricing_date_list, maturity_list)


pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 03-Mar-2014   18-Jul-2014    0   0.500  10.000   0.500  -->  4.507
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 03-Mar-2014   18-Jul-2014    0   2.500  15.000   5.500  -->  0.022
 03-Mar-2014   18-Jul-2014  150   2.490  17.012   4.665  -->  0.005
Optimization terminated successfully.
         Current function value: 0.004840
         Iterations: 146
         Function evaluations: 296
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 04-Mar-2014   18-Jul-2014    0   2.497  17.010   4.674  -->  0.048
 04-Mar-2014   18-Jul-2014  150   2.474  17.633   4.738  -->  0.003
Optimization terminated successfully.
         Current function value: 0.002750
         Iterations: 70
         Function evaluations: 164
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 05-Mar-2014   18-Jul-2014    0   2.474  17.633   4.738  -->  0.008
 05-Mar-2014   18-Jul-2014  150   3.042  17.856   4.919  -->  0.003
 05-Mar-2014   18-Jul-2014  300   4.407  17.995   5.667  -->  0.003
Warning: Maximum number of function evaluations has been exceeded.
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 06-Mar-2014   18-Jul-2014    0   4.407  17.995   5.668  -->  0.004
 06-Mar-2014   18-Jul-2014  150   4.543  18.209   5.661  -->  0.003
Optimization terminated successfully.
         Current function value: 0.003179
         Iterations: 76
         Function evaluations: 175
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 07-Mar-2014   18-Jul-2014    0   4.543  18.209   5.661  -->  0.030
 07-Mar-2014   18-Jul-2014  150   4.958  18.332   5.553  -->  0.005
Optimization terminated successfully.
         Current function value: 0.004775
         Iterations: 84
         Function evaluations: 183
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 10-Mar-2014   18-Jul-2014    0   4.958  18.332   5.553  -->  0.086
 10-Mar-2014   18-Jul-2014  150   4.816  18.733   5.722  -->  0.003
Optimization terminated successfully.
         Current function value: 0.002975
         Iterations: 75
         Function evaluations: 173
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 11-Mar-2014   18-Jul-2014    0   4.816  18.733   5.722  -->  0.006
 11-Mar-2014   18-Jul-2014  150   4.281  19.060   5.162  -->  0.004
Optimization terminated successfully.
         Current function value: 0.004069
         Iterations: 100
         Function evaluations: 210
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 12-Mar-2014   18-Jul-2014    0   4.281  19.060   5.162  -->  0.008
 12-Mar-2014   18-Jul-2014  150   4.461  18.959   5.231  -->  0.005
Optimization terminated successfully.
         Current function value: 0.004915
         Iterations: 67
         Function evaluations: 164
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 13-Mar-2014   18-Jul-2014    0   4.461  18.959   5.231  -->  0.007
 13-Mar-2014   18-Jul-2014  150   4.515  18.920   5.333  -->  0.006
Optimization terminated successfully.
         Current function value: 0.005971
         Iterations: 84
         Function evaluations: 189
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 14-Mar-2014   18-Jul-2014    0   4.515  18.920   5.333  -->  0.017
 14-Mar-2014   18-Jul-2014  150   5.124  18.963   5.952  -->  0.003
Optimization terminated successfully.
         Current function value: 0.002936
         Iterations: 131
         Function evaluations: 280
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 17-Mar-2014   18-Jul-2014    0   5.223  19.002   5.997  -->  0.025
 17-Mar-2014   18-Jul-2014  150   5.330  18.581   6.097  -->  0.004
Optimization terminated successfully.
         Current function value: 0.003809
         Iterations: 81
         Function evaluations: 185
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 18-Mar-2014   18-Jul-2014    0   5.330  18.581   6.097  -->  0.006
 18-Mar-2014   18-Jul-2014  150   3.838  18.503   5.161  -->  0.003
Optimization terminated successfully.
         Current function value: 0.002652
         Iterations: 144
         Function evaluations: 300
 18-Mar-2014   18-Jul-2014  300   3.191  18.288   4.852  -->  0.003
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 19-Mar-2014   18-Jul-2014    0   3.191  18.288   4.852  -->  0.005
 19-Mar-2014   18-Jul-2014  150   3.136  18.084   4.968  -->  0.003
Optimization terminated successfully.
         Current function value: 0.003397
         Iterations: 67
         Function evaluations: 169
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 20-Mar-2014   18-Jul-2014    0   3.136  18.084   4.968  -->  0.010
 20-Mar-2014   18-Jul-2014  150   2.936  18.441   4.849  -->  0.002
Optimization terminated successfully.
         Current function value: 0.002263
         Iterations: 128
         Function evaluations: 267
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 21-Mar-2014   18-Jul-2014    0   2.928  18.450   4.842  -->  0.044
 21-Mar-2014   18-Jul-2014  150   2.935  19.134   4.876  -->  0.004
Optimization terminated successfully.
         Current function value: 0.003655
         Iterations: 64
         Function evaluations: 158
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 24-Mar-2014   18-Jul-2014    0   2.935  19.134   4.876  -->  0.021
 24-Mar-2014   18-Jul-2014  150   5.169  18.555   6.217  -->  0.004
Optimization terminated successfully.
         Current function value: 0.004381
         Iterations: 138
         Function evaluations: 297
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 25-Mar-2014   18-Jul-2014    0   5.653  18.592   6.449  -->  0.014
 25-Mar-2014   18-Jul-2014  150   6.252  18.525   6.554  -->  0.003
Optimization terminated successfully.
         Current function value: 0.002918
         Iterations: 107
         Function evaluations: 231
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 26-Mar-2014   18-Jul-2014    0   6.251  18.525   6.553  -->  0.014
 26-Mar-2014   18-Jul-2014  150   5.189  18.301   6.063  -->  0.003
Optimization terminated successfully.
         Current function value: 0.002839
         Iterations: 107
         Function evaluations: 243
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 27-Mar-2014   18-Jul-2014    0   5.189  18.301   6.063  -->  0.006
 27-Mar-2014   18-Jul-2014  150   5.789  18.693   6.112  -->  0.003
Optimization terminated successfully.
         Current function value: 0.002992
         Iterations: 112
         Function evaluations: 248
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 28-Mar-2014   18-Jul-2014    0   5.788  18.693   6.111  -->  0.003
 28-Mar-2014   18-Jul-2014  150   5.684  18.828   5.974  -->  0.003
Optimization terminated successfully.
         Current function value: 0.002811
         Iterations: 97
         Function evaluations: 216
pricing_date maturity_date    i   kappa   theta    vola -->    MSE
 31-Mar-2014   18-Jul-2014    0   5.683  18.828   5.974  -->  0.009
 31-Mar-2014   18-Jul-2014  150  12.121  18.656   8.053  -->  0.004
 31-Mar-2014   18-Jul-2014  300  15.247  18.578   8.978  -->  0.004
Warning: Maximum number of function evaluations has been exceeded.
CPU times: user 1min 23s, sys: 9.24 s, total: 1min 32s
Wall time: 1min 33s

Calibration Results

The results are now stored in the pandas DataFrame called parameters. We set a new index and inspect the last results. Throughout the MSE is pretty low indicated a good fit of the model to the market quotes.


In [22]:
paramet = parameters.set_index('pricing_date')
paramet.tail()


Out[22]:
MSE initial_value kappa maturity sigma theta
pricing_date
2014-03-25 0.002918 18.2637 6.250875 2014-07-18 6.553352 18.525022
2014-03-26 0.002839 17.5869 5.189260 2014-07-18 6.062754 18.301087
2014-03-27 0.002992 17.6397 5.787693 2014-07-18 6.111093 18.693053
2014-03-28 0.002811 17.0324 5.683422 2014-07-18 5.974289 18.827773
2014-03-31 0.003657 17.6639 15.246458 2014-07-18 8.978325 18.578233

This is also illustrated by the visualization of the time series data for the calibrated/optimal parameter values. The MSE is below 0.01 throughout.


In [23]:
%matplotlib inline
paramet[['kappa', 'theta', 'sigma', 'MSE']].plot(subplots=True, color='b', figsize=(10, 12))
plt.tight_layout()


The following generates a plot of the calibration results for the last calibration day. The absolute price differences are below 0.10 EUR for all options.


In [24]:
index = paramet.index[-1]
opt = np.array(paramet[['kappa', 'theta', 'sigma']].loc[index])
option_selection = get_option_selection(index, maturity_list[0], tol=tol)[0]
model_values = np.sort(np.array(calculate_model_values(opt).values()))[::-1]
import matplotlib.pyplot as plt
%matplotlib inline
fix, (ax1, ax2) = plt.subplots(2, sharex=True, figsize=(8, 8))
strikes = option_selection['STRIKE'].values
ax1.plot(strikes, option_selection['PRICE'], label='market quotes')
ax1.plot(strikes, model_values, 'ro', label='model values')
ax1.set_ylabel('option values')
ax1.grid(True)
ax1.legend(loc=0)
wi = 0.25
ax2.bar(strikes - wi / 2., model_values - option_selection['PRICE'],
        label='market quotes', width=wi)
ax2.grid(True)
ax2.set_ylabel('differences')
ax2.set_xlabel('strikes')


Out[24]:
<matplotlib.text.Text at 0x10d00db50>

Copyright, License & Disclaimer

© Dr. Yves J. Hilpisch | The Python Quants GmbH

DX Analytics (the "dx library") is licensed under the GNU Affero General Public License version 3 or later (see http://www.gnu.org/licenses/).

DX Analytics comes with no representations or warranties, to the extent permitted by applicable law.


http://www.pythonquants.com | analytics@pythonquants.com | http://twitter.com/dyjh

Python Quant Platform | http://quant-platform.com

Derivatives Analytics with Python (Wiley Finance) | http://derivatives-analytics-with-python.com

Python for Finance (O'Reilly) | http://shop.oreilly.com/product/0636920032441.do