Gamma Risk#

Calculation#

Gamma, technically cross-gamma, risks are calculated in rateslib in a very similar manner to delta, albeit the expression of the result is more complicated, since cross-gamma risks are a matrix of values, whereas delta risk is typically a vector.

The output is a DataFrame indexed with a hierarchical index allowing the information to be viewed all at once or sliced using pandas indexing tools.

The below gives a full example of constructing solvers with dependency chains, then constructing a multi-currency portfolio and viewing the gamma risks in local and base currencies.

First we initialise the Curve s. A SOFR, ESTR and cross-currency curve for valuing EUR cashflows collateralized in USD.

In [1]: sofr = Curve(
   ...:     nodes={dt(2022, 1, 1): 1.0, dt(2032, 1, 1): 1.0, dt(2042, 1, 1): 1.0},
   ...:     id="sofr"
   ...: )
   ...: 

In [2]: estr = Curve(
   ...:     nodes={dt(2022, 1, 1): 1.0, dt(2032, 1, 1): 1.0, dt(2042, 1, 1): 1.0},
   ...:     id="estr"
   ...: )
   ...: 

In [3]: eurusd = Curve(
   ...:     nodes={dt(2022, 1, 1): 1.0, dt(2032, 1, 1): 1.0, dt(2042, 1, 1): 1.0},
   ...:     id="eurusd"
   ...: )
   ...: 

Then we define our FXForwards object and associations.

In [4]: fxr = FXRates({"eurusd": 1.05}, settlement=dt(2022, 1, 3))

In [5]: fxf = FXForwards(fxr, {
   ...:     "eureur": estr,
   ...:     "eurusd": eurusd,
   ...:     "usdusd": sofr
   ...: })
   ...: 

Then we define the instruments that will be incorporated into our Solver s.

In [6]: instruments = [
   ...:      IRS(dt(2022, 1, 1), "10y", "A", currency="usd", curves="sofr"),
   ...:      IRS(dt(2032, 1, 1), "10y", "A", currency="usd", curves="sofr"),
   ...:      IRS(dt(2022, 1, 1), "10y", "A", currency="eur", curves="estr"),
   ...:      IRS(dt(2032, 1, 1), "10y", "A", currency="eur", curves="estr"),
   ...:      XCS(dt(2022, 1, 1), "10y", "A", currency="usd", leg2_currency="usd", curves=["estr", "eurusd", "sofr", "sofr"]),
   ...:      XCS(dt(2032, 1, 1), "10y", "A", currency="usd", leg2_currency="eur", curves=["estr", "eurusd", "sofr", "sofr"]),
   ...:  ]
   ...: 

Then we solve the SOFR and ESTR curves independently given local currency swap markets.

In [7]: sofr_solver= Solver(
   ...:     curves=[sofr],
   ...:     instruments=instruments[:2],
   ...:     s=[3.45, 2.85],
   ...:     instrument_labels=["10y", "10y10y"],
   ...:     id="sofr",
   ...:     fx=fxf
   ...: )
   ...: 
SUCCESS: `func_tol` reached after 6 iterations (levenberg_marquardt), `f_val`: 6.1823256691788175e-15, `time`: 0.0229s

In [8]: estr_solver= Solver(
   ...:     curves=[estr],
   ...:     instruments=instruments[2:4],
   ...:     s=[2.25, 0.90],
   ...:     instrument_labels=["10y", "10y10y"],
   ...:     id="estr",
   ...:     fx=fxf
   ...: )
   ...: 
SUCCESS: `func_tol` reached after 6 iterations (levenberg_marquardt), `f_val`: 2.2273797378672649e-13, `time`: 0.0260s

Finally we solve the cross-currency solver with a dependency to the single currency markets, as specified within the pre_solvers argument.

In [9]: solver= Solver(
   ...:     curves=[eurusd],
   ...:     instruments=instruments[4:],
   ...:     s=[-10, -15],
   ...:     instrument_labels=["10y", "10y10y"],
   ...:     id="eurusd",
   ...:     fx=fxf,
   ...:     pre_solvers=[sofr_solver, estr_solver],
   ...: )
   ...: 
SUCCESS: `func_tol` reached after 4 iterations (levenberg_marquardt), `f_val`: 3.01104003064156e-17, `time`: 0.0752s

Now we create a multi-currency Portfolio and calculate its cross-gamma.

In [10]: pf = Portfolio([
   ....:      IRS(dt(2022, 1, 1), "20Y", "A", currency="eur", fixed_rate=2.0, notional=1e8, curves="estr"),
   ....:      IRS(dt(2022, 1, 1), "20Y", "A", currency="usd", fixed_rate=1.5, notional=-1.1e8, curves="sofr")
   ....:  ])
   ....:  cgamma = pf.gamma(solver=solver, base="eur")
   ....:  cgamma
   ....: 
  Cell In[10], line 5
    cgamma = pf.gamma(solver=solver, base="eur")
    ^
IndentationError: unexpected indent

We can slice this to display only the EUR risk.

In [11]: idx = ("eur", "eur", slice(None), ["estr", "fx"], slice(None))

In [12]: cgamma.loc[idx, (slice(None), ["estr", "fx"], slice(None))]
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[12], line 1
----> 1 cgamma.loc[idx, (slice(None), ["estr", "fx"], slice(None))]

NameError: name 'cgamma' is not defined