Coverage Report

Created: 2025-12-08 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/instruments/makeswaption.cpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2007, 2008, 2014 Ferdinando Ametrano
5
 Copyright (C) 2007 Giorgio Facchinetti
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/cashflows/cashflows.hpp>
22
#include <ql/exercise.hpp>
23
#include <ql/indexes/swapindex.hpp>
24
#include <ql/instruments/makeois.hpp>
25
#include <ql/instruments/makeswaption.hpp>
26
#include <ql/instruments/makevanillaswap.hpp>
27
#include <ql/pricingengines/swap/discountingswapengine.hpp>
28
#include <ql/optional.hpp>
29
#include <ql/settings.hpp>
30
#include <utility>
31
32
namespace QuantLib {
33
34
    MakeSwaption::MakeSwaption(ext::shared_ptr<SwapIndex> swapIndex,
35
                               const Period& optionTenor,
36
                               Rate strike)
37
0
    : swapIndex_(std::move(swapIndex)), delivery_(Settlement::Physical),
38
0
      settlementMethod_(Settlement::PhysicalOTC), optionTenor_(optionTenor),
39
0
      optionConvention_(ModifiedFollowing), strike_(strike),
40
0
      underlyingType_(Swap::Payer), nominal_(1.0) {}
41
42
    MakeSwaption::MakeSwaption(ext::shared_ptr<SwapIndex> swapIndex,
43
                               const Date& fixingDate,
44
                               Rate strike)
45
0
    : swapIndex_(std::move(swapIndex)), delivery_(Settlement::Physical),
46
0
      settlementMethod_(Settlement::PhysicalOTC), optionConvention_(ModifiedFollowing),
47
0
      fixingDate_(fixingDate), strike_(strike), underlyingType_(Swap::Payer) {}
48
49
0
    MakeSwaption::operator Swaption() const {
50
0
        ext::shared_ptr<Swaption> swaption = *this;
51
0
        return *swaption;
52
0
    }
53
54
0
    MakeSwaption::operator ext::shared_ptr<Swaption>() const {
55
56
0
        const Calendar& fixingCalendar = swapIndex_->fixingCalendar();
57
0
        Date refDate = Settings::instance().evaluationDate();
58
        // if the evaluation date is not a business day
59
        // then move to the next business day
60
0
        refDate = fixingCalendar.adjust(refDate);
61
0
        if (fixingDate_ == Date())
62
0
            fixingDate_ = fixingCalendar.advance(refDate, optionTenor_,
63
0
                                                 optionConvention_);
64
0
        if (exerciseDate_ == Date()) {
65
0
            exercise_ = ext::shared_ptr<Exercise>(new
66
0
                EuropeanExercise(fixingDate_));
67
0
        } else {
68
0
            QL_REQUIRE(exerciseDate_ <= fixingDate_,
69
0
                       "exercise date (" << exerciseDate_ << ") must be less "
70
0
                       "than or equal to fixing date (" << fixingDate_ << ")");
71
0
            exercise_ = ext::shared_ptr<Exercise>(new
72
0
                EuropeanExercise(exerciseDate_));
73
0
        }
74
75
0
        Rate usedStrike;
76
0
        ext::shared_ptr<OvernightIndexedSwapIndex> OIswap_index = ext::dynamic_pointer_cast<OvernightIndexedSwapIndex>(swapIndex_);
77
0
        if (strike_ == Null<Rate>()) {
78
            // ATM on curve(s) attached to index
79
0
            QL_REQUIRE(!swapIndex_->forwardingTermStructure().empty(),
80
0
                       "null term structure set to this instance of " <<
81
0
                       swapIndex_->name());
82
0
            if (OIswap_index) {
83
0
                auto temp = OIswap_index->underlyingSwap(fixingDate_);
84
0
                temp->setPricingEngine(
85
0
                    ext::make_shared<DiscountingSwapEngine>(
86
0
                        swapIndex_->exogenousDiscount()
87
0
                        ? swapIndex_->discountingTermStructure()
88
0
                        : swapIndex_->forwardingTermStructure(),
89
0
                        false
90
0
                    )
91
0
                );
92
0
                usedStrike = temp->fairRate();
93
0
            } else {
94
0
                auto temp = swapIndex_->underlyingSwap(fixingDate_);
95
0
                temp->setPricingEngine(
96
0
                    ext::make_shared<DiscountingSwapEngine>(
97
0
                        swapIndex_->exogenousDiscount()
98
0
                        ? swapIndex_->discountingTermStructure()
99
0
                        : swapIndex_->forwardingTermStructure(),
100
0
                        false
101
0
                    )
102
0
                );
103
0
                usedStrike = temp->fairRate();
104
0
            }
105
0
        } else {
106
0
            usedStrike = strike_;
107
0
        }
108
109
0
        BusinessDayConvention bdc = swapIndex_->fixedLegConvention();
110
0
        if (OIswap_index) {
111
0
            underlyingSwap_ =
112
0
                (ext::shared_ptr<OvernightIndexedSwap>)(
113
0
                    MakeOIS(swapIndex_->tenor(),
114
0
                            OIswap_index->overnightIndex(), usedStrike)
115
0
                    .withEffectiveDate(swapIndex_->valueDate(fixingDate_))
116
0
                    .withPaymentCalendar(swapIndex_->fixingCalendar())
117
0
                    .withFixedLegDayCount(swapIndex_->dayCounter())
118
0
                    .withPaymentAdjustment(bdc)
119
0
                    .withFixedLegConvention(bdc)
120
0
                    .withFixedLegTerminationDateConvention(bdc)
121
0
                    .withType(underlyingType_)
122
0
                    .withNominal(nominal_)
123
0
                    );
124
0
        } else {
125
0
            underlyingSwap_ =
126
0
                (ext::shared_ptr<VanillaSwap>)(
127
0
                    MakeVanillaSwap(swapIndex_->tenor(),
128
0
                                    swapIndex_->iborIndex(), usedStrike)
129
0
                    .withEffectiveDate(swapIndex_->valueDate(fixingDate_))
130
0
                    .withFixedLegCalendar(swapIndex_->fixingCalendar())
131
0
                    .withFixedLegDayCount(swapIndex_->dayCounter())
132
0
                    .withFixedLegTenor(swapIndex_->fixedLegTenor())
133
0
                    .withFixedLegConvention(bdc)
134
0
                    .withFixedLegTerminationDateConvention(bdc)
135
0
                    .withType(underlyingType_)
136
0
                    .withNominal(nominal_)
137
0
                    .withIndexedCoupons(useIndexedCoupons_)
138
0
                    );
139
0
        }
140
0
        ext::shared_ptr<Swaption> swaption = ext::make_shared<Swaption>(
141
0
            underlyingSwap_, exercise_, delivery_, settlementMethod_);
142
0
        swaption->setPricingEngine(engine_);
143
0
        return swaption;
144
0
    }
145
146
0
    MakeSwaption& MakeSwaption::withSettlementType(Settlement::Type delivery) {
147
0
        delivery_ = delivery;
148
0
        return *this;
149
0
    }
150
151
    MakeSwaption& MakeSwaption::withSettlementMethod(
152
0
        Settlement::Method settlementMethod) {
153
0
        settlementMethod_ = settlementMethod;
154
0
        return *this;
155
0
    }
156
157
    MakeSwaption&
158
0
    MakeSwaption::withOptionConvention(BusinessDayConvention bdc) {
159
0
        optionConvention_ = bdc;
160
0
        return *this;
161
0
    }
162
163
0
    MakeSwaption& MakeSwaption::withExerciseDate(const Date& date) {
164
0
        exerciseDate_ = date;
165
0
        return *this;
166
0
    }
167
168
0
    MakeSwaption& MakeSwaption::withUnderlyingType(const Swap::Type type) {
169
0
        underlyingType_ = type;
170
0
        return *this;
171
0
    }
172
173
    MakeSwaption& MakeSwaption::withPricingEngine(
174
0
                             const ext::shared_ptr<PricingEngine>& engine) {
175
0
        engine_ = engine;
176
0
        return *this;
177
0
    }
178
179
0
    MakeSwaption& MakeSwaption::withNominal(Real n) {
180
0
        nominal_ = n;
181
0
        return *this;
182
0
    }
183
184
0
    MakeSwaption& MakeSwaption::withIndexedCoupons(const ext::optional<bool>& b) {
185
0
        useIndexedCoupons_ = b;
186
0
        return *this;
187
0
    }
188
189
0
    MakeSwaption& MakeSwaption::withAtParCoupons(bool b) {
190
0
        useIndexedCoupons_ = !b;
191
0
        return *this;
192
0
    }
193
194
}