diff options
Diffstat (limited to 'python/analytics/scenarios.py')
| -rw-r--r-- | python/analytics/scenarios.py | 53 |
1 files changed, 35 insertions, 18 deletions
diff --git a/python/analytics/scenarios.py b/python/analytics/scenarios.py index 1a99562d..0c132076 100644 --- a/python/analytics/scenarios.py +++ b/python/analytics/scenarios.py @@ -3,6 +3,10 @@ from joblib import delayed, Parallel import pandas as pd from copy import deepcopy import numpy as np +from contextlib import contextmanager +from itertools import chain +from functools import partial +from multiprocessing import Pool def run_swaption_scenarios(swaption, date_range, spread_shock, vol_shock, vol_surface, params=["pv"]): @@ -21,12 +25,13 @@ def run_swaption_scenarios(swaption, date_range, spread_shock, vol_shock, swaption = deepcopy(swaption) spreads = swaption.ref * (1 + spread_shock) + r = [] for date in date_range: swaption.index.trade_date = date.date() T = swaption.T for s in spreads: swaption.ref = s - curr_vol = float(max(0, vol_surface(T, swaption.moneyness))) + curr_vol = max(0, float(vol_surface(T, swaption.moneyness))) for vs in vol_shock: swaption.sigma = curr_vol * (1 + vs) r.append([date, s, vs] + [getattr(swaption, p) for p in params]) @@ -34,7 +39,7 @@ def run_swaption_scenarios(swaption, date_range, spread_shock, vol_shock, return df.set_index('date') -def run_index_scenarios(index, date_range, spread_shock): +def run_index_scenarios(index, date_range, spread_shock, params=['pnl']): index = deepcopy(index) spreads = index.spread * (1 + spread_shock) @@ -43,12 +48,21 @@ def run_index_scenarios(index, date_range, spread_shock): index.trade_date = date.date() for s in spreads: index.spread = s - r.append([date, s, index.pnl]) - df = pd.DataFrame.from_records(r, columns=['date', 'spread_shock', 'pnl']) + r.append([date, s] + [getattr(index, p) for p in params]) + df = pd.DataFrame.from_records(r, columns=['date', 'spread_shock'] + params) return df.set_index('date') -def run_portfolio_scenarios(portf, date_range, spread_shock, vol_shock, - vol_surface, params=["pnl"]): +def _aux(portf, curr_vols, params, vs): + for swaption, curr_vol in zip(portf.swaptions, curr_vols): + swaption.sigma = curr_vol * (1 + vs) + return [vs] + [getattr(portf, p) for p in params] + +@contextmanager +def MaybePool(nproc): + yield Pool(nproc) if nproc > 0 else None + +def run_portfolio_scenarios_multiproc(portf, date_range, spread_shock, vol_shock, + vol_surface, params=["pnl"], nproc=-1): """computes the pnl of a portfolio for a range of scenarios Parameters @@ -60,20 +74,23 @@ def run_portfolio_scenarios(portf, date_range, spread_shock, vol_shock, vol_surface : VolSurface params : list of strings list of attributes to call on the Portfolio object. + nproc : int + if nproc > 0 run with nproc processes. """ portf = deepcopy(portf) spreads = portf.index.spread * (1 + spread_shock) + r = [] - for date in date_range: - portf.index.trade_date = date.date() - t = [swaption.T for swaption in portf.swaptions] - mon = [swaption.moneyness for swaption in portf.swaptions] - curr_vols = np.maximum(vol_surface.ev(t, mon), 0) - for s in spreads: - portf.index.ref = s - for vs in vol_shock: - for swaption, curr_vol in zip(portf.swaptions, curr_vols): - swaption.sigma = curr_vol * (1 + vs) - r.append([date, s, vs] + [getattr(portf, p) for p in params]) - df = pd.DataFrame.from_records(r, columns=['date', 'spread_shock', 'vol_shock'] + params) + with MaybePool(nproc) as pool: + pmap = pool.map if pool else map + for date in date_range: + portf.index.trade_date = date.date() + t = [swaption.T for swaption in portf.swaptions] + for s in spreads: + portf.index.ref = s + mon = [swaption.moneyness for swaption in portf.swaptions] + curr_vols = np.maximum(vol_surface.ev(t, mon), 0) + temp = pmap(partial(_aux, portf, curr_vols, params), vol_shock) + r.append([[date, s] + rec for rec in temp]) + df = pd.DataFrame.from_records(chain(*r), columns=['date', 'spread_shock', 'vol_shock'] + params) return df.set_index('date') |
