diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/analytics/scenarios.py | 92 |
1 files changed, 64 insertions, 28 deletions
diff --git a/python/analytics/scenarios.py b/python/analytics/scenarios.py index 16a7921a..9996d405 100644 --- a/python/analytics/scenarios.py +++ b/python/analytics/scenarios.py @@ -1,16 +1,13 @@ -from analytics import ATMstrike -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 itertools import chain, groupby +from functools import partial, reduce from multiprocessing import Pool from .index_data import _get_singlenames_curves from .curve_trades import curve_shape from scipy.interpolate import RectBivariateSpline -from functools import reduce def run_swaption_scenarios(swaption, date_range, spread_shock, vol_shock, vol_surface, params=["pv"], vol_time_roll=True): @@ -68,8 +65,9 @@ def _aux(portf, curr_vols, params, vs): def MaybePool(nproc): yield Pool(nproc) if nproc > 0 else None + def run_portfolio_scenarios_module(portf, date_range, spread_shock, vol_shock, - vol_surface, nproc=-1, vol_time_roll=True): + vol_surface, nproc=-1, vol_time_roll=True): """computes the pnl of a portfolio for a range of scenarios, but running each component individually """ @@ -77,7 +75,7 @@ def run_portfolio_scenarios_module(portf, date_range, spread_shock, vol_shock, temp_results = [] for inst in portf.swaptions: temp = run_swaption_scenarios(inst, date_range, spread_shock, vol_shock, - vol_surface, params=["pnl", 'delta'], vol_time_roll=True) + vol_surface, params=["pnl", 'delta'], vol_time_roll=True) temp.delta *= inst.notional temp_results.append(temp) results = reduce(lambda x, y: x.add(y, fill_value=0), temp_results) @@ -90,10 +88,24 @@ def run_portfolio_scenarios_module(portf, date_range, spread_shock, vol_shock, results.set_index('vol_shock', append=True) return results.drop(['pnl_idx'], axis=1) - -def run_portfolio_scenarios(portf, date_range, spread_shock, vol_shock, - vol_surface, params=["pnl"], nproc=-1, vol_time_roll=True): +def join_dfs(l_df): + d = {} + # first we concat together dataframes with the same indices + for k, v in groupby(l_df.items(), lambda x: tuple(x[1].index.names)): + keys, dfs = zip(*v) + d[k] = pd.concat(dfs, axis=1, keys=keys).reset_index() + # then we merge them one by one on the common column + # (which should be spread_shock) + dfs = reduce(lambda df1, df2: pd.merge(df1, df2), d.values()) + # then we set back the index + index_names = set() + for k in d.keys(): + index_names |= set(k) + return dfs.set_index(list(index_names)) + + +def run_portfolio_scenarios(portf, date_range, params=["pnl"], **kwargs): """computes the pnl of a portfolio for a range of scenarios Parameters @@ -108,25 +120,49 @@ def run_portfolio_scenarios(portf, date_range, spread_shock, vol_shock, nproc : int if nproc > 0 run with nproc processes. """ - portf = deepcopy(portf) - spreads = np.hstack([index.spread * (1 + spread_shock) for index in portf.indices]) + d = {} + for date in date_range: + portf.value_date = date.date() + d[date] = join_dfs(portf.shock(params, **kwargs)) + return pd.concat(d, names=['date'] + d[date].index.names) - t = [swaption.T for swaption in portf.swaptions] - r = [] - with MaybePool(nproc) as pool: - pmap = pool.map if pool else map - for date in date_range: - portf.value_date = date.date() - if vol_time_roll: - t = [swaption.T for swaption in portf.swaptions] - for s in spreads: - portf.spread = 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', 'vol_shock'] + params) - return df.set_index('date') +# def run_portfolio_scenarios(portf, date_range, spread_shock, vol_shock, +# vol_surface, params=["pnl"], nproc=-1, vol_time_roll=True): +# """computes the pnl of a portfolio for a range of scenarios + +# Parameters +# ---------- +# swaption : Swaption +# date_range : `pandas.Datetime.Index` +# spread_shock : `np.array` +# vol_shock : `np.array` +# 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 = np.hstack([index.spread * (1 + spread_shock) for index in portf.indices]) + +# t = [swaption.T for swaption in portf.swaptions] +# r = [] +# with MaybePool(nproc) as pool: +# pmap = pool.map if pool else map +# for date in date_range: +# portf.value_date = date.date() +# for t in portf.trades: +# d[type(t)] +# if vol_time_roll: +# t = [swaption.T for swaption in portf.swaptions] +# for s in spreads: +# portf.spread = 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', 'vol_shock'] + params) +# return df.set_index('date') def run_tranche_scenarios(tranche, spread_range, date_range, corr_map=False): """computes the pnl of a tranche for a range of spread scenarios |
