22#include <ql/cashflows/floatingratecoupon.hpp>
23#include <ql/cashflows/simplecashflow.hpp>
24#include <ql/instruments/swap.hpp>
25#include <ql/pricingengines/swap/discountingswapengine.hpp>
26#include <ql/pricingengines/vanilla/analyticeuropeanengine.hpp>
27#include <ql/quotes/compositequote.hpp>
33 const std::string& baseCcy,
const std::map<std::string, Handle<YieldTermStructure>>& discountCurves,
34 const std::map<std::string, Handle<Quote>>& fxSpots,
const Handle<DefaultProbabilityTermStructure>& defaultCurve,
35 const Handle<Quote>& recoveryRate,
const Handle<BlackVolTermStructure>& volatility,
36 const bool alwaysRecomputeOptionRepresentation,
const Size maxGapDays,
const Size maxDiscretisationPoints)
38 maxDiscretisationPoints),
39 volatility_(volatility), alwaysRecomputeOptionRepresentation_(alwaysRecomputeOptionRepresentation) {
46 "AnalyticXCcyBlackRiskParticipationAgreementEngine::protectionLegNpv(): callability is not supported");
49 "AnalyticXCcyBlackRiskParticipationAgreementEngine::protectionLegNpv(): empty discount curve");
51 std::string domCcy =
arguments_.underlyingCcys[0];
52 std::string forCcy = domCcy;
54 for (
auto const& ccy :
arguments_.underlyingCcys) {
61 "AnalyticXCcyBlackRiskParticipationAgreementEngine::protectionLegNpv(): empty discount curve for ccy "
64 "AnalyticXCcyBlackRiskParticipationAgreementEngine::protectionLegNpv(): empty discount curve for ccy "
68 "AnalyticXCcyBlackRiskParticipationAgreementEngine::protectionLegNpv(): empty discount curve for ccy pair "
72 "AnalyticXCcyBlackRiskParticipationAgreementEngine::protectionLegNpv(): empty discount curve for ccy pair "
76 Real operator()(Real x, Real y)
const {
return x / y; }
79 Handle<Quote> fxSpot(QuantLib::ext::make_shared<CompositeQuote<divide>>(
fxSpots_[forCcy],
fxSpots_[domCcy], divide()));
87 results_.optionRepresentationPeriods.clear();
88 results_.optionRepresentation.clear();
93 for (Size i = 0; i <
gridDates_.size() - 1; ++i) {
96 Date mid = start + (end - start) / 2;
100 results_.optionRepresentationPeriods.push_back(std::make_tuple(mid, start, end));
103 for (
auto const& e :
results_.optionRepresentationPeriods) {
104 Date d = std::get<0>(e);
106 arguments_.underlyingCcys, std::get<0>(e), forCcy, domCcy,
108 bool instrumentSet =
false;
113 Option::Type type = matcher.
amount1() > 0.0 ? Option::Call : Option::Put;
114 results_.optionRepresentation.push_back(QuantLib::ext::make_shared<VanillaOption>(
115 QuantLib::ext::make_shared<PlainVanillaPayoff>(type, strike), QuantLib::ext::make_shared<EuropeanExercise>(d)));
117 instrumentSet =
true;
120 if (!instrumentSet) {
125 results_.optionRepresentation.push_back(QuantLib::ext::make_shared<Swap>(
126 std::vector<Leg>{{QuantLib::ext::make_shared<SimpleCashFlow>(amount, d)}}, std::vector<bool>{
false}));
127 results_.optionMultiplier.push_back(1.0);
132 results_.optionRepresentationReferenceDate =
arguments_.optionRepresentationReferenceDate;
136 QL_REQUIRE(
results_.optionRepresentation.size() ==
results_.optionRepresentationPeriods.size(),
137 "AnalyticXCcyBlackRiskParticipationAgreementEngine::calculate(): inconsistent option representation "
139 QL_REQUIRE(
results_.optionRepresentation.size() ==
results_.optionMultiplier.size(),
140 "AnalyticXCcyBlackRiskParticipationAgreementEngine::calculate(): inconsistent option multiplier");
145 auto swapEngine = QuantLib::ext::make_shared<DiscountingSwapEngine>(
discountCurves_[domCcy]);
146 auto optionEngine = QuantLib::ext::make_shared<AnalyticEuropeanEngine>(QuantLib::ext::make_shared<GeneralizedBlackScholesProcess>(
149 for (
auto s :
results_.optionRepresentation) {
150 if (
auto tmp = QuantLib::ext::dynamic_pointer_cast<VanillaOption>(s))
151 s->setPricingEngine(optionEngine);
152 else if (
auto tmp = QuantLib::ext::dynamic_pointer_cast<Swap>(s))
153 s->setPricingEngine(swapEngine);
155 QL_FAIL(
"AnalyticXCcyBlackRiskParticipationAgreementEngine::protectionLegNpv(): internal error, could not "
156 "cast representative instrument to either VanillaOption or Swap");
162 QL_REQUIRE(!
fxSpots_[domCcy].empty(),
163 "AnalyticBlackRiskParticipationAgreementEngine::protectionLegNpv(): empty fx spot for ccy pair "
167 std::vector<Real> optionPv(
results_.optionRepresentationPeriods.size(), 0.0);
168 for (Size i = 0; i <
results_.optionRepresentationPeriods.size(); ++i) {
170 std::get<2>(
results_.optionRepresentationPeriods[i]));
171 Real swpNpv =
results_.optionRepresentation[i]->NPV() *
results_.optionMultiplier[i];
173 optionPv[i] = swpNpv;
178 QuantLib::ext::shared_ptr<PricingEngine> emptyEngine;
179 for (
auto s :
results_.optionRepresentation)
180 s->setPricingEngine(emptyEngine);
184 std::vector<Real> optionStrikes;
185 std::vector<Date> optionExerciseDates;
186 for (
auto const& r :
results_.optionRepresentation) {
187 if (
auto o = QuantLib::ext::dynamic_pointer_cast<VanillaOption>(r)) {
188 if (
auto p = QuantLib::ext::dynamic_pointer_cast<PlainVanillaPayoff>(o->payoff())) {
189 optionStrikes.push_back(p->strike());
191 optionStrikes.push_back(0.0);
193 if (!o->exercise()->dates().empty()) {
194 optionExerciseDates.push_back(o->exercise()->dates().front());
196 optionExerciseDates.push_back(Date());
198 }
else if (
auto s = QuantLib::ext::dynamic_pointer_cast<Swap>(r)) {
199 optionStrikes.push_back(0.0);
200 if (!s->leg(0).empty()) {
201 optionExerciseDates.push_back(s->leg(0).front()->date());
203 optionExerciseDates.push_back(Date());
208 results_.additionalResults[
"OptionNpvs"] = optionPv;
211 results_.additionalResults[
"DomesticCurrency"] = domCcy;
212 results_.additionalResults[
"ForeignCurrency"] = forCcy;
214 results_.additionalResults[
"OptionStrikes"] = optionStrikes;
215 results_.additionalResults[
"OptionExerciseDates"] = optionExerciseDates;
const Instrument::results * results_
const bool alwaysRecomputeOptionRepresentation_
const Handle< BlackVolTermStructure > volatility_
Real protectionLegNpv() const override
AnalyticXCcyBlackRiskParticipationAgreementEngine(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< BlackVolTermStructure > &volatility, const bool alwaysRecomputeOptionRepresentation, const Size maxGapDays=Null< Size >(), const Size maxDiscretisationPoints=Null< Size >())
Real effectiveRecoveryRate_
std::vector< Date > gridDates_
std::map< std::string, Handle< Quote > > fxSpots_
std::map< std::string, Handle< YieldTermStructure > > discountCurves_
Handle< DefaultProbabilityTermStructure > defaultCurve_
SafeStack< ValueType > value
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
Serializable Credit Default Swap.
Swap::arguments * arguments_