diff options
| -rw-r--r-- | python/exploration/tranches.py | 76 | ||||
| -rw-r--r-- | python/notebooks/tranche and swaption portfolio strategy.ipynb | 205 |
2 files changed, 206 insertions, 75 deletions
diff --git a/python/exploration/tranches.py b/python/exploration/tranches.py index 430e8492..a8e8d05e 100644 --- a/python/exploration/tranches.py +++ b/python/exploration/tranches.py @@ -9,7 +9,6 @@ import pandas as pd from analytics import Swaption, BlackSwaption, Index, BlackSwaptionVolSurface, Portfolio, ProbSurface from analytics.scenarios import run_swaption_scenarios, run_index_scenarios, run_portfolio_scenarios, run_tranche_scenarios -import exploration.swaption_calendar_spread as spread from scipy.interpolate import interp1d from datetime import date @@ -77,7 +76,7 @@ def dispersion(): maturities = {} settings = Settings() for series in [24, 25, 26, 27, 28, 29]: - index_temp = idx_bkt.MarkitBasketIndex('IG', series, ["5yr",], trade_date=trade_date) + index_temp = idx_bkt.MarkitBasketIndex('IG', series, ["5yr",], value_date=trade_date) maturities[series] = index_temp.maturities[0] cds_schedule = Schedule.from_rule(settings.evaluation_date, Date.from_datetime(maturities[series]), Period('3M'), WeekendsOnly(), date_generation_rule=Rule.CDS2015) @@ -95,76 +94,3 @@ def dispersion(): dispersion = pd.concat(disp) curve_df.groupby(['series', 'maturity']).mean() curve_df.groupby(['series', 'maturity']).std() - -def run_scen(portf, tranche, spread_shock): - - #Start with swaptions - index = portf.indices[0].index_type - series = portf.indices[0].series - trade_date=portf.indices[0].trade_date - - earliest_expiry = min(portf.swaptions, key=lambda x: x.exercise_date).exercise_date - date_range = pd.bdate_range(trade_date, earliest_expiry - pd.offsets.BDay(), freq='5B') - vs = BlackSwaptionVolSurface(index,series, trade_date=trade_date) - ps = ProbSurface(index,series, trade_date=trade_date) - vol_surface = vs[vs.list(option_type='payer')[-1]] - df = run_portfolio_scenarios(portf, date_range, spread_shock, np.array([0]), - vol_surface, params=["pnl", "delta"]) - df['frac_year'] = (df.index - pd.to_datetime(trade_date)).days/365 - df['prob'] = df.apply(lambda df: ps.tail_prob(df.frac_year, df.spread, ps.list()[-1]), axis=1) - - #now do the tranches - spread_range = (1+ spread_shock) * portf.indices[0].spread - results = run_tranche_scenarios(tranche, spread_range, date_range) - results.date = pd.to_datetime(results.date) - notional = 10000000 - results['delta_tranche'] = -notional * (results['0-3_delta'] - 6* results['7-15_delta']) - results['pnl_tranche'] = notional * (results['0-3_pnl'] + results['0-3_carry'] - - 6* (results['7-15_pnl'] + results['7-15_carry'])) - results.index.name = 'spread' - - #combine - df = df.reset_index().merge(results.reset_index(), on=['date', 'spread']) - df['final_pnl'] = df.pnl_tranche + df.pnl - df['final_delta'] = df.delta_tranche + df.delta - - return df - -def set_port(): - - #Construct Portfolio - option_delta = Index.from_name('IG', 30, '5yr') - option_delta.spread = 59 - - option1 = BlackSwaption(option_delta, date(2018, 6, 20), 80, option_type="payer") - option1.sigma = .621 - option1.direction = 'Short' - - option1.notional = 150_000_000 - option_delta.notional = 1 - - portf = Portfolio([option1, option_delta]) - portf.reset_pv() - trade_date = (pd.datetime.today() - pd.offsets.BDay(1)).normalize() - tranche = bkt.TrancheBasket('IG', 29, '5yr', trade_date=trade_date) - - return portf, tranche - -def set_df(): - - portf, tranche = set_port() - - shock_min = -.3 - shock_max = .8 - spread_shock = np.arange(shock_min, shock_max, 0.05) - shock_range = (1+ spread_shock) * portf.indices[0].spread - - results = run_scen(portf, tranche, spread_shock) - results = results.set_index('date') - return results, shock_range - -def plot_scenarios(): - - df, shock_range = set_df() - plot_time_color_map(df, shock_range, attr="final_pnl") - plot_time_color_map(df, shock_range, attr="final_delta", color_map= 'rainbow', centered = False) diff --git a/python/notebooks/tranche and swaption portfolio strategy.ipynb b/python/notebooks/tranche and swaption portfolio strategy.ipynb new file mode 100644 index 00000000..8e73f973 --- /dev/null +++ b/python/notebooks/tranche and swaption portfolio strategy.ipynb @@ -0,0 +1,205 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import analytics.tranche_basket as bkt\n", + "import pandas as pd\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "from analytics.scenarios import run_tranche_scenarios, run_portfolio_scenarios\n", + "from analytics import Swaption, BlackSwaption, Index, BlackSwaptionVolSurface, Portfolio, ProbSurface\n", + "from db import dbengine\n", + "from datetime import date\n", + "from graphics import plot_time_color_map\n", + "\n", + "dawnengine = dbengine('dawndb')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "value_date = (pd.datetime.today() - pd.offsets.BDay(1)).date()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#Construct IG Swaption Portfolio\n", + "index = 'IG'\n", + "series = 30\n", + "option_delta = Index.from_name(index, series, '5yr')\n", + "option_delta.spread = 65\n", + "option1 = BlackSwaption(option_delta, date(2018, 10, 17), 60, option_type=\"payer\")\n", + "option1.sigma = .398\n", + "option1.direction = 'Long'\n", + "option2 = BlackSwaption(option_delta, date(2018, 10, 17), 100, option_type=\"payer\")\n", + "option2.sigma = .609\n", + "option2.direction = 'Short'\n", + "option1.notional = 100_000_000\n", + "option2.notional = 300_000_000\n", + "option_delta.notional = option1.notional * option1.delta + option2.notional * option2.delta\n", + "\n", + "portf = Portfolio([option1, option2, option_delta])\n", + "portf.value_date = value_date\n", + "portf.reset_pv()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#Run Swaption sensitivities\n", + "#Set Shock range\n", + "shock_min = -.3\n", + "shock_max = 1.5\n", + "spread_shock = np.arange(shock_min, shock_max, 0.05)\n", + "#Set Date range\n", + "earliest_expiry = min(portf.swaptions, key=lambda x: x.exercise_date).exercise_date\n", + "date_range = pd.bdate_range(value_date, earliest_expiry - pd.offsets.BDay(), freq='20B')\n", + "#Setup Vol Surface\n", + "vs = BlackSwaptionVolSurface(index,series, value_date=value_date)\n", + "ps = ProbSurface(index,series, value_date=value_date)\n", + "vol_surface = vs[vs.list(option_type='payer')[-1]]\n", + "swaption_scens = run_portfolio_scenarios(portf, date_range, spread_shock, np.array([0]),\n", + " vol_surface, params=[\"pnl\", \"delta\"])\n", + "#swaption delta is in protection terms: switch to risk terms\n", + "swaption_scens.delta = -swaption_scens.delta" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#Get current Tranche positions\n", + "sql_string = \"select * from list_tranche_marks(%s)\"\n", + "pos = pd.read_sql_query(sql_string, dawnengine, params=(value_date,), parse_dates=['maturity'])\n", + "tranche_port = []\n", + "for i, r in pos.iterrows():\n", + " tranche_port.append(bkt.TrancheBasket(r.p_index, r.p_series, '5yr'))\n", + " tranche_port[i].build_skew()\n", + "pos['basket'] = tranche_port\n", + "#Set Shock Range\n", + "spread_range = (1+ spread_shock) * option_delta.spread\n", + "#Run tranche scenarios\n", + "temp = []\n", + "for i, r in pos.iterrows():\n", + " df = run_tranche_scenarios(r.basket, spread_range, date_range, corr_map=False)\n", + " temp.append(r.notional*df.xs(str(r.attach) + \"-\" + str(r.detach), axis=1, level=1))\n", + "tranches_scens = sum(temp)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "total_scens = swaption_scens.reset_index().merge(tranches_scens.reset_index(), \n", + " left_on=['date', 'spread'], \n", + " right_on=['date', 'spread_range'], \n", + " suffixes=['_s', '_t'])\n", + "total_scens['pnl'] = total_scens['pnl_s'] + total_scens['pnl_t']\n", + "total_scens['delta'] = total_scens['delta_s'] + total_scens['delta_t']\n", + "total_scens_single_date = total_scens.set_index('date').xs(date_range[0])\n", + "total_scens_single_date = total_scens_single_date.set_index('spread', drop=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#tranche positions delta at different spreads \n", + "ax = total_scens_single_date.delta_t.plot()\n", + "ax.ticklabel_format(style='plain')\n", + "plt.tight_layout()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#Tranche + Swaptions positions delta at different spreads\n", + "ax1 = total_scens_single_date.delta.plot()\n", + "ax1.ticklabel_format(style='plain')\n", + "plt.tight_layout()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "total_scens_single_date[['delta', 'delta_t', 'delta_s']].plot()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "total_scens_single_date[['pnl', 'pnl_t', 'pnl_s']].plot()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "total_scens.date = pd.to_datetime(total_scens.date)\n", + "total_scens = total_scens.set_index(['date'])\n", + "plot_time_color_map(total_scens, spread_range, attr=\"pnl\")\n", + "#plot_time_color_map(df, shock_range, attr=\"final_delta\", color_map= 'rainbow', centered = False)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} |
