# Plotting a CSA curve in QuantLib

### IRS under a CSA

Let's consider an example of Interest Rate Swap under a CSA. To calculate discount factors that can be used to discount cashflows in one currency, $$C_{1}$$, collateralized in another currency, $$C_{2}$$, all we need are the FX spot and forward rates from $$C_{1}$$ to $$C_{2}$$ and the discount factors in $$C_{2}$$. Let

$$FX_{C1\rightarrow C2}^{FWD}(T)$$ = $$FX\: forward\: rate\: to\: convert\: from$$ $$C_{1}$$ $$to$$ $$C_{1}$$ $$at\: time\: T$$

$$FX_{C1\rightarrow C2}^{SPOT}$$ = $$FX_{C1\rightarrow C2}^{FWD}(0)$$ = $$FX\: spot\: rate\: to\: convert\: from$$ $$C_{1}$$ $$to$$ $$C_{1}$$

$$DF_{C2}(T)$$ = $$discount\: factor\:at\: time\: T\: for\: currency$$ $$C_{2}$$,

Then under the assumption that FX forwards are independent of collateralization we conclude that

$$\Large\frac{FX_{C1\rightarrow\:C2}^{CSA}(T)}{DF_{C2}(T)}$$ $$\Large=$$ $$\Large\frac{FX_{C1\rightarrow\:C2}^{FWD}(T)}{FX_{C1\rightarrow\:C2}^{FWD}(0)}$$

### Question

Is it possible to find such functions in QuantLib that will directly find the discount factors of the CSA curve (And we know how to build an ZeroRate Curve here)? Please guide me in the right direction.

Thank you!

• When I last checked, QuantLib did not offer a cross-currency based bootstrapping or other multi-currency curve building out-of-the-box. The Python documentation hints at the existence of an FXImpliedCurve, maybe that could be a starting point: quantlib-python-docs.readthedocs.io/en/latest/… Commented Jun 23, 2021 at 12:31
• @Kermittfrog, Thank you! I will investigate this in detail. Hope this section (FXImpliedCurve) will be updated in the future. Commented Jun 23, 2021 at 12:54

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"],
)


Yes this is supported in QuantLib - see the answer in https://quant.stackexchange.com/a/78325/70402

The example linked there is modeling the use case you describe.