So this "SOFR vs fixed" swap has a fixed leg paying 5.231% yearly and a floating leg paying yearly the yearly compounded SOFR rate, and has a 1W term. If it has started today, it won't have any cashflows exchanged as 1W < 1Y. So necessarily it is a swap having started earlier but then, which swap is it ?
-
1$\begingroup$ The fixed leg has daycount convention Actual / 360. You'd calculate the actual days (7, perhaps plus-minus some because of holidays). The floating leg pays SOFR observed daily and accrued over this many days. The fixed leg pays annual coupon rate $\times$ this many days / 360. Theae cash flows are netted, and paid at maturity, which is in this many days. You should be able to see cash flows in SWPM. $\endgroup$– Dimitri VulisJul 23 at 16:43
-
$\begingroup$ I just checked on bloomberg, indeed. Ok, so that the 1Y payment freq for the fixed and floating leg are wrong in the DES ? For instance, for US0SFR1F Curncy (18M term) in BB, the cashflows are 29/1/2024 and 29/1/2025 and not some date around 23/7/24 = today + 6M and some date around 23/11/24 = today + 18M. Shall I conclude that the cashflows are determined yearly and backwards from settlement date + term date ? If so, where could I find official document stating all the convention and generation of cashflows payments dates and start end periods etc ? $\endgroup$– EricFlorentNoubeJul 23 at 16:56
-
$\begingroup$ For 1S6M - yes, having the 6 months stub at the end is a little arbitrary, but makes more sense than having it instead at the beginning would be. A bespoke e.g. 15mo swap should have 3mo sub at the end too. As for maturities <= 1 year, I emphatically agree that showing Frequency = Annual is both misleading and imprecise. It would be better if Bloomberg showed frequency "Once", meaning single cash flow at maturity, as e.g. Quantlib has. $\endgroup$– Dimitri VulisJul 23 at 17:24
-
1$\begingroup$ The fixed and the floating leg should accrue over the same number of actual days in the odd coupon. I don't know of an official document, but you may find quant.opengamma.io/… (2013, before SOFR) insightful. $\endgroup$– Dimitri VulisJul 23 at 18:40
-
1$\begingroup$ I second @Dimiti Vulis, the period is 1week only, for both legs. The additional detail on the Des page is the generic explanation of the SOFR swap.conventions. The cashflow tab in SWPM will show all relevant details. $\endgroup$– AKdemyJul 23 at 23:06
1 Answer
The DES page always displays very generic information, the basic SOFR swap conventions in the case of US0SFR1Z
.
Settlement, term and quote are all for the specific ticker though. So you have a fixed-float SOFR swap, which settles on 25th of July and matures in 1 week (August 1st).
In terms of computing, this is actually simpler with such short term swaps. The next screenshot shows how SWPM matches the HP, which is the quoted swap with standard T+2 settlement.
I chose a historical start date because you can directly observe the fixings on the Resets
tab to compute the actual cashflows.
Replicating the computation in Python looks like this:
from datetime import date
import pandas as pd
from math import prod
start = date(2023, 7, 13)
end = date(2023, 7, 20)
pd.date_range(start, end, freq='B')
df = pd.DataFrame({"Dates" : pd.date_range(start, end, freq='B'), "Reset Rate" : [5.06,5.05,5.06,5.06,5.05, 5.06]})
days = [(df.Dates[i+1]-df.Dates[i]).days for i in range(0,len(df)-1)]
days.append(0)
df["Days"] = days
df["Rate"] = 1+df["Reset Rate"]/100*df.Days/360
df
This creates a DataFrame that shows the Dates, associated Resets (fixings), and the computed rate, which is computed as $1+df["Reset Rate"]/100*df.Days/360$ to adjust for ACT/360 daycount.
The fixed leg is trivial, and for the float leg, one needs to round the compounded value by 7 decimal points and adjust for daycount again to get an annual value, called Equivalent Coupon
in SWPM.
N = 10000000
quote = 0.05058
fixed_leg = N*(1+quote*7/360)
Equiv_Coupon = round((prod(df.Rate[0:5])-1)*360/7,7)
float_leg = 10000000*(1+Equiv_Coupon*7/360)
pd.set_option('display.float_format', lambda x: '%.7f' % x)
pd.DataFrame({"Notional" : [N], "Quote" : [quote], "Fixed Leg Payment" : fixed_leg, "Equivalent Coupon" : Equiv_Coupon, "Float Leg Payment" : float_leg,})