I'm currently working on building a yield curve using OIS swaps. However, I'm encountering an issue with the cash flow start date that I'm struggling to understand. Here's a simplified version of my code:
Reproducible example
import QuantLib as ql
calculation_date = ql.Date().todaysDate() #When I posted this on Quant exchange the date was 25/5/2023
ql.Settings.instance().evaluationDate = calculation_date
index = ql.OvernightIndex("USD Overnight Index", 2, ql.USDCurrency(), ql.UnitedStates(ql.UnitedStates.Settlement), ql.Actual360())
swaps = {
ql.Period("1W"): 0.05064,
ql.Period("2W"): 0.05067,
ql.Period("3W"): 0.05072,
ql.Period("1M"): 0.051021000000000004,
ql.Period("2M"): 0.051391,
ql.Period("3M"): 0.051745,
ql.Period("4M"): 0.05194,
ql.Period("5M"): 0.051980000000000005,
ql.Period("6M"): 0.051820000000000005,
ql.Period("7M"): 0.051584000000000005,
ql.Period("8M"): 0.05131,
ql.Period("9M"): 0.050924,
ql.Period("10M"): 0.050603999999999996,
ql.Period("11M"): 0.050121,
ql.Period("12M"): 0.049550000000000004,
ql.Period("18M"): 0.04558500000000001,
ql.Period("2Y"): 0.042630999999999995,
ql.Period("3Y"): 0.038952,
ql.Period("4Y"): 0.036976,
ql.Period("5Y"): 0.035919,
ql.Period("6Y"): 0.03535,
ql.Period("7Y"): 0.034998,
ql.Period("8Y"): 0.034808,
ql.Period("9Y"): 0.034738000000000005,
ql.Period("10Y"): 0.034712,
ql.Period("12Y"): 0.034801,
ql.Period("15Y"): 0.034923,
ql.Period("20Y"): 0.034662,
ql.Period("25Y"): 0.03375,
ql.Period("30Y"): 0.032826,
ql.Period("40Y"): 0.030834999999999998,
ql.Period("50Y"): 0.02896
}
rate_helpers = []
for tenor, rate in swaps.items():
helper = ql.OISRateHelper(2, tenor, ql.QuoteHandle(ql.SimpleQuote(rate)), index)
rate_helpers.append(helper)
yts = ql.RelinkableYieldTermStructureHandle()
curve = ql.PiecewiseSplineCubicDiscount(calculation_date, rate_helpers, ql.Actual360())
yts.linkTo(curve)
index = index.clone(yts)
engine = ql.DiscountingSwapEngine(yts)
print("maturity | market | model")
for tenor, rate in swaps.items():
schedule = ql.Schedule(calculation_date,
calculation_date + tenor,
ql.Period('1D'),
ql.UnitedStates(ql.UnitedStates.GovernmentBond),
ql.ModifiedFollowing,
ql.ModifiedFollowing,
ql.DateGeneration.Forward,
False)
swap = ql.OvernightIndexedSwap(ql.OvernightIndexedSwap.Payer,
1.0,
schedule,
0.01,
ql.Actual360(),
index)
swap.setPricingEngine(engine)
print(f" {tenor} | {rate:.6f} | {swap.fairRate():.6f}")
The issue I'm facing is that the cash flow start date for the swaps is appearing two days before the evaluation date (May 23rd, 2023 and Evaluation date May 25rd, 2023), which doesn't align with my expectations. I have set the evaluation date as the current date in my code, so the cash flow start date should be either on the evaluation date or after it.
File "AAA", line 173, in build_curve_v2 print(f" {tenor} | {rate:.6f} | {swap.fairRate():.6f}") ^^^^^^^^^^^^^^^ File "AAA", line 12, in <module> bootstrap.Curve_Build() RuntimeError: 2nd leg: Missing USD Overnight IndexSN Actual/360 fixing for May 23rd, 2023
I suspect there might be something wrong with my bootstrapping method or the way I'm constructing the yield curve. Any guidance or suggestions on how to resolve this issue would be greatly appreciated.
A Possible explanation :
When an OvernightIndexedSwap
is created, the floating leg's schedule is generated with its first date being T+2 days before the start of the swap, where T is the start of the swap. In my case, if the swap starts on the evaluation date of May 25th, 2023, the floating leg's schedule will begin on May 23rd, 2023. As a result, a fixing for the overnight rate on May 23rd, 2023, is required.