Fixings Exposures and Reset Ladders#
Every Instrument that has an exposure to a floating interest rate contains a method that will obtain the risk and specific notional equivalent for an individual fixing. This is a very useful display for fixed income rates derivative trading.
The column headers for the resultant DataFrames will be dynamically determined from the id
of the Curve which forecasts the exposed fixing.
# Setup some Curves against which fixing exposure will be measured
In [1]: estr = Curve({dt(2000, 1, 1): 1.0, dt(2005, 1, 1): 0.95}, calendar="tgt", id="estr", convention="act360")
In [2]: euribor1m = Curve({dt(2000, 1, 1): 1.0, dt(2005, 1, 1): 0.95}, calendar="tgt", id="euribor1m", convention="act360")
In [3]: euribor3m = Curve({dt(2000, 1, 1): 1.0, dt(2005, 1, 1): 0.95}, calendar="tgt", id="euribor3m", convention="act360")
In [4]: euribor6m = Curve({dt(2000, 1, 1): 1.0, dt(2005, 1, 1): 0.95}, calendar="tgt", id="euribor6m", convention="act360")
An IRS has exposure only via its FloatLeg
.
In [5]: irs = IRS(
...: effective=dt(2000, 1, 10),
...: termination="1w",
...: spec="eur_irs",
...: curves=estr,
...: notional=2e6,
...: )
...:
In [6]: irs.fixings_table()
Out[6]:
estr
notional risk dcf rates
obs_dates
2000-01-10 1999943.85 0.56 0.00 1.01
2000-01-11 2000000.00 0.56 0.00 1.01
2000-01-12 2000056.15 0.56 0.00 1.01
2000-01-13 2000112.30 0.56 0.00 1.01
2000-01-14 2000168.46 1.67 0.01 1.01
A ZCS has exposure only via its ZeroFloatLeg
.
In [7]: zcs = ZCS(
...: effective=dt(2000, 1, 10),
...: termination="4m",
...: frequency="M",
...: convention="act360",
...: leg2_fixing_method="ibor",
...: leg2_method_param=2,
...: curves=[euribor1m, estr],
...: notional=1.5e6,
...: )
...:
In [8]: zcs.fixings_table()
Out[8]:
euribor1m
notional risk dcf rates
obs_dates
2000-01-06 1499915.78 12.90 0.09 1.01
2000-02-08 1501221.77 12.07 0.08 1.01
2000-03-08 1502444.53 12.90 0.09 1.01
2000-04-06 1503752.72 12.49 0.08 1.01
An SBS has exposure on each one of its two FloatLeg
.
In [9]: sbs = SBS(
...: effective=dt(2000, 1, 6),
...: termination="6m",
...: spec="eur_sbs36",
...: curves=[euribor3m, estr, euribor6m, estr],
...: notional=3e6,
...: )
...:
In [10]: sbs.fixings_table()
Out[10]:
euribor3m euribor6m
notional risk dcf rates notional risk dcf rates
obs_dates
2000-01-04 -3000000.00 -75.63 0.25 1.01 3000000.00 150.87 0.51 1.01
2000-04-04 -3000000.00 -75.44 0.25 1.01 NaN NaN NaN NaN
An IIRS has exposure only via its FloatLeg
.
In [11]: iirs = IIRS(
....: effective=dt(2000, 1, 10),
....: termination="3m",
....: frequency="M",
....: index_base=100.0,
....: index_lag=3,
....: leg2_fixing_method="ibor",
....: leg2_method_param=2,
....: curves=[estr, estr, euribor1m, estr],
....: notional=4e6,
....: )
....:
In [12]: iirs.fixings_table()
Out[12]:
euribor1m
notional risk dcf rates
obs_dates
2000-01-06 3944983.96 33.93 0.09 1.01
2000-02-08 3944983.96 31.72 0.08 1.01
2000-03-08 3944983.96 33.88 0.09 1.01
A FRA has exposure only via its modified FloatPeriod
.
In [13]: fra = FRA(
....: effective=get_imm(code="H0"),
....: termination=get_imm(code="M0"),
....: roll="imm",
....: spec="eur_fra3",
....: curves=[euribor3m, estr],
....: notional=5e6,
....: )
....:
In [14]: fra.fixings_table()
Out[14]:
euribor3m
notional risk dcf rates
obs_dates
2000-03-13 5325191.08 135.46 0.26 1.01
A XCS has exposure only via its FloatLeg
or
FloatLegMtm
. Any FixedLegs will not contribute.
In [15]: sofr = Curve({dt(2000, 1, 1): 1.0, dt(2005, 1, 1): 0.93}, calendar="nyc", id="sofr", convention="act360")
In [16]: xcs = XCS(
....: effective=dt(2000, 1, 7),
....: termination="9m",
....: spec="eurusd_xcs",
....: leg2_fixed=True,
....: leg2_mtm=False,
....: fixing_method="ibor",
....: method_param=2,
....: curves=[euribor3m, estr, sofr, sofr],
....: notional=1e6,
....: )
....:
In [17]: xcs.fixings_table()
Out[17]:
euribor3m
notional risk dcf rates
obs_dates
2000-01-05 -999887.71 -25.21 0.25 1.01
2000-04-05 -999887.71 -25.14 0.25 1.01
2000-07-05 -1010553.18 -26.18 0.26 1.01
A STIRFuture has exposure only due to its modified FloatPeriod
.
In [18]: stir = STIRFuture(
....: effective=get_imm(code="H0"),
....: termination="3m",
....: spec="eur_stir3",
....: curves=[euribor3m],
....: contracts=10,
....: )
....:
In [19]: stir.fixings_table()
Out[19]:
euribor3m
notional risk dcf rates
obs_dates
2000-03-13 -9828306.70 -250.00 0.26 1.01
A FloatRateNote has exposure only to its FloatLeg
.
In [20]: frn = FloatRateNote(
....: effective=dt(2000, 1, 13),
....: termination="6m",
....: frequency="Q",
....: fixing_method="ibor",
....: method_param=2,
....: float_spread=120.0,
....: curves=[euribor3m, estr]
....: )
....:
In [21]: frn.fixings_table()
Out[21]:
euribor3m
notional risk dcf rates
obs_dates
2000-01-11 -986301.37 -24.86 0.25 2.21
2000-04-11 -986301.37 -24.80 0.25 2.21
Performance: approximate
and right
#
Calculating fixings exposures, particularly for every daily RFR rate, is an expensive calculation.
The performance can be improved by firstly using approximate
which yields almost exactly
the same results but performs a faster, more generic calculation, and also using the right
bound, which avoids doing any calculation for exposures out-of-scope.
In [22]: irs = IRS(
....: effective=dt(2000, 1, 10),
....: termination="4y",
....: spec="eur_irs",
....: curves=estr,
....: notional=2e6,
....: )
....:
In [23]: irs.fixings_table(approximate=True, right=dt(2000, 1, 24))
Out[23]:
estr
notional risk dcf rates
obs_dates
2000-01-10 1999943.85 0.56 0.00 1.02
2000-01-11 2000000.00 0.56 0.00 1.02
2000-01-12 2000056.15 0.56 0.00 1.02
2000-01-13 2000112.30 0.56 0.00 1.02
2000-01-14 2000280.77 1.67 0.01 1.02
2000-01-17 2000336.93 0.56 0.00 1.02
2000-01-18 2000393.09 0.56 0.00 1.02
2000-01-19 2000449.25 0.56 0.00 1.02
2000-01-20 2000505.42 0.56 0.00 1.02
2000-01-21 2000673.92 1.67 0.01 1.02
2000-01-24 2000730.09 0.56 0.00 1.02
In [24]: zcs = ZCS(
....: effective=dt(2000, 1, 10),
....: termination="1y",
....: frequency="M",
....: convention="act360",
....: leg2_fixing_method="ibor",
....: leg2_method_param=2,
....: curves=[euribor1m, estr],
....: notional=1.5e6,
....: )
....:
In [25]: zcs.fixings_table(approximate=True, right=dt(2000, 3, 17))
Out[25]:
euribor1m
notional risk dcf rates
obs_dates
2000-01-06 1499915.85 12.90 0.09 1.01
2000-02-08 1501221.84 12.07 0.08 1.01
2000-03-08 1502444.60 12.90 0.09 1.01
In [26]: sbs = SBS(
....: effective=dt(2000, 1, 6),
....: termination="1y",
....: spec="eur_sbs36",
....: curves=[euribor3m, estr, euribor6m, estr],
....: notional=3e6,
....: )
....:
In [27]: sbs.fixings_table(approximate=True, right=dt(2000, 8, 16))
Out[27]:
euribor3m euribor6m
notional risk dcf rates notional risk dcf rates
obs_dates
2000-01-04 -3000000.00 -75.63 0.25 1.01 3000000.00 150.87 0.51 1.01
2000-04-04 -3000000.00 -75.44 0.25 1.01 NaN NaN NaN NaN
2000-07-04 -3000000.00 -76.07 0.26 1.01 3000000.00 153.39 0.52 1.01
In [28]: iirs = IIRS(
....: effective=dt(2000, 1, 10),
....: termination="1y",
....: frequency="M",
....: index_base=100.0,
....: index_lag=3,
....: leg2_fixing_method="ibor",
....: leg2_method_param=2,
....: curves=[estr, estr, euribor1m, estr],
....: notional=4e6,
....: )
....:
In [29]: iirs.fixings_table(approximate=True, right=dt(2000, 8, 16))
Out[29]:
euribor1m
notional risk dcf rates
obs_dates
2000-01-06 3944983.96 33.93 0.09 1.01
2000-02-08 3944983.96 31.72 0.08 1.01
2000-03-08 3944983.96 33.88 0.09 1.01
2000-04-06 3944983.96 32.76 0.08 1.01
2000-05-08 3706102.12 33.82 0.09 1.01
2000-06-08 3944983.96 32.70 0.08 1.01
2000-07-06 3944983.96 33.76 0.09 1.01
2000-08-08 3821810.51 33.73 0.09 1.01
In [30]: fra = FRA(
....: effective=get_imm(code="H0"),
....: termination=get_imm(code="M0"),
....: roll="imm",
....: spec="eur_fra3",
....: curves=[euribor3m, estr],
....: notional=5e6,
....: )
....:
In [31]: fra.fixings_table(approximate=True, right=dt(2000, 8, 16))
Out[31]:
euribor3m
notional risk dcf rates
obs_dates
2000-03-13 5325191.08 135.46 0.26 1.01
In [32]: sofr = Curve({dt(2000, 1, 1): 1.0, dt(2005, 1, 1): 0.93}, calendar="nyc", id="sofr", convention="act360")
In [33]: xcs = XCS(
....: effective=dt(2000, 1, 7),
....: termination="2y",
....: spec="eurusd_xcs",
....: leg2_fixed=True,
....: leg2_mtm=False,
....: fixing_method="ibor",
....: method_param=2,
....: curves=[euribor3m, estr, sofr, sofr],
....: notional=1e6,
....: )
....:
In [34]: xcs.fixings_table(approximate=True, right=dt(2000, 8, 16))
Out[34]:
euribor3m
notional risk dcf rates
obs_dates
2000-01-05 -999887.71 -25.21 0.25 1.01
2000-04-05 -999887.71 -25.14 0.25 1.01
2000-07-05 -1010553.18 -26.18 0.26 1.01
In [35]: stir = STIRFuture(
....: effective=get_imm(code="H0"),
....: termination="3m",
....: spec="eur_stir3",
....: curves=[euribor3m],
....: contracts=10,
....: )
....:
In [36]: stir.fixings_table(approximate=True, right=dt(2000, 8, 16))
Out[36]:
euribor3m
notional risk dcf rates
obs_dates
2000-03-13 -9828306.70 -250.00 0.26 1.01
In [37]: frn = FloatRateNote(
....: effective=dt(2000, 1, 13),
....: termination="2y",
....: frequency="Q",
....: fixing_method="ibor",
....: method_param=2,
....: float_spread=120.0,
....: curves=[euribor3m, estr]
....: )
....:
In [38]: frn.fixings_table(approximate=True, right=dt(2000, 8, 16))
Out[38]:
euribor3m
notional risk dcf rates
obs_dates
2000-01-11 -986301.37 -24.86 0.25 2.21
2000-04-11 -986301.37 -24.80 0.25 2.21
2000-07-11 -986301.37 -25.00 0.26 2.21
Aggregation of fixings exposures#
Adding many Instruments to a Portfolio
, provided those
Instruments have been properly configured, allows their fixing exposures to be
analysed and aggregated. Instruments with no fixing exposures, such as a FixedRateBond,
will simply be ignored.
In [39]: frb = FixedRateBond(dt(2000, 1, 3), "10y", fixed_rate=2.5, spec="us_gb")
In [40]: pf = Portfolio([irs, sbs, fra, xcs, frn, stir, iirs, zcs, frb])
In [41]: pf.fixings_table(approximate=True, right=dt(2000, 8, 1))
Out[41]:
estr euribor3m euribor6m euribor1m
notional risk dcf rates notional risk dcf rates notional risk dcf rates notional risk dcf rates
obs_dates
2000-01-04 NaN NaN NaN NaN -3000000.00 -75.63 0.25 1.01 3000000.00 150.87 0.51 1.01 NaN NaN NaN NaN
2000-01-05 NaN NaN NaN NaN -999887.71 -25.21 0.25 1.01 NaN NaN NaN NaN NaN NaN NaN NaN
2000-01-06 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 5444899.81 46.83 0.09 1.01
2000-01-10 1999943.85 0.56 0.00 1.02 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2000-01-11 2000000.00 0.56 0.00 1.02 -986301.37 -24.86 0.25 2.21 NaN NaN NaN NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2000-07-26 2011092.25 0.56 0.00 1.02 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2000-07-27 2011148.72 0.56 0.00 1.02 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2000-07-28 2011318.11 1.67 0.01 1.02 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2000-07-31 2011374.58 0.56 0.00 1.02 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2000-08-01 2011431.05 0.56 0.00 1.02 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
[147 rows x 16 columns]