Search code examples
quantlibquantlib-swig

QuantLib swap pricing, index fixing leg missing


I upgraded QuantLib to the latest version 1.29, but my existing code started an error of vanilla swap pricing. I went back to documentation, and tried the sample code, but the error comes too.

The error message as followings,

RuntimeError: 2nd leg: Missing USDLibor3M Actual/360 fixing for April 5th, 2023

http://gouthamanbalaraman.com/blog/interest-rate-swap-quantlib-python.html

import QuantLib as ql

calculation_date = ql.Date(1, 4, 2023)

risk_free_rate = 0.01
libor_rate = 0.02
day_count = ql.Actual365Fixed()

discount_curve = ql.YieldTermStructureHandle(
    ql.FlatForward(calculation_date, risk_free_rate, day_count)
)

libor_curve = ql.YieldTermStructureHandle(
    ql.FlatForward(calculation_date, libor_rate, day_count)
)
#libor3M_index = ql.Euribor3M(libor_curve)  
libor3M_index = ql.USDLibor(ql.Period(3, ql.Months), libor_curve)

calendar = ql.TARGET()
settle_date = calendar.advance(calculation_date, 5, ql.Days)
maturity_date = calendar.advance(settle_date, 10, ql.Years)

fixed_leg_tenor = ql.Period(6, ql.Months)
fixed_schedule = ql.Schedule(settle_date, maturity_date, 
                             fixed_leg_tenor, calendar,
                             ql.ModifiedFollowing, ql.ModifiedFollowing,
                             ql.DateGeneration.Forward, False)

float_leg_tenor = ql.Period(3, ql.Months)
float_schedule = ql.Schedule (settle_date, maturity_date, 
                              float_leg_tenor, calendar,
                              ql.ModifiedFollowing, ql.ModifiedFollowing,
                              ql.DateGeneration.Forward, False)

notional = 10000000
fixed_rate = 0.025
fixed_leg_daycount = ql.Actual360()
float_spread = 0.004
float_leg_daycount = ql.Actual360()

ir_swap = ql.VanillaSwap(ql.VanillaSwap.Payer, notional, fixed_schedule, 
               fixed_rate, fixed_leg_daycount, float_schedule,
               libor3M_index, float_spread, float_leg_daycount )

swap_engine = ql.DiscountingSwapEngine(discount_curve)
ir_swap.setPricingEngine(swap_engine)

print(ir_swap.NPV()) 

Solution

  • You don't seem to be setting the global evaluation date. You need a line like

    ql.Settings.instance().evaluationDate = calculation_date
    

    otherwise the evaluation date will be the real-world date and the first coupon will be considered as fixing in the past.