The Python Quants

DX Analytics Library

Valuation Classes

In [1]:
from dx import *

Single Risk Factor Classes

There are the following single risk factor valuation classes available:

  • valuation_mcs_european_single
  • valuation_mcs_american_single
In [2]:
r = constant_short_rate('r', 0.06)
In [3]:
me = market_environment('me', dt.datetime(2015, 1, 1))
In [4]:
me.add_constant('initial_value', 36.)
me.add_constant('volatility', 0.2)
me.add_constant('final_date', dt.datetime(2015, 12, 31))
me.add_constant('currency', 'EUR')
me.add_constant('frequency', 'W')
me.add_constant('paths', 25000)
In [5]:
me.add_curve('discount_curve', r)
In [6]:
gbm = geometric_brownian_motion('gbm', me)

valuation_mcs_european_single

In [7]:
me.add_constant('maturity', dt.datetime(2015, 12, 31))
# me.add_constant('strike', 40.)
In [8]:
call_eur = valuation_mcs_european_single('call_eur', gbm, me,
                                  'np.maximum(maturity_value - 40, 0)')
In [9]:
call_eur.present_value()
Out[9]:
2.175997
In [10]:
call_eur.delta()
Out[10]:
0.4444
In [11]:
call_eur.vega()
Out[11]:
14.1882
In [12]:
%%time
s_list = np.arange(34., 46.1, 2.)
pv = []; de = []; ve = []
for s in s_list:
    call_eur.update(s)
    pv.append(call_eur.present_value())
    de.append(call_eur.delta(.5))
    ve.append(call_eur.vega(0.2))
CPU times: user 2.05 s, sys: 231 ms, total: 2.28 s
Wall time: 2.28 s

In [13]:
%matplotlib inline
In [14]:
from dx_plot import *
plot_option_stats(s_list, pv, de, ve)

valuation_mcs_american_single

In [15]:
me.add_constant('initial_value', 36.)
  # reset initial_value
In [16]:
put_ame = valuation_mcs_american_single('put_eur', gbm, me,
                                  'np.maximum(40. - instrument_values, 0)')
In [17]:
put_ame.present_value()
Out[17]:
0.675422
In [18]:
put_ame.delta()
Out[18]:
-0.1538
In [19]:
put_ame.vega()
Out[19]:
10.7465
In [20]:
%%time
s_list = np.arange(34., 46.1, 2.)
pv = []; de = []; ve = []
for s in s_list:
    put_ame.update(s)
    pv.append(put_ame.present_value())
    de.append(put_ame.delta(.5))
    ve.append(put_ame.vega(0.2))
CPU times: user 11.6 s, sys: 576 ms, total: 12.2 s
Wall time: 12.1 s

In [21]:
plot_option_stats(s_list, pv, de, ve)

Portfolio Valuation

These are the classes for portfolio valuation:

  • derivatives_position
  • derivatives_portfolio

derivatives_position

In [22]:
me.add_constant('model', 'gbm')
In [23]:
put = derivatives_position(
                name='put',
                quantity=1,
                underlyings=['gbm'],
                mar_env=me,
                otype='American single',
                payoff_func='np.maximum(40. - instrument_values, 0)')
In [24]:
put.get_info()
NAME
put 

QUANTITY
1 

UNDERLYINGS
['gbm'] 

MARKET ENVIRONMENT

**Constants**
paths 25000
maturity 2015-12-31 00:00:00
initial_value 36.0
currency EUR
frequency W
final_date 2015-12-31 00:00:00
model gbm
volatility 0.2

**Lists**

**Curves**
discount_curve <dx.dx_frame.constant_short_rate object at 0x109305090>

OPTION TYPE
American single 

PAYOFF FUNCTION
np.maximum(40. - instrument_values, 0)

derivatives_portfolio

Uncorrelated Underlyings

In [25]:
me_jump = market_environment('me_jump', dt.datetime(2015, 1, 1))
In [26]:
me_jump.add_environment(me)
me_jump.add_constant('lambda', 0.8)
me_jump.add_constant('mu', -0.8)
me_jump.add_constant('delta', 0.1)
me_jump.add_constant('model', 'jd')
In [27]:
call_jump = derivatives_position('call_jump', 3, ['jd'], me_jump, 'European single',
                      'np.maximum(maturity_value - 36., 0)')
In [28]:
underlyings = {'gbm': me, 'jd' : me_jump}
positions = {'put' : put, 'call_jump' : call_jump}
In [29]:
val_env = market_environment('general', dt.datetime(2015, 1, 1))
val_env.add_constant('frequency', 'M')
val_env.add_constant('paths', 50000)
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)
In [30]:
port = derivatives_portfolio('portfolio', positions, val_env, underlyings)
In [31]:
%%time
port.get_statistics()
CPU times: user 1 s, sys: 189 ms, total: 1.19 s
Wall time: 1.18 s

Out[31]:
position name quantity value currency pos_value pos_delta pos_vega
0 put put 1 4.409976 EUR 4.409976 -0.6523 11.2375
1 call_jump call_jump 3 1.795832 EUR 5.387496 0.9807 18.6639

2 rows × 8 columns

In [32]:
port.get_positions()

--------------------------------------------------
NAME
put 

QUANTITY
1 

UNDERLYINGS
['gbm'] 

MARKET ENVIRONMENT

**Constants**
paths 50000
maturity 2015-12-31 00:00:00
initial_value 36.0
currency EUR
frequency M
final_date 2015-12-31 00:00:00
model gbm
starting_date 2015-01-01 00:00:00
volatility 0.2

**Lists**
time_grid [datetime.datetime(2015, 1, 1, 0, 0) datetime.datetime(2015, 1, 31, 0, 0)
 datetime.datetime(2015, 2, 28, 0, 0) datetime.datetime(2015, 3, 31, 0, 0)
 datetime.datetime(2015, 4, 30, 0, 0) datetime.datetime(2015, 5, 31, 0, 0)
 datetime.datetime(2015, 6, 30, 0, 0) datetime.datetime(2015, 7, 31, 0, 0)
 datetime.datetime(2015, 8, 31, 0, 0) datetime.datetime(2015, 9, 30, 0, 0)
 datetime.datetime(2015, 10, 31, 0, 0)
 datetime.datetime(2015, 11, 30, 0, 0)
 datetime.datetime(2015, 12, 31, 0, 0)]

**Curves**
discount_curve <dx.dx_frame.constant_short_rate object at 0x109305090>

OPTION TYPE
American single 

PAYOFF FUNCTION
np.maximum(40. - instrument_values, 0)

--------------------------------------------------

--------------------------------------------------
NAME
call_jump 

QUANTITY
3 

UNDERLYINGS
['jd'] 

MARKET ENVIRONMENT

**Constants**
paths 50000
lambda 0.8
initial_value 36.0
mu -0.8
currency EUR
frequency M
delta 0.1
final_date 2015-12-31 00:00:00
model jd
volatility 0.2
starting_date 2015-01-01 00:00:00
maturity 2015-12-31 00:00:00

**Lists**
time_grid [datetime.datetime(2015, 1, 1, 0, 0) datetime.datetime(2015, 1, 31, 0, 0)
 datetime.datetime(2015, 2, 28, 0, 0) datetime.datetime(2015, 3, 31, 0, 0)
 datetime.datetime(2015, 4, 30, 0, 0) datetime.datetime(2015, 5, 31, 0, 0)
 datetime.datetime(2015, 6, 30, 0, 0) datetime.datetime(2015, 7, 31, 0, 0)
 datetime.datetime(2015, 8, 31, 0, 0) datetime.datetime(2015, 9, 30, 0, 0)
 datetime.datetime(2015, 10, 31, 0, 0)
 datetime.datetime(2015, 11, 30, 0, 0)
 datetime.datetime(2015, 12, 31, 0, 0)]

**Curves**
discount_curve <dx.dx_frame.constant_short_rate object at 0x109305090>

OPTION TYPE
European single 

PAYOFF FUNCTION
np.maximum(maturity_value - 36., 0)

--------------------------------------------------

Correlated Underlyings

In [33]:
correlations = [['gbm', 'jd', 0.9]]
In [34]:
port = derivatives_portfolio('portfolio', positions, val_env, underlyings,
                 correlations, fixed_seed=True)
In [35]:
port.get_statistics()
Out[35]:
position name quantity value currency pos_value pos_delta pos_vega
0 put put 1 4.414078 EUR 4.414078 -0.6547 11.3350
1 call_jump call_jump 3 1.810719 EUR 5.432157 0.9015 18.6027

2 rows × 8 columns

In [36]:
port.val_env.lists['cholesky_matrix']
Out[36]:
array([[ 1.        ,  0.        ],
       [ 0.9       ,  0.43588989]])
In [37]:
path_no = 0
paths1 = port.underlying_objects['gbm'].get_instrument_values()[:, path_no]
paths2 = port.underlying_objects['jd'].get_instrument_values()[:, path_no]
In [38]:
plt.plot(port.time_grid, paths1, 'r', label='gbm')
plt.plot(port.time_grid, paths2, 'b', label='jd')
plt.gcf().autofmt_xdate()
plt.legend(loc=0); plt.grid(True)
# highly correlated underlyings -- until a jump occurs