I've checked similar questions and answers but even after setting the evaluation date in ql.settings I still get zero. Like another poster, I also have the QL cookbook and have read everything I could find, but still struggling. Thanks for any help!

import QuantLib as ql 
calc_date= ql.Date(21,ql.July,2023)

dayConvention = ql.Thirty360(ql.Thirty360.BondBasis)
calendar = ql.UnitedStates(ql.UnitedStates.NYSE)

trade_date = ql.Date(20,ql.July,2023)
maturityDate = ql.Date(4,ql.August,2023)

spotDates = [ql.Date(20,ql.July,2023), ql.Date(4,ql.August,2023), ql.Date(4,ql.August,2024)]
spotRates = [0.01318, 00.01318,0.01318]

compounding = ql.Simple
compoundingFrequency = ql.Annual

spotCurve = ql.ZeroCurve(spotDates, spotRates, dayConvention, calendar, ql.Linear(), compounding, compoundingFrequency)

spotCurveHandle = ql.YieldTermStructureHandle(spotCurve)

index = ql.USDLibor(ql.Period('1W'), spotCurveHandle)
index.addFixing(ql.Date(18, ql.July, 2023),0.01318)
# index.addFixing(ql.Date(26, 6, 2020), 0.05)
notional = 54760000
rate = 1.37825/100

fra = ql.ForwardRateAgreement(trade_date, maturityDate, ql.Position.Long, rate, notional, index, spotCurveHandle)
print('NPV:', fra.NPV())

1 Answer 1


This is not an FX Forward but a Forward Rate Agreement (a rates product). I'm not sure if QuantLib has a FX Forward pricer but they do have one for FX swaps (see FXSwapRateHelper).

Now, to get a non-zero NPV you probably want to add a valuation date before the settlement date:

for day in [18, 19, 20]:
    ql.Settings.instance().evaluationDate = ql.Date(day, 7, 2023)
    fra = ql.ForwardRateAgreement(trade_date, maturityDate, ql.Position.Long, rate, notional, index, spotCurveHandle)
    print('NPV:', round(fra.NPV(), 2), "Expired:", fra.isExpired())

Which gives:

NPV: -1373.95 Expired: False
NPV: -1373.95 Expired: False
NPV: 0.0 Expired: True

Remember that a FRA pays at the beginning of the period (see e.g. this paper). This is also explained in the QL documentation here: "the FRA settles and expires on the valueDate, not on the (later) maturityDate". The life cycle looks as follows:

enter image description here

  • $\begingroup$ thanks so much!! $\endgroup$ Aug 1 at 23:35
  • 2
    $\begingroup$ No worries - if you're happy with the answer, feel free to accept it @PythonAutomation $\endgroup$
    – oronimbus
    Aug 2 at 7:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.