Coverage Report

Created: 2025-08-05 06:45

/src/quantlib/ql/pricingengines/swap/discountingswapengine.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) 2007, 2009 StatPro Italia srl
5
 Copyright (C) 2011 Ferdinando Ametrano
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/cashflows/cashflows.hpp>
22
#include <ql/pricingengines/swap/discountingswapengine.hpp>
23
#include <ql/utilities/dataformatters.hpp>
24
#include <ql/optional.hpp>
25
#include <utility>
26
27
namespace QuantLib {
28
29
    DiscountingSwapEngine::DiscountingSwapEngine(
30
        Handle<YieldTermStructure> discountCurve,
31
        const ext::optional<bool>& includeSettlementDateFlows,
32
        Date settlementDate,
33
        Date npvDate)
34
0
    : discountCurve_(std::move(discountCurve)),
35
0
      includeSettlementDateFlows_(includeSettlementDateFlows), settlementDate_(settlementDate),
36
0
      npvDate_(npvDate) {
37
0
        registerWith(discountCurve_);
38
0
    }
39
40
0
    void DiscountingSwapEngine::calculate() const {
41
0
        QL_REQUIRE(!discountCurve_.empty(),
42
0
                   "discounting term structure handle is empty");
43
44
0
        results_.value = 0.0;
45
0
        results_.errorEstimate = Null<Real>();
46
47
0
        Date refDate = discountCurve_->referenceDate();
48
49
0
        Date settlementDate = settlementDate_;
50
0
        if (settlementDate_==Date()) {
51
0
            settlementDate = refDate;
52
0
        } else {
53
0
            QL_REQUIRE(settlementDate>=refDate,
54
0
                       "settlement date (" << settlementDate << ") before "
55
0
                       "discount curve reference date (" << refDate << ")");
56
0
        }
57
58
0
        results_.valuationDate = npvDate_;
59
0
        if (npvDate_==Date()) {
60
0
            results_.valuationDate = refDate;
61
0
        } else {
62
0
            QL_REQUIRE(npvDate_>=refDate,
63
0
                       "npv date (" << npvDate_  << ") before "
64
0
                       "discount curve reference date (" << refDate << ")");
65
0
        }
66
0
        results_.npvDateDiscount = discountCurve_->discount(results_.valuationDate);
67
68
0
        Size n = arguments_.legs.size();
69
0
        results_.legNPV.resize(n);
70
0
        results_.legBPS.resize(n);
71
0
        results_.startDiscounts.resize(n);
72
0
        results_.endDiscounts.resize(n);
73
74
0
        bool includeRefDateFlows = includeSettlementDateFlows_ ? // NOLINT(readability-implicit-bool-conversion)
75
0
                                       *includeSettlementDateFlows_ :
76
0
                                       Settings::instance().includeReferenceDateEvents();
77
78
0
        for (Size i=0; i<n; ++i) {
79
0
            try {
80
0
                const YieldTermStructure& discount_ref = **discountCurve_;
81
0
                std::tie(results_.legNPV[i], results_.legBPS[i]) =
82
0
                    CashFlows::npvbps(arguments_.legs[i],
83
0
                                      discount_ref,
84
0
                                      includeRefDateFlows,
85
0
                                      settlementDate,
86
0
                                      results_.valuationDate);
87
0
                results_.legNPV[i] *= arguments_.payer[i];
88
0
                results_.legBPS[i] *= arguments_.payer[i];
89
90
0
                if (!arguments_.legs[i].empty()) {
91
0
                    Date d1 = CashFlows::startDate(arguments_.legs[i]);
92
0
                    if (d1>=refDate)
93
0
                        results_.startDiscounts[i] = discountCurve_->discount(d1);
94
0
                    else
95
0
                        results_.startDiscounts[i] = Null<DiscountFactor>();
96
97
0
                    Date d2 = CashFlows::maturityDate(arguments_.legs[i]);
98
0
                    if (d2>=refDate)
99
0
                        results_.endDiscounts[i] = discountCurve_->discount(d2);
100
0
                    else
101
0
                        results_.endDiscounts[i] = Null<DiscountFactor>();
102
0
                } else {
103
0
                    results_.startDiscounts[i] = Null<DiscountFactor>();
104
0
                    results_.endDiscounts[i] = Null<DiscountFactor>();
105
0
                }
106
107
0
            } catch (std::exception &e) {
108
0
                QL_FAIL(io::ordinal(i+1) << " leg: " << e.what());
109
0
            }
110
0
            results_.value += results_.legNPV[i];
111
0
        }
112
0
    }
113
114
}