1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2008 Roland Lichters
5 Copyright (C) 2021 Lew Wei Hao
6
7 This file is part of QuantLib, a free-software/open-source library
8 for financial quantitative analysts and developers - http://quantlib.org/
9
10 QuantLib is free software: you can redistribute it and/or modify it
11 under the terms of the QuantLib license. You should have received a
12 copy of the license along with this program; if not, please email
13 <quantlib-dev@lists.sf.net>. The license is also available online at
14 <http://quantlib.org/license.shtml>.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the license for more details.
19*/
20
21#include <ql/pricingengines/bond/riskybondengine.hpp>
22#include <ql/cashflows/cashflows.hpp>
23#include <ql/cashflows/coupon.hpp>
24#include <utility>
25
26
27namespace QuantLib {
28
29 RiskyBondEngine::RiskyBondEngine(Handle<DefaultProbabilityTermStructure> defaultTS,
30 Real recoveryRate,
31 Handle<YieldTermStructure> yieldTS)
32 : defaultTS_(std::move(defaultTS)),
33 recoveryRate_(recoveryRate),
34 yieldTS_(std::move(yieldTS)) {
35 registerWith(h: defaultTS_);
36 registerWith(h: yieldTS_);
37 }
38
39 void RiskyBondEngine::calculate() const {
40 Date npvDate = yieldTS()->referenceDate();
41 Date settlementDate = arguments_.settlementDate;
42 Date startDate = CashFlows::startDate(leg: arguments_.cashflows);
43 Date d1 = std::max(a: npvDate, b: startDate);
44
45 Real NPV = 0.0;
46 Real settlementValue = 0.0;
47 for (auto& cf : arguments_.cashflows) {
48 Date d2 = cf->date();
49 if (d2 > npvDate) {
50
51 Real weightedCouponAmount = cf->amount() * defaultTS()->survivalProbability(d: d2);
52 NPV += weightedCouponAmount * yieldTS()->discount(d: d2);
53 if (d2 > settlementDate)
54 settlementValue += weightedCouponAmount * yieldTS()->discount(d: d2);
55
56 auto coupon = ext::dynamic_pointer_cast<Coupon>(r: cf);
57 if (coupon != nullptr) {
58 Date defaultDate = d1 + (d2 - d1) / 2;
59 Real weightedRecovery = coupon->nominal() * recoveryRate() *
60 (defaultTS()->survivalProbability(d: d1) -
61 defaultTS()->survivalProbability(d: d2));
62 NPV += weightedRecovery * yieldTS()->discount(d: defaultDate);
63 if (d2 > settlementDate)
64 settlementValue += weightedRecovery * yieldTS()->discount(d: defaultDate);
65
66 d1 = d2;
67 }
68 }
69 }
70
71 results_.value = NPV;
72 results_.settlementValue = settlementValue / yieldTS()->discount(d: settlementDate);
73 results_.valuationDate = npvDate;
74 }
75
76}
77

source code of quantlib/ql/pricingengines/bond/riskybondengine.cpp