I'm attempting to calculate a GBP yield curve using a USD OIS rate curve and the FX Forward rates using Quantlib. I am trying to replicate the output of a different library, and am close but can't seem to quite get it right. Firstly, bootstrapping the USD yield curve from the OIS swap rates: # Set the calculation date start_date = ql.Date(1, 2, 2024) ql.Settings.instance().evaluationDate = start_date
Define calendar
calendar = ql.UnitedStates(0) convention = ql.Following endOfMonth = False spot_date = calendar.advance(start_date, 2, ql.Days)
Fixed leg payment frequency and conventions
fixed_frequency = ql.Annual
fixed_day_count = ql.Actual360()
fixed_convention = convention
fixed_payment_convention = convention
Rule for generating the schedule
rule = ql.DateGeneration.Backward
Define the overnight index as Fed Funds
overnight_index = ql.FedFunds()
Market data for OIS rates and their specific maturity dates
maturity_dates = ois_data["end_date"].to_list() # Specific maturity dates ois_rates = ois_data["Value"].to_list() # Corresponding OIS rates
Create OIS Rate Helpers with specific maturity dates for the Fed Funds rate
ois_helpers = [ ql.OISRateHelper( 2, ql.Period(maturity_date - spot_date, ql.Days), ql.QuoteHandle(ql.SimpleQuote(rate)), overnight_index, paymentLag=0, paymentFrequency=fixed_frequency, paymentConvention=fixed_payment_convention, paymentCalendar=calendar, endOfMonth=endOfMonth, ) for rate, maturity_date in zip(ois_rates, maturity_dates) ]
Bootstrap the OIS curve
day_count = ql.Actual365Fixed() ois_curve = ql.PiecewiseLogLinearDiscount(start_date, ois_helpers, day_count) usd_yield_curve = ql.YieldTermStructureHandle(ois_curve) When I compare the discount factors, I am getting the correct figures. Next, I attempt to bootstrap the GBP yield curve: fx_prices = fx_fwd["Value"].tolist() settlement_dates = fx_fwd["Settlement Date"].dt.date.tolist() joint_calendar = ql.JointCalendar( ql.UnitedKingdom(), calendar, ql.JoinHolidays ) rate_helpers = [ ql.FxSwapRateHelper( ql.QuoteHandle(ql.SimpleQuote(price - spot_price)), ql.QuoteHandle(ql.SimpleQuote(spot_price)), ql.Period(ql.Date.from_date(settlement_date) - start_date, ql.Days), 0, joint_calendar, ql.ModifiedFollowing, True, False, usd_yield_curve, ) for price, settlement_date in zip(fx_prices, settlement_dates) ]
Bootstrap the OIS curve
day_count = ql.Actual365Fixed()
day_count = ql.Actual360()
gbp_curve = ql.PiecewiseFlatForward(start_date, rate_helpers, day_count) gbp_yield_curve = ql.YieldTermStructureHandle(gbp_curve) This time when I plot the discount factors, compared with the other library, they are different. Only by between 1-50 bp, but that is enough to throw off instrument pricing further down the line when using these yield curves. I've tried a few different iterations of the arguments to the helpers but can't seem to get it to work. Any help would be really appreciated.


