Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
discountingcurrencyswapengine.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016 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
20
21#include <ql/cashflows/cashflows.hpp>
22#include <ql/cashflows/floatingratecoupon.hpp>
23#include <ql/exchangerate.hpp>
24#include <ql/utilities/dataformatters.hpp>
25
26#include <ql/cashflows/cashflows.hpp>
27#include <ql/errors.hpp>
28
29namespace QuantExt {
30
32 const std::vector<Handle<YieldTermStructure> >& discountCurves, const std::vector<Handle<Quote> >& fxQuotes,
33 const std::vector<Currency>& currencies, const Currency& npvCurrency,
34 boost::optional<bool> includeSettlementDateFlows, Date settlementDate, Date npvDate,
35 const std::vector<Date>& spotFXSettleDateVec)
36 : discountCurves_(discountCurves), fxQuotes_(fxQuotes), currencies_(currencies), npvCurrency_(npvCurrency),
37 includeSettlementDateFlows_(includeSettlementDateFlows), settlementDate_(settlementDate), npvDate_(npvDate),
38 spotFXSettleDateVec_(spotFXSettleDateVec) {
39
40 QL_REQUIRE(discountCurves_.size() == currencies_.size(), "Number of "
41 "currencies does not match number of discount curves.");
42 QL_REQUIRE(fxQuotes_.size() == currencies_.size(), "Number of "
43 "currencies does not match number of FX quotes.");
44
45 for (Size i = 0; i < discountCurves_.size(); i++) {
46 registerWith(discountCurves_[i]);
47 registerWith(fxQuotes_[i]);
48 }
49}
50
51Handle<YieldTermStructure> DiscountingCurrencySwapEngine::fetchTS(Currency ccy) const {
52 std::vector<Currency>::const_iterator i = std::find(currencies_.begin(), currencies_.end(), ccy);
53 if (i == currencies_.end())
54 return Handle<YieldTermStructure>();
55 else
56 return discountCurves_[i - currencies_.begin()];
57}
58
59Handle<Quote> DiscountingCurrencySwapEngine::fetchFX(Currency ccy) const {
60 std::vector<Currency>::const_iterator i = std::find(currencies_.begin(), currencies_.end(), ccy);
61 if (i == currencies_.end())
62 return Handle<Quote>();
63 else
64 return fxQuotes_[i - currencies_.begin()];
65}
66
68
69 Size numCurrencies = arguments_.currency.size();
70 for (Size i = 0; i < numCurrencies; i++) {
71 Currency ccy = arguments_.currency[i];
72 Handle<YieldTermStructure> yts = fetchTS(ccy);
73 QL_REQUIRE(!yts.empty(), "Discounting term structure is "
74 "empty for "
75 << ccy.name());
76 Handle<Quote> fxQuote = fetchFX(ccy);
77 QL_REQUIRE(!fxQuote.empty(), "FX quote is empty "
78 "for "
79 << ccy.name());
80 }
81
82 Handle<YieldTermStructure> npvCcyYts = fetchTS(npvCurrency_);
83
84 // Instrument settlement date
85 Date referenceDate = npvCcyYts->referenceDate();
86 Date settlementDate = settlementDate_;
87 if (settlementDate_ == Date()) {
88 settlementDate = referenceDate;
89 } else {
90 QL_REQUIRE(settlementDate >= referenceDate, "Settlement date (" << settlementDate
91 << ") cannot be before discount curve "
92 "reference date ("
93 << referenceDate << ")");
94 }
95
96 // Prepare the results containers
97 Size numLegs = arguments_.legs.size();
98
99 // - Instrument::results
100 if (npvDate_ == Date()) {
101 results_.valuationDate = referenceDate;
102 } else {
103 QL_REQUIRE(npvDate_ >= referenceDate, "NPV date (" << npvDate_
104 << ") cannot be before "
105 "discount curve reference date ("
106 << referenceDate << ")");
107 results_.valuationDate = npvDate_;
108 }
109
110 //check spotFXSettleDateVec_
111 std::vector<Date> spotFXSettleDateVec = spotFXSettleDateVec_;
112 if (spotFXSettleDateVec.size() == 0) {
113 spotFXSettleDateVec.resize(numCurrencies, referenceDate);
114 } else {
115 QL_REQUIRE(spotFXSettleDateVec.size() == numCurrencies, "Number of "
116 "currencies does not match number of FX settlement dates.");
117 }
118 for (Size i = 0; i < numCurrencies; ++i) {
119 if (spotFXSettleDateVec[i] == Date()) {
120 spotFXSettleDateVec[i] = referenceDate;
121 } else {
122 Currency ccy = arguments_.currency[i];
123 QL_REQUIRE(spotFXSettleDateVec[i] >= referenceDate, "FX settlement date (" << spotFXSettleDateVec[i]
124 << ") for currency " << ccy <<
125 " cannot be before discount curve "
126 "reference date ("
127 << referenceDate << ")");
128 }
129 }
130
131 results_.value = 0.0;
132 results_.errorEstimate = Null<Real>();
133
134 // - CurrencySwap::results
135 results_.legNPV.resize(numLegs);
136 results_.legBPS.resize(numLegs);
137 results_.inCcyLegNPV.resize(numLegs);
138 results_.inCcyLegBPS.resize(numLegs);
139 results_.startDiscounts.resize(numLegs);
140 results_.endDiscounts.resize(numLegs);
141
142 bool includeRefDateFlows =
143 includeSettlementDateFlows_ ? *includeSettlementDateFlows_ : Settings::instance().includeReferenceDateEvents();
144
145 results_.npvDateDiscount = npvCcyYts->discount(results_.valuationDate);
146
147 for (Size i = 0; i < numLegs; ++i) {
148 try {
149 Currency ccy = arguments_.currency[i];
150 Handle<YieldTermStructure> yts = fetchTS(ccy);
151
152 std::tie(results_.inCcyLegNPV[i], results_.inCcyLegBPS[i]) = QuantLib::CashFlows::npvbps(
153 arguments_.legs[i], **yts, includeRefDateFlows, settlementDate, results_.valuationDate);
154
155 results_.inCcyLegNPV[i] *= arguments_.payer[i];
156 if (results_.inCcyLegBPS[i] != Null<Real>()) {
157 results_.inCcyLegBPS[i] *= arguments_.payer[i];
158 }
159
160 // Converts into base currency and adds.
161 Handle<Quote> fx = fetchFX(ccy);
162 //results_.legNPV[i] = results_.inCcyLegNPV[i] * fx->value();
163 Real spotFXRate = fx->value();
164 if( spotFXSettleDateVec[i] != referenceDate ) {
165 // Use the parity relation between discount factors and fx rates to compute spotFXRate
166 // Generic formula: fx(T1)/fx(T2) = FwdDF_Quote(T1->T2) / FwdDF_Base(T1->T2),
167 // where fx represents the currency ratio Base/Quote
168 Real npvCcyDF = npvCcyYts->discount(spotFXSettleDateVec[i]);
169 Real ccyDF = yts->discount(spotFXSettleDateVec[i]);
170 QL_REQUIRE(ccyDF != 0.0, "Discount Factor associated with currency " << ccy
171 << " at maturity " << spotFXSettleDateVec[i] << " cannot be zero");
172 spotFXRate *= npvCcyDF / ccyDF;
173 }
174 results_.legNPV[i] = results_.inCcyLegNPV[i] * spotFXRate;
175
176 if (results_.inCcyLegBPS[i] != Null<Real>()) {
177 //results_.legBPS[i] = results_.inCcyLegBPS[i] * fx->value();
178 results_.legBPS[i] = results_.inCcyLegBPS[i] * spotFXRate;
179 } else {
180 results_.legBPS[i] = Null<Real>();
181 }
182
183 results_.value += results_.legNPV[i];
184
185 if (!arguments_.legs[i].empty()) {
186 Date d1 = CashFlows::startDate(arguments_.legs[i]);
187 if (d1 >= referenceDate)
188 results_.startDiscounts[i] = yts->discount(d1);
189 else
190 results_.startDiscounts[i] = Null<DiscountFactor>();
191
192 Date d2 = CashFlows::maturityDate(arguments_.legs[i]);
193 if (d2 >= referenceDate)
194 results_.endDiscounts[i] = yts->discount(d2);
195 else
196 results_.endDiscounts[i] = Null<DiscountFactor>();
197 } else {
198 results_.startDiscounts[i] = Null<DiscountFactor>();
199 results_.endDiscounts[i] = Null<DiscountFactor>();
200 }
201
202 } catch (std::exception& e) {
203 QL_FAIL("leg " << i << ": " << e.what());
204 }
205 }
206}
207} // namespace QuantExt
const Instrument::results * results_
Definition: cdsoption.cpp:81
DiscountingCurrencySwapEngine(const std::vector< Handle< YieldTermStructure > > &discountCurves, const std::vector< Handle< Quote > > &fxQuotes, const std::vector< Currency > &currencies, const Currency &npvCurrency, boost::optional< bool > includeSettlementDateFlows=boost::none, Date settlementDate=Date(), Date npvDate=Date(), const std::vector< Date > &spotFXSettleDateVec=std::vector< Date >())
Handle< YieldTermStructure > fetchTS(Currency ccy) const
std::vector< Handle< YieldTermStructure > > discountCurves_
discounting currency swap engine
Swap::arguments * arguments_