Does QuantLib support valuation of Cross currency swaps ? Eg. SOFR / SONIA cross currency swap.
-
$\begingroup$ With resetting notional? $\endgroup$– Dimitri VulisCommented Feb 1, 2023 at 18:55
-
$\begingroup$ Yes Dimitri , with resetting Notional. $\endgroup$– Rohit GajareCommented Feb 2, 2023 at 3:29
-
1$\begingroup$ Have you tried rkapl123.github.io/QLAnnotatedSource/d0/df1/… ? $\endgroup$– Dimitri VulisCommented Feb 2, 2023 at 4:09
-
1$\begingroup$ Unfortunately not possible with quantlib functions directly. You can do some workaround... $\endgroup$– EAKCommented Mar 1, 2023 at 15:44
2 Answers
I trade IRSs and XCSs so this answer is based on my own processes and requirements, as such I have written rateslib
in Python, which does not have any of the stochastic processes of quantlib
, but is centred about the delta and gamma metrics of linear multi-currency rate derivatives.
In order to establish a pricing and risk framework for multi-currency derivatives we need Curves, FXRates, Instruments and a trade or portfolio which to value.
Create the Curves first. 3 lines for the USD, GBP and GBPUSD cross currency discounting curve. Their discount factors will be calibrated shortly.
from rateslib import *
gbp = Curve({dt(2023, 8, 2): 1.0, dt(2024, 8, 2): 1.0}, id="sonia", calendar="ldn")
usd = Curve({dt(2023, 8, 2): 1.0, dt(2024, 8, 2): 1.0}, id="sofr", calendar="nyc")
gbpusd = Curve(
nodes={dt(2023, 8, 2): 1.0, dt(2024, 2, 2): 1.0, dt(2024, 8, 2): 1.0},
id="gbpusd",
)
Now we will create the FXRates and associate it with Curves to define a collateral consistent FXForwards space.
fxr = FXRates({"gbpusd": 1.25}, settlement=dt(2023, 8, 4))
fxf = FXForwards(
fx_rates=fxr,
fx_curves={
"usdusd": usd,
"gbpgbp": gbp,
"gbpusd": gbpusd,
}
)
Now we will solver everything relative to market data and calibrating Instruments
solver = Solver(
curves=[gbp, usd, gbpusd],
instruments=[
IRS(dt(2023, 8, 2), "1y", spec="gbp_irs", curves="sonia"),
IRS(dt(2023, 8, 2), "1y", spec="usd_irs", curves="sofr"),
XCS(dt(2023, 8, 2), "6m", spec="gbpusd_xcs", curves=["sonia", "gbpusd", "sofr", "sofr"]),
XCS(dt(2023, 8, 2), "1y", spec="gbpusd_xcs", curves=["sonia", "gbpusd", "sofr", "sofr"]),
],
s=[4.75, 5.35, -6, -14],
fx=fxf,
instrument_labels=["1y gbp", "1y usd", "6m gbpusd", "1y gbpusd"],
id="solver",
)
SUCCESS: `func_tol` reached after 3 iterations (levenberg_marquardt)
Notice these instruments have their parameters pre-configured by a market specification (spec) input.
With this Solver and set of calibrated Curves you can now do quite a lot of things. SOme of those involve constructing an existing cross currency swap and then pricing and risking it.
Here I will create a historical MTM-XCS and attached fixings to it which have valid fixing data upto the last RFR for reference value date 1st Aug 2023.
my_xcs=XCS(
dt(2023, 5, 16), "1Y", spec="gbpusd_xcs",
fx_fixings=[1.25],
float_spread=-2.5,
notional=100e6, #GBP
curves=["sonia", "gbpusd", "sofr", "sofr"],
fixings=defaults.fixings.sonia,
leg2_fixings=defaults.fixings.sofr
)
We can value and risk this swap:
my_xcs.npv(solver=solver, local=True)
{"usd": 126,378,590.04,
"gbp": -101,071,269.19}
my_xcs.npv(solver=solver, base="gbp")
35,487.48
my_xcs.delta(solver=solver)
Can also see the cashflows including all the MTM exchanges:
my_xcs.cashflows(solver=solver)
At this time there's not a cross-currency instrument as such (it might take a while) but it's possible to build its cashflows and calculate their value. There's a write-up available at https://www.implementingquantlib.com/2023/09/cross-currency-swaps.html.