QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
crosscurrencyratehelpers.cpp
Go to the documentation of this file.
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
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 // on the settlement date
76 npv += (-1.0) * discountRef.discount(CashFlows::startDate(iborLeg));
77 // on maturity date
78 npv += discountRef.discount(CashFlows::maturityDate(iborLeg));
79 bps /= basisPoint;
80 return { npv, bps };
81 }
82
83 class ResettingLegHelper {
84 public:
85 explicit ResettingLegHelper(const YieldTermStructure& discountCurve,
86 const YieldTermStructure& foreignCurve)
87 : discountCurve_(discountCurve), foreignCurve_(foreignCurve) {}
88 DiscountFactor discount(const Date& d) const {
89 return discountCurve_.discount(d);
90 }
91 Real notionalAdjustment(const Date& d) const {
92 return foreignCurve_.discount(d) / discountCurve_.discount(d);
93 }
94
95 private:
96 const YieldTermStructure& discountCurve_;
97 const YieldTermStructure& foreignCurve_;
98 };
99
100 class ResettingLegCalculator : public AcyclicVisitor, public Visitor<Coupon> {
101 public:
102 explicit ResettingLegCalculator(const YieldTermStructure& discountCurve,
103 const YieldTermStructure& foreignCurve)
104 : helper_(discountCurve, foreignCurve) {}
105 void visit(Coupon& c) override {
106 Date start = c.accrualStartDate();
107 Date end = c.accrualEndDate();
108 Time accrual = c.accrualPeriod();
109 Real adjustedNotional = c.nominal() * helper_.notionalAdjustment(start);
110 DiscountFactor discountStart = helper_.discount(start);
111 DiscountFactor discountEnd = helper_.discount(end);
112
113 // NPV of a resetting coupon consists of a redemption of borrowed amount occurring
114 // at the end of the accrual period plus the accrued interest, minus the borrowed
115 // amount at the start of the period. All amounts are corrected by an adjustment
116 // corresponding to the implied forward exchange rate, which is estimated by
117 // the ratio of foreign and domestic curves discount factors.
118 Real npvRedeemedAmount =
119 adjustedNotional * discountEnd * (1.0 + c.rate() * accrual);
120 Real npvBorrowedAmount = -adjustedNotional * discountStart;
121
122 npv_ += npvRedeemedAmount + npvBorrowedAmount;
123 bps_ += adjustedNotional * discountEnd * accrual;
124 }
125 Real NPV() const { return npv_; }
126 Real BPS() const { return bps_; }
127
128 private:
129 ResettingLegHelper helper_;
130 Real npv_ = 0.0;
131 Real bps_ = 0.0;
132 };
133
134 std::pair<Real, Real> npvbpsResettingLeg(const Leg& iborLeg,
135 const Handle<YieldTermStructure>& discountCurveHandle,
136 const Handle<YieldTermStructure>& foreignCurveHandle) {
137 const YieldTermStructure& discountCurveRef = **discountCurveHandle;
138 const YieldTermStructure& foreignCurveRef = **foreignCurveHandle;
139
140 ResettingLegCalculator calc(discountCurveRef, foreignCurveRef);
141 for (const auto& i : iborLeg) {
142 CashFlow& cf = *i;
143 cf.accept(calc);
144 }
145 return { calc.NPV(), calc.BPS() };
146 }
147 }
148
150 const Handle<Quote>& basis,
151 const Period& tenor,
152 Natural fixingDays,
153 Calendar calendar,
154 BusinessDayConvention convention,
155 bool endOfMonth,
156 ext::shared_ptr<IborIndex> baseCurrencyIndex,
157 ext::shared_ptr<IborIndex> quoteCurrencyIndex,
158 Handle<YieldTermStructure> collateralCurve,
159 bool isFxBaseCurrencyCollateralCurrency,
160 bool isBasisOnFxBaseCurrencyLeg)
161 : RelativeDateRateHelper(basis), tenor_(tenor), fixingDays_(fixingDays),
162 calendar_(std::move(calendar)), convention_(convention), endOfMonth_(endOfMonth),
163 baseCcyIdx_(std::move(baseCurrencyIndex)), quoteCcyIdx_(std::move(quoteCurrencyIndex)),
164 collateralHandle_(std::move(collateralCurve)),
165 isFxBaseCurrencyCollateralCurrency_(isFxBaseCurrencyCollateralCurrency),
166 isBasisOnFxBaseCurrencyLeg_(isBasisOnFxBaseCurrencyLeg) {
171 }
172
182 }
183
186 QL_REQUIRE(!termStructureHandle_.empty(), "term structure not set");
187 QL_REQUIRE(!collateralHandle_.empty(), "collateral term structure not set");
189 }
190
193 QL_REQUIRE(!termStructureHandle_.empty(), "term structure not set");
194 QL_REQUIRE(!collateralHandle_.empty(), "collateral term structure not set");
196 }
197
199 // do not set the relinkable handle as an observer -
200 // force recalculation when needed
201 bool observer = false;
202
203 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
204 termStructureHandle_.linkTo(temp, observer);
205
207 }
208
210 const Handle<Quote>& basis,
211 const Period& tenor,
212 Natural fixingDays,
213 const Calendar& calendar,
214 BusinessDayConvention convention,
215 bool endOfMonth,
216 const ext::shared_ptr<IborIndex>& baseCurrencyIndex,
217 const ext::shared_ptr<IborIndex>& quoteCurrencyIndex,
218 const Handle<YieldTermStructure>& collateralCurve,
219 bool isFxBaseCurrencyCollateralCurrency,
220 bool isBasisOnFxBaseCurrencyLeg)
222 tenor,
223 fixingDays,
224 calendar,
225 convention,
226 endOfMonth,
227 baseCurrencyIndex,
228 quoteCurrencyIndex,
229 collateralCurve,
230 isFxBaseCurrencyCollateralCurrency,
231 isBasisOnFxBaseCurrencyLeg) {}
232
234 Real npvBaseCcy = 0.0, bpsBaseCcy = 0.0;
235 std::tie(npvBaseCcy, bpsBaseCcy) = npvbpsConstNotionalLeg(baseCcyIborLeg_, baseCcyLegDiscountHandle());
236 Real npvQuoteCcy = 0.0, bpsQuoteCcy = 0.0;
237 std::tie(npvQuoteCcy, bpsQuoteCcy) = npvbpsConstNotionalLeg(quoteCcyIborLeg_, quoteCcyLegDiscountHandle());
238 Real bps = isBasisOnFxBaseCurrencyLeg_ ? -bpsBaseCcy : bpsQuoteCcy;
239 return -(npvQuoteCcy - npvBaseCcy) / bps;
240 }
241
244 if (v1 != nullptr)
245 v1->visit(*this);
246 else
248 }
249
251 const Handle<Quote>& basis,
252 const Period& tenor,
253 Natural fixingDays,
254 const Calendar& calendar,
255 BusinessDayConvention convention,
256 bool endOfMonth,
257 const ext::shared_ptr<IborIndex>& baseCurrencyIndex,
258 const ext::shared_ptr<IborIndex>& quoteCurrencyIndex,
259 const Handle<YieldTermStructure>& collateralCurve,
260 bool isFxBaseCurrencyCollateralCurrency,
261 bool isBasisOnFxBaseCurrencyLeg,
262 bool isFxBaseCurrencyLegResettable)
264 tenor,
265 fixingDays,
266 calendar,
267 convention,
268 endOfMonth,
269 baseCurrencyIndex,
270 quoteCurrencyIndex,
271 collateralCurve,
272 isFxBaseCurrencyCollateralCurrency,
273 isBasisOnFxBaseCurrencyLeg),
274 isFxBaseCurrencyLegResettable_(isFxBaseCurrencyLegResettable) {}
275
277 Real npvBaseCcy = 0.0, bpsBaseCcy = 0.0;
278 Real npvQuoteCcy = 0.0, bpsQuoteCcy = 0.0;
280 std::tie(npvBaseCcy, bpsBaseCcy) =
281 npvbpsResettingLeg(baseCcyIborLeg_, baseCcyLegDiscountHandle(),
283 std::tie(npvQuoteCcy, bpsQuoteCcy) =
284 npvbpsConstNotionalLeg(quoteCcyIborLeg_, quoteCcyLegDiscountHandle());
285 } else {
286 std::tie(npvBaseCcy, bpsBaseCcy) =
287 npvbpsConstNotionalLeg(baseCcyIborLeg_, baseCcyLegDiscountHandle());
288 std::tie(npvQuoteCcy, bpsQuoteCcy) =
289 npvbpsResettingLeg(quoteCcyIborLeg_, quoteCcyLegDiscountHandle(),
291 }
292
293 Real bps = isBasisOnFxBaseCurrencyLeg_ ? -bpsBaseCcy : bpsQuoteCcy;
294
295 return -(npvQuoteCcy - npvBaseCcy) / bps;
296 }
297
299 auto* v1 = dynamic_cast<Visitor<MtMCrossCurrencyBasisSwapRateHelper>*>(&v);
300 if (v1 != nullptr)
301 v1->visit(*this);
302 else
304 }
305}
Real bps_
Definition: cashflows.cpp:419
Real npv_
Definition: cashflows.cpp:1185
const YieldTermStructure & discountCurve_
Definition: cashflows.cpp:418
Cash-flow analysis functions.
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:473
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.
ResettingLegHelper helper_
const YieldTermStructure & foreignCurve_
FX and cross currency basis swaps rate helpers.
const DefaultType & t
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
Date d
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
Coupon paying a Libor-type index.
Definition: any.hpp:35
MarketModelMultiProduct::CashFlow CashFlow
std::vector< ext::shared_ptr< CashFlow > > Leg
Sequence of cash-flows.
Definition: cashflow.hpp:78
STL namespace.
empty deleter for shared_ptr
ext::shared_ptr< BlackVolTermStructure > v
Predetermined cash flow.