QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
crosscurrencyratehelpers.cpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2021 Marcin Rybacki
5
6 This file is part of QuantLib, a free-software/open-source library
7 for financial quantitative analysts and developers - http://quantlib.org/
8
9 QuantLib is free software: you can redistribute it and/or modify it
10 under the terms of the QuantLib license. You should have received a
11 copy of the license along with this program; if not, please email
12 <quantlib-dev@lists.sf.net>. The license is also available online at
13 <http://quantlib.org/license.shtml>.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
20#include <ql/cashflows/iborcoupon.hpp>
21#include <ql/cashflows/cashflows.hpp>
22#include <ql/cashflows/simplecashflow.hpp>
23#include <ql/experimental/termstructures/crosscurrencyratehelpers.hpp>
24#include <ql/utilities/null_deleter.hpp>
25#include <utility>
26
27namespace QuantLib {
28
29 namespace {
30
31 Schedule legSchedule(const Date& evaluationDate,
32 const Period& tenor,
33 const Period& frequency,
34 Natural fixingDays,
35 const Calendar& calendar,
36 BusinessDayConvention convention,
37 bool endOfMonth) {
38 QL_REQUIRE(tenor >= frequency,
39 "XCCY instrument tenor should not be smaller than coupon frequency.");
40
41 Date referenceDate = calendar.adjust(evaluationDate);
42 Date earliestDate = calendar.advance(referenceDate, fixingDays * Days, convention);
43 Date maturity = earliestDate + tenor;
44 return MakeSchedule()
45 .from(earliestDate)
46 .to(maturity)
47 .withTenor(frequency)
48 .withCalendar(calendar)
49 .withConvention(convention)
50 .endOfMonth(endOfMonth)
51 .backwards();
52 }
53
54 Leg buildIborLeg(const Date& evaluationDate,
55 const Period& tenor,
56 Natural fixingDays,
57 const Calendar& calendar,
58 BusinessDayConvention convention,
59 bool endOfMonth,
60 const ext::shared_ptr<IborIndex>& idx) {
61 Schedule sch = legSchedule(evaluationDate, tenor, idx->tenor(), fixingDays, calendar,
62 convention, endOfMonth);
63 return IborLeg(sch, idx).withNotionals(1.0);
64 }
65
66 std::pair<Real, Real> npvbpsConstNotionalLeg(const Leg& iborLeg,
67 const Handle<YieldTermStructure>& discountCurveHandle) {
68 const Spread basisPoint = 1.0e-4;
69 Date refDt = discountCurveHandle->referenceDate();
70 const YieldTermStructure& discountRef = **discountCurveHandle;
71 bool includeSettleDtFlows = true;
72 Real npv, bps;
73 std::tie(npv, bps) = CashFlows::npvbps(iborLeg, discountRef, includeSettleDtFlows, refDt, refDt);
74 // Include NPV of the notional exchange at start and maturity.
75 npv += discountRef.discount(iborLeg.back()->date()) - 1.0;
76 bps /= basisPoint;
77 return { npv, bps };
78 }
79
80 class ResettingLegHelper {
81 public:
82 explicit ResettingLegHelper(const YieldTermStructure& discountCurve,
83 const YieldTermStructure& foreignCurve)
84 : discountCurve_(discountCurve), foreignCurve_(foreignCurve) {}
85 DiscountFactor discount(const Date& d) const {
86 return discountCurve_.discount(d);
87 }
88 Real notionalAdjustment(const Date& d) const {
89 return foreignCurve_.discount(d) / discountCurve_.discount(d);
90 }
91
92 private:
93 const YieldTermStructure& discountCurve_;
94 const YieldTermStructure& foreignCurve_;
95 };
96
97 class ResettingLegCalculator : public AcyclicVisitor, public Visitor<Coupon> {
98 public:
99 explicit ResettingLegCalculator(const YieldTermStructure& discountCurve,
100 const YieldTermStructure& foreignCurve)
101 : helper_(discountCurve, foreignCurve) {}
102 void visit(Coupon& c) override {
103 Date start = c.accrualStartDate();
104 Date end = c.accrualEndDate();
105 Time accrual = c.accrualPeriod();
106 Real adjustedNotional = c.nominal() * helper_.notionalAdjustment(start);
107 DiscountFactor discountStart = helper_.discount(start);
108 DiscountFactor discountEnd = helper_.discount(end);
109
110 // NPV of a resetting coupon consists of a redemption of borrowed amount occurring
111 // at the end of the accrual period plus the accrued interest, minus the borrowed
112 // amount at the start of the period. All amounts are corrected by an adjustment
113 // corresponding to the implied forward exchange rate, which is estimated by
114 // the ratio of foreign and domestic curves discount factors.
115 Real npvRedeemedAmount =
116 adjustedNotional * discountEnd * (1.0 + c.rate() * accrual);
117 Real npvBorrowedAmount = -adjustedNotional * discountStart;
118
119 npv_ += npvRedeemedAmount + npvBorrowedAmount;
120 bps_ += adjustedNotional * discountEnd * accrual;
121 }
122 Real NPV() const { return npv_; }
123 Real BPS() const { return bps_; }
124
125 private:
126 ResettingLegHelper helper_;
127 Real npv_ = 0.0;
128 Real bps_ = 0.0;
129 };
130
131 std::pair<Real, Real> npvbpsResettingLeg(const Leg& iborLeg,
132 const Handle<YieldTermStructure>& discountCurveHandle,
133 const Handle<YieldTermStructure>& foreignCurveHandle) {
134 const YieldTermStructure& discountCurveRef = **discountCurveHandle;
135 const YieldTermStructure& foreignCurveRef = **foreignCurveHandle;
136
137 ResettingLegCalculator calc(discountCurveRef, foreignCurveRef);
138 for (const auto& i : iborLeg) {
139 CashFlow& cf = *i;
140 cf.accept(calc);
141 }
142 return { calc.NPV(), calc.BPS() };
143 }
144 }
145
147 const Handle<Quote>& basis,
148 const Period& tenor,
149 Natural fixingDays,
150 Calendar calendar,
151 BusinessDayConvention convention,
152 bool endOfMonth,
153 ext::shared_ptr<IborIndex> baseCurrencyIndex,
154 ext::shared_ptr<IborIndex> quoteCurrencyIndex,
155 Handle<YieldTermStructure> collateralCurve,
156 bool isFxBaseCurrencyCollateralCurrency,
157 bool isBasisOnFxBaseCurrencyLeg)
158 : RelativeDateRateHelper(basis), tenor_(tenor), fixingDays_(fixingDays),
159 calendar_(std::move(calendar)), convention_(convention), endOfMonth_(endOfMonth),
160 baseCcyIdx_(std::move(baseCurrencyIndex)), quoteCcyIdx_(std::move(quoteCurrencyIndex)),
161 collateralHandle_(std::move(collateralCurve)),
162 isFxBaseCurrencyCollateralCurrency_(isFxBaseCurrencyCollateralCurrency),
163 isBasisOnFxBaseCurrencyLeg_(isBasisOnFxBaseCurrencyLeg) {
168 }
169
179 }
180
183 QL_REQUIRE(!termStructureHandle_.empty(), "term structure not set");
184 QL_REQUIRE(!collateralHandle_.empty(), "collateral term structure not set");
186 }
187
190 QL_REQUIRE(!termStructureHandle_.empty(), "term structure not set");
191 QL_REQUIRE(!collateralHandle_.empty(), "collateral term structure not set");
193 }
194
196 // do not set the relinkable handle as an observer -
197 // force recalculation when needed
198 bool observer = false;
199
200 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
201 termStructureHandle_.linkTo(temp, observer);
202
204 }
205
207 const Handle<Quote>& basis,
208 const Period& tenor,
209 Natural fixingDays,
210 const Calendar& calendar,
211 BusinessDayConvention convention,
212 bool endOfMonth,
213 const ext::shared_ptr<IborIndex>& baseCurrencyIndex,
214 const ext::shared_ptr<IborIndex>& quoteCurrencyIndex,
215 const Handle<YieldTermStructure>& collateralCurve,
216 bool isFxBaseCurrencyCollateralCurrency,
217 bool isBasisOnFxBaseCurrencyLeg)
219 tenor,
220 fixingDays,
221 calendar,
222 convention,
223 endOfMonth,
224 baseCurrencyIndex,
225 quoteCurrencyIndex,
226 collateralCurve,
227 isFxBaseCurrencyCollateralCurrency,
228 isBasisOnFxBaseCurrencyLeg) {}
229
231 Real npvBaseCcy = 0.0, bpsBaseCcy = 0.0;
232 std::tie(npvBaseCcy, bpsBaseCcy) = npvbpsConstNotionalLeg(baseCcyIborLeg_, baseCcyLegDiscountHandle());
233 Real npvQuoteCcy = 0.0, bpsQuoteCcy = 0.0;
234 std::tie(npvQuoteCcy, bpsQuoteCcy) = npvbpsConstNotionalLeg(quoteCcyIborLeg_, quoteCcyLegDiscountHandle());
235 Real bps = isBasisOnFxBaseCurrencyLeg_ ? -bpsBaseCcy : bpsQuoteCcy;
236 return -(npvQuoteCcy - npvBaseCcy) / bps;
237 }
238
240 auto* v1 = dynamic_cast<Visitor<ConstNotionalCrossCurrencyBasisSwapRateHelper>*>(&v);
241 if (v1 != nullptr)
242 v1->visit(*this);
243 else
245 }
246
248 const Handle<Quote>& basis,
249 const Period& tenor,
250 Natural fixingDays,
251 const Calendar& calendar,
252 BusinessDayConvention convention,
253 bool endOfMonth,
254 const ext::shared_ptr<IborIndex>& baseCurrencyIndex,
255 const ext::shared_ptr<IborIndex>& quoteCurrencyIndex,
256 const Handle<YieldTermStructure>& collateralCurve,
257 bool isFxBaseCurrencyCollateralCurrency,
258 bool isBasisOnFxBaseCurrencyLeg,
259 bool isFxBaseCurrencyLegResettable)
261 tenor,
262 fixingDays,
263 calendar,
264 convention,
265 endOfMonth,
266 baseCurrencyIndex,
267 quoteCurrencyIndex,
268 collateralCurve,
269 isFxBaseCurrencyCollateralCurrency,
270 isBasisOnFxBaseCurrencyLeg),
271 isFxBaseCurrencyLegResettable_(isFxBaseCurrencyLegResettable) {}
272
274 Real npvBaseCcy = 0.0, bpsBaseCcy = 0.0;
275 Real npvQuoteCcy = 0.0, bpsQuoteCcy = 0.0;
277 std::tie(npvBaseCcy, bpsBaseCcy) =
278 npvbpsResettingLeg(baseCcyIborLeg_, baseCcyLegDiscountHandle(),
280 std::tie(npvQuoteCcy, bpsQuoteCcy) =
281 npvbpsConstNotionalLeg(quoteCcyIborLeg_, quoteCcyLegDiscountHandle());
282 } else {
283 std::tie(npvBaseCcy, bpsBaseCcy) =
284 npvbpsConstNotionalLeg(baseCcyIborLeg_, baseCcyLegDiscountHandle());
285 std::tie(npvQuoteCcy, bpsQuoteCcy) =
286 npvbpsResettingLeg(quoteCcyIborLeg_, quoteCcyLegDiscountHandle(),
288 }
289
290 Real bps = isBasisOnFxBaseCurrencyLeg_ ? -bpsBaseCcy : bpsQuoteCcy;
291
292 return -(npvQuoteCcy - npvBaseCcy) / bps;
293 }
294
296 auto* v1 = dynamic_cast<Visitor<MtMCrossCurrencyBasisSwapRateHelper>*>(&v);
297 if (v1 != nullptr)
298 v1->visit(*this);
299 else
301 }
302}
degenerate base class for the Acyclic Visitor pattern
Definition: visitor.hpp:33
virtual void accept(AcyclicVisitor &)
virtual void setTermStructure(TS *)
sets the term structure to be used for pricing
calendar class
Definition: calendar.hpp:61
static Date maturityDate(const Leg &leg)
Definition: cashflows.cpp:52
static Date startDate(const Leg &leg)
Definition: cashflows.cpp:38
static std::pair< Real, Real > npvbps(const Leg &leg, const YieldTermStructure &discountCurve, bool includeSettlementDateFlows, Date settlementDate=Date(), Date npvDate=Date())
NPV and BPS of the cash flows.
Definition: cashflows.cpp:484
ConstNotionalCrossCurrencyBasisSwapRateHelper(const Handle< Quote > &basis, const Period &tenor, Natural fixingDays, const Calendar &calendar, BusinessDayConvention convention, bool endOfMonth, const ext::shared_ptr< IborIndex > &baseCurrencyIndex, const ext::shared_ptr< IborIndex > &quoteCurrencyIndex, const Handle< YieldTermStructure > &collateralCurve, bool isFxBaseCurrencyCollateralCurrency, bool isBasisOnFxBaseCurrencyLeg)
Base class for cross-currency basis swap rate helpers.
void setTermStructure(YieldTermStructure *) override
RelinkableHandle< YieldTermStructure > termStructureHandle_
const Handle< YieldTermStructure > & baseCcyLegDiscountHandle() const
const Handle< YieldTermStructure > & quoteCcyLegDiscountHandle() const
CrossCurrencyBasisSwapRateHelperBase(const Handle< Quote > &basis, const Period &tenor, Natural fixingDays, Calendar calendar, BusinessDayConvention convention, bool endOfMonth, ext::shared_ptr< IborIndex > baseCurrencyIndex, ext::shared_ptr< IborIndex > quoteCurrencyIndex, Handle< YieldTermStructure > collateralCurve, bool isFxBaseCurrencyCollateralCurrency, bool isBasisOnFxBaseCurrencyLeg)
Shared handle to an observable.
Definition: handle.hpp:41
MtMCrossCurrencyBasisSwapRateHelper(const Handle< Quote > &basis, const Period &tenor, Natural fixingDays, const Calendar &calendar, BusinessDayConvention convention, bool endOfMonth, const ext::shared_ptr< IborIndex > &baseCurrencyIndex, const ext::shared_ptr< IborIndex > &quoteCurrencyIndex, const Handle< YieldTermStructure > &collateralCurve, bool isFxBaseCurrencyCollateralCurrency, bool isBasisOnFxBaseCurrencyLeg, bool isFxBaseCurrencyLegResettable)
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
Definition: observable.hpp:228
Bootstrap helper with date schedule relative to global evaluation date.
Visitor for a specific class
Definition: visitor.hpp:40
virtual void visit(T &)=0
Interest-rate term structure.
BusinessDayConvention
Business Day conventions.
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
QL_REAL Real
real number
Definition: types.hpp:50
Real DiscountFactor
discount factor between dates
Definition: types.hpp:66
unsigned QL_INTEGER Natural
positive integer
Definition: types.hpp:43
Real Spread
spreads on interest rates
Definition: types.hpp:74
Definition: any.hpp:35
MarketModelMultiProduct::CashFlow CashFlow
std::vector< ext::shared_ptr< CashFlow > > Leg
Sequence of cash-flows.
Definition: cashflow.hpp:78
STL namespace.