Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
discountingswapenginedeltagamma.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/instruments/vanillaswap.hpp>
22
23namespace QuantExt {
24
25namespace detail {
26
27template <class Key> Real& getMapEntry(std::map<Key, Real>& map, const Key& key) {
28 auto f = map.find(key);
29 if (f == map.end()) {
30 return map.insert(std::make_pair(key, 0.0)).first->second;
31 } else {
32 return f->second;
33 }
34}
35
36NpvDeltaGammaCalculator::NpvDeltaGammaCalculator(Handle<YieldTermStructure> discountCurve, const Real payer, Real& npv,
37 Real& bps, const bool computeDelta, const bool computeGamma,
38 const bool computeBPS, std::map<Date, Real>& deltaDiscount,
39 std::map<Date, Real>& deltaForward, std::map<Date, Real>& deltaBPS,
40 std::map<Date, Real>& gammaDiscount,
41 std::map<std::pair<Date, Date>, Real>& gammaForward,
42 std::map<std::pair<Date, Date>, Real>& gammaDscFwd,
43 std::map<Date, Real>& gammaBPS, Real& fxLinkedForeignNpv,
44 const bool excludeSimpleCashFlowsFromSensis, Real& simpleCashFlowNpv)
45 : discountCurve_(discountCurve), payer_(payer), npv_(npv), bps_(bps), computeDelta_(computeDelta),
46 computeGamma_(computeGamma), computeBPS_(computeBPS), deltaDiscount_(deltaDiscount), deltaForward_(deltaForward),
47 deltaBPS_(deltaBPS), gammaDiscount_(gammaDiscount), gammaForward_(gammaForward), gammaDscFwd_(gammaDscFwd),
48 gammaBPS_(gammaBPS), fxLinkedForeignNpv_(fxLinkedForeignNpv),
49 excludeSimpleCashFlowsFromSensis_(excludeSimpleCashFlowsFromSensis), simpleCashFlowNpv_(simpleCashFlowNpv) {}
50
52 Real dsc = discountCurve_->discount(c.date());
53 Real a = payer_ * c.amount() * dsc;
54 npv_ += a;
55 Real t = discountCurve_->timeFromReference(c.date());
56 if (computeDelta_) {
57 getMapEntry(deltaDiscount_, c.date()) += -t * a;
58 }
59 if (computeGamma_) {
60 getMapEntry(gammaDiscount_, c.date()) += t * t * a;
61 }
62}
63
64void NpvDeltaGammaCalculator::visit(SimpleCashFlow& c) {
66 // even when excluding the cf from the sensis we want to colect their npv contribution, but in a separate field
67 Real dsc = discountCurve_->discount(c.date());
68 Real a = payer_ * c.amount() * dsc;
70 return;
71 }
72 visit(static_cast<CashFlow&>(c));
73}
74
75void NpvDeltaGammaCalculator::visit(FixedRateCoupon& c) {
76 Real dsc = discountCurve_->discount(c.date());
77 Real a = payer_ * c.amount() * dsc;
78 npv_ += a;
79 Real t = discountCurve_->timeFromReference(c.date());
80 if (computeDelta_) {
81 getMapEntry(deltaDiscount_, c.date()) += -t * a;
82 }
83 if (computeGamma_) {
84 getMapEntry(gammaDiscount_, c.date()) += t * t * a;
85 }
86 if (computeBPS_) {
87 Real tau = c.accrualPeriod();
88 bps_ += payer_ * c.nominal() * tau * dsc;
89 if (computeDelta_) {
90 getMapEntry(deltaBPS_, c.date()) += -t * payer_ * c.nominal() * tau * dsc;
91 }
92 if (computeGamma_) {
93 getMapEntry(gammaBPS_, c.date()) += t * t * payer_ * c.nominal() * tau * dsc;
94 }
95 }
96}
97
99 Real dsc = discountCurve_->discount(c.date());
100 Real a = payer_ * c.amount() * dsc;
101 npv_ += a;
102 Date d3 = c.date();
103 Real t3 = discountCurve_->timeFromReference(d3);
104 if (computeDelta_) {
105 getMapEntry(deltaDiscount_, d3) += -t3 * a;
106 }
107 if (computeGamma_) {
108 getMapEntry(gammaDiscount_, d3) += t3 * t3 * a;
109 }
110 if (computeBPS_) {
111 Real tau = c.accrualPeriod();
112 bps_ += payer_ * tau * c.nominal() * dsc;
113 if (computeDelta_) {
114 getMapEntry(deltaBPS_, d3) += -t3 * payer_ * tau * c.nominal() * dsc;
115 }
116 if (computeGamma_) {
117 getMapEntry(gammaBPS_, d3) += t3 * t3 * payer_ * tau * c.nominal() * dsc;
118 }
119 }
120 Date fixing = c.fixingDate();
121
122 // is it actually a floating rate coupon?
123 if (fixing > discountCurve_->referenceDate() ||
124 (fixing == discountCurve_->referenceDate() && c.index()->pastFixing(fixing) == Null<Real>())) {
125 Date d1 = c.index()->valueDate(fixing);
126 Date d2;
127 if (IborCoupon::Settings::instance().usingAtParCoupons() && fixing <= c.accrualStartDate()) {
128 // par coupon approximation
129 Date nextFixingDate =
130 c.index()->fixingCalendar().advance(c.accrualEndDate(), -static_cast<Integer>(c.fixingDays()), Days);
131 d2 = c.index()->fixingCalendar().advance(nextFixingDate, c.fixingDays(), Days);
132 } else if (IborCoupon::Settings::instance().usingAtParCoupons()) {
133 // in arreas
134 d2 = c.index()->maturityDate(d1);
135 } else {
136 // use indexed coupon
137 d2 = c.index()->maturityDate(d1);
138 }
139
140 // if the coupon is degenerated we exit early
141 if (d2 <= d1)
142 return;
143
144 Real t1 = discountCurve_->timeFromReference(d1);
145 Real t2 = discountCurve_->timeFromReference(d2);
146 Real r = payer_ * dsc *
147 (c.nominal() * c.accrualPeriod() *
148 (c.gearing() / c.index()->dayCounter().yearFraction(d1, d2) - c.spread()));
149 if (computeDelta_) {
150 getMapEntry(deltaForward_, d1) += -t1 * (a + r);
151 getMapEntry(deltaForward_, d2) += t2 * (a + r);
152 }
153 if (computeGamma_) {
154 getMapEntry(gammaForward_, std::make_pair(d1, d1)) += t1 * t1 * (a + r);
155 getMapEntry(gammaForward_, std::make_pair(d2, d2)) += t2 * t2 * (a + r);
156 getMapEntry(gammaForward_, std::make_pair(d1, d2)) += -2.0 * t1 * t2 * (a + r);
157 getMapEntry(gammaDscFwd_, std::make_pair(d3, d1)) += t1 * t3 * (a + r);
158 getMapEntry(gammaDscFwd_, std::make_pair(d3, d2)) += -t2 * t3 * (a + r);
159 }
160 }
161} // process IborCoupon
162
164
166 // only add to the foreign npv (and hence effectively to the fx spot delta) if the fx rate is not yet fixed
167
168 if (c.fxFixingDate() > discountCurve_->referenceDate() ||
169 (c.fxFixingDate() == discountCurve_->referenceDate() &&
170 c.fxIndex()->pastFixing(c.fxFixingDate()) == Null<Real>())) {
171 Real tmp = c.fxIndex()->forecastFixing(0.0);
172 fxLinkedForeignNpv_ += payer_ * c.amount() * discountCurve_->discount(c.date()) / tmp;
173 }
175}
176
178 Real dsc = discountCurve_->discount(c.date());
179 Real a = payer_ * c.amount() * dsc;
180 npv_ += a;
181 Real t = discountCurve_->timeFromReference(c.date());
182 if (computeDelta_) {
183 getMapEntry(deltaDiscount_, c.date()) += -t * a;
184 }
185 if (computeGamma_) {
186 getMapEntry(gammaDiscount_, c.date()) += t * t * a;
187 }
188 // only add to the foreign npv (and hence effectively to the fx spot delta) if the fx rate is not yet fixed
189 if (c.fxFixingDate() > discountCurve_->referenceDate() ||
190 (c.fxFixingDate() == discountCurve_->referenceDate() &&
191 c.fxIndex()->pastFixing(c.fxFixingDate()) == Null<Real>())) {
192 Real tmp = c.fxIndex()->forecastFixing(0.0);
193 Real b = a / tmp;
195 }
196}
197
199{
201}
202
203std::vector<Real> rebucketDeltas(const std::vector<Time>& deltaTimes, const std::map<Date, Real>& deltaRaw,
204 const Date& referenceDate, const DayCounter& dc, const bool linearInZero) {
205 std::vector<Real> delta(deltaTimes.size(), 0.0);
206 for (std::map<Date, Real>::const_iterator i = deltaRaw.begin(); i != deltaRaw.end(); ++i) {
207 Real t = dc.yearFraction(referenceDate, i->first);
208 Size b = std::upper_bound(deltaTimes.begin(), deltaTimes.end(), t) - deltaTimes.begin();
209 if (b == 0) {
210 delta[0] += i->second;
211 } else if (b == deltaTimes.size()) {
212 delta.back() += i->second;
213 } else {
214 Real tmp = (deltaTimes[b] - t) / (deltaTimes[b] - deltaTimes[b - 1]);
215 if (linearInZero) {
216 delta[b - 1] += i->second * tmp;
217 delta[b] += i->second * (1.0 - tmp);
218 } else {
219 delta[b - 1] += i->second * tmp * deltaTimes[b - 1] / t;
220 delta[b] += i->second * (1.0 - tmp) * deltaTimes[b] / t;
221 }
222 }
223 }
224 return delta;
225}
226
227Matrix rebucketGammas(const std::vector<Time>& gammaTimes, const std::map<Date, Real>& gammaDscRaw,
228 std::map<std::pair<Date, Date>, Real>& gammaForward,
229 std::map<std::pair<Date, Date>, Real>& gammaDscFwd, const bool forceFullMatrix,
230 const Date& referenceDate, const DayCounter& dc, const bool linearInZero) {
231 int n = gammaTimes.size();
232 // if we have two curves c1, c2, the matrix contains c1-c1, c1-c2, c2-c1, c2-c2 blocks
233 Size n2 = !forceFullMatrix && gammaForward.empty() && gammaDscFwd.empty() ? n : 2 * n;
234 Matrix gamma(n2, n2, 0.0);
235 // pure dsc
236 for (std::map<Date, Real>::const_iterator i = gammaDscRaw.begin(); i != gammaDscRaw.end(); ++i) {
237 Real t = dc.yearFraction(referenceDate, i->first);
238 int b = (int)(std::upper_bound(gammaTimes.begin(), gammaTimes.end(), t) - gammaTimes.begin());
239 if (b == 0) {
240 gamma[0][0] += i->second;
241 } else if (b == n) {
242 gamma[n - 1][n - 1] += i->second;
243 } else {
244 Real tmp = (gammaTimes[b] - t) / (gammaTimes[b] - gammaTimes[b - 1]);
245 if (linearInZero) {
246 gamma[b - 1][b - 1] += i->second * tmp * tmp;
247 gamma[b - 1][b] += i->second * (1.0 - tmp) * tmp;
248 gamma[b][b - 1] += i->second * tmp * (1.0 - tmp);
249 gamma[b][b] += i->second * (1.0 - tmp) * (1.0 - tmp);
250 } else {
251 gamma[b - 1][b - 1] += i->second * tmp * tmp * gammaTimes[b - 1] * gammaTimes[b - 1] / (t * t);
252 gamma[b - 1][b] += i->second * (1.0 - tmp) * tmp * gammaTimes[b] * gammaTimes[b - 1] / (t * t);
253 gamma[b][b - 1] += i->second * tmp * (1.0 - tmp) * gammaTimes[b - 1] * gammaTimes[b] / (t * t);
254 gamma[b][b] += i->second * (1.0 - tmp) * (1.0 - tmp) * gammaTimes[b] * gammaTimes[b] / (t * t);
255 }
256 }
257 }
258 // dsc-fwd
259 if (!gammaDscFwd.empty()) {
260 Matrix gammadf(n, n, 0.0);
261 for (std::map<std::pair<Date, Date>, Real>::const_iterator i = gammaDscFwd.begin(); i != gammaDscFwd.end();
262 ++i) {
263 Real t1 = dc.yearFraction(referenceDate, i->first.first);
264 Real t2 = dc.yearFraction(referenceDate, i->first.second);
265 int b1 = (int)(std::upper_bound(gammaTimes.begin(), gammaTimes.end(), t1) - gammaTimes.begin());
266 int b2 = (int)(std::upper_bound(gammaTimes.begin(), gammaTimes.end(), t2) - gammaTimes.begin());
267 Real w1 = 0.0, w2 = 0.0;
268 int i1 = 0, i2 = 0;
269 if (b1 == 0) {
270 w1 = 1.0;
271 i1 = 0;
272 } else if (b1 == n) {
273 w1 = 0.0;
274 i1 = n - 2;
275 } else {
276 w1 = (gammaTimes[b1] - t1) / (gammaTimes[b1] - gammaTimes[b1 - 1]);
277 i1 = b1 - 1;
278 }
279 if (b2 == 0) {
280 w2 = 1.0;
281 i2 = 0;
282 } else if (b2 == n) {
283 w2 = 0.0;
284 i2 = n - 2;
285 } else {
286 w2 = (gammaTimes[b2] - t2) / (gammaTimes[b2] - gammaTimes[b2 - 1]);
287 i2 = b2 - 1;
288 }
289 if (i1 >= 0) {
290 if (i2 < n - 1)
291 gammadf[i1][i2 + 1] += w1 * (1.0 - w2) * i->second *
292 (linearInZero ? 1.0 : gammaTimes[b1 - 1] * gammaTimes[b2] / (t1 * t2));
293 if (i2 >= 0) {
294 gammadf[i1][i2] += w1 * w2 * i->second *
295 (linearInZero ? 1.0 : gammaTimes[b1 - 1] * gammaTimes[b2 - 1] / (t1 * t2));
296 }
297 }
298 if (i2 >= 0 && i1 < n - 1) {
299 gammadf[i1 + 1][i2] += (1.0 - w1) * w2 * i->second *
300 (linearInZero ? 1.0 : gammaTimes[b1] * gammaTimes[b2 - 1] / (t1 * t2));
301 }
302 if (i1 < n - 1 && i2 < n - 1) {
303 gammadf[i1 + 1][i2 + 1] += (1.0 - w1) * (1.0 - w2) * i->second *
304 (linearInZero ? 1.0 : gammaTimes[b1] * gammaTimes[b2] / (t1 * t2));
305 }
306 }
307 for (int i = 0; i < n; ++i) {
308 for (int j = 0; j < n; ++j) {
309 gamma[i][n + j] = gamma[n + j][i] = gammadf[i][j];
310 }
311 }
312 }
313 // fwd-fwd
314 for (std::map<std::pair<Date, Date>, Real>::const_iterator i = gammaForward.begin(); i != gammaForward.end(); ++i) {
315 Real t1 = dc.yearFraction(referenceDate, i->first.first);
316 Real t2 = dc.yearFraction(referenceDate, i->first.second);
317 int b1 = (int)(std::upper_bound(gammaTimes.begin(), gammaTimes.end(), t1) - gammaTimes.begin());
318 int b2 = (int)(std::upper_bound(gammaTimes.begin(), gammaTimes.end(), t2) - gammaTimes.begin());
319 Real tmp = 0.5 * i->second;
320 Real w1 = 0.0, w2 = 0.0;
321 int i1 = 0, i2 = 0;
322 if (b1 == 0) {
323 w1 = 1.0;
324 i1 = 0;
325 } else if (b1 == n) {
326 w1 = 0.0;
327 i1 = n - 2;
328 } else {
329 w1 = (gammaTimes[b1] - t1) / (gammaTimes[b1] - gammaTimes[b1 - 1]);
330 i1 = b1 - 1;
331 }
332 if (b2 == 0) {
333 w2 = 1.0;
334 i2 = 0;
335 } else if (b2 == n) {
336 w2 = 0.0;
337 i2 = n - 2;
338 } else {
339 w2 = (gammaTimes[b2] - t2) / (gammaTimes[b2] - gammaTimes[b2 - 1]);
340 i2 = b2 - 1;
341 }
342 if (i1 >= 0) {
343 if (i2 < n - 1) {
344 gamma[n + i1][n + i2 + 1] +=
345 w1 * (1.0 - w2) * tmp * (linearInZero ? 1.0 : gammaTimes[b1 - 1] * gammaTimes[b2] / (t1 * t2));
346 gamma[n + i2 + 1][n + i1] +=
347 w1 * (1.0 - w2) * tmp * (linearInZero ? 1.0 : gammaTimes[b1 - 1] * gammaTimes[b2] / (t1 * t2));
348 }
349 if (i2 >= 0) {
350 gamma[n + i1][n + i2] +=
351 w1 * w2 * tmp * (linearInZero ? 1.0 : gammaTimes[b1 - 1] * gammaTimes[b2 - 1] / (t1 * t2));
352 gamma[n + i2][n + i1] +=
353 w1 * w2 * tmp * (linearInZero ? 1.0 : gammaTimes[b1 - 1] * gammaTimes[b2 - 1] / (t1 * t2));
354 }
355 }
356 if (i2 >= 0 && i1 < n - 1) {
357 gamma[n + i1 + 1][n + i2] +=
358 (1.0 - w1) * w2 * tmp * (linearInZero ? 1.0 : gammaTimes[b1] * gammaTimes[b2 - 1] / (t1 * t2));
359 gamma[n + i2][n + i1 + 1] +=
360 (1.0 - w1) * w2 * tmp * (linearInZero ? 1.0 : gammaTimes[b1] * gammaTimes[b2 - 1] / (t1 * t2));
361 }
362 if (i1 < n - 1 && i2 < n - 1) {
363 gamma[n + i1 + 1][n + i2 + 1] +=
364 (1.0 - w1) * (1.0 - w2) * tmp * (linearInZero ? 1.0 : gammaTimes[b1] * gammaTimes[b2] / (t1 * t2));
365 gamma[n + i2 + 1][n + i1 + 1] +=
366 (1.0 - w1) * (1.0 - w2) * tmp * (linearInZero ? 1.0 : gammaTimes[b1] * gammaTimes[b2] / (t1 * t2));
367 }
368 }
369
370 return gamma;
371} // rebucketGammas
372
373} // namespace detail
374
375DiscountingSwapEngineDeltaGamma::DiscountingSwapEngineDeltaGamma(const Handle<YieldTermStructure>& discountCurve,
376 const std::vector<Time>& bucketTimes,
377 const bool computeDelta, const bool computeGamma,
378 const bool computeBPS, const bool linearInZero)
379 : discountCurve_(discountCurve), bucketTimes_(bucketTimes), computeDelta_(computeDelta),
380 computeGamma_(computeGamma), computeBPS_(computeBPS), linearInZero_(linearInZero) {
381 registerWith(discountCurve_);
382 QL_REQUIRE(!bucketTimes_.empty() || (!computeDelta && !computeGamma),
383 "bucket times are empty, although sensitivities have to be calculated");
384}
385
387 QL_REQUIRE(!discountCurve_.empty(), "discounting term structure handle is empty");
388
389 // compute npv and raw deltas
390
391 results_.value = 0.0;
392 results_.errorEstimate = Null<Real>();
393 results_.legNPV.resize(arguments_.legs.size());
394 if (computeBPS_)
395 results_.legBPS.resize(arguments_.legs.size());
396
397 std::map<Date, Real> deltaDiscountRaw, deltaForwardRaw, gammaDiscountRaw;
398 std::map<std::pair<Date, Date>, Real> gammaForwardRaw, gammaDscFwdRaw;
399
400 std::vector<std::vector<Real>> deltaBPS;
401 std::vector<Matrix> gammaBPS;
402
403 Real empty = 0.0;
404
405 for (Size j = 0; j < arguments_.legs.size(); ++j) {
406 Real npv = 0.0, bps = 0.0;
407 std::map<Date, Real> deltaBPSRaw, gammaBPSRaw; // these results are per leg
409 computeGamma_, computeBPS_, deltaDiscountRaw, deltaForwardRaw, deltaBPSRaw,
410 gammaDiscountRaw, gammaForwardRaw, gammaDscFwdRaw, gammaBPSRaw, empty,
411 false, empty);
412 Leg& leg = arguments_.legs[j];
413 for (Size i = 0; i < leg.size(); ++i) {
414 CashFlow& cf = *leg[i];
415 if (cf.date() <= discountCurve_->referenceDate()) {
416 continue;
417 }
418 cf.accept(calc);
419 }
420 results_.legNPV[j] = npv;
421 results_.value += npv;
422 if (computeBPS_) {
423 std::map<std::pair<Date, Date>, Real> empty;
424 results_.legBPS[j] += bps;
425 // bps delta and gamma are per leg, i.e. we have to compute delta and gamma already here,
426 // the result vectors are then set below where the rest of the delta / gamma computation is done
427 std::vector<Real> tmp = detail::rebucketDeltas(bucketTimes_, deltaBPSRaw, discountCurve_->referenceDate(),
428 discountCurve_->dayCounter(), linearInZero_);
429 deltaBPS.push_back(tmp);
430 Matrix tmp2 =
431 detail::rebucketGammas(bucketTimes_, gammaBPSRaw, empty, empty, false, discountCurve_->referenceDate(),
432 discountCurve_->dayCounter(), linearInZero_);
433 gammaBPS.push_back(tmp2);
434 }
435 }
436
437 // convert raw deltas to given bucketing structure
438
439 results_.additionalResults["bucketTimes"] = bucketTimes_;
440
441 if (computeDelta_) {
442 std::vector<Real> deltaDiscount =
443 detail::rebucketDeltas(bucketTimes_, deltaDiscountRaw, discountCurve_->referenceDate(),
444 discountCurve_->dayCounter(), linearInZero_);
445 std::vector<Real> deltaForward =
446 detail::rebucketDeltas(bucketTimes_, deltaForwardRaw, discountCurve_->referenceDate(),
447 discountCurve_->dayCounter(), linearInZero_);
448
449 results_.additionalResults["deltaDiscount"] = deltaDiscount;
450 results_.additionalResults["deltaForward"] = deltaForward;
451 if (computeBPS_) {
452 results_.additionalResults["deltaBPS"] = deltaBPS;
453 }
454 }
455
456 // convert raw gammas to given bucketing structure
457
458 if (computeGamma_) {
459 Matrix gamma =
460 detail::rebucketGammas(bucketTimes_, gammaDiscountRaw, gammaForwardRaw, gammaDscFwdRaw, true,
461 discountCurve_->referenceDate(), discountCurve_->dayCounter(), linearInZero_);
462 results_.additionalResults["gamma"] = gamma;
463 if (computeBPS_) {
464 results_.additionalResults["gammaBPS"] = gammaBPS;
465 }
466 }
467
468} // calculate()
469
470} // namespace QuantExt
const Instrument::results * results_
Definition: cdsoption.cpp:81
DiscountingSwapEngineDeltaGamma(const Handle< YieldTermStructure > &discountCurve=Handle< YieldTermStructure >(), const std::vector< Time > &bucketTimes=std::vector< Time >(), const bool computeDelta=false, const bool computeGamma=false, const bool computeBPS=false, const bool linearInZero=true)
Real amount() const override
Date date() const override
const QuantLib::ext::shared_ptr< FxIndex > & fxIndex() const
Date fxFixingDate() const
std::map< std::pair< Date, Date >, Real > & gammaDscFwd_
NpvDeltaGammaCalculator(Handle< YieldTermStructure > discountCurve, const Real payer, Real &npv, Real &bps, const bool computeDelta, const bool computeGamma, const bool computeBPS, std::map< Date, Real > &deltaDiscount, std::map< Date, Real > &deltaForward, std::map< Date, Real > &deltaBPS, std::map< Date, Real > &gammaDiscount, std::map< std::pair< Date, Date >, Real > &gammaForward, std::map< std::pair< Date, Date >, Real > &gammaDscFwd, std::map< Date, Real > &gammaBPS, Real &fxLinkedForeignNpv, const bool excludeSimpleCashFlowsFromSensis, Real &simpleCashFlowNpv)
std::map< std::pair< Date, Date >, Real > & gammaForward_
Swap engine providing analytical deltas and gammas for vanilla swaps.
Matrix rebucketGammas(const std::vector< Time > &gammaTimes, const std::map< Date, Real > &gammaDscRaw, std::map< std::pair< Date, Date >, Real > &gammaForward, std::map< std::pair< Date, Date >, Real > &gammaDscFwd, const bool forceFullMatrix, const Date &referenceDate, const DayCounter &dc, const bool linearInZero)
Real & getMapEntry(std::map< Key, Real > &map, const Key &key)
std::vector< Real > rebucketDeltas(const std::vector< Time > &deltaTimes, const std::map< Date, Real > &deltaRaw, const Date &referenceDate, const DayCounter &dc, const bool linearInZero)
Swap::arguments * arguments_