Coverage Report

Created: 2025-09-04 07:11

/src/quantlib/ql/experimental/credit/nthtodefault.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2008 Roland Lichters
5
6
 This file is part of QuantLib, a free-software/open-source library
7
 for financial quantitative analysts and developers - http://quantlib.org/
8
9
 QuantLib is free software: you can redistribute it and/or modify it
10
 under the terms of the QuantLib license.  You should have received a
11
 copy of the license along with this program; if not, please email
12
 <quantlib-dev@lists.sf.net>. The license is also available online at
13
 <https://www.quantlib.org/license.shtml>.
14
15
 This program is distributed in the hope that it will be useful, but WITHOUT
16
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
 FOR A PARTICULAR PURPOSE.  See the license for more details.
18
*/
19
20
#include <ql/experimental/credit/nthtodefault.hpp>
21
#include <ql/experimental/credit/lossdistribution.hpp>
22
#include <ql/instruments/claim.hpp>
23
#include <ql/cashflows/fixedratecoupon.hpp>
24
#include <ql/termstructures/yieldtermstructure.hpp>
25
#include <ql/event.hpp>
26
#include <ql/experimental/credit/basket.hpp>
27
28
namespace QuantLib {
29
30
31
    NthToDefault::NthToDefault(
32
        const ext::shared_ptr<Basket>& basket,
33
        Size n,
34
        Protection::Side side,
35
        Schedule premiumSchedule,
36
        Rate upfrontRate,
37
        Rate premiumRate,
38
        const DayCounter& dayCounter,
39
        Real nominal,
40
        bool settlePremiumAccrual
41
        )
42
0
    : basket_(basket), n_(n),
43
0
      side_(side), nominal_(nominal),
44
0
      premiumSchedule_(std::move(premiumSchedule)), premiumRate_(premiumRate),
45
0
      upfrontRate_(upfrontRate),
46
0
      dayCounter_(dayCounter), settlePremiumAccrual_(settlePremiumAccrual)
47
0
    {
48
0
        QL_REQUIRE(n_ <= basket_->size(),
49
0
                   "NTD order provided is larger than the basket size.");
50
51
        // Basket inception must lie before contract protection start.
52
0
        QL_REQUIRE(basket->refDate() <= premiumSchedule_.startDate(),
53
            //using the start date of the schedule might be wrong, think of the CDS rule
54
0
            "Basket did not exist before contract start.");
55
56
0
        premiumLeg_ = FixedRateLeg(premiumSchedule_)
57
0
            .withNotionals(nominal)
58
0
            .withCouponRates(premiumRate, dayCounter)
59
0
            .withPaymentAdjustment(Unadjusted);
60
61
0
        registerWith(basket_);
62
0
    }
Unexecuted instantiation: QuantLib::NthToDefault::NthToDefault(boost::shared_ptr<QuantLib::Basket> const&, unsigned long, QuantLib::Protection::Side, QuantLib::Schedule, double, double, QuantLib::DayCounter const&, double, bool)
Unexecuted instantiation: QuantLib::NthToDefault::NthToDefault(boost::shared_ptr<QuantLib::Basket> const&, unsigned long, QuantLib::Protection::Side, QuantLib::Schedule, double, double, QuantLib::DayCounter const&, double, bool)
63
64
65
// SOME OF THESE ARE INLINES---------------------------------
66
0
    Size NthToDefault::basketSize() const { return basket_->size(); }
67
68
0
    bool NthToDefault::isExpired() const {
69
0
        return detail::simple_event(premiumLeg_.back()->date()).hasOccurred();
70
0
    }
71
72
0
    Rate NthToDefault::fairPremium() const {
73
0
        calculate();
74
0
        QL_REQUIRE(fairPremium_ != Null<Rate>(),
75
0
                   "fair premium not available");
76
0
        return fairPremium_;
77
0
    }
78
79
0
    Real NthToDefault::premiumLegNPV() const {
80
0
        calculate();
81
0
        QL_REQUIRE(premiumValue_ != Null<Rate>(),
82
0
                   "premium leg not available");
83
0
        QL_REQUIRE(upfrontPremiumValue_ != Null<Rate>(),
84
0
                   "upfront value not available");
85
0
        return premiumValue_ + upfrontPremiumValue_;
86
0
    }
87
88
0
    Real NthToDefault::protectionLegNPV() const {
89
0
        calculate();
90
0
        QL_REQUIRE(protectionValue_ != Null<Rate>(),
91
0
                   "protection leg not available");
92
0
        return protectionValue_;
93
0
    }
94
95
0
    Real NthToDefault::errorEstimate() const {
96
0
        calculate();
97
0
        QL_REQUIRE(errorEstimate_ != Null<Rate>(),
98
0
                   "error estimate not available");
99
0
        return errorEstimate_;
100
101
0
    }
102
103
0
    void NthToDefault::setupExpired() const {
104
0
        Instrument::setupExpired();
105
106
0
        premiumValue_ = 0.0;
107
0
        protectionValue_ = 0.0;
108
0
        upfrontPremiumValue_ = 0.0;
109
0
        fairPremium_ = 0.0;
110
0
        errorEstimate_ = 0.0;
111
0
    }
112
113
0
    void NthToDefault::setupArguments(PricingEngine::arguments* args) const {
114
0
        auto* arguments = dynamic_cast<NthToDefault::arguments*>(args);
115
0
        QL_REQUIRE(arguments != nullptr, "wrong argument type");
116
0
        arguments->basket = basket_;
117
0
        arguments->side = side_;
118
0
        arguments->premiumLeg = premiumLeg_;
119
0
        arguments->ntdOrder = n_;
120
0
        arguments->settlePremiumAccrual = settlePremiumAccrual_;
121
0
        arguments->notional = nominal_;
122
0
        arguments->premiumRate = premiumRate_;
123
0
        arguments->upfrontRate = upfrontRate_;
124
0
    }
125
126
0
    void NthToDefault::fetchResults(const PricingEngine::results* r) const {
127
0
        Instrument::fetchResults(r);
128
129
0
        const auto* results = dynamic_cast<const NthToDefault::results*>(r);
130
0
        QL_REQUIRE(results != nullptr, "wrong result type");
131
132
0
        premiumValue_ = results->premiumValue;
133
0
        protectionValue_ = results->protectionValue;
134
0
        upfrontPremiumValue_ = results->upfrontPremiumValue;
135
0
        fairPremium_ = results->fairPremium;
136
0
        errorEstimate_ = results->errorEstimate;
137
0
    }
138
139
0
    void NthToDefault::results::reset() {
140
0
        Instrument::results::reset();
141
0
        premiumValue = Null<Real>();
142
0
        protectionValue = Null<Real>();
143
0
        upfrontPremiumValue = Null<Real>();
144
0
        fairPremium = Null<Real>();
145
0
        errorEstimate = Null<Real>();
146
0
        additionalResults.clear();
147
0
    }
148
149
0
    void NthToDefault::arguments::validate() const {
150
0
        QL_REQUIRE(basket && !basket->names().empty(), "no basket given");
151
0
        QL_REQUIRE(side != Protection::Side(-1), "side not set");
152
0
        QL_REQUIRE(premiumRate != Null<Real>(), "no premium rate given");
153
0
        QL_REQUIRE(upfrontRate != Null<Real>(), "no upfront rate given");
154
0
        QL_REQUIRE(notional != Null<Real>(), "no notional given");
155
0
        QL_REQUIRE(ntdOrder != Null<Size>(), "no NTD order given");
156
0
    }
157
158
}