21#include <ql/cashflows/cashflowvectors.hpp>
22#include <ql/experimental/callablebonds/blackcallablebondengine.hpp>
23#include <ql/experimental/callablebonds/callablebond.hpp>
24#include <ql/math/solvers1d/brent.hpp>
25#include <ql/termstructures/yield/zerospreadedtermstructure.hpp>
31 const Date& maturityDate,
35 const Date& issueDate,
37 :
Bond(settlementDays, calendar, issueDate),
38 paymentDayCounter_(
std::move(paymentDayCounter)),
39 putCallSchedule_(
std::move(putCallSchedule)), faceAmount_(faceAmount) {
46 finalOptionDate = std::max(finalOptionDate, i->date());
49 "Bond cannot mature before last call/put date");
59 "null settlement date");
63 "positive redemption required: "
67 "different number of callability dates and prices");
69 "different number of coupon dates and amounts");
73 class CallableBond::ImpliedVolHelper {
81 ext::shared_ptr<PricingEngine> engine_;
84 ext::shared_ptr<SimpleQuote> vol_;
88 CallableBond::ImpliedVolHelper::ImpliedVolHelper(
93 : targetValue_(targetValue), matchNPV_(matchNPV) {
95 vol_ = ext::make_shared<SimpleQuote>(0.0);
104 Real CallableBond::ImpliedVolHelper::operator()(
Volatility x)
const {
107 Real value = matchNPV_ ? results_->value : results_->settlementValue;
108 return value - targetValue_;
119 QL_REQUIRE(!
isExpired(),
"instrument expired");
121 Real dirtyTargetPrice;
122 switch (targetPrice.
type()) {
124 dirtyTargetPrice = targetPrice.
amount();
130 QL_FAIL(
"unknown price type");
135 ImpliedVolHelper f(*
this, discountCurve, targetValue,
false);
138 return solver.
solve(f, accuracy, guess, minVol, maxVol);
149 explicit RestoreVal(T &ref):
160 OASHelper(
const ext::function<
Real(Real)>& npvhelper,
162 npvhelper_(npvhelper),
163 targetValue_(targetValue)
167 Real operator()(Spread x)
const
169 return targetValue_ - npvhelper_(x);
172 const ext::function<
Real(Real)>& npvhelper_;
182 const Handle<YieldTermStructure>& yts,
183 const DayCounter& dayCounter,
187 Real zz=yts->zeroRate(b.maturityDate(),
191 InterestRate baseRate(zz,
195 InterestRate spreadedRate(oas+zz,
199 Real br=baseRate.equivalentRate(dayCounter,
202 yts->referenceDate(),
203 b.maturityDate()).rate();
204 Real sr=spreadedRate.equivalentRate(dayCounter,
207 yts->referenceDate(),
208 b.maturityDate()).rate();
218 const Handle<YieldTermStructure>& yts,
219 const DayCounter& dayCounter,
223 Real zz=yts->zeroRate(b.maturityDate(),
227 InterestRate baseRate(zz,
232 InterestRate spreadedRate(oas+zz,
236 Real br=baseRate.equivalentRate(dayCounter,
239 yts->referenceDate(),
240 b.maturityDate()).rate();
241 Real sr=spreadedRate.equivalentRate(dayCounter,
244 yts->referenceDate(),
245 b.maturityDate()).rate();
253 class CallableBond::NPVSpreadHelper {
255 explicit NPVSpreadHelper(CallableBond& bond);
256 Real operator()(Spread x)
const;
259 const Instrument::results* results_;
262 CallableBond::NPVSpreadHelper::NPVSpreadHelper(CallableBond& bond):
266 bond.setupArguments(bond.engine_->getArguments());
269 Real CallableBond::NPVSpreadHelper::operator()(
Real x)
const
271 auto* args =
dynamic_cast<CallableBond::arguments*
>(bond_.engine_->getArguments());
273 RestoreVal<Spread> restorer(args->spread);
275 bond_.engine_->calculate();
276 return results_->
value;
289 if (settlement ==
Date())
294 ext::function<
Real(
Real)> f = NPVSpreadHelper(*
this);
301 Spread oas=solver.
solve(obj, accuracy, guess, step);
303 return continuousToConv(oas,
320 if (settlement ==
Date())
323 oas=convToContinuous(oas,
330 ext::function<
Real(
Real)> f = NPVSpreadHelper(*
this);
365 return (Pmm-Ppp)/(2*P*bump);
397 return (Ppp + Pmm - 2*P) / ( std::pow(bump,2) * P);
409 QL_REQUIRE(
arguments !=
nullptr,
"no arguments given");
424 for (
Size i=0; i<cfs.size()-1; i++) {
425 if (!cfs[i]->hasOccurred(settlement,
false)
426 && !cfs[i]->tradingExCoupon(settlement)) {
442 if (!i->hasOccurred(settlement,
false)) {
465 const bool IncludeToday =
false;
468 if (!cashflow->hasOccurred(settlement, IncludeToday)) {
469 ext::shared_ptr<Coupon> coupon = ext::dynamic_pointer_cast<Coupon>(cashflow);
470 if (coupon !=
nullptr)
472 return coupon->accruedAmount(settlement) /
486 const std::vector<Rate>& coupons,
490 const Date& issueDate,
492 const Period& exCouponPeriod,
495 bool exCouponEndOfMonth)
496 :
CallableBond(settlementDays, schedule.dates().back(), schedule.calendar(),
497 accrualDayCounter, faceAmount, issueDate, putCallSchedule) {
519 const Date& maturityDate,
523 const Date& issueDate,
526 dayCounter, faceAmount, issueDate, putCallSchedule) {
Real cleanPrice() const
theoretical clean price
void setupArguments(PricingEngine::arguments *) const override
bool isExpired() const override
returns whether the instrument might have value greater than zero.
void addRedemptionsToCashflows(const std::vector< Real > &redemptions=std::vector< Real >())
virtual Real accruedAmount(Date d=Date()) const
accrued amount at a given date
const Leg & cashflows() const
Real dirtyPrice() const
theoretical dirty price
const ext::shared_ptr< CashFlow > & redemption() const
void setSingleRedemption(Real notional, Real redemption, const Date &date)
Date maturityDate() const
virtual Real notional(Date d=Date()) const
Date settlementDate(Date d=Date()) const
Date adjust(const Date &, BusinessDayConvention convention=Following) const
std::vector< Date > callabilityDates
Real redemption
redemption = face amount * redemption / 100.
std::vector< Real > couponAmounts
DayCounter paymentDayCounter
std::vector< Date > couponDates
std::vector< Real > callabilityPrices
bond full/dirty/cash prices
void validate() const override
CallabilitySchedule putCallSchedule
results for a callable bond calculation
Callable bond base class.
CallabilitySchedule putCallSchedule_
Real accrued(Date settlement) const
Real effectiveDuration(Real oas, const Handle< YieldTermStructure > &engineTS, const DayCounter &dayCounter, Compounding compounding, Frequency frequency, Real bump=2e-4)
Spread OAS(Real cleanPrice, const Handle< YieldTermStructure > &engineTS, const DayCounter &dayCounter, Compounding compounding, Frequency frequency, Date settlementDate=Date(), Real accuracy=1.0e-10, Size maxIterations=100, Rate guess=0.0)
Calculate the Option Adjusted Spread (OAS)
Real effectiveConvexity(Real oas, const Handle< YieldTermStructure > &engineTS, const DayCounter &dayCounter, Compounding compounding, Frequency frequency, Real bump=2e-4)
CallableBond(Natural settlementDays, const Date &maturityDate, const Calendar &calendar, DayCounter paymentDayCounter, Real faceAmount, const Date &issueDate=Date(), CallabilitySchedule putCallSchedule=CallabilitySchedule())
void setupArguments(PricingEngine::arguments *args) const override
Real cleanPriceOAS(Real oas, const Handle< YieldTermStructure > &engineTS, const DayCounter &dayCounter, Compounding compounding, Frequency frequency, Date settlementDate=Date())
Volatility impliedVolatility(const Bond::Price &targetPrice, const Handle< YieldTermStructure > &discountCurve, Real accuracy, Size maxEvaluations, Volatility minVol, Volatility maxVol) const
returns the Black implied forward yield volatility
DayCounter paymentDayCounter_
CallableFixedRateBond(Natural settlementDays, Real faceAmount, const Schedule &schedule, const std::vector< Rate > &coupons, const DayCounter &accrualDayCounter, BusinessDayConvention paymentConvention=Following, Real redemption=100.0, const Date &issueDate=Date(), const CallabilitySchedule &putCallSchedule={}, const Period &exCouponPeriod=Period(), const Calendar &exCouponCalendar=Calendar(), BusinessDayConvention exCouponConvention=Unadjusted, bool exCouponEndOfMonth=false)
CallableZeroCouponBond(Natural settlementDays, Real faceAmount, const Calendar &calendar, const Date &maturityDate, const DayCounter &dayCounter, BusinessDayConvention paymentConvention=Following, Real redemption=100.0, const Date &issueDate=Date(), const CallabilitySchedule &putCallSchedule={})
static Date minDate()
earliest allowed date
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 & withExCouponPeriod(const Period &, const Calendar &, BusinessDayConvention, bool endOfMonth=false)
Shared handle to an observable.
ext::shared_ptr< PricingEngine > engine_
template class providing a null value for a given type.
Frequency frequency() const
const Period & tenor() const
void setMaxEvaluations(Size evaluations)
Real solve(const F &f, Real accuracy, Real guess, Real step) const
Frequency
Frequency of events.
BusinessDayConvention
Business Day conventions.
@ Once
only once, e.g., a zero-coupon
@ NoFrequency
null frequency
unsigned QL_INTEGER Natural
positive integer
Real Volatility
volatility
Real Spread
spreads on interest rates
std::size_t Size
size of a container
Compounding
Interest rate coumpounding rule.
std::vector< ext::shared_ptr< Callability > > CallabilitySchedule
std::vector< ext::shared_ptr< CashFlow > > Leg
Sequence of cash-flows.