`Bond`

class. The description of the individual bonds will follow in a future post.
`Bond`

ClassThe `Bond`

class has two constructors.

Bond(Natural settlementDays, const Calendar& calendar, const Date& issueDate = Date(), const Leg& coupons = Leg()); Bond(Natural settlementDays, const Calendar& calendar, Real faceAmount, const Date& maturityDate, const Date& issueDate = Date(), const Leg& cashflows = Leg());

The first of these constructors is the preferred method of creating a Bond object. `settlementDays`

specifies the number of days, counted from the evaluation date, until the settlement of the bond. The `calendar`

prescribes which calendar should be used in date calculations. An optional parameter, the `issueDate`

, allows the setting of the date at which the bond is issued. Finally the coupon payments can be specified in the fourth parameter. Note that `Leg`

is simply a `std::vector`

of shared pointers to `CashFlow`

objects.

typedef std::vector<boost::shared_ptr<CashFlow> > Leg;

The second constructor allows the creation of non-amortizing bonds only. In addition to the parameters of the first constructor, one needs to specify the face value of the bond and the maturity date.

The `Bond`

class implements the abstract `isExpired()`

method from the `Instrument`

class.

bool isExpired() const;

This method returns true if the cash flows are expired. The method simply calls the static `CashFlows::isExpired()`

method, passing the `cashflows`

as argument.

Two inspectors are provided that simply return the values supplied in the constructor.

Natural settlementDays() const; const Calendar& calendar() const;

A `Bond`

will contain different types of cash flows. The coupons are paid according to the `cashflows`

passed to the bond in the constructor. In addition `Bond`

will calculate and add redemption cash flows. Two methods will return a reference to a cash flow vector.

const Leg& cashflows() const; const Leg& redemptions() const;

The `cashflows()`

method returns a `Leg`

contining all the cash flows, including the any amortizing payments and redemption cash flows. In contrast, `redemptions()`

will only return the amortizing payments and redemption cash flows.

Redemptions are calculated automatically if the first constructor has been used to create the `Bond`

. In this case, the notional values of all the `Coupon`

s passed to the constructor are inspected. On dates where the notional changes, there will be an amortizing cash flow, encoded by the class `AmortizingPayment`

. On the date of the last cash flow a redemption cash flow is added, encoded by the class `Redemption`

. By default, all amortizing payments and redemption cash flows will assume a redemption rate of 100%. Specific bond types, derived from the `Bond`

class can override this behaviour and set specific redemption rates.

The last cash flow in the redemptions cash flow vector can be obtained by calling `redemption()`

.

const boost::shared_ptr<CashFlow>& redemption() const;

A vector of the distinct notional values of the coupons is returned by the `notionals()`

method. This is simply a vector of `Real`

numbers, not associated with any dates. The `notionals`

vector will not contain an entry for each cash flow but only entries for distinct notional values.

const std::vector<Real>& notionals() const; virtual Real notional(Date d = Date()) const; bool isTradable(Date d = Date()) const;

The `notional()`

method takes a date and returns the corresponding notional value for that date. If the date is during the life time of the bond then the function returns the notional of the last coupon that came before or on that date. If the date falls after the last cash flow a value of 0.0 is returned. For dates before the first cash flow this function returns the notional of the first cash flow. If no date is specified then `Settings.evaluationDate()`

will be used. **Note** that `notional`

is declared virtual. Specific bond types may override the behaviour.

Finally `isTradable()`

will return `true`

if the notional value for the bond on the given date is non-zero.

Some important dates are evaluated by the following methods.

Date issueDate() const; Date startDate() const; Date maturityDate() const; Date settlementDate(Date d = Date()) const;

The method `issueDate()`

simply returns the value of the issue date passed to the `Bond`

in the constructor. The other two methods evaluate the cash flows vector to find the start date and the maturity date of the bond. In fact they don’t really do anything themselves. They simply pass the `cashflows`

vector to the static methods `CashFlows::startDate()`

and `CashFlows::maturityDate()`

. These methods return the dates of the first cash flow and the last cash flow respectively. For further information read the information on the `CashFlows`

utility class.

The `settlementDate()`

is calculated from the given date by adding the number of settlement days to the date. If an issue date has been specified and it lies after the settlement date calculated in this way, then the issue date is returned instead.

The following methods return cash flows dates and the coupon rates that immediatly precede or follow a given date.

Date Bond::previousCashFlowDate(Date settlement) const; Date Bond::nextCashFlowDate(Date settlement) const; Rate Bond::previousCouponRate(Date settlement) const; Rate Bond::nextCouponRate(Date settlement) const;

The method `previousCashFlowDate`

will return the date of the last cash flow on or before the given date while `nextCashFlowDate`

will return the date of the next cash flow after the given date. The functions `previousCouponRate`

and `nextCouponRate`

will return the coupon rate of the previous or the next coupon in the leg, with respect to the settlement date. As above, all four methods simply forward the call to the corresponding static methods in the `CashFlows`

utility class.

The `Bond`

class provides a number of methods useful for the valuation of the bond.

virtual Real accruedAmount(Date d = Date()) const;

This method will return the accrued amount for a given date. This will call the `accruedAmount`

static method in the `CashFlows`

utility class, passing the `cashflows`

array as argument. This class will find the next `Coupon`

cash flow on or after the given date. Then the accrued amounts for all the cash flows on the date of that cash flow are added up. The result is then divided by the notional of the date given.

$$I_A \equiv I_{A,\mathrm{Bond}} = \frac{100}{N} I_{A,\mathrm{Cash Flows}}$$

Here \(N\) is the notional specified in percent and \(I_{A,\mathrm{Bond}}\) is the accrued amount of the bond and \(I_{A,\mathrm{Cash Flows}}\) is the accrued amount of the cash flows.

The following method returns the settlement value of the bond.

Real settlementValue() const; Real settlementValue(Real cleanPrice) const;

The method `settlementValue()`

that doesn’t take arguments invokes the pricing engine of the bond which will calculate a settlement value. This value is then returned. In order to use this method, a `PricingEngine`

has to be supplied to the bond and the result will depend on the implementation of the pricing engine.

If the clean price of the bond is known then the settlement value can simply be calculated using the formula

$$\mathrm{settlement value} = \frac{N}{100} \left(\mathrm{clean price} + I_A\right)$$

The theoretical prices of the bond are given by the following three methods.

Real dirtyPrice() const; Real cleanPrice() const; Rate yield(const DayCounter& dc, Compounding comp, Frequency freq, Real accuracy = 1.0e-8, Size maxEvaluations = 100) const;

The theoretical dirty price is calculated from the pricing engine’s settlement value by dividing it by the notional.

$$\mathrm{dirty price} = \frac{100}{N} \mathrm{settlement value}$$

The clean price is then calculated from the dirty price by subtracting the accrued amount from it.

$$\mathrm{clean price} = \mathrm{dirty price} – I_A = \frac{100}{N} \mathrm{settlement value} – I_A$$

Finally the theoretical yield is calculated using the theoretical settlement value. The yield method passes the calculation on to the `CashFlows`

utility class.

If a yield is given then the following two methods can be used to calculate the clean price and the dirty price.

Real cleanPrice(Rate yield, const DayCounter& dc, Compounding comp, Frequency freq, Date settlementDate = Date()) const; Real dirtyPrice(Rate yield, const DayCounter& dc, Compounding comp, Frequency freq, Date settlementDate = Date()) const;

This `cleanPrice`

method constructs an `InteresRate`

object from the yield, day counter, compounding rule and the frequency. This interest rate is then used to calculate the NPV of the cash flows using the static `npv`

method in the `CashFlows`

utility class. The clean price is then calculated by dividing by the current notional of the bond.

$$\mathrm{clean price} = \frac{100}{N} \mathrm{NPV} – I_A$$

The `dirtyPrice`

method simply calls `cleanPrice`

and then calculates the dirty price according to

$$\mathrm{dirty price} = \mathrm{clean price} + I_A$$

If, on the other hand, the clean price of the bond is known, then we can calculate the yield.

Rate yield(Real cleanPrice, const DayCounter& dc, Compounding comp, Frequency freq, Date settlementDate = Date(), Real accuracy = 1.0e-8, Size maxEvaluations = 100) const;

From the clean price passed to the method, an NPV is calculated according to

$$\mathrm{NPV} = \frac{N}{100} \left(\mathrm{clean price} + I_A\right)$$

This NPV is passed to the `yield`

method in the `CashFlows`

utility class to calculate the yield of the bond.

QuantLib provides a number of functions that calculate the NPV of a series of cash flows. These are defined as static methods inside the `CashFlows`

class. The simplest calculation of the NPV will take a constant interest rate over the period of the cash flows.

static Real npv(const Leg& leg, const InterestRate& yield, bool includeSettlementDateFlows, Date settlementDate = Date(), Date npvDate = Date()); static Real npv(const Leg& leg, Rate yield, const DayCounter& dayCounter, Compounding compounding, Frequency frequency, bool includeSettlementDateFlows, Date settlementDate = Date(), Date npvDate = Date());

The first function takes a `Leg`

of cash flows and an interest rate that defines the yield. The interest rate is passed using the InterestRate class. In short, `InterestRate `

contains information about interest rates such as the rate itself, the compounding rule, the frequency and a day counting convention. Note that this allows the `InterestRate`

class to calculate a discount factor for a given time interval. The settlement date can be passed as fourth argument. Only cash flows that occur on or after the settlement date will contribute to the NPV. The inclusion of cash flows on the settlement date is governed by the flag `includeSettlementDateFlows`

. As always the parameters are simply passed to the `hasOccured`

method of the cash flow to determine if the cash flow has already occurred. If the settlement date is not set the global evaluation date will be used. The last parameter can be used to specify a different date to which the cash flows are discount back to. This means that the discounting factor is calculated using `npvDate`

. If `npvDate`

is not set, the settlement date will be taken.

Note that the interest rate is calculated by compounding the factor calculated for the cash flow intervals. What this means is that the discount rate is calculated using the compounding rules defined in the `InteresRate yield`

object for the intervals between two cash flows. Let’s say that \(d_i\) and \(d_{i-1}\) are the dates of two successive cash flows, then the interval discount factor is calculated as a function of these two dates.

$$\mathrm{Discount Factor}_i = DInt_{i, i-1}(d_i, d_{i-1})$$

Here \(DInt\) is the discount rate calculated by the `InterestRate`

object and might use simple, continuous compounding or use a compounding discount factor with a frequency that does not necessarily match the frequency of the cash flows. To get the discount factor of a cash flow these interval discount factors are compounded by multiplying them together.

$$D_i = \prod_{i=1}^{N} DInt_{i, i-1}(d_i, d_{i-1})$$

The final net present value is then calculated using the individual discount factors.

$$\mathrm{NPV} = \sum_{i=1}^{N} D_i \times R_i$$

In many realistic cases, one won’t have a constant interest rate over the period of the cash flows. In this case the NPV of a `Leg`

has to be calculated using a yield curve. In QuantLib yield curves are represented by `YieldTermStructure`

.The `CashFlows`

class provides a static method for evaluating the NPV in this case.

Real npv(const Leg& leg, const YieldTermStructure& discountCurve, bool includeSettlementDateFlows, Date settlementDate = Date(), Date npvDate = Date());

As with the two methods described above, `includeSettlementDateFlows`

determines if cash flows on the settlement date are taken into account for the calculation. The date `settlementDate`

is the settlement date which enters into the `hasOccured`

method of the cash flows. Again, this means only cash flows on or after the settlement date are included in the calculation. The `npvDate`

is a date that the NPV is discounted back to. To understand what the function calculates, assume that \(D(d_i)\) is the discount factor returned by the yield curve for a given date \(d_i\). This discount factor is simply the return value of the `discount`

method of `YieldTermStructure`

. The NPV is then calculated using the formula

$$\mathrm{NPV} = \frac{\sum_{i=1}^{N} D(d_i) \times R_i}{D(\mathrm{npvDate})}$$

The last function for calculating the NPV takes the zero spread of the cash flows into account.

Real npv(const Leg& leg, const boost::shared_ptr<YieldTermStructure>& discount, Spread zSpread, const DayCounter& dayCounter, Compounding compounding, Frequency frequency, bool includeSettlementDateFlows, Date settlementDate = Date(), Date npvDate = Date());

This function uses the zero spread, given by `zSpread`

, the day counter, the compounding rule and the frequency to construct a modified yield curve. This modified yield curve is simply the original curve passed to the function with an added zero spread. The modified curve is then passed to the previous function for calculating the NPV.