21#include <ql/exercise.hpp>
22#include <ql/pricingengines/blackformula.hpp>
23#include <ql/pricingengines/credit/isdacdsengine.hpp>
24#include <ql/pricingengines/credit/midpointcdsengine.hpp>
25#include <ql/termstructures/credit/flathazardrate.hpp>
26#include <ql/termstructures/yield/flatforward.hpp>
27#include <ql/time/daycounters/actual360.hpp>
40 const Handle<YieldTermStructure>& discountSwapCurrency,
41 const Handle<YieldTermStructure>& discountTradeCollateral,
42 const Handle<QuantExt::CreditVolCurve>& volatility)
43 : probabilities_({probability}), recoveries_({recovery}), discountSwapCurrency_(discountSwapCurrency),
44 discountTradeCollateral_(discountTradeCollateral), volatility_(volatility), indexRecovery_(recovery) {
48IndexCdsOptionBaseEngine::IndexCdsOptionBaseEngine(
const vector<Handle<DefaultProbabilityTermStructure>>& probabilities,
49 const vector<Real>& recoveries,
50 const Handle<YieldTermStructure>& discountSwapCurrency,
51 const Handle<YieldTermStructure>& discountTradeCollateral,
52 const Handle<QuantExt::CreditVolCurve>& volatility,
54 : probabilities_(probabilities), recoveries_(recoveries), discountSwapCurrency_(discountSwapCurrency),
55 discountTradeCollateral_(discountTradeCollateral), volatility_(volatility), indexRecovery_(indexRecovery) {
57 QL_REQUIRE(!probabilities_.empty(),
"IndexCdsOptionBaseEngine: need at least one probability curve.");
58 QL_REQUIRE(probabilities_.size() == recoveries_.size(),
"IndexCdsOptionBaseEngine: mismatch between size"
59 <<
" of probabilities (" << probabilities_.size()
60 <<
") and recoveries (" << recoveries_.size() <<
").");
65 if (indexRecovery_ == Null<Real>())
66 indexRecovery_ = accumulate(recoveries_.begin(), recoveries_.end(), 0.0) / recoveries_.size();
69const vector<Handle<DefaultProbabilityTermStructure>>& IndexCdsOptionBaseEngine::probabilities()
const {
70 return probabilities_;
73const vector<Real>& IndexCdsOptionBaseEngine::recoveries()
const {
return recoveries_; }
75const Handle<YieldTermStructure> IndexCdsOptionBaseEngine::discountSwapCurrency()
const {
76 return discountSwapCurrency_;
79const Handle<YieldTermStructure> IndexCdsOptionBaseEngine::discountTradeCollateral()
const {
80 return discountTradeCollateral_;
83const Handle<QuantExt::CreditVolCurve> IndexCdsOptionBaseEngine::volatility()
const {
return volatility_; }
85void IndexCdsOptionBaseEngine::calculate()
const {
91 if (probabilities_.size() > 1) {
92 notionals_ = cds.underlyingNotionals();
93 QL_REQUIRE(probabilities_.size() == notionals_.size(),
"IndexCdsOptionBaseEngine: mismatch between size"
94 <<
" of probabilities (" << probabilities_.size()
95 <<
") and notionals (" << notionals_.size() <<
").");
97 notionals_ = {cds.notional()};
102 results_.additionalResults = cds.additionalResults();
108Real IndexCdsOptionBaseEngine::fep()
const {
111 const Date& exerciseDate =
arguments_.exercise->dates().front();
118 for (Size i = 0; i < probabilities_.size(); ++i) {
119 fep += (1 - recoveries_[i]) * probabilities_[i]->defaultProbability(exerciseDate) * notionals_[i];
121 results_.additionalResults[
"UnrealisedFEP"] = fep;
125 results_.additionalResults[
"FEP"] = fep;
128 fep *= discountTradeCollateral_->discount(exerciseDate);
129 results_.additionalResults[
"discountedFEP"] = fep;
134void IndexCdsOptionBaseEngine::registerWithMarket() {
135 for (
const auto& p : probabilities_)
137 registerWith(discountTradeCollateral_);
138 registerWith(discountSwapCurrency_);
139 registerWith(volatility_);
const Instrument::results * results_
IndexCdsOptionBaseEngine(const QuantLib::Handle< QuantLib::DefaultProbabilityTermStructure > &probability, QuantLib::Real recovery, const Handle< YieldTermStructure > &discountSwapCurrency, const Handle< YieldTermStructure > &discountTradeCollateral, const QuantLib::Handle< QuantExt::CreditVolCurve > &volatility)
Constructor taking a default probability term structure bootstrapped from the index spreads.
Base class for index cds option pricing engines.
Swap::arguments * arguments_