Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
crossccybasismtmresetswap.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#include <boost/assign/list_of.hpp>
20using boost::assign::list_of;
21
22#include <ql/cashflows/iborcoupon.hpp>
23#include <ql/cashflows/simplecashflow.hpp>
24
29
30namespace QuantExt {
31
33 Real foreignNominal, const Currency& foreignCurrency, const Schedule& foreignSchedule,
34 const QuantLib::ext::shared_ptr<IborIndex>& foreignIndex, Spread foreignSpread, const Currency& domesticCurrency,
35 const Schedule& domesticSchedule, const QuantLib::ext::shared_ptr<IborIndex>& domesticIndex, Spread domesticSpread,
36 const QuantLib::ext::shared_ptr<FxIndex>& fxIdx, bool receiveDomestic, Size foreignPaymentLag, Size domesticPaymentLag,
37 boost::optional<bool> foreignIncludeSpread, boost::optional<Period> foreignLookback,
38 boost::optional<Size> foreignFixingDays, boost::optional<Size> foreignRateCutoff,
39 boost::optional<bool> foreignIsAveraged, boost::optional<bool> domesticIncludeSpread,
40 boost::optional<Period> domesticLookback, boost::optional<Size> domesticFixingDays,
41 boost::optional<Size> domesticRateCutoff, boost::optional<bool> domesticIsAveraged, const bool telescopicValueDates,
42 const bool fairSpreadLegIsForeign)
43 : CrossCcySwap(3), foreignNominal_(foreignNominal), foreignCurrency_(foreignCurrency),
44 foreignSchedule_(foreignSchedule), foreignIndex_(foreignIndex), foreignSpread_(foreignSpread),
45 domesticCurrency_(domesticCurrency), domesticSchedule_(domesticSchedule), domesticIndex_(domesticIndex),
46 domesticSpread_(domesticSpread), fxIndex_(fxIdx), receiveDomestic_(receiveDomestic),
47 foreignPaymentLag_(foreignPaymentLag), domesticPaymentLag_(domesticPaymentLag),
48 foreignIncludeSpread_(foreignIncludeSpread), foreignLookback_(foreignLookback),
49 foreignFixingDays_(foreignFixingDays), foreignRateCutoff_(foreignRateCutoff),
50 foreignIsAveraged_(foreignIsAveraged), domesticIncludeSpread_(domesticIncludeSpread),
51 domesticLookback_(domesticLookback), domesticFixingDays_(domesticFixingDays),
52 domesticRateCutoff_(domesticRateCutoff), domesticIsAveraged_(domesticIsAveraged),
53 telescopicValueDates_(telescopicValueDates), fairSpreadLegIsForeign_(fairSpreadLegIsForeign) {
54 registerWith(foreignIndex_);
55 registerWith(domesticIndex_);
56 registerWith(fxIndex_);
57 initialize();
58}
59
61 // Pay (foreign) leg
62 if (auto on = QuantLib::ext::dynamic_pointer_cast<QuantLib::OvernightIndex>(foreignIndex_)) {
63 // ON leg
73 } else {
83 }
84 } else {
85 // Ibor leg
86 legs_[0] = IborLeg(foreignSchedule_, foreignIndex_)
90 }
91 receiveDomestic_ ? payer_[0] = -1.0 : payer_[0] = +1.0;
92
94 // Pay leg notional exchange at start.
95 Date initialPayDate = foreignSchedule_.dates().front();
96 QuantLib::ext::shared_ptr<CashFlow> initialPayCF(new SimpleCashFlow(-foreignNominal_, initialPayDate));
97 legs_[0].insert(legs_[0].begin(), initialPayCF);
98 // Pay leg notional exchange at end.
99 Date finalPayDate = foreignSchedule_.dates().back();
100 QuantLib::ext::shared_ptr<CashFlow> finalPayCF(new SimpleCashFlow(foreignNominal_, finalPayDate));
101 legs_[0].push_back(finalPayCF);
102
103 // Receive (domestic/resettable) leg
104 // start by creating a dummy vanilla floating leg
105 if (auto on = QuantLib::ext::dynamic_pointer_cast<QuantLib::OvernightIndex>(domesticIndex_)) {
106 // ON leg
109 .withNotional(0.0)
116 } else {
118 .withNotionals(0.0)
126 }
127 } else {
128 // Ibor leg
129 legs_[1] = IborLeg(domesticSchedule_, domesticIndex_)
130 .withNotionals(0.0)
133 }
134 receiveDomestic_ ? payer_[1] = +1.0 : payer_[1] = -1.0;
136 // replace the coupons with a FloatingRateFXLinkedNotionalCoupon
137 // (skip the first coupon as it has a fixed notional)
138 for (Size j = 0; j < legs_[1].size(); ++j) {
139 QuantLib::ext::shared_ptr<FloatingRateCoupon> coupon = QuantLib::ext::dynamic_pointer_cast<FloatingRateCoupon>(legs_[1][j]);
140 Date fixingDate = fxIndex_->fixingCalendar().advance(coupon->accrualStartDate(),
141 -static_cast<Integer>(fxIndex_->fixingDays()), Days);
142 QuantLib::ext::shared_ptr<FloatingRateFXLinkedNotionalCoupon> fxLinkedCoupon(
144 legs_[1][j] = fxLinkedCoupon;
145 }
146 // now build a separate leg to store the domestic (resetting) notionals
147 receiveDomestic_ ? payer_[2] = +1.0 : payer_[2] = -1.0;
149 for (Size j = 0; j < legs_[1].size(); j++) {
150 QuantLib::ext::shared_ptr<Coupon> c = QuantLib::ext::dynamic_pointer_cast<Coupon>(legs_[1][j]);
151 QL_REQUIRE(c, "Resetting XCCY - expected Coupon"); // TODO: fixed fx resettable?
152 // build a pair of notional flows, one at the start and one at the end of
153 // the accrual period. Both with the same FX fixing date
154 Date fixingDate = fxIndex_->fixingCalendar().advance(c->accrualStartDate(),
155 -static_cast<Integer>(fxIndex_->fixingDays()), Days);
156 legs_[2].push_back(QuantLib::ext::shared_ptr<CashFlow>(
157 new FXLinkedCashFlow(c->accrualStartDate(), fixingDate, -foreignNominal_, fxIndex_)));
158 legs_[2].push_back(QuantLib::ext::shared_ptr<CashFlow>(
159 new FXLinkedCashFlow(c->accrualEndDate(), fixingDate, foreignNominal_, fxIndex_)));
160 }
161
162 // Register the instrument with all cashflows on each leg.
163 for (Size legNo = 0; legNo < legs_.size(); legNo++) {
164 Leg::iterator it;
165 for (it = legs_[legNo].begin(); it != legs_[legNo].end(); ++it) {
166 registerWith(*it);
167 }
168 }
169}
170
171void CrossCcyBasisMtMResetSwap::setupArguments(PricingEngine::arguments* args) const {
172
174
176
177 /* Returns here if e.g. args is CrossCcySwap::arguments which
178 is the case if PricingEngine is a CrossCcySwap::engine. */
179 if (!arguments)
180 return;
181
184}
185
186void CrossCcyBasisMtMResetSwap::fetchResults(const PricingEngine::results* r) const {
187
189
191 if (results) {
192 /* If PricingEngine::results are of type
193 CrossCcyBasisSwap::results */
196 } else {
197 /* If not, e.g. if the engine is a CrossCcySwap::engine */
198 fairForeignSpread_ = Null<Spread>();
199 fairDomesticSpread_ = Null<Spread>();
200 }
201
202 /* Calculate the fair pay and receive spreads if they are null */
203 static Spread basisPoint = 1.0e-4;
204 if (fairForeignSpread_ == Null<Spread>()) {
205 if (legBPS_[0] != Null<Real>())
206 fairForeignSpread_ = foreignSpread_ - NPV_ / (legBPS_[0] / basisPoint);
207 }
208 if (fairDomesticSpread_ == Null<Spread>()) {
209 if (legBPS_[1] != Null<Real>())
210 fairDomesticSpread_ = domesticSpread_ - NPV_ / (legBPS_[1] / basisPoint);
211 }
212}
213
216 fairForeignSpread_ = Null<Spread>();
217 fairDomesticSpread_ = Null<Spread>();
218}
219
222 QL_REQUIRE(foreignSpread != Null<Spread>(), "Pay spread cannot be null");
223 QL_REQUIRE(domesticSpread != Null<Spread>(), "Rec spread cannot be null");
224}
225
228 fairForeignSpread = Null<Spread>();
229 fairDomesticSpread = Null<Spread>();
230}
231} // namespace QuantExt
coupon paying the weighted average of the daily overnight rate
helper class building a sequence of overnight coupons
AverageONLeg & withSpread(Spread spread)
AverageONLeg & withPaymentLag(Natural lag)
AverageONLeg & withNotional(Real notional)
AverageONLeg & withLookback(const Period &lookback)
AverageONLeg & withRateCutoff(Natural rateCutoff)
AverageONLeg & withTelescopicValueDates(bool telescopicValueDates)
AverageONLeg & withFixingDays(const Size fixingDays)
boost::optional< QuantLib::Period > foreignLookback_
QuantLib::ext::shared_ptr< FxIndex > fxIndex_
boost::optional< QuantLib::Period > domesticLookback_
QuantLib::ext::shared_ptr< IborIndex > foreignIndex_
boost::optional< QuantLib::Size > domesticFixingDays_
void setupArguments(PricingEngine::arguments *args) const override
CrossCcyBasisMtMResetSwap(Real foreignNominal, const Currency &foreignCurrency, const Schedule &foreignSchedule, const QuantLib::ext::shared_ptr< IborIndex > &foreignIndex, Spread foreignSpread, const Currency &domesticCurrency, const Schedule &domesticSchedule, const QuantLib::ext::shared_ptr< IborIndex > &domesticIndex, Spread domesticSpread, const QuantLib::ext::shared_ptr< FxIndex > &fxIdx, bool receiveDomestic=true, Size foreignPaymentLag=0, Size recPaymentLag=0, boost::optional< bool > foreignIncludeSpread=boost::none, boost::optional< Period > foreignLookback=boost::none, boost::optional< Size > foreignFixingDays=boost::none, boost::optional< Size > foreignRateCutoff=boost::none, boost::optional< bool > foreignIsAveraged=boost::none, boost::optional< bool > domesticIncludeSpread=boost::none, boost::optional< Period > domesticLookback=boost::none, boost::optional< Size > domesticFixingDays=boost::none, boost::optional< Size > domesticRateCutoff=boost::none, boost::optional< bool > domesticIsAveraged=boost::none, const bool telescopicValueDates=false, bool fairSpreadLegIsForeign=true)
void fetchResults(const PricingEngine::results *) const override
boost::optional< QuantLib::Size > foreignFixingDays_
QuantLib::ext::shared_ptr< IborIndex > domesticIndex_
void validate() const override
Cross currency swap.
void setupArguments(PricingEngine::arguments *args) const override
void setupExpired() const override
void fetchResults(const PricingEngine::results *) const override
std::vector< Currency > currencies_
helper class building a sequence of overnight coupons
OvernightLeg & withLookback(const Period &lookback)
OvernightLeg & withTelescopicValueDates(bool telescopicValueDates)
OvernightLeg & withFixingDays(const Natural fixingDays)
OvernightLeg & withNotionals(Real notional)
OvernightLeg & withRateCutoff(const Natural rateCutoff)
OvernightLeg & withSpreads(Spread spread)
OvernightLeg & includeSpread(bool includeSpread)
OvernightLeg & withPaymentLag(Natural lag)
Cross currency basis swap instrument with MTM reset.
Coupon paying a Libor-type index but with an FX linked notional.
coupon paying the compounded daily overnight rate, copy of QL class, added includeSpread flag