Coverage Report

Created: 2026-10-31 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/pricingengines/bond/riskybondengine.cpp
Line
Count
Source
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
 <https://www.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
27
namespace QuantLib {
28
29
    RiskyBondEngine::RiskyBondEngine(Handle<DefaultProbabilityTermStructure> defaultTS,
30
                                     Real recoveryRate,
31
                                     Handle<YieldTermStructure> yieldTS)
32
0
    : defaultTS_(std::move(defaultTS)), 
33
0
      recoveryRate_(recoveryRate), 
34
0
      yieldTS_(std::move(yieldTS)) {
35
0
        registerWith(defaultTS_);
36
0
        registerWith(yieldTS_);
37
0
    }
38
39
0
    void RiskyBondEngine::calculate() const {
40
0
        Date npvDate = yieldTS()->referenceDate();
41
0
        Date settlementDate = arguments_.settlementDate;
42
0
        Date startDate = CashFlows::startDate(arguments_.cashflows);
43
0
        Date d1 = std::max(npvDate, startDate);
44
45
0
        Real NPV = 0.0;
46
0
        Real settlementValue = 0.0;
47
0
        for (auto& cf : arguments_.cashflows) {
48
0
            Date d2 = cf->date();
49
0
            if (d2 > npvDate) {
50
51
0
                Real weightedCouponAmount = cf->amount() * defaultTS()->survivalProbability(d2);
52
0
                NPV += weightedCouponAmount * yieldTS()->discount(d2);
53
0
                if (d2 > settlementDate)
54
0
                    settlementValue += weightedCouponAmount * yieldTS()->discount(d2);
55
56
0
                auto coupon = coupon_cast(cf);
57
0
                if (coupon != nullptr) {
58
0
                    Date defaultDate = d1 + (d2 - d1) / 2;
59
0
                    Real weightedRecovery = coupon->nominal() * recoveryRate() *
60
0
                                    (defaultTS()->survivalProbability(d1) -
61
0
                                     defaultTS()->survivalProbability(d2)); 
62
0
                    NPV += weightedRecovery * yieldTS()->discount(defaultDate);
63
0
                    if (d2 > settlementDate)
64
0
                        settlementValue += weightedRecovery * yieldTS()->discount(defaultDate);
65
66
0
                    d1 = d2;
67
0
                }
68
0
            }
69
0
        }
70
71
0
        results_.value = NPV;
72
0
        results_.settlementValue = settlementValue / yieldTS()->discount(settlementDate);
73
0
        results_.valuationDate = npvDate;
74
0
    }
75
76
}