Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
blackcdsoptionengine.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2021 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#include <ql/exercise.hpp>
21#include <ql/pricingengines/blackformula.hpp>
22#include <string>
23
24using namespace QuantLib;
25using std::string;
26
27namespace QuantExt {
28
29BlackCdsOptionEngine::BlackCdsOptionEngine(const Handle<DefaultProbabilityTermStructure>& probability, Real recovery,
30 const Handle<YieldTermStructure>& discount,
31 const QuantLib::Handle<QuantExt::CreditVolCurve>& volatility)
32 : probability_(probability), recovery_(recovery), discount_(discount), volatility_(volatility) {
33 registerWith(probability_);
34 registerWith(discount_);
35 registerWith(volatility_);
36}
37
38const Handle<DefaultProbabilityTermStructure>& BlackCdsOptionEngine::probability() const {
39 return probability_;
40}
41
43 return recovery_;
44}
45
46const Handle<YieldTermStructure> BlackCdsOptionEngine::discount() const {
47 return discount_;
48}
49
50const Handle<CreditVolCurve> BlackCdsOptionEngine::volatility() const {
51 return volatility_;
52}
53
54
56
57 QL_REQUIRE(arguments_.strikeType == CdsOption::Spread, "BlackCdsOptionEngine does not support valuation" <<
58 " of single name options quoted in terms of strike price.");
59
60 // Reference to the underlying forward starting CDS, from expiry date $t_E$ to maturity $T$.
61 const auto& cds = *arguments_.swap;
62
63 // Get the additional results of the underlying CDS (need to call NPV first for calculation).
64 cds.NPV();
65 results_.additionalResults = cds.additionalResults();
66
67 // Add some entries to additional results.
68 Real forward = cds.fairSpreadClean();
69 results_.additionalResults["forwardSpread"] = forward;
70 const Real& strike = arguments_.strike;
71 results_.additionalResults["strikeSpread"] = strike;
72
73 // Calculate risky PV01, as of the valuation date i.e. time 0, for the period from $t_E$ to underlying
74 // CDS maturity $T$. This risky PV01 does not include the non-risky accrual from the CDS premium leg coupon date
75 // immediately preceding the expiry date up to the expiry date.
76 Real rpv01 = std::abs(cds.couponLegNPV() + cds.accrualRebateNPV()) / (cds.notional() * cds.runningSpread());
77 results_.additionalResults["riskyAnnuity"] = rpv01;
78
79 // Read the volatility from the volatility surface, assumed to have strike dimension in terms of spread.
80 const Date& exerciseDate = arguments_.exercise->dates().front();
81 Real underlyingLength = volatility_->dayCounter().yearFraction(exerciseDate, cds.maturity());
82 Real vol = volatility_->volatility(exerciseDate, underlyingLength, strike, CreditVolCurve::Type::Spread);
83 Real stdDev = vol * std::sqrt(volatility_->timeFromReference(exerciseDate));
84 results_.additionalResults["volatility"] = vol;
85 results_.additionalResults["standardDeviation"] = stdDev;
86
87 // Option type
88 Option::Type callPut = cds.side() == Protection::Buyer ? Option::Call : Option::Put;
89 results_.additionalResults["callPut"] = callPut == Option::Call ? string("Call") : string("Put");
90
91 // NPV, Section 9.3.7 O'Kane 2008.
92 results_.value = rpv01 * cds.notional() * blackFormula(callPut, strike, forward, stdDev, 1.0);
93
94 // If it is non-knockout and a payer, add the value of the default payout.
95 // Section 2.2 of Richard J.Martin, 2019 or Section 9.3.7 O'Kane 2008.
96 if (!arguments_.knocksOut && cds.side() == Protection::Buyer) {
97
98 DiscountFactor disc = discount_->discount(exerciseDate);
99 results_.additionalResults["discountToExercise"] = disc;
100
101 Probability sp = probability_->survivalProbability(exerciseDate);
102 results_.additionalResults["survivalProbabilityToExercise"] = sp;
103
104 Real nonKoPv = disc * sp * (1 - recovery_);
105 results_.additionalResults["nonKnockoutPv"] = nonKoPv;
106
107 results_.value += nonKoPv;
108 }
109}
110
111}
Black credit default swap option engine.
const Instrument::results * results_
Definition: cdsoption.cpp:81
const QuantLib::Handle< QuantLib::YieldTermStructure > discount() const
QuantLib::Handle< QuantLib::DefaultProbabilityTermStructure > probability_
const QuantLib::Handle< QuantExt::CreditVolCurve > volatility() const
QuantLib::Handle< QuantLib::YieldTermStructure > discount_
BlackCdsOptionEngine(const QuantLib::Handle< QuantLib::DefaultProbabilityTermStructure > &probability, QuantLib::Real recovery, const QuantLib::Handle< QuantLib::YieldTermStructure > &discount, const QuantLib::Handle< QuantExt::CreditVolCurve > &volatility)
QuantLib::Handle< QuantExt::CreditVolCurve > volatility_
const QuantLib::Handle< QuantLib::DefaultProbabilityTermStructure > & probability() const
Swap::arguments * arguments_