Coverage Report

Created: 2026-06-23 06:40

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& calendar = exerciseCalendar_.empty()
57
0
            ? swapIndex_->fixingCalendar()
58
0
            : exerciseCalendar_;
59
0
        Date refDate = Settings::instance().evaluationDate();
60
        // if the evaluation date is not a business day
61
        // then move to the next business day
62
0
        refDate = calendar.adjust(refDate);
63
0
        if (fixingDate_ == Date())
64
0
            fixingDate_ = calendar.advance(refDate, optionTenor_,
65
0
                                           optionConvention_);
66
0
        if (exerciseDate_ == Date()) {
67
0
            exercise_ = ext::shared_ptr<Exercise>(new
68
0
                EuropeanExercise(fixingDate_));
69
0
        } else {
70
0
            QL_REQUIRE(exerciseDate_ <= fixingDate_,
71
0
                       "exercise date (" << exerciseDate_ << ") must be less "
72
0
                       "than or equal to fixing date (" << fixingDate_ << ")");
73
0
            exercise_ = ext::shared_ptr<Exercise>(new
74
0
                EuropeanExercise(exerciseDate_));
75
0
        }
76
77
0
        Rate usedStrike;
78
0
        ext::shared_ptr<OvernightIndexedSwapIndex> OIswap_index = ext::dynamic_pointer_cast<OvernightIndexedSwapIndex>(swapIndex_);
79
0
        if (strike_ == Null<Rate>()) {
80
            // ATM on curve(s) attached to index
81
0
            QL_REQUIRE(!swapIndex_->forwardingTermStructure().empty(),
82
0
                       "null term structure set to this instance of " <<
83
0
                       swapIndex_->name());
84
0
            if (OIswap_index) {
85
0
                auto temp = OIswap_index->underlyingSwap(fixingDate_);
86
0
                temp->setPricingEngine(
87
0
                    ext::make_shared<DiscountingSwapEngine>(
88
0
                        swapIndex_->exogenousDiscount()
89
0
                        ? swapIndex_->discountingTermStructure()
90
0
                        : swapIndex_->forwardingTermStructure(),
91
0
                        false
92
0
                    )
93
0
                );
94
0
                usedStrike = temp->fairRate();
95
0
            } else {
96
0
                auto temp = swapIndex_->underlyingSwap(fixingDate_);
97
0
                temp->setPricingEngine(
98
0
                    ext::make_shared<DiscountingSwapEngine>(
99
0
                        swapIndex_->exogenousDiscount()
100
0
                        ? swapIndex_->discountingTermStructure()
101
0
                        : swapIndex_->forwardingTermStructure(),
102
0
                        false
103
0
                    )
104
0
                );
105
0
                usedStrike = temp->fairRate();
106
0
            }
107
0
        } else {
108
0
            usedStrike = strike_;
109
0
        }
110
111
0
        BusinessDayConvention bdc = swapIndex_->fixedLegConvention();
112
0
        if (OIswap_index) {
113
0
            underlyingSwap_ =
114
0
                (ext::shared_ptr<OvernightIndexedSwap>)(
115
0
                    MakeOIS(swapIndex_->tenor(),
116
0
                            OIswap_index->overnightIndex(), usedStrike)
117
0
                    .withEffectiveDate(swapIndex_->valueDate(fixingDate_))
118
0
                    .withPaymentCalendar(swapIndex_->fixingCalendar())
119
0
                    .withFixedLegDayCount(swapIndex_->dayCounter())
120
0
                    .withPaymentAdjustment(bdc)
121
0
                    .withFixedLegConvention(bdc)
122
0
                    .withFixedLegTerminationDateConvention(bdc)
123
0
                    .withType(underlyingType_)
124
0
                    .withNominal(nominal_)
125
0
                    );
126
0
        } else {
127
0
            underlyingSwap_ =
128
0
                (ext::shared_ptr<VanillaSwap>)(
129
0
                    MakeVanillaSwap(swapIndex_->tenor(),
130
0
                                    swapIndex_->iborIndex(), usedStrike)
131
0
                    .withEffectiveDate(swapIndex_->valueDate(fixingDate_))
132
0
                    .withFixedLegCalendar(swapIndex_->fixingCalendar())
133
0
                    .withFixedLegDayCount(swapIndex_->dayCounter())
134
0
                    .withFixedLegTenor(swapIndex_->fixedLegTenor())
135
0
                    .withFixedLegConvention(bdc)
136
0
                    .withFixedLegTerminationDateConvention(bdc)
137
0
                    .withType(underlyingType_)
138
0
                    .withNominal(nominal_)
139
0
                    .withIndexedCoupons(useIndexedCoupons_)
140
0
                    );
141
0
        }
142
0
        ext::shared_ptr<Swaption> swaption = ext::make_shared<Swaption>(
143
0
            underlyingSwap_, exercise_, delivery_, settlementMethod_);
144
0
        swaption->setPricingEngine(engine_);
145
0
        return swaption;
146
0
    }
147
148
0
    MakeSwaption& MakeSwaption::withSettlementType(Settlement::Type delivery) {
149
0
        delivery_ = delivery;
150
0
        return *this;
151
0
    }
152
153
    MakeSwaption& MakeSwaption::withSettlementMethod(
154
0
        Settlement::Method settlementMethod) {
155
0
        settlementMethod_ = settlementMethod;
156
0
        return *this;
157
0
    }
158
159
    MakeSwaption&
160
0
    MakeSwaption::withOptionConvention(BusinessDayConvention bdc) {
161
0
        optionConvention_ = bdc;
162
0
        return *this;
163
0
    }
164
165
0
    MakeSwaption& MakeSwaption::withExerciseDate(const Date& date) {
166
0
        exerciseDate_ = date;
167
0
        return *this;
168
0
    }
169
170
0
    MakeSwaption& MakeSwaption::withExerciseCalendar(const Calendar& cal) {
171
0
        exerciseCalendar_ = cal;
172
0
        return *this;
173
0
    }
174
175
0
    MakeSwaption& MakeSwaption::withUnderlyingType(const Swap::Type type) {
176
0
        underlyingType_ = type;
177
0
        return *this;
178
0
    }
179
180
    MakeSwaption& MakeSwaption::withPricingEngine(
181
0
                             const ext::shared_ptr<PricingEngine>& engine) {
182
0
        engine_ = engine;
183
0
        return *this;
184
0
    }
185
186
0
    MakeSwaption& MakeSwaption::withNominal(Real n) {
187
0
        nominal_ = n;
188
0
        return *this;
189
0
    }
190
191
0
    MakeSwaption& MakeSwaption::withIndexedCoupons(const ext::optional<bool>& b) {
192
0
        useIndexedCoupons_ = b;
193
0
        return *this;
194
0
    }
195
196
0
    MakeSwaption& MakeSwaption::withAtParCoupons(bool b) {
197
0
        useIndexedCoupons_ = !b;
198
0
        return *this;
199
0
    }
200
201
}