22#include <ql/cashflows/fixedratecoupon.hpp>
23#include <ql/cashflows/simplecashflow.hpp>
24#include <ql/instruments/claim.hpp>
25#include <ql/instruments/creditdefaultswap.hpp>
26#include <ql/math/solvers1d/brent.hpp>
27#include <ql/pricingengines/credit/isdacdsengine.hpp>
28#include <ql/pricingengines/credit/midpointcdsengine.hpp>
29#include <ql/quotes/simplequote.hpp>
30#include <ql/termstructures/credit/flathazardrate.hpp>
31#include <ql/termstructures/yieldtermstructure.hpp>
32#include <ql/time/calendars/weekendsonly.hpp>
33#include <ql/time/schedule.hpp>
34#include <ql/optional.hpp>
46 bool paysAtDefaultTime,
47 const Date& protectionStart,
48 ext::shared_ptr<Claim> claim,
50 const bool rebatesAccrual,
51 const Date& tradeDate,
53 : side_(side), notional_(notional), upfront_(ext::nullopt), runningSpread_(spread),
54 settlesAccrual_(settlesAccrual), paysAtDefaultTime_(paysAtDefaultTime),
55 claim_(
std::move(claim)),
56 protectionStart_(protectionStart ==
Null<
Date>() ? schedule[0] : protectionStart),
57 tradeDate_(tradeDate), cashSettlementDays_(cashSettlementDays) {
70 bool paysAtDefaultTime,
71 const Date& protectionStart,
72 const Date& upfrontDate,
73 ext::shared_ptr<Claim> claim,
75 const bool rebatesAccrual,
76 const Date& tradeDate,
78 : side_(side), notional_(notional), upfront_(upfront), runningSpread_(runningSpread),
79 settlesAccrual_(settlesAccrual), paysAtDefaultTime_(paysAtDefaultTime),
80 claim_(
std::move(claim)),
81 protectionStart_(protectionStart ==
Null<
Date>() ? schedule[0] : protectionStart),
82 tradeDate_(tradeDate), cashSettlementDays_(cashSettlementDays) {
84 init(schedule, convention, dayCounter, lastPeriodDayCounter,
rebatesAccrual, upfrontDate);
89 bool rebatesAccrual,
const Date& upfrontDate) {
91 QL_REQUIRE(!schedule.
empty(),
"CreditDefaultSwap needs a non-empty schedule.");
93 bool postBigBang =
false;
100 QL_REQUIRE(
protectionStart_ <= schedule[0],
"protection can not start after accrual");
119 Date effectiveUpfrontDate = upfrontDate;
120 if (effectiveUpfrontDate ==
Date()) {
125 "The cash settlement date must not be before the protection start date.");
128 Real upfrontAmount = 0.0;
131 upfrontPayment_ = ext::make_shared<SimpleCashFlow>(upfrontAmount, effectiveUpfrontDate);
140 Real rebateAmount = 0.0;
144 for (
Size i = 0; i <
leg_.size(); ++i) {
145 const ext::shared_ptr<CashFlow>& cf =
leg_[i];
146 if (refDate > cf->date()) {
149 }
else if (refDate == cf->date()) {
152 if (i <
leg_.size() - 1)
156 ext::shared_ptr<FixedRateCoupon> frc = ext::dynamic_pointer_cast<FixedRateCoupon>(cf);
157 rebateAmount = frc->amount();
163 ext::shared_ptr<FixedRateCoupon> frc = ext::dynamic_pointer_cast<FixedRateCoupon>(cf);
164 rebateAmount = frc->accruedAmount(refDate);
170 accrualRebate_ = ext::make_shared<SimpleCashFlow>(rebateAmount, effectiveUpfrontDate);
174 claim_ = ext::make_shared<FaceValueClaim>();
208 for (
auto i =
leg_.rbegin(); i !=
leg_.rend(); ++i) {
209 if (!(*i)->hasOccurred())
225 QL_REQUIRE(
arguments !=
nullptr,
"wrong argument type");
247 QL_REQUIRE(
results !=
nullptr,
"wrong result type");
262 "fair upfront not available");
269 "fair spread not available");
276 "coupon-leg BPS not available");
283 "coupon-leg NPV not available");
290 "default-leg NPV not available");
297 "upfront NPV not available");
304 "upfront BPS not available");
311 "accrual Rebate NPV not available");
317 class ObjectiveFunction {
319 ObjectiveFunction(
Real target,
323 : target_(target), quote_(quote),
324 engine_(engine), results_(
results) {}
327 quote_.setValue(guess);
329 return results_->value - target_;
334 PricingEngine& engine_;
335 const CreditDefaultSwap::results* results_;
348 ext::shared_ptr<SimpleQuote> flatRate = ext::make_shared<SimpleQuote>(0.0);
355 ext::shared_ptr<PricingEngine>
engine;
358 engine = ext::make_shared<MidPointCdsEngine>(
359 probability, recoveryRate, discountCurve);
362 engine = ext::make_shared<IsdaCdsEngine>(
363 probability, recoveryRate, discountCurve,
370 QL_FAIL(
"unknown CDS pricing model: " << model);
379 Real step = 0.1 * guess;
380 return Brent().
solve(f, accuracy, guess, step);
384 Real conventionalRecovery,
389 ext::shared_ptr<SimpleQuote> flatRate = ext::make_shared<SimpleQuote>(0.0);
396 ext::shared_ptr<PricingEngine>
engine;
399 engine = ext::make_shared<MidPointCdsEngine>(
400 probability, conventionalRecovery, discountCurve);
403 engine = ext::make_shared<IsdaCdsEngine>(
404 probability, conventionalRecovery, discountCurve,
411 QL_FAIL(
"unknown CDS pricing model: " << model);
419 Real step = guess * 0.1;
431 return ext::dynamic_pointer_cast<Coupon>(
leg_.back())
458 QL_REQUIRE(
notional != 0.0,
"null notional set");
459 QL_REQUIRE(spread !=
Null<Rate>(),
"spread not set");
460 QL_REQUIRE(!leg.empty(),
"coupons not set");
462 QL_REQUIRE(claim,
"claim not set");
464 "protection start date not set");
466 "maturity date not set");
484 "cdsMaturity should only be used with date generation rule CDS2015, CDS or OldCDS");
487 "cdsMaturity expects a tenor that is a multiple of 3 months.");
490 QL_REQUIRE(tenor != 0 *
Months,
"A tenor of 0M is not supported for OldCDS.");
496 if (tenor.
length() == 0) {
503 Date maturity = anchorDate + tenor + 3 *
Months;
504 QL_REQUIRE(maturity >
tradeDate,
"error calculating CDS maturity. Tenor is " << tenor <<
", trade date is " <<
Date advance(const Date &, Integer n, TimeUnit unit, BusinessDayConvention convention=Following, bool endOfMonth=false) const
ext::shared_ptr< Claim > claim
ext::shared_ptr< SimpleCashFlow > accrualRebate
ext::optional< Rate > upfront
ext::shared_ptr< SimpleCashFlow > upfrontPayment
void validate() const override
Natural cashSettlementDays() const
const Date & protectionStartDate() const
The first date for which defaults will trigger the contract.
const ext::shared_ptr< SimpleCashFlow > & upfrontPayment() const
void init(const Schedule &schedule, BusinessDayConvention paymentConvention, const DayCounter &dayCounter, const DayCounter &lastPeriodDayCounter, bool rebatesAccrual, const Date &upfrontDate=Date())
Shared initialisation.
bool paysAtDefaultTime() const
void setupArguments(PricingEngine::arguments *) const override
bool isExpired() const override
returns whether the instrument might have value greater than zero.
const Date & tradeDate() const
CreditDefaultSwap(Protection::Side side, Real notional, Rate spread, const Schedule &schedule, BusinessDayConvention paymentConvention, const DayCounter &dayCounter, bool settlesAccrual=true, bool paysAtDefaultTime=true, const Date &protectionStart=Date(), ext::shared_ptr< Claim >=ext::shared_ptr< Claim >(), const DayCounter &lastPeriodDayCounter=DayCounter(), bool rebatesAccrual=true, const Date &tradeDate=Date(), Natural cashSettlementDays=3)
CDS quoted as running-spread only.
const Leg & coupons() const
ext::shared_ptr< Claim > claim_
ext::shared_ptr< SimpleCashFlow > accrualRebate_
Real couponLegNPV() const
ext::optional< Rate > upfront() const
Natural cashSettlementDays_
Real defaultLegNPV() const
bool settlesAccrual() const
Real couponLegBPS() const
ext::optional< Rate > upfront_
Rate impliedHazardRate(Real targetNPV, const Handle< YieldTermStructure > &discountCurve, const DayCounter &dayCounter, Real recoveryRate=0.4, Real accuracy=1.0e-8, PricingModel model=Midpoint) const
Implied hazard rate calculation.
const ext::shared_ptr< SimpleCashFlow > & accrualRebate() const
void setupExpired() const override
const Date & protectionEndDate() const
The last date for which defaults will trigger the contract.
void fetchResults(const PricingEngine::results *) const override
Rate conventionalSpread(Real conventionalRecovery, const Handle< YieldTermStructure > &discountCurve, const DayCounter &dayCounter, PricingModel model=Midpoint) const
Conventional/standard upfront-to-spread conversion.
ext::shared_ptr< SimpleCashFlow > upfrontPayment_
Rate runningSpread() const
Real accrualRebateNPV() const
Protection::Side side() const
bool rebatesAccrual() const
helper class building a sequence of fixed rate coupons
FixedRateLeg & withNotionals(Real)
FixedRateLeg & withPaymentAdjustment(BusinessDayConvention)
FixedRateLeg & withCouponRates(Rate, const DayCounter &paymentDayCounter, Compounding comp=Simple, Frequency freq=Annual)
FixedRateLeg & withLastPeriodDayCounter(const DayCounter &)
PricingEngine::arguments * getArguments() const override
const PricingEngine::results * getResults() const override
Shared handle to an observable.
void calculate() const override
virtual void fetchResults(const PricingEngine::results *) const
virtual void setupExpired() const
template class providing a null value for a given type.
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
interface for pricing engines
const Calendar & calendar() const
const std::vector< Date > & dates() const
DateGeneration::Rule rule() const
market element returning a stored value
Real solve(const F &f, Real accuracy, Real guess, Real step) const
BusinessDayConvention
Business Day conventions.
detail::iso_date_holder iso_date(const Date &d)
output dates in ISO format (yyyy-mm-dd)
unsigned QL_INTEGER Natural
positive integer
std::size_t Size
size of a container
const boost::none_t & nullopt
Date previousTwentieth(const Date &d, DateGeneration::Rule rule)
Date cdsMaturity(const Date &tradeDate, const Period &tenor, DateGeneration::Rule rule)
std::vector< ext::shared_ptr< CashFlow > > Leg
Sequence of cash-flows.
information on a default-protection contract