# QuantLib Python: how to calculate the npv of irregular cashflows?

I am trying to learn QuantLib for Python but I must say I am banging my head against the documentation (I also bought Ballabio's python cookbook) - maybe it's me, but even finding the most basic concepts seems a struggle.

How can I do something as banal as discounting a set of irregular cashflows? The cashflows could be anything - the returns from a real estate investment, an asset-backed bond, etc.

The code below runs without any errors, but the result is... zero!

What I have done:

My questions:

• What am I doing wrong?
• Should calc_date be... what? The date of the first cashflow? I have tried that, I have tried days before, nothing.
• does FlatForward(calc_date, rate, ql.ActualActual()) define a yield curve from calc_date to infinity? Or do we need to specify a start date and an end date for the curve?
• is there any way to inspect / debug the SimpleCashFlow instances ( I use Spyder)? cfs[0] returns <QuantLib.QuantLib.SimpleCashFlow; proxy of <Swig Object of type 'ext::shared_ptr< SimpleCashFlow > *' at 0x0000021354440B40> > but how can I check what date and values are really there?

This is the code:

import QuantLib as ql
d1 = ql.Date(15,1,2011)
cfs = [ql.SimpleCashFlow(10, d1),
ql.SimpleCashFlow(10, d1 + 365),
ql.SimpleCashFlow(110, d1 + 365*2)]

calc_date = ql.Date(15,1,2011)
risk_free_rate = 0.05
discount_curve = ql.YieldTermStructureHandle(
ql.FlatForward(calc_date, risk_free_rate, ql.ActualActual()))

# WHY is this zero??
pv = ql.CashFlows.npv(cfs, discount_curve, True)


By default, QuantLib will set the evaluation data as the present date.

If you inspect your current date with:

ql.Settings.instance().evaluationDate


You will see that you are trying to get the npv of all past cashflows, which would be zero.

Try inserting this line after defining the d1.

ql.Settings.instance().setEvaluationDate(d1)

• It seems we stepped on each other's toes :) Feb 6, 2021 at 22:53

QuantLib has a concept of evaluation date (for a number of reasons that I'm now glossing over). By default, it's today's date, which implies that all your cashflows are in the past and thus worthless. If you want to calculate the NPV as of the calc date, add:

ql.Settings.instance().evaluationDate = calc_date


before calculating. Your construction of the curve is correct.

(Also, if you have any suggestion on how to document this better, I'm all ears—I would have thought you'd come across this in the examples, but evidently I was wrong...)

To inspect the cashflows, you can use their interface: for instance, cf[0].date() and cf[0].amount() will work.

• Grazie! I suppose I was confused because I didn't see it in this other example stackoverflow.com/questions/43115075/… and because I would have expected to find it mentioned in the docs, especially in the docs for the npv function. Now that I know to look for it I noticed it is mentioned in your Python cookbook. However, I raised another question here: quant.stackexchange.com/questions/61005/… because the output doesn't seem right Feb 6, 2021 at 23:27