Parallel Valuation of Large Portfolios ====================================== Derivatives (portfolio) valuation by Monte Carlo simulation is a **computationally demanding task**. For practical applications, when valuation speed plays an important role, **parallelization of both simulation and valuation tasks** might prove a useful strategy. DX Analytics has built in a basic parallelization option which allows the use of the Python ``mulitprocessing`` module. Depending on the tasks at hand this can already lead to significant speed-ups. .. code:: python from dx import * import time import matplotlib.pyplot as plt import seaborn as sns; sns.set() %matplotlib inline Single Risk Factor ------------------ The example is based on a **single risk factor**, a ``geometric_brownian_motion`` object. .. code:: python # constant short rate r = constant_short_rate('r', 0.02) .. code:: python # market environments me_gbm = market_environment('gbm', dt.datetime(2015, 1, 1)) .. code:: python # geometric Brownian motion me_gbm.add_constant('initial_value', 100.) me_gbm.add_constant('volatility', 0.2) me_gbm.add_constant('currency', 'EUR') me_gbm.add_constant('model', 'gbm') .. code:: python # valuation environment val_env = market_environment('val_env', dt.datetime(2015, 1, 1)) val_env.add_constant('paths', 25000) val_env.add_constant('frequency', 'M') val_env.add_curve('discount_curve', r) val_env.add_constant('starting_date', dt.datetime(2015, 1, 1)) val_env.add_constant('final_date', dt.datetime(2015, 12, 31)) .. code:: python # add valuation environment to market environments me_gbm.add_environment(val_env) .. code:: python risk_factors = {'gbm' : me_gbm} American Put Option ------------------- We also model only a **single derivative instrument**. .. code:: python gbm = geometric_brownian_motion('gbm_obj', me_gbm) .. code:: python me_put = market_environment('put', dt.datetime(2015, 1, 1)) me_put.add_constant('maturity', dt.datetime(2015, 12, 31)) me_put.add_constant('strike', 40.) me_put.add_constant('currency', 'EUR') me_put.add_environment(val_env) .. code:: python am_put = valuation_mcs_american_single( 'am_put', mar_env=me_put, underlying=gbm, payoff_func='np.maximum(strike - instrument_values, 0)') Large Portfolio --------------- However, the ``derivatives_portfolio`` object we compose consists of **100 derivatives positions**. Each option differes with respect to the strike. .. code:: python positions = {} strikes = np.linspace(80, 120, 100) for i, strike in enumerate(strikes): positions[i] = derivatives_position( name='am_put_pos_%s' % strike, quantity=1, underlyings=['gbm'], mar_env=me_put, otype='American single', payoff_func='np.maximum(%5.3f - instrument_values, 0)' % strike) Sequential Valuation ~~~~~~~~~~~~~~~~~~~~ First, the derivatives portfolio with **sequential valuation**. .. code:: python port_sequ = derivatives_portfolio( name='portfolio', positions=positions, val_env=val_env, risk_factors=risk_factors, correlations=None, parallel=False) # sequential calculation The call of the ``get_values`` method to **value all instruments** ... .. code:: python t0 = time.time() ress = port_sequ.get_values() ts = time.time() - t0 print "Time in sec %.2f" % ts .. parsed-literal:: Total pos_value 839.603 dtype: float64 Time in sec 4.86 ... and the **results visualized**. .. code:: python ress['strike'] = strikes ress.set_index('strike')['value'].plot(figsize=(10, 6)) plt.ylabel('option value estimates') .. parsed-literal:: .. image:: 06_dx_portfolio_parallel_files/06_dx_portfolio_parallel_26_1.png Parallel Valuation ~~~~~~~~~~~~~~~~~~ Second, the derivatives portfolio with **parallel valuation**. .. code:: python port_para = derivatives_portfolio( 'portfolio', positions, val_env, risk_factors, correlations=None, parallel=True) # parallel valuation The call of the ``get_values`` method for the parall valuation case. .. code:: python t0 = time.time() resp = port_para.get_values() # parallel valuation with as many cores as available tp = time.time() - t0 print "Time in sec %.2f" % tp .. parsed-literal:: Total pos_value 840.238 dtype: float64 Time in sec 2.82 Again, the **results visualized** (and compared to the sequential results). .. code:: python plt.figure(figsize=(10, 6)) plt.plot(strikes, resp['value'].values, 'r.', label='parallel') plt.plot(strikes, ress['value'].values, 'b', label='sequential') plt.legend(loc=0) plt.ylabel('option value estimates') .. parsed-literal:: .. image:: 06_dx_portfolio_parallel_files/06_dx_portfolio_parallel_33_1.png Speed.up ~~~~~~~~ The **realized speed-up** is of course dependend on the hardware used, and in particular the number of cores (threads) available. .. code:: python ts / tp # speed-up factor # of course harware-dependent .. parsed-literal:: 1.7246142546350862 .. code:: python wi = 0.4 plt.figure(figsize=(10, 6)) plt.bar((1.5 - wi/2, 2.5 - wi/2), (ts/ts, tp/ts), width=wi) plt.xticks((1.5, 2.5), ('sequential', 'parallel')) plt.ylim(0, 1.1), plt.xlim(0.75, 3.25) plt.ylabel('relative performance (lower = better)') plt.title('DX Analytics Portfolio Valuation') .. parsed-literal:: .. image:: 06_dx_portfolio_parallel_files/06_dx_portfolio_parallel_37_1.png **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