PvK
PvK

Reputation: 370

How to price a SimpleCashFlow

I would like to use QuantLib to price a portfolio of liabilities, which are modeled to be deterministic future cash-flows. I am now modelling them as a strip of FixedRateBonds with zero coupons, which seems like a very inelegant solution.

Problem:

Question 1: Is there a way to create an 'Instrument' that is just a 'SimpleCashFlow', 'Redemption' etc. and price it on a discount curve?

Question 2: Is it possible to construct a 'CashFlows' object or Instrument from multiple SimpleCashFlow's and price it on a curve?

Many thanks in advance

Code Example:

See code below for an example of what I am trying to do.

from QuantLib import *

# set params
calc_date = Date(30, 3, 2017)
risk_free_rate = 0.01
discount_curve = YieldTermStructureHandle(
                     FlatForward(calc_date, risk_free_rate, ActualActual()))
bond_engine = DiscountingBondEngine(discount_curve)

# characteristics of the cash-flow that I am trying to NPV
paymentdate = Date(30, 3, 2018)
paymentamount = 1000

# this works: pricing a fixed rate bond with no coupons
schedule = Schedule(paymentdate-1, paymentdate, Period(Annual),  TARGET(),
Unadjusted, Unadjusted, DateGeneration.Backward, False)
fixed_rate_bond = FixedRateBond(0, paymentamount, schedule, [0.0],ActualActual())
bond_engine = DiscountingBondEngine(discount_curve)
fixed_rate_bond.setPricingEngine(bond_engine)
print(fixed_rate_bond.NPV())

# create a simple cashflow
simple_cash_flow = SimpleCashFlow(paymentamount, paymentdate)
# Q1: how to create instrument, set pricing engine and price a SimpleCashFlow?
#wrongcode:# simple_cash_flow.setPricingEngine(bond_engine)
#wrongcode:# print(simple_cash_flow.NPV())

# Q2: can I stick multiple cashflows into a single instrument, e.g.:
# how do I construct and price a CashFlows object from multiple 'SimpleCashFlow's?
simple_cash_flow2 = SimpleCashFlow(paymentamount, Date(30, 3, 2019))
#wrongcode:# cashflows_multiple = CashFlows([simple_cash_flow, simple_cash_flow2])
#wrongcode:# cashflows_multiple.setPricingEngine(bond_engine)
#wrongcode:# print(cashflows_multiple.NPV())

Upvotes: 2

Views: 1256

Answers (1)

Luigi Ballabio
Luigi Ballabio

Reputation: 4333

There are a couple of possible approaches. If you want to use an instrument, you can use a ZeroCouponBond instead of the fixed-rate one you're currently using:

bond = ZeroCouponBond(0, TARGET(), paymentamount, paymentdate)
bond.setPricingEngine(bond_engine)
print(bond.NPV())

Using an instrument will give you notifications and recalculation if the discount curve were to change, but might be overkill if you want a single pricing. In that case, you might work directly with the cashflows by using the methods of the CashFlows class:

cf = SimpleCashFlow(paymentamount, paymentdate)
print(CashFlows.npv([cf], discount_curve, True))

where the last parameter is True if you want to include any cashflow happening on today's date and False otherwise (note that this will give you a result a bit different from your calculation; that's because the payment date you used is a TARGET holiday, and the FixedRateBond constructor adjusts it to the next business day).

The above also works with several cash flows:

cfs = [SimpleCashFlow(paymentamount, paymentdate),
       SimpleCashFlow(paymentamount*0.5, paymentdate+180),
       SimpleCashFlow(paymentamount*2, paymentdate+360)]
print(CashFlows.npv(cfs, discount_curve, True))

Finally, if you want to do the same with an instrument, you can use the base Bond class and pass the cashflows directly:

custom_bond = Bond(0, TARGET(), 100.0, Date(), Date(), cfs)
custom_bond.setPricingEngine(bond_engine)
print(custom_bond.NPV())

this works but is kind of a kludge: the bond uses the passed cashflows directly and ignores the passed face amount and maturity date.

Upvotes: 6

Related Questions