You can also validate the QuantLib
implementation with rateslib
.
To define local currency EUR and USD you need to specify two RFR curves:
from rateslib import *
eureur = Curve({dt(2024, 2, 16): 1.0, dt(2024, 8, 16): 1.0, dt(2025, 2, 19): 1.0}, calendar="tgt", convention="act360", interpolation="log_linear")
usdusd = Curve({dt(2024, 2, 16): 1.0, dt(2024, 8, 16): 1.0, dt(2025, 2, 19): 1.0}, calendar="nyc", convention="act360", interpolation="log_linear")
To define cross-currency or FXswap markets you need a CSA curve for EUR cashflows collateralised with USD.
eurusd = Curve({dt(2024, 2, 16): 1.0, dt(2024, 8, 16): 1.0, dt(2025, 2, 19): 1.0}, convention="act360", interpolation="log_linear")
The discount factor points are placed at the 6m and 1Y points on all curves.
Now we will associate these objects together in an FXForwards
framework with prevailing FXRates
fxf = FXForwards(
fx_rates=FXRates({"eurusd": 1.080}, settlement=dt(2024, 2, 20)),
fx_curves={"usdusd": usdusd, "eureur": eureur, "eurusd": eurusd}
)
Now solve and update these Curves according to market instrument rates as of 16th Feb 2024, aligning with 6m and 1Y instruments for simplicity.
solver = Solver(
curves=[eureur, usdusd, eurusd],
instruments=[
IRS(dt(2024, 2, 16), "6m", spec="usd_irs", curves=usdusd),
IRS(dt(2024, 2, 16), "1y", spec="usd_irs", curves=usdusd),
IRS(dt(2024, 2, 16), "6m", spec="eur_irs", curves=eureur),
IRS(dt(2024, 2, 16), "1y", spec="eur_irs", curves=eureur),
XCS(dt(2024, 2, 16), "6m", spec="eurusd_xcs", curves=[eureur, eurusd, usdusd, usdusd]),
XCS(dt(2024, 2, 16), "1y", spec="eurusd_xcs", curves=[eureur, eurusd, usdusd, usdusd]),
],
s=[5.205, 5.00, 3.72, 3.40, -6.1, -11.9],
instrument_labels=["6mUS", "1yUS", "6mEU", "1yEU", "6mUS/EU", "1yUS/EU"],
fx=fxf,
)
SUCCESS: `func_tol` reached after 3 iterations (levenberg_marquardt) , `f_val`: 4.884e-12, `time`: 0.0580s
The updated FXForwards
object can now return Curves for any of the following:
USD cashflows with:
- USD collateral:
fxf.curve("usd", "usd") # type: Curve
- EUR collateral:
fxf.curve("usd", "eur") # type: ProxyCurve
- USD+EUR collateral:
fxf.curve("usd", ["usd", "eur"]) # type: MultiCsaCurve
EUR cashflows with
- USD collateral:
fxf.curve("eur", "usd") # type: Curve
- EUR collateral:
fxf.curve("eur", "eur") # type: Curve
- USD+EUR collateral:
fxf.curve("eur", ["usd", "eur"]) # type: MultiCsaCurve
ProxyCurves
take discount factors from the relevant underlying Curves
and perform cross multiplications (similar to your formulae). They are objects capable of calculating discount factors or rates, etc.
MultiCsaCurves
combine collateral curves to calculate intrinsic multi-collateral curves (without optionality). Again they are curve objects capable of producing discount factors and rates.
They can also plot
.
fxf.curve("usd", "usd").plot("1b",
comparators=[fxf.curve("usd", "eur"), fxf.curve("usd", ["usd", "eur"])],
labels=["local", "eur", "local+eur"],
)
FXImpliedCurve
, maybe that could be a starting point: quantlib-python-docs.readthedocs.io/en/latest/… $\endgroup$