Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
fixedbmaswap.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2018 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19/*! \file fixedbmaswap.hpp
20 \brief fixed vs averaged bma swap
21
22 \ingroup instruments
23*/
24
25#include <ql/cashflows/fixedratecoupon.hpp>
26#include <ql/currencies/america.hpp>
27#include <ql/pricingengines/swap/discountingswapengine.hpp>
28#include <ql/time/daycounters/thirty360.hpp>
30
31using namespace QuantLib;
32
33namespace QuantExt {
34
36 // Fixed leg
37 const Schedule& fixedSchedule, Rate fixedRate, const DayCounter& fixedDayCount,
38 // BMA leg
39 const Schedule& bmaSchedule, const QuantLib::ext::shared_ptr<BMAIndex>& bmaIndex,
40 const DayCounter& bmaDayCount)
41 : Swap(2), type_(type), nominal_(nominal), fixedRate_(fixedRate) {
42
43 legs_[0] = FixedRateLeg(fixedSchedule)
44 .withNotionals(nominal)
45 .withCouponRates(fixedRate, fixedDayCount)
46 .withPaymentAdjustment(fixedSchedule.businessDayConvention());
47
48 legs_[1] = AverageBMALeg(bmaSchedule, bmaIndex)
49 .withNotionals(nominal)
50 .withPaymentDayCounter(bmaDayCount)
51 .withPaymentAdjustment(bmaSchedule.businessDayConvention());
52
53 for (Size j = 0; j < 2; ++j) {
54 for (Leg::iterator i = legs_[j].begin(); i != legs_[j].end(); ++i)
55 registerWith(*i);
56 }
57
58 switch (type_) {
59 case Payer:
60 payer_[0] = +1.0;
61 payer_[1] = -1.0;
62 break;
63 case Receiver:
64 payer_[0] = -1.0;
65 payer_[1] = +1.0;
66 break;
67 default:
68 QL_FAIL("Unknown BMA-swap type");
69 }
70}
71
72Real FixedBMASwap::fixedRate() const { return fixedRate_; }
73
74Real FixedBMASwap::nominal() const { return nominal_; }
75
77
78const Leg& FixedBMASwap::fixedLeg() const { return legs_[0]; }
79
80const Leg& FixedBMASwap::bmaLeg() const { return legs_[1]; }
81
83 calculate();
84 QL_REQUIRE(legBPS_[0] != Null<Real>(), "result not available");
85 return legBPS_[0];
86}
87
89 calculate();
90 QL_REQUIRE(legNPV_[0] != Null<Real>(), "result not available");
91 return legNPV_[0];
92}
93
95 calculate();
96 QL_REQUIRE(fairRate_ != Null<Rate>(), "result not available");
97 return fairRate_;
98}
99
101 calculate();
102 QL_REQUIRE(legBPS_[1] != Null<Real>(), "result not available");
103 return legBPS_[1];
104}
105
107 calculate();
108 QL_REQUIRE(legNPV_[1] != Null<Real>(), "result not available");
109 return legNPV_[1];
110}
111
112void FixedBMASwap::fetchResults(const PricingEngine::results* r) const {
113 static const Spread basisPoint = 1.0e-4;
114
115 Swap::fetchResults(r);
116
117 const FixedBMASwap::results* results = dynamic_cast<const FixedBMASwap::results*>(r);
118 if (results) { // might be a swap engine, so no error is thrown
120 } else {
121 fairRate_ = Null<Rate>();
122 }
123 if (fairRate_ == Null<Rate>()) {
124 // calculate it from other results
125 if (legBPS_[0] != Null<Real>())
126 fairRate_ = fixedRate_ - NPV_ / (legBPS_[0] / basisPoint);
127 }
128}
129
131 Swap::results::reset();
132 fairRate = Null<Rate>();
133}
134
135MakeFixedBMASwap::MakeFixedBMASwap(const Period& swapTenor, const QuantLib::ext::shared_ptr<BMAIndex>& index, Rate fixedRate,
136 const Period& forwardStart)
137 : swapTenor_(swapTenor), bmaIndex_(index), fixedRate_(fixedRate), forwardStart_(forwardStart),
138 settlementDays_(bmaIndex_->fixingDays()), fixedCalendar_(index->fixingCalendar()),
139 bmaCalendar_(index->fixingCalendar()), type_(FixedBMASwap::Payer), nominal_(1.0), bmaLegTenor_(3 * Months),
140 fixedConvention_(ModifiedFollowing), fixedTerminationDateConvention_(ModifiedFollowing),
141 bmaConvention_(ModifiedFollowing), bmaTerminationDateConvention_(ModifiedFollowing),
142 fixedRule_(DateGeneration::Backward), bmaRule_(DateGeneration::Backward), fixedEndOfMonth_(false),
143 bmaEndOfMonth_(false), fixedFirstDate_(Date()), fixedNextToLastDate_(Date()), bmaFirstDate_(Date()),
144 bmaNextToLastDate_(Date()), bmaDayCount_(index->dayCounter()) {}
145
146MakeFixedBMASwap::operator FixedBMASwap() const {
147 QuantLib::ext::shared_ptr<FixedBMASwap> swap = *this;
148 return *swap;
149}
150
151MakeFixedBMASwap::operator QuantLib::ext::shared_ptr<FixedBMASwap>() const {
152 Date startDate;
153
154 // start dates and end dates
155 if (effectiveDate_ != Date())
156 startDate = effectiveDate_;
157 else {
158 Date refDate = Settings::instance().evaluationDate();
159 // if the evaluation date is not a business day
160 // then move to the next business day
161 refDate = bmaCalendar_.adjust(refDate);
162 Date spotDate = bmaCalendar_.advance(refDate, settlementDays_ * Days);
163 startDate = spotDate + forwardStart_;
164 if (forwardStart_.length() < 0)
165 startDate = bmaCalendar_.adjust(startDate, Preceding);
166 else
167 startDate = bmaCalendar_.adjust(startDate, Following);
168 }
169
170 Date endDate = terminationDate_;
171 if (endDate == Date()) {
172 if (bmaEndOfMonth_)
173 endDate = bmaCalendar_.advance(startDate, swapTenor_, ModifiedFollowing, bmaEndOfMonth_);
174 else
175 endDate = startDate + swapTenor_;
176 }
177
178 const Currency& curr = bmaIndex_->currency();
179 QL_REQUIRE(curr == USDCurrency(), "Only USD is supported for fixed vs BMA swaps.");
180
181 // schedules
182
183 Period fixedTenor;
184 if (fixedTenor_ != Period())
185 fixedTenor = fixedTenor_;
186 else
187 // Default according to Bloomberg & OpenGamma
188 fixedTenor = 6 * Months;
189
190 Schedule fixedSchedule(startDate, endDate, fixedTenor, fixedCalendar_, fixedConvention_,
191 fixedTerminationDateConvention_, fixedRule_, fixedEndOfMonth_, fixedFirstDate_,
192 fixedNextToLastDate_);
193
194 Schedule bmaSchedule(startDate, endDate, bmaLegTenor_, bmaCalendar_, bmaConvention_, bmaTerminationDateConvention_,
195 bmaRule_, bmaEndOfMonth_, bmaFirstDate_, bmaNextToLastDate_);
196
197 DayCounter fixedDayCount;
198 if (fixedDayCount_ != DayCounter())
199 fixedDayCount = fixedDayCount_;
200 else {
201 // Default according to Bloomberg & OpenGamma
202 fixedDayCount = Thirty360(Thirty360::USA);
203 }
204
205 Rate usedFixedRate = fixedRate_;
206 if (fixedRate_ == Null<Rate>()) {
207 FixedBMASwap temp(type_, nominal_, fixedSchedule,
208 0.0, // fixed rate
209 fixedDayCount, bmaSchedule, bmaIndex_, bmaDayCount_);
210 if (engine_ != 0)
211 temp.setPricingEngine(engine_);
212 else
213 QL_FAIL("Null fixed rate and no discounting curve provided to fixed vs BMA swap.");
214 usedFixedRate = temp.fairRate();
215 }
216
217 QuantLib::ext::shared_ptr<FixedBMASwap> swap(new FixedBMASwap(type_, nominal_, fixedSchedule, usedFixedRate, fixedDayCount,
218 bmaSchedule, bmaIndex_, bmaDayCount_));
219
220 if (engine_ != 0)
221 swap->setPricingEngine(engine_);
222
223 return swap;
224}
225
228 return *this;
229}
230
232 type_ = type;
233 return *this;
234}
235
237 nominal_ = n;
238 return *this;
239}
240
242 QL_REQUIRE(tenor.units() == Months, "Average BMA Leg coupons should pay as a multiple of months.");
243 bmaLegTenor_ = tenor;
244 return *this;
245}
246
248 settlementDays_ = settlementDays;
249 effectiveDate_ = Date();
250 return *this;
251}
252
254 effectiveDate_ = effectiveDate;
255 return *this;
256}
257
259 terminationDate_ = terminationDate;
260 swapTenor_ = Period();
261 return *this;
262}
263
265 bool includeSettlementDateFlows = false;
266 engine_ = QuantLib::ext::shared_ptr<PricingEngine>(new DiscountingSwapEngine(d, includeSettlementDateFlows));
267 return *this;
268}
269
270MakeFixedBMASwap& MakeFixedBMASwap::withPricingEngine(const QuantLib::ext::shared_ptr<PricingEngine>& engine) {
271 engine_ = engine;
272 return *this;
273}
274
276 fixedTenor_ = t;
277 return *this;
278}
279
281 fixedCalendar_ = cal;
282 return *this;
283}
284
286 fixedConvention_ = bdc;
287 return *this;
288}
289
292 return *this;
293}
294
296 fixedRule_ = r;
297 return *this;
298}
299
301 fixedEndOfMonth_ = flag;
302 return *this;
303}
304
306 fixedFirstDate_ = d;
307 return *this;
308}
309
312 return *this;
313}
314
316 fixedDayCount_ = dc;
317 return *this;
318}
319} // namespace QuantExt
QuantLib::ext::shared_ptr< PricingEngine > engine_
Definition: cdsoption.cpp:78
swap paying a fixed rate against BMA coupons
Type type() const
"payer" or "receiver" refer to the BMA leg
const Leg & bmaLeg() const
Real fixedLegBPS() const
FixedBMASwap(Type type, Real nominal, const Schedule &fixedSchedule, Rate fixedRate, const DayCounter &fixedDayCount, const Schedule &bmaSchedule, const QuantLib::ext::shared_ptr< BMAIndex > &bmaIndex, const DayCounter &bmaDayCount)
const Leg & fixedLeg() const
void fetchResults(const PricingEngine::results *) const override
Real fixedLegNPV() const
FixedBMASwap::Type type_
MakeFixedBMASwap & withFixedLegNextToLastDate(const Date &d)
BusinessDayConvention fixedConvention_
MakeFixedBMASwap & withFixedLegTenor(const Period &t)
MakeFixedBMASwap & withPricingEngine(const QuantLib::ext::shared_ptr< PricingEngine > &engine)
MakeFixedBMASwap & withFixedLegRule(DateGeneration::Rule r)
MakeFixedBMASwap & withTerminationDate(const Date &)
MakeFixedBMASwap & withType(FixedBMASwap::Type type)
MakeFixedBMASwap & withFixedLegFirstDate(const Date &d)
MakeFixedBMASwap & withFixedLegDayCount(const DayCounter &dc)
MakeFixedBMASwap & withDiscountingTermStructure(const Handle< YieldTermStructure > &discountCurve)
MakeFixedBMASwap & withFixedLegTerminationDateConvention(BusinessDayConvention bdc)
QuantLib::ext::shared_ptr< PricingEngine > engine_
MakeFixedBMASwap & withSettlementDays(Natural settlementDays)
DateGeneration::Rule fixedRule_
MakeFixedBMASwap & withFixedLegConvention(BusinessDayConvention bdc)
MakeFixedBMASwap & withEffectiveDate(const Date &)
MakeFixedBMASwap & withNominal(Real n)
MakeFixedBMASwap & withFixedLegEndOfMonth(bool flag=true)
MakeFixedBMASwap & withBMALegTenor(const Period &tenor)
BusinessDayConvention fixedTerminationDateConvention_
MakeFixedBMASwap(const Period &swapTenor, const QuantLib::ext::shared_ptr< BMAIndex > &bmaIndex, Rate fixedRate=Null< Rate >(), const Period &forwardStart=0 *Days)
MakeFixedBMASwap & receiveFixed(bool flag=true)
MakeFixedBMASwap & withFixedLegCalendar(const Calendar &cal)
fixed vs averaged bma swap