# Substituting the basis swap for the FX forward

I have come across a response to the question titled "Cross currency swap a combination of 2 Interest rate swap" on this site. There, it is stated the following:

Long story short: As @Dimitri Vulis explained, this statement does not generally hold, and is at best an approximation. However, this Citibank webpage illustrates how you can decompose fixed to fixed (FXFX) and fixed to float (FXFL) cross currency swaps into swaps (and basis swaps). If you substitute the basis swap for the FX forward, you have the decomposition used in your paper.

What does it mean actually? Is a basis swap and FX forward basically the same? How it can be? A basis swap involves float + float rate, but a forward involves only fixed.

Let's be more specific using the screenshot of a Fixed-Floating Cross-currency swap example from the Citibank webpage mentioned in the quote above:

As it showed, for hedging, Citi-Banking unit (CitiBU) initiates a Float-Float Basis swap with Citi Basis Swap bank (CitiBS). Here I wonder how exactly this basis-swap can be substituted with a Forward?

Let say CF happens in each 3-month, and currently we are at time t=0. So we know how much USD and JPY will be transacted at 3m time. Here I see only risk factor is the Spot FX rate for USD-JPY at 3-month period. I understand that this risk can be hedged with FX Forward. Therefore, for the upcoming CF, this Basis swap can be substituted with FX Forward, which appears to be clear to me.

But what about CFs happening at 6m, 9m,.. period? How excatly Swap-basis CFs at those time-points can be substituted by FX Forwards?

• As.mentioned in the answer, you can use Fwd FX rates (several, for each cashflow) to calculate the implied borrowing cost in another currency. For example, the implied basis can be derived from Covered Interest Rate Parity from making a 3 month EURIBOR loan and converting it into USD via a 3 month FX swap. The difference between the implied cost and the 3m Libor curve is the basis. Nowadays, we are in a post libor world bit the same logic applies to RFR rates. Commented Aug 11, 2023 at 10:37
• @AKdemy Thanks for your response. However I don't think I fully understood such substitution strategy for all CFs of Basis-Swap. I have updated my original post with a specific example based on the link provided in the original comment. Appreciate, if you could explain w.r.t. an example (preferably the Citi example which I have added) Commented Aug 11, 2023 at 17:42

It is best to understand this from basic principles. I will construct these instruments in Python's rateslib so that you can also visualise the cashflows and the delta.

### Calculation Engine

In order to do this we need to set up a framework. This framework will comprise, interest rate curves in EUR and USD and a curve that values EUR cashflows in USD collateral (acting as the basis curve).

from rateslib import *

usdusd = Curve({dt(2023, 1, 1): 1.0, dt(2024, 1, 1): 1.0}, id="usdusd")
eureur = Curve({dt(2023, 1, 1): 1.0, dt(2024, 1, 1): 1.0}, id="eureur")
eurusd = Curve({dt(2023, 1, 1): 1.0, dt(2024, 1, 1): 1.0}, id="eurusd")
fxr = FXRates({"eurusd": 1.10}, settlement=dt(2023, 1, 1))
fxf = FXForwards(
fx_rates=fxr,
fx_curves={
"usdusd": usdusd,
"eureur": eureur,
"eurusd": eurusd,
}
)


Next we calibrate our curves so that the 1Y USD swap is 5% the 1Y EUR swap at 3.5% and the cross-currency basis swap is -10bps.

solver = Solver(
curves=[usdusd, eureur, eurusd],
instruments=[
IRS(dt(2023, 1, 1), "1Y", "A", currency="usd", curves="usdusd"),
IRS(dt(2023, 1, 1), "1Y", "A", currency="eur", curves="eureur"),
XCS(dt(2023, 1, 1), "1Y", "Q", currency="eur", leg2_currency="usd", curves=["eureur", "eurusd", "usdusd", "usdusd"])
],
s=[5.0, 3.5, -10.0],
instrument_labels=["1Y USD", "1Y EUR", "1Y EUR/USD"],
fx=fxf,
)
SUCCESS: func_tol reached after 3 iters, f_val: 3.96e-17, time: 35ms


### 1) The equivalence of FXSwap and 2 FXExchanges (or forwards)

Next we will show that an FXSwap is essentially 2 FXExchanges, which are two forward FX transactions. A market agreed FXSwap contains 4 fixed cashflows. Create a 3M FXSwap and have a look:

fxs = FXSwap(
effective=dt(2023, 1, 1),
terminination="3M",
currency="eur",
leg2_currency="usd",
fx_fixing=1.10,
points=42.335246,
curves=[None, "eurusd", None, "usdusd"]
)
fxs.cashflows_table(solver=solver)


Now we build the replicating trades as 2 FXExchanges in the opposite directions.

args = dict(
currency="eur",
leg2_currency="usd",
curves=[None, "eurusd", None, "usdusd"]
)
fxe1 = FXExchange(
settlement=dt(2023, 1, 1),
notional=1e6,
fx_rate=1.10,
**args
)
fxe2 = FXExchange(
settlement=dt(2023, 4, 1),
notional=-1e6,
fx_rate=1.1042335246,
**args
)


If we add the FXSwap and the replicating FXExchanges to a combined Portfolio we can see that all the cashflows and delta risks net out.

pf = Portfolio([fxs, fxe1, fxe2])
pf.cashflows_table(solver=solver)
pf.delta(solver=solver)


### 2) The equivalence of an FXSwap and a single period NonMtmFixedFixedXCS

Now we can show that the 4 cashflows of an FXSwap (which is just 2 FX forwards) can replicate a non-mark-to-market fixed-fixed cross-currency swap.

ffxcs = NonMtmFixedFixedXCS(
effective=dt(2023, 1, 1),
termination="3M",
frequency="A",
currency="eur",
notional=-1e6,
leg2_currency="usd",
fixed_rate=0.0,
leg2_fixed_rate=1.539463,
fx_fixing=1.10,
payment_lag=0,
curves=[None, "eurusd", None, "usdusd"],
)


Since these legs are fixed rate all the cashflows are fixed, again, so we can see the cashflows table:

ffxcs.cashflows_table(solver=solver)


This is the opposite of the original FXSwap. If we combine the instruments to a Portfolio we see they net out.

pf = Portfolio([fxs, ffxcs])
pf.cashflows_table(solver=solver)
pf.delta(solver=solver)


### 3) The Equiavlence of a NonMtmFixedFixedXCS with 2 IRS and 1 NonMtmXCS

So lastly we show that a non-mtm float-float cross-currency swap plus 2 interest rate swaps are equivalently a non-mtm fixed-fixed cross-currency swap.

xcs = NonMtmXCS(
effective=dt(2023, 1, 1),
termination="3M",
frequency="A",
currency="eur",
notional=-1e6,
leg2_currency="usd",
fx_fixing=1.10,
payment_lag=0,
curves=["eureur", "eurusd", "usdusd", "usdusd"],
)
eur_irs = IRS(
effective=dt(2023, 1, 1),
termination="3M",
frequency="A",
notional=-1e6,
currency="eur",
payment_lag=0,
curves=["eureur", "eurusd"],
fixed_rate=0.0
)
usd_irs = IRS(
effective=dt(2023, 1, 1),
termination="3M",
frequency="A",
notional=1.1e6,
currency="usd",
payment_lag=0,
curves=["usdusd", "usdusd"],
fixed_rate=1.539463
)

pf = Portfolio([xcs, eur_irs, usd_irs])
pf.cashflows_table(solver=solver)


These are exactly the opposite of the underlying FXSwap so when we combine everything, we get a completely cashflow and delta neutral portfolio.

pf = Portfolio([xcs, eur_irs, usd_irs, fxs])
pf.delta(solver=solver).style.format(precision=4)


### 4) Conclusion

By showing each stage we assert that 2 FXExchanges completely replicates 2 single period fixed-float IRS in each currency and a single period non-mtm float-float cross-currency basis swap (NonMtmXCS).

The pricing parameters on all instruments have been fixed to net out all the cashflows (the FXExchanges are at mid market and value to zero).

A string of these such combinations could be used to replicate swaps with more than a single period.

• many thanks for this workout. How can I change above code if I want to replicate this for 1 year swap with 3M cashflow time? Commented Aug 14, 2023 at 12:07
• frequency="Q", and termination="1Y"
– Attack68
Commented Aug 15, 2023 at 20:07