QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
cvaswapengine.cpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2015 Jose Aparicio
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/pricingengines/swap/cvaswapengine.hpp>
21#include <ql/cashflows/fixedratecoupon.hpp>
22#include <ql/cashflows/floatingratecoupon.hpp>
23#include <ql/indexes/iborindex.hpp>
24#include <ql/instruments/makevanillaswap.hpp>
25#include <ql/exercise.hpp>
26#include <ql/pricingengines/swap/discountingswapengine.hpp>
27#include <ql/termstructures/credit/flathazardrate.hpp>
28#include <ql/pricingengines/swaption/blackswaptionengine.hpp>
29#include <ql/time/calendars/nullcalendar.hpp>
30
31namespace QuantLib {
32
34 const Handle<YieldTermStructure>& discountCurve,
35 const Handle<PricingEngine>& swaptionEngine,
37 Real ctptyRecoveryRate,
39 Real invstRecoveryRate)
40 : baseSwapEngine_(Handle<PricingEngine>(
41 ext::make_shared<DiscountingSwapEngine>(discountCurve))),
42 swaptionletEngine_(swaptionEngine),
43 discountCurve_(discountCurve),
44 defaultTS_(ctptyDTS),
45 ctptyRecoveryRate_(ctptyRecoveryRate),
46 invstDTS_(invstDTS.empty() ? Handle<DefaultProbabilityTermStructure>(
47 ext::make_shared<FlatHazardRate>(0, NullCalendar(), 1.e-12,
48 ctptyDTS->dayCounter()) ) : invstDTS ),
49 invstRecoveryRate_(invstRecoveryRate)
50 {
51 registerWith(discountCurve);
52 registerWith(ctptyDTS);
53 registerWith(invstDTS_);
54 registerWith(swaptionEngine);
55 }
56
58 const Handle<YieldTermStructure>& discountCurve,
59 const Volatility blackVol,
61 Real ctptyRecoveryRate,
63 Real invstRecoveryRate)
64 : baseSwapEngine_(Handle<PricingEngine>(
65 ext::make_shared<DiscountingSwapEngine>(discountCurve))),
66 swaptionletEngine_(Handle<PricingEngine>(
67 ext::make_shared<BlackSwaptionEngine>(discountCurve,
68 blackVol))),
69 discountCurve_(discountCurve),
70 defaultTS_(ctptyDTS),
71 ctptyRecoveryRate_(ctptyRecoveryRate),
72 invstDTS_(invstDTS.empty() ? Handle<DefaultProbabilityTermStructure>(
73 ext::make_shared<FlatHazardRate>(0, NullCalendar(), 1.e-12,
74 ctptyDTS->dayCounter()) ) : invstDTS ),
75 invstRecoveryRate_(invstRecoveryRate)
76 {
77 registerWith(discountCurve);
78 registerWith(ctptyDTS);
79 registerWith(invstDTS_);
80 }
81
83 const Handle<YieldTermStructure>& discountCurve,
84 const Handle<Quote>& blackVol,
86 Real ctptyRecoveryRate,
88 Real invstRecoveryRate)
89 : baseSwapEngine_(Handle<PricingEngine>(
90 ext::make_shared<DiscountingSwapEngine>(discountCurve))),
91 swaptionletEngine_(Handle<PricingEngine>(
92 ext::make_shared<BlackSwaptionEngine>(discountCurve,
93 blackVol))),
94 discountCurve_(discountCurve),
95 defaultTS_(ctptyDTS),
96 ctptyRecoveryRate_(ctptyRecoveryRate),
97 invstDTS_(invstDTS.empty() ? Handle<DefaultProbabilityTermStructure>(
98 ext::make_shared<FlatHazardRate>(0, NullCalendar(), 1.e-12,
99 ctptyDTS->dayCounter()) ) : invstDTS ),
100 invstRecoveryRate_(invstRecoveryRate)
101 {
102 registerWith(discountCurve);
103 registerWith(ctptyDTS);
104 registerWith(invstDTS_);
105 registerWith(blackVol);
106 }
107
109 /* both DTS, YTS ref dates and pricing date consistency
110 checks? settlement... */
111 QL_REQUIRE(!discountCurve_.empty(),
112 "no discount term structure set");
113 QL_REQUIRE(!defaultTS_.empty(),
114 "no ctpty default term structure set");
115 QL_REQUIRE(!swaptionletEngine_.empty(),
116 "no swap option engine set");
117
118 QL_REQUIRE(arguments_.nominal != Null<Real>(),
119 "non-constant nominals are not supported yet");
120
121 Date priceDate = defaultTS_->referenceDate();
122
123 Real cumOptVal = 0.,
124 cumPutVal = 0.;
125 // Vanilla swap so 0 leg is floater
126
127 std::vector<Date>::const_iterator nextFD =
128 arguments_.fixedPayDates.begin();
129 Date swapletStart = priceDate;
130 while (*nextFD < priceDate) ++nextFD;
131
132 // Compute fair spread for strike value:
133 // copy args into the non risky engine
134 auto* noCVAArgs = dynamic_cast<Swap::arguments*>(baseSwapEngine_->getArguments());
135 QL_REQUIRE(noCVAArgs != nullptr, "wrong argument type");
136
137 noCVAArgs->legs = this->arguments_.legs;
138 noCVAArgs->payer = this->arguments_.payer;
139
140 baseSwapEngine_->calculate();
141
142 ext::shared_ptr<FixedRateCoupon> coupon = ext::dynamic_pointer_cast<FixedRateCoupon>(arguments_.legs[0][0]);
143 QL_REQUIRE(coupon,"dynamic cast of fixed leg coupon failed.");
144 Rate baseSwapRate = coupon->rate();
145
146 const auto* vSResults = dynamic_cast<const Swap::results*>(baseSwapEngine_->getResults());
147 QL_REQUIRE(vSResults != nullptr, "wrong result type");
148
149 Rate baseSwapFairRate = -baseSwapRate * vSResults->legNPV[1] /
150 vSResults->legNPV[0];
151 Real baseSwapNPV = vSResults->value;
152
153 Swap::Type reversedType = arguments_.type == Swap::Payer ? Swap::Receiver : Swap::Payer;
154
155 // Swaplet options summatory:
156 while(nextFD != arguments_.fixedPayDates.end()) {
157 // iFD coupon not fixed, create swaptionlet:
158 ext::shared_ptr<FloatingRateCoupon> floatCoupon = ext::dynamic_pointer_cast<FloatingRateCoupon>(arguments_.legs[1][0]);
159 QL_REQUIRE(floatCoupon,"dynamic cast of floating leg coupon failed.");
160 ext::shared_ptr<IborIndex> swapIndex = ext::dynamic_pointer_cast<IborIndex>(floatCoupon->index());
161 QL_REQUIRE(swapIndex,"dynamic cast of floating leg index failed.");
162
163 // Alternatively one could cap this period to, say, 1M
164 // Period swapPeriod = ext::dynamic_pointer_cast<FloatingRateCoupon>(
165 // arguments_.legs[1][0])->index()->tenor();
166
167 Period baseSwapsTenor(arguments_.fixedPayDates.back().serialNumber()
168 - swapletStart.serialNumber(), Days);
169 ext::shared_ptr<VanillaSwap> swaplet = MakeVanillaSwap(
170 baseSwapsTenor,
171 swapIndex,
172 baseSwapFairRate // strike
173 )
174 .withType(arguments_.type)
175 .withNominal(arguments_.nominal)
177 .withEffectiveDate(swapletStart)
178 .withTerminationDate(arguments_.fixedPayDates.back());
179 ext::shared_ptr<VanillaSwap> revSwaplet = MakeVanillaSwap(
180 baseSwapsTenor,
181 swapIndex,
182 baseSwapFairRate // strike
183 )
184 .withType(reversedType)
185 .withNominal(arguments_.nominal)
187 .withEffectiveDate(swapletStart)
188 .withTerminationDate(arguments_.fixedPayDates.back());
189
190 Swaption swaptionlet(swaplet,
191 ext::make_shared<EuropeanExercise>(swapletStart));
192 Swaption putSwaplet(revSwaplet,
193 ext::make_shared<EuropeanExercise>(swapletStart));
194 swaptionlet.setPricingEngine(swaptionletEngine_.currentLink());
195 putSwaplet.setPricingEngine(swaptionletEngine_.currentLink());
196
197 // atm underlying swap means that the value of put = value
198 // call so this double pricing is not needed
199 cumOptVal += swaptionlet.NPV() * defaultTS_->defaultProbability(
200 swapletStart, *nextFD);
201 cumPutVal += putSwaplet.NPV() * invstDTS_->defaultProbability(
202 swapletStart, *nextFD);
203
204 swapletStart = *nextFD;
205 ++nextFD;
206 }
207
208 results_.value = baseSwapNPV - (1.-ctptyRecoveryRate_) * cumOptVal
209 + (1.-invstRecoveryRate_) * cumPutVal;
210
211 results_.fairRate = -baseSwapRate * (vSResults->legNPV[1]
212 - (1.-ctptyRecoveryRate_) * cumOptVal +
213 (1.-invstRecoveryRate_) * cumPutVal )
214 / vSResults->legNPV[0];
215
216 }
217
218
219}
Shifted Lognormal Black-formula swaption engine.
Handle< YieldTermStructure > discountCurve_
Handle< PricingEngine > swaptionletEngine_
Handle< DefaultProbabilityTermStructure > invstDTS_
Handle< PricingEngine > baseSwapEngine_
Handle< DefaultProbabilityTermStructure > defaultTS_
CounterpartyAdjSwapEngine(const Handle< YieldTermStructure > &discountCurve, const Handle< PricingEngine > &swaptionEngine, const Handle< DefaultProbabilityTermStructure > &ctptyDTS, Real ctptyRecoveryRate, const Handle< DefaultProbabilityTermStructure > &invstDTS=Handle< DefaultProbabilityTermStructure >(), Real invstRecoveryRate=0.999)
Concrete date class.
Definition: date.hpp:125
Date::serial_type serialNumber() const
Definition: date.hpp:408
Default probability term structure.
Flat hazard-rate curve.
Shared handle to an observable.
Definition: handle.hpp:41
Real NPV() const
returns the net present value of the instrument.
Definition: instrument.hpp:167
void setPricingEngine(const ext::shared_ptr< PricingEngine > &)
set the pricing engine to be used.
Definition: instrument.cpp:35
MakeVanillaSwap & withEffectiveDate(const Date &)
MakeVanillaSwap & withTerminationDate(const Date &)
MakeVanillaSwap & withNominal(Real n)
MakeVanillaSwap & withType(Swap::Type type)
Calendar for reproducing theoretical calculations.
template class providing a null value for a given type.
Definition: null.hpp:76
interface for pricing engines
Swaption class
Definition: swaption.hpp:81
QL_REAL Real
real number
Definition: types.hpp:50
Real Volatility
volatility
Definition: types.hpp:78
Real Rate
interest rates
Definition: types.hpp:70
Definition: any.hpp:35