Quickstart

This brief first part illustrates---without much explanation---the usage of the DX Analytics library. It models two risk factors, two derivatives instruments and values these in a portfolio context.


In [1]:
import dx
import datetime as dt
import pandas as pd
import seaborn as sns; sns.set()

Risk Factor Models

The first step is to define a model for the risk-neutral discounting.


In [2]:
r = dx.constant_short_rate('r', 0.01)

We then define a market environment containing the major parameter specifications needed,


In [3]:
me_1 = dx.market_environment('me', dt.datetime(2015, 1, 1))

In [4]:
me_1.add_constant('initial_value', 100.)
  # starting value of simulated processes
me_1.add_constant('volatility', 0.2)
  # volatiltiy factor
me_1.add_constant('final_date', dt.datetime(2016, 6, 30))
  # horizon for simulation
me_1.add_constant('currency', 'EUR')
  # currency of instrument
me_1.add_constant('frequency', 'W')
  # frequency for discretization
me_1.add_constant('paths', 10000)
  # number of paths
me_1.add_curve('discount_curve', r)
  # number of paths

Next, the model object for the first risk factor, based on the geometric Brownian motion (Black-Scholes-Merton (1973) model).


In [5]:
gbm_1 = dx.geometric_brownian_motion('gbm_1', me_1)

Some paths visualized.


In [6]:
pdf = pd.DataFrame(gbm_1.get_instrument_values(), index=gbm_1.time_grid)

In [7]:
%matplotlib inline
pdf.ix[:, :10].plot(legend=False, figsize=(10, 6))


Out[7]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fb487d5c750>

Second risk factor with higher volatility. We overwrite the respective value in the market environment.


In [8]:
me_2 = dx.market_environment('me_2', me_1.pricing_date)
me_2.add_environment(me_1)  # add complete environment
me_2.add_constant('volatility', 0.5)  # overwrite value

In [9]:
gbm_2 = dx.geometric_brownian_motion('gbm_2', me_2)

In [10]:
pdf = pd.DataFrame(gbm_2.get_instrument_values(), index=gbm_2.time_grid)

In [11]:
pdf.ix[:, :10].plot(legend=False, figsize=(10, 6))


Out[11]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fb487d2fe90>

Valuation Models

Based on the risk factors, we can then define derivatives models for valuation. To this end, we need to add at least one (the maturity), in general two (maturity and strike), parameters to the market environments.


In [12]:
me_opt = dx.market_environment('me_opt', me_1.pricing_date)
me_opt.add_environment(me_1)
me_opt.add_constant('maturity', dt.datetime(2016, 6, 30))
me_opt.add_constant('strike', 110.)

The first derivative is an American put option on the first risk factor gbm_1.


In [13]:
am_put = dx.valuation_mcs_american_single(
            name='am_put',
            underlying=gbm_1,
            mar_env=me_opt,
            payoff_func='np.maximum(strike - instrument_values, 0)')

Let us calculate a Monte Carlo present value estimate and estimates for the major Greeks.


In [14]:
am_put.present_value()


Out[14]:
15.019

In [15]:
am_put.delta()


Out[15]:
-0.539

In [16]:
am_put.vega()


Out[16]:
57.1

The second derivative is a European call option on the second risk factor gbm_2.


In [17]:
eur_call = dx.valuation_mcs_european_single(
            name='eur_call',
            underlying=gbm_2,
            mar_env=me_opt,
            payoff_func='np.maximum(maturity_value - strike, 0)')

Valuation and Greek estimation for this option.


In [18]:
eur_call.present_value()


Out[18]:
20.659128

In [19]:
eur_call.delta()


Out[19]:
0.8459

In [20]:
eur_call.vega()


Out[20]:
48.3196

Options Portfolio

Modeling

In a portfolio context, we need to add information about the model class(es) to be used to the market environments of the risk factors.


In [21]:
me_1.add_constant('model', 'gbm')
me_2.add_constant('model', 'gbm')

To compose a portfolio consisting of our just defined options, we need to define derivatives positions. Note that this step is independent from the risk factor model and option model definitions. We only use the market environment data and some additional information needed (e.g. payoff functions).


In [22]:
put = dx.derivatives_position(
            name='put',
            quantity=2,
            underlyings=['gbm_1'],
            mar_env=me_opt,
            otype='American single',
            payoff_func='np.maximum(strike - instrument_values, 0)')

In [23]:
call = dx.derivatives_position(
            name='call',
            quantity=3,
            underlyings=['gbm_2'],
            mar_env=me_opt,
            otype='European single',
            payoff_func='np.maximum(maturity_value - strike, 0)')

Let us define the relevant market by 2 Python dictionaries, the correlation between the two risk factors and a valuation environment.


In [24]:
risk_factors = {'gbm_1': me_1, 'gbm_2' : me_2}
correlations = [['gbm_1', 'gbm_2', -0.4]]
positions = {'put' : put, 'call' : call}

In [25]:
val_env = dx.market_environment('general', dt.datetime(2015, 1, 1))
val_env.add_constant('frequency', 'W')
val_env.add_constant('paths', 10000)
val_env.add_constant('starting_date', val_env.pricing_date)
val_env.add_constant('final_date', val_env.pricing_date)
val_env.add_curve('discount_curve', r)

These are used to define the derivatives portfolio.


In [26]:
port = dx.derivatives_portfolio(
            name='portfolio',  # name 
            positions=positions,  # derivatives positions
            val_env=val_env,  # valuation environment
            risk_factors=risk_factors, # relevant risk factors
            correlations=correlations, parallel=True)  # correlation between risk factors

Simulation and Valuation

Now, we can get the position values for the portfolio via the get_values method.


In [27]:
port.get_values()


Total
pos_value    91.26292
dtype: float64
Out[27]:
position name quantity otype risk_facts value currency pos_value
0 put put 2 American single [gbm_1] 15.01700 EUR 30.03400
1 call call 3 European single [gbm_2] 20.40964 EUR 61.22892

Via the get_statistics methods delta and vega values are provided as well.


In [28]:
port.get_statistics()


Totals
pos_value     91.26292
pos_delta      0.56440
pos_vega     232.76960
dtype: float64
Out[28]:
position name quantity otype risk_facts value currency pos_value pos_delta pos_vega
0 put put 2 American single [gbm_1] 15.01700 EUR 30.03400 -1.1480 95.0000
1 call call 3 European single [gbm_2] 20.40964 EUR 61.22892 1.7124 137.7696

Much more complex scenarios are possible with DX Analytics

Risk Reports

Having modeled the derivatives portfolio, risk reports are only two method calls away.


In [29]:
deltas, benchvalue = port.get_port_risk(Greek='Delta')


gbm_1
0.8 0.9 1.0 1.1 1.2 
gbm_2
0.8 0.9 1.0 1.1 1.2 



In [30]:
dx.risk_report(deltas)


gbm_1_Delta
           0.8     0.9     1.0     1.1     1.2
factor   80.00   90.00  100.00  110.00  120.00
value   121.91  104.85   91.26   80.74   73.19

gbm_2_Delta
          0.8   0.9     1.0     1.1     1.2
factor  80.00  90.0  100.00  110.00  120.00
value   61.75  75.4   91.26  109.17  128.75

In [31]:
dx.risk_report(deltas.ix[:, :, 'value'] - benchvalue)


gbm_1_Delta
0.8    30.65
0.9    13.59
1.0     0.00
1.1   -10.52
1.2   -18.07
Name: gbm_1_Delta, dtype: float64

gbm_2_Delta
0.8   -29.51
0.9   -15.86
1.0     0.00
1.1    17.91
1.2    37.49
Name: gbm_2_Delta, dtype: float64

In [32]:
vegas, benchvalue = port.get_port_risk(Greek='Vega', step=0.05)


gbm_1
0.8 0.85 0.9 0.95 1.0 1.05 1.1 1.15 1.2 
gbm_2
0.8 0.85 0.9 0.95 1.0 1.05 1.1 1.15 1.2 



In [33]:
dx.risk_report(vegas)


gbm_1_Vega
         0.80   0.85   0.90   0.95   1.00   1.05   1.10   1.15   1.20
factor   0.16   0.17   0.18   0.19   0.20   0.21   0.22   0.23   0.24
value   87.61  88.48  89.36  90.31  91.26  92.21  93.16  94.07  95.02

gbm_2_Vega
         0.80   0.85   0.90   0.95   1.00   1.05   1.10    1.15    1.20
factor   0.40   0.43   0.45   0.48   0.50   0.53   0.55    0.58    0.60
value   77.33  80.84  84.33  87.80  91.26  94.70  98.12  101.51  104.88

In [34]:
dx.risk_report(vegas.ix[:, :, 'value'] - benchvalue)


gbm_1_Vega
0.80   -3.66
0.85   -2.78
0.90   -1.90
0.95   -0.96
1.00    0.00
1.05    0.95
1.10    1.90
1.15    2.81
1.20    3.76
Name: gbm_1_Vega, dtype: float64

gbm_2_Vega
0.80   -13.94
0.85   -10.43
0.90    -6.93
0.95    -3.46
1.00     0.00
1.05     3.44
1.10     6.85
1.15    10.25
1.20    13.62
Name: gbm_2_Vega, dtype: float64

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://tpq.io | team@tpq.io | http://twitter.com/dyjh

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

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

Python for Finance (O'Reilly) | http://python-for-finance.com