QuantLib NPV Depends on the Evaluation Date
Summary
The document diagnoses why a QuantLib calculation of the present value of irregular cash flows returns zero. The cash flows and flat discount curve are constructed for a historical date, but QuantLib’s evaluation date defaults to the current date. Since all listed payments are therefore in the past relative to the valuation date, the cash-flow NPV is zero under the library’s conventions.
The remedy is to set the global evaluation date to the intended valuation date before calculating NPV. The accepted explanations confirm that the flat curve setup itself is valid, and also show how to inspect individual cash-flow dates and amounts through the cash-flow interface. This is a practical library-specific debugging lesson rather than a general discounting derivation. The example depends on the evaluation date and cash-flow schedule; users must set the valuation date appropriate to their own analysis and check that the payments fall on the intended side of it.
Key ideas
- QuantLib uses a global evaluation date that defaults to the current date.
- Cash flows dated before the evaluation date may be treated as expired and contribute zero to NPV.
- Set the evaluation date to the intended valuation date before calculating present value.
- Cash-flow objects expose methods for inspecting their dates and amounts.
- The discount curve construction can be valid even when an NPV result is unexpectedly zero.
Tags
Full text
# QuantLib Python: how to calculate the npv of irregular cashflows?
# 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:
- I have defined the cashflows with SimpleCashFlow - is that the right class to use?
- I then use a FlatForward to define a flat yield curve.
- What I use for discount_curve is taken from page 57 of the Python cookbook.
- I looked for examples of how CashFlows.npv works, but I couldn't find any here https://quantlib-python-docs.readthedocs.io/en/latest/termstructures.html#yield-term-structures and this other page https://rkapl123.github.io/QLAnnotatedSource/d8/d7d/class_quant_lib_1_1_cash_flows.html isn't the clearest.
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)
```
## Answer by David Duarte (score 3, accepted)
https://quant.stackexchange.com/a/61002
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)
```
## Answer by Luigi Ballabio (score 2)
https://quant.stackexchange.com/a/61003
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.Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.