I have 2 questions:
If I want to discount a set of irregular cashflows, I can do it using the SimpleCashFlow class, or defining a bond with custom cashflows (thank you to Ballabio and David Duarte for their previous clarifications on this. I have copied a toy example below.
- However, can I calculate duration and convexity with SimpleCashFlow, too, or does that work only for bonds?
I see it in the docs that CashFlows does have the
convexity methods, but I can't seem to get the syntax right.
The last lines of my toy example are what I have tried - to no avail.
- May I ask where this is documented, or how to interpret the documentation? The lines I wrote seem to match the syntax I find on https://quantlib-python-docs.readthedocs.io/en/latest/cashflows.html?highlight=duration#id5 , but evidently I am wrong because they don't work.
If instead I search github https://rkapl123.github.io/QLAnnotatedSource/d3/d50/struct_quant_lib_1_1_duration.html I honestly understand absolutely nothing at all on how the syntax should look like.
Could any one please be kind enough to point me to which docs/where explain what the correct syntax should be? I am basically in a position where I can't make sense of the docs and must ask for help for even the most banal calculations. Thank you!
import QuantLib as ql import pandas as pd from datetime import date import numpy as np d1 = ql.Date(15,1,2001) ql.Settings.instance().setEvaluationDate(d1) cfs = [ql.SimpleCashFlow(0, d1), ql.SimpleCashFlow(110, d1 + 365)] calc_date = d1 risk_free_rate = 0.1 curve_act_365 = ql.YieldTermStructureHandle( ql.FlatForward(calc_date, risk_free_rate, ql.Actual365Fixed() , ql.Compounded, ql.Annual )) curve_30_360 = ql.YieldTermStructureHandle( ql.FlatForward(calc_date, risk_free_rate, ql.Thirty360(), ql.Compounded, ql.Annual )) # The present value is the same 9as it should be!) # whether I calculate it as # 1) cashflows - act365 # 2) cashflows - 30/360 # 3) custom bond - act465 pv_act_365 = ql.CashFlows.npv(cfs, curve_act_365, True) pv_30_360 = ql.CashFlows.npv(cfs, curve_30_360, True) custom_bond = ql.Bond(0, ql.TARGET(), 100.0, ql.Date(), ql.Date(), cfs) bond_engine = ql.DiscountingBondEngine(curve_act_365) custom_bond.setPricingEngine(bond_engine) pv_bond = custom_bond.NPV() # I can also use the custom bond to calculate duration and convexity y = ql.InterestRate(0.1, ql.Actual365Fixed(), ql.Compounded, ql.Annual) dur_bond = ql.BondFunctions.duration(custom_bond, y, ql.Duration.Macaulay) conv_bond = ql.BondFunctions.convexity(custom_bond, y) # manually recalculating the convexity just as a check conv_check = 1 / (100 * 1.1**2)*110* (1+1**2)/(1.1) # Can I use the CashFlows class to calculate duration and convexity, too? # I have tried all the combinations below but none works cf_dur = ql.CashFlows.duration(cfs, y, ql.Duration.Macaulay) leg = ql.Leg(cfs) cf_dur = ql.CashFlows.duration(leg, y, ql.Duration.Macaulay) cf_dur = ql.CashFlows.duration(leg, 0.1, ql.Duration.Macaulay, False) cf_conv = x = ql.CashFlows.convexity(cfs, y)
UPDATE in light of Francis' answer below:
- So the duration function can take either a list of dates, or a Leg object created from the same list, right? Is there any difference between the two?
- The docs state that
settlementDate = ql.Date()and that
npvDate = ql.Date(). Does this mean that ql.Date() is the default value? Or that they are of type ql.Date()? I don't understand, because running ql.Date() returns an empty object. I would have expected
ql.Date()to equal today's date, or the date set with