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(
95 vol_ = ext::make_shared<SimpleQuote>(0.0);
104 Real CallableBond::ImpliedVolHelper::operator()(
Volatility x)
const {
121 Real dirtyTargetPrice;
122 switch (targetPrice.
type()) {
124 dirtyTargetPrice = targetPrice.
amount();
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,
167 Real operator()(Spread x)
const
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();
289 if (settlement ==
Date())
290 settlement = settlementDate();
292 Real dirtyPrice = cleanPrice + accruedAmount(settlement);
294 ext::function<
Real(
Real)>
f = NPVSpreadHelper(*
this);
295 OASHelper obj(
f, dirtyPrice);
301 Spread oas=solver.
solve(obj, accuracy, guess, step);
303 return continuousToConv(oas,
320 if (settlement ==
Date())
321 settlement = settlementDate();
323 oas=convToContinuous(oas,
330 ext::function<
Real(
Real)>
f = NPVSpreadHelper(*
this);
332 Real P =
f(oas) - accruedAmount(settlement);
344 Real P = cleanPriceOAS(oas,
350 Real Ppp = cleanPriceOAS(oas+bump,
355 Real Pmm = cleanPriceOAS(oas-bump,
365 return (Pmm-Ppp)/(2*P*bump);
376 Real P = cleanPriceOAS(oas,
382 Real Ppp = cleanPriceOAS(oas+bump,
387 Real Pmm = cleanPriceOAS(oas-bump,
397 return (Ppp + Pmm - 2*P) / ( std::pow(bump,2) * P);
405 Bond::setupArguments(args);
417 const Leg& cfs = cashflows();
424 for (
Size i=0; i<cfs.size()-1; i++) {
425 if (!cfs[i]->hasOccurred(settlement,
false)
426 && !cfs[i]->tradingExCoupon(settlement)) {
441 for (
const auto& i : putCallSchedule_) {
442 if (!i->hasOccurred(settlement,
false)) {
446 if (i->price().type() == Bond::Price::Clean) {
461 Real CallableBond::accrued(
Date settlement)
const {
463 if (settlement ==
Date()) settlement = settlementDate();
465 const bool IncludeToday =
false;
466 for (
const auto& cashflow : cashflows_) {
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) /
473 notional(settlement) * 100.0;
482 CallableFixedRateBond::CallableFixedRateBond(
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) {
Black-formula callable bond engines.
const ext::function< Real(Real)> & npvhelper_
Cash flow vector builders.
ext::shared_ptr< SimpleQuote > vol_
ext::shared_ptr< PricingEngine > engine_
const Instrument::results * results_
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 ext::shared_ptr< CashFlow > & redemption() const
void setSingleRedemption(Real notional, Real redemption, const Date &date)
Date maturityDate() 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_
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
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
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
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
#define QL_FAIL(message)
throw an error (possibly with file and line information)
ext::function< Real(Real)> b
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.
Zero spreaded term structure.