/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 | | } |