Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
analyticblackriskparticipationagreementengine.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2019 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
22
23#include <ql/cashflows/floatingratecoupon.hpp>
24#include <ql/pricingengines/swaption/blackswaptionengine.hpp>
25
26namespace ore {
27namespace data {
28
30 const std::string& baseCcy, const std::map<std::string, Handle<YieldTermStructure>>& discountCurves,
31 const std::map<std::string, Handle<Quote>>& fxSpots, const Handle<DefaultProbabilityTermStructure>& defaultCurve,
32 const Handle<Quote>& recoveryRate, const Handle<SwaptionVolatilityStructure>& volatility,
33 const QuantLib::ext::shared_ptr<SwapIndex>& swapIndexBase, const bool matchUnderlyingTenor, const Real reversion,
34 const bool alwaysRecomputeOptionRepresentation, const Size maxGapDays, const Size maxDiscretisationPoints)
35 : RiskParticipationAgreementBaseEngine(baseCcy, discountCurves, fxSpots, defaultCurve, recoveryRate, maxGapDays,
36 maxDiscretisationPoints),
37 volatility_(volatility), swapIndexBase_(swapIndexBase), matchUnderlyingTenor_(matchUnderlyingTenor),
38 reversion_(reversion), alwaysRecomputeOptionRepresentation_(alwaysRecomputeOptionRepresentation) {
39 registerWith(volatility_);
40 registerWith(swapIndexBase_);
41}
42
44
45 QL_REQUIRE(!volatility_.empty(),
46 "AnalyticBlackRiskParticipationAgreementEngine::calculate(): empty discount curve");
47
48 // check if we can reuse the swaption representation, otherwise compute it
49
50 if (alwaysRecomputeOptionRepresentation_ || arguments_.optionRepresentationReferenceDate == Date() ||
51 referenceDate_ != arguments_.optionRepresentationReferenceDate) {
52
53 results_.optionRepresentationReferenceDate = referenceDate_;
54 results_.optionRepresentationPeriods.clear();
55 results_.optionRepresentation.clear();
56
57 /* we construct one swaption per floating rate coupon on the midpoint of the accrual period
58 but only keep those with an underlying length of at least 1M */
59
60 for (Size i = 0; i < gridDates_.size() - 1; ++i) {
61 Date start = gridDates_[i];
62 Date end = gridDates_[i + 1];
63 Date mid = start + (end - start) / 2;
64 // mid might be = reference date degenerate cases where the first two discretisation points
65 // are only one day apart from each other
66 if (mid + 1 * Months <= arguments_.underlyingMaturity && mid > discountCurves_[baseCcy_]->referenceDate())
67 results_.optionRepresentationPeriods.push_back(std::make_tuple(mid, start, end));
68 }
69
70 QL_REQUIRE(
71 arguments_.underlying.size() == 2,
72 "AnalyticBlackRiskParticipationAgreementEngine::protectionLegNpv(): expected two underlying legs, got "
73 << arguments_.underlying.size());
74 QL_REQUIRE(arguments_.underlyingCcys[0] == arguments_.underlyingCcys[1],
75 "AnalyticBlackRiskParticipationAgreementEngine::protectionLegNpv(): expected underlying legs in "
76 "samwe currency, got "
77 << arguments_.underlyingCcys[0] << ", " << arguments_.underlyingCcys[1]);
78 QL_REQUIRE(!discountCurves_[arguments_.underlyingCcys[0]].empty(),
79 "AnalyticBlackRiskParticipationAgreementEngine::protectionLegNpv(): empty discount curve for ccy "
80 << arguments_.underlyingCcys[0]);
81
85 for (auto const& e : results_.optionRepresentationPeriods) {
86 auto swp = matcher.representativeSwaption(
87 std::get<0>(e), QuantExt::RepresentativeSwaptionMatcher::InclusionCriterion::PayDateGtExercise);
88 // swp might be null, if there are not underlying flows left, this is handled below
89 results_.optionRepresentation.push_back(swp);
90 }
91 } else {
92 results_.optionRepresentationReferenceDate = arguments_.optionRepresentationReferenceDate;
93 results_.optionRepresentationPeriods = arguments_.optionRepresentationPeriods;
94 results_.optionRepresentation = arguments_.optionRepresentation;
95 QL_REQUIRE(
96 results_.optionRepresentation.size() == results_.optionRepresentationPeriods.size(),
97 "AnalyticBlackRiskParticipationAgreementEngine::calculate(): inconsistent swaption representation periods");
98 }
99
100 // attach an engine to the representative swaptions
101
102 QuantLib::ext::shared_ptr<PricingEngine> engine;
103 if (volatility_->volatilityType() == ShiftedLognormal) {
104 engine = QuantLib::ext::make_shared<BlackSwaptionEngine>(discountCurves_[arguments_.underlyingCcys[0]], volatility_);
105 } else {
106 engine =
107 QuantLib::ext::make_shared<BachelierSwaptionEngine>(discountCurves_[arguments_.underlyingCcys[0]], volatility_);
108 }
109
110 for (auto s : results_.optionRepresentation) {
111 if (s) {
112 if (auto tmp = QuantLib::ext::dynamic_pointer_cast<Swaption>(s)) {
113 s->setPricingEngine(engine);
114 } else {
115 QL_FAIL("AnalyticBlackRiskParticipationAgreementEngine::protectionLegNpv(): internal error, could not "
116 "cast representative instrument to Swaption");
117 }
118 }
119 }
120
121 // compute a CVA using the representative swaptions
122
123 QL_REQUIRE(!fxSpots_[arguments_.underlyingCcys[0]].empty(),
124 "AnalyticBlackRiskParticipationAgreementEngine::protectionLegNpv(): empty fx spot for ccy pair "
125 << arguments_.underlyingCcys[0] + baseCcy_);
126
127 Real cva = 0.0;
128 std::vector<Real> optionPv(results_.optionRepresentationPeriods.size(), 0.0);
129 for (Size i = 0; i < results_.optionRepresentationPeriods.size(); ++i) {
130 if (auto s = results_.optionRepresentation[i]) {
131 Real pd = defaultCurve_->defaultProbability(std::get<1>(results_.optionRepresentationPeriods[i]),
132 std::get<2>(results_.optionRepresentationPeriods[i]));
133 Real swpNpv = s ? s->NPV() : 0.0; // if s = null, there are no underlying flows left => NPV = 0
134 cva += pd * (1.0 - effectiveRecoveryRate_) * swpNpv * fxSpots_[arguments_.underlyingCcys[0]]->value();
135 optionPv[i] = swpNpv;
136 }
137 }
138
139 // detach pricing engine from result swaption representation
140
141 QuantLib::ext::shared_ptr<PricingEngine> emptyEngine;
142 for (auto s : results_.optionRepresentation)
143 if (s)
144 s->setPricingEngine(emptyEngine);
145
146 // set additional results
147
148 std::vector<Date> optionExerciseDates;
149 for (auto const& e : results_.optionRepresentationPeriods) {
150 optionExerciseDates.push_back(std::get<0>(e));
151 }
152
153 results_.additionalResults["OptionNpvs"] = optionPv;
154 results_.additionalResults["FXSpot"] = fxSpots_[arguments_.underlyingCcys[0]]->value();
155 results_.additionalResults["OptionExerciseDates"] = optionExerciseDates;
156
157 // return result
158
159 return arguments_.participationRate * cva;
160}
161
162} // namespace data
163} // namespace ore
const Instrument::results * results_
boost::shared_ptr< Swaption > representativeSwaption(Date exerciseDate, const InclusionCriterion criterion=InclusionCriterion::AccrualStartGeqExercise)
AnalyticBlackRiskParticipationAgreementEngine(const std::string &baseCcy, const std::map< std::string, Handle< YieldTermStructure > > &discountCurves, const std::map< std::string, Handle< Quote > > &fxSpots, const Handle< DefaultProbabilityTermStructure > &defaultCurve, const Handle< Quote > &recoveryRate, const Handle< SwaptionVolatilityStructure > &volatility, const QuantLib::ext::shared_ptr< SwapIndex > &swapIndexBase, const bool matchUnderlyingTenor, const Real reversion, const bool alwaysRecomputeOptionRepresentation, const Size maxGapDays=Null< Size >(), const Size maxDiscretisationPoints=Null< Size >())
std::map< std::string, Handle< YieldTermStructure > > discountCurves_
@ data
Definition: log.hpp:77
Date referenceDate
Definition: utilities.cpp:442
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Swap::arguments * arguments_