In this answer to a question about cross currency swaps, the author shows the following deltas for a xCCY swap, but it shows no FX risk. How come? If we enter a EUR USD xCCY swap and we are based in EUR, then the USD leg needs to be converted to EUR and that gives us some fx risk.
- $\begingroup$ Why don’t you put this as a comment to that answer? $\endgroup$Alper– Alper2025-09-24 20:54:20 +00:00Commented Sep 24 at 20:54
- $\begingroup$ Because it's a question, not a comment. $\endgroup$Aktuary4– Aktuary42025-09-24 21:08:47 +00:00Commented Sep 24 at 21:08
- $\begingroup$ Comments can be questions as well if it is directly about the answer. In addition, the chances the OP sees it and responds would be higher. $\endgroup$Alper– Alper2025-09-24 22:01:01 +00:00Commented Sep 24 at 22:01
2 Answers
The rateslib EURUSD FX rate risk is expressed per EURUSD pip, i.e. for a movement in the rate of 0.0001.
The actual value calculated in the DataFrame is 0.029846181396350164 EUR per pip, which you have rounded to 0.
You can also validate this with a finite difference calculation:
xcs = XCS( dt(2023, 1, 1), "1Y", "Q", notional=100e6, currency="eur", spec="eurusd_xcs", fx_fixings=1.10, float_spread=-10.0, curves=["eur", "eurusd", "usd", "usd"] ) df = xcs.delta(solver=solver, base="eur") before = xcs.npv(solver=solver, base="eur") fxr.update({"eurusd": 1.1001}) solver.iterate() after = xcs.npv(solver=solver, base="eur") print("finite diff for 1 pip in EURUSD:", after - before) # finite diff for 1 pip in EURUSD: <Dual: 0.029843, (eur0, eur1, eurusd0, ...), [0.0, 0.0, -0.0, ...]> If you want to scale this per unit of EURUSD the value is 298.4 EUR. If you want to scale this per 1% movement in EURUSD FX rate the value is 0.0298 * 100 * 1.10 = 3.27 EUR
If you enter no fx_fixings then there is no FX risk.
One further comment is that the constructed XCS has cashflows today, so the NPV of each currency leg nets outs. If you build a XCS whose notional exchange was in the past, then each leg has a large NPV in the respective currency and you will get much more FX risk:
# Use IBOR here so only need to provide 1 historical fixing xcs = XCS( dt(2022, 12, 1), "1Y", "Q", notional=100e6, currency="eur", spec="eurusd_xcs", fixing_method="ibor", leg2_fixing_method="ibor", fixings=[1.0], leg2_fixings=[1.0], fx_fixings=1.10, float_spread=-10.0, curves=["eur", "eurusd", "usd", "usd"] ) xcs.delta(solver=solver, base="eur") - $\begingroup$ Why is there no fx risk if there are no fx fixings? For example, consider a 1period CCY swap, no basis, then: foreign leg: +1 - (1 + if )/(1+rf) * spotfx (if = foreign fixing, rf = foreign discount) domestic leg: -1 + (1 + rd)/(1+rd) = 0 so value = (1 - (1 + if )/(1+rf)) * spotfx this clearly has fx risk $\endgroup$JakcieJnr– JakcieJnr2025-09-26 14:59:45 +00:00Commented Sep 26 at 14:59
- $\begingroup$ Consider the OP's alternate post: quant.stackexchange.com/q/84052/29443 $\endgroup$2025-09-26 15:08:06 +00:00Commented Sep 26 at 15:08
- $\begingroup$ if you dont enter FX fixings, the contract is not determined so the fx fixings is considered as dynamic and pre-execution. $\endgroup$2025-09-26 15:09:38 +00:00Commented Sep 26 at 15:09
You are correct. There is FX risk on the foreign leg, so this is a mistake in rateslib.
- $\begingroup$ Rateslib gives the FX rate delta 'per pip' which the user has rounded to zero. The value in rateslib is correct. Additionally the XCS has both notional cashflows payable (initial and final) so the majority of FX risk nets out. See my answer. $\endgroup$2025-09-26 07:55:46 +00:00Commented Sep 26 at 7:55

