Skip to content

Commit 8f3ac76

Browse files
Farah Khashmanjenkins
authored andcommitted
Merge remote-tracking branch 'origin/master' into QPR-11670
1 parent 2876431 commit 8f3ac76

1 file changed

Lines changed: 141 additions & 30 deletions

File tree

OREData/ored/portfolio/capfloor.cpp

Lines changed: 141 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
#include <ored/utilities/log.hpp>
2929
#include <ored/utilities/to_string.hpp>
3030

31+
#include <qle/cashflows/averageonindexedcoupon.hpp>
32+
#include <qle/cashflows/overnightindexedcoupon.hpp>
33+
#include <qle/cashflows/cappedflooredaveragebmacoupon.hpp>
34+
3135
#include <ql/experimental/coupons/strippedcapflooredcoupon.hpp>
3236
#include <ql/instruments/capfloor.hpp>
3337
#include <ql/instruments/compositeinstrument.hpp>
@@ -541,42 +545,149 @@ const std::map<std::string, boost::any>& CapFloor::additionalData() const {
541545
boost::shared_ptr<FloatingRateCoupon> frc = boost::dynamic_pointer_cast<FloatingRateCoupon>(flow);
542546
if (frc) {
543547
fixingDates.push_back(frc->fixingDate());
544-
indexFixings.push_back(frc->indexFixing());
548+
549+
// indexFixing for overnight indices
550+
if (auto on = boost::dynamic_pointer_cast<QuantExt::AverageONIndexedCoupon>(frc)) {
551+
indexFixings.push_back((on->rate() - on->spread()) / on->gearing());
552+
} else if (auto on = boost::dynamic_pointer_cast<QuantExt::OvernightIndexedCoupon>(frc)) {
553+
indexFixings.push_back((on->rate() - on->effectiveSpread()) / on->gearing());
554+
} else if (auto c = boost::dynamic_pointer_cast<QuantExt::CappedFlooredOvernightIndexedCoupon>(
555+
frc)) {
556+
indexFixings.push_back((c->underlying()->rate() - c->underlying()->effectiveSpread()) /
557+
c->underlying()->gearing());
558+
} else if (auto c = boost::dynamic_pointer_cast<QuantExt::CappedFlooredAverageONIndexedCoupon>(frc)) {
559+
indexFixings.push_back((c->underlying()->rate() - c->underlying()->spread()) /
560+
c->underlying()->gearing());
561+
}
562+
// indexFixing for BMA and subPeriod Coupons
563+
else if (auto c = boost::dynamic_pointer_cast<QuantLib::AverageBMACoupon>(frc)) {
564+
indexFixings.push_back((c->rate() - c->spread()) / c->gearing());
565+
} else if (auto c = boost::dynamic_pointer_cast<QuantExt::CappedFlooredAverageBMACoupon>(frc)) {
566+
indexFixings.push_back((c->underlying()->rate() - c->underlying()->spread()) / c->underlying()->gearing());
567+
} else if (auto sp = boost::dynamic_pointer_cast<QuantExt::SubPeriodsCoupon1>(frc))
568+
indexFixings.push_back((sp->rate() - sp->spread()) / sp->gearing());
569+
else {
570+
// this sets indexFixing to the last single overnight fixing
571+
indexFixings.push_back(frc->indexFixing());
572+
}
573+
545574
spreads.push_back(frc->spread());
546575

547576
// The below code adds cap/floor levels, vols, and amounts
548-
// for capped/floored Ibor coupons
549-
550-
boost::shared_ptr<StrippedCappedFlooredCoupon> strippedCfc =
551-
boost::dynamic_pointer_cast<StrippedCappedFlooredCoupon>(flow);
552-
if (!strippedCfc)
577+
// for capped/floored Ibor coupons and overnight coupons
578+
boost::shared_ptr<CashFlow> c = flow;
579+
if (auto strippedCfc = boost::dynamic_pointer_cast<StrippedCappedFlooredCoupon>(flow)) {
580+
c = strippedCfc->underlying();
581+
} else
553582
continue;
554583

555-
boost::shared_ptr<CappedFlooredCoupon> cfc = strippedCfc->underlying();
556-
// enfore coupon pricer to hold the results of the current coupon
557-
cfc->deepUpdate();
558-
cfc->amount();
559-
boost::shared_ptr<IborCouponPricer> pricer =
560-
boost::dynamic_pointer_cast<IborCouponPricer>(cfc->pricer());
561-
if (pricer && (cfc->fixingDate() > asof)) {
562-
// We write the vols if an Ibor coupon pricer is found and the fixing date is in the future
563-
if (cfc->isCapped()) {
564-
caps.push_back(cfc->cap());
565-
const Rate effectiveCap = cfc->effectiveCap();
566-
effectiveCaps.push_back(effectiveCap);
567-
capletVols.push_back(
568-
pricer->capletVolatility()->volatility(cfc->fixingDate(), effectiveCap));
569-
capletAmounts.push_back(pricer->capletRate(effectiveCap) * coupon->accrualPeriod() *
570-
coupon->nominal());
584+
if (auto cfc = boost::dynamic_pointer_cast<CappedFlooredCoupon>(c)) {
585+
// enfore coupon pricer to hold the results of the current coupon
586+
cfc->deepUpdate();
587+
cfc->amount();
588+
boost::shared_ptr<IborCouponPricer> pricer =
589+
boost::dynamic_pointer_cast<IborCouponPricer>(cfc->pricer());
590+
if (pricer && (cfc->fixingDate() > asof)) {
591+
// We write the vols if an Ibor coupon pricer is found and the fixing date is in the
592+
// future
593+
if (cfc->isCapped()) {
594+
caps.push_back(cfc->cap());
595+
const Rate effectiveCap = cfc->effectiveCap();
596+
effectiveCaps.push_back(effectiveCap);
597+
capletVols.push_back(
598+
pricer->capletVolatility()->volatility(cfc->fixingDate(), effectiveCap));
599+
capletAmounts.push_back(pricer->capletRate(effectiveCap) * coupon->accrualPeriod() *
600+
coupon->nominal());
601+
}
602+
if (cfc->isFloored()) {
603+
floors.push_back(cfc->floor());
604+
const Rate effectiveFloor = cfc->effectiveFloor();
605+
effectiveFloors.push_back(effectiveFloor);
606+
floorletVols.push_back(
607+
pricer->capletVolatility()->volatility(cfc->fixingDate(), effectiveFloor));
608+
floorletAmounts.push_back(pricer->floorletRate(effectiveFloor) *
609+
coupon->accrualPeriod() * coupon->nominal());
610+
}
611+
}
612+
} else if (auto tmp = boost::dynamic_pointer_cast<QuantExt::CappedFlooredOvernightIndexedCoupon>(c)) {
613+
tmp->deepUpdate();
614+
tmp->amount();
615+
boost::shared_ptr<QuantExt::CappedFlooredOvernightIndexedCouponPricer> pricer =
616+
boost::dynamic_pointer_cast<QuantExt::CappedFlooredOvernightIndexedCouponPricer>(
617+
tmp->pricer());
618+
if (pricer && (tmp->fixingDate() > asof)) {
619+
if (tmp->isCapped()) {
620+
caps.push_back(tmp->cap());
621+
const Rate effectiveCap = tmp->effectiveCap();
622+
effectiveCaps.push_back(effectiveCap);
623+
capletVols.push_back(
624+
pricer->capletVolatility()->volatility(tmp->fixingDate(), effectiveCap));
625+
capletAmounts.push_back(pricer->capletRate(effectiveCap) * coupon->accrualPeriod() *
626+
coupon->nominal());
627+
}
628+
if (tmp->isFloored()) {
629+
floors.push_back(tmp->floor());
630+
const Rate effectiveFloor = tmp->effectiveFloor();
631+
effectiveFloors.push_back(effectiveFloor);
632+
floorletVols.push_back(
633+
pricer->capletVolatility()->volatility(tmp->fixingDate(), effectiveFloor));
634+
floorletAmounts.push_back(pricer->floorletRate(effectiveFloor) *
635+
coupon->accrualPeriod() * coupon->nominal());
636+
}
571637
}
572-
if (cfc->isFloored()) {
573-
floors.push_back(cfc->floor());
574-
const Rate effectiveFloor = cfc->effectiveFloor();
575-
effectiveFloors.push_back(effectiveFloor);
576-
floorletVols.push_back(
577-
pricer->capletVolatility()->volatility(cfc->fixingDate(), effectiveFloor));
578-
floorletAmounts.push_back(pricer->floorletRate(effectiveFloor) * coupon->accrualPeriod() *
579-
coupon->nominal());
638+
} else if (auto tmp =
639+
boost::dynamic_pointer_cast<QuantExt::CappedFlooredAverageONIndexedCoupon>(c)) {
640+
tmp->deepUpdate();
641+
tmp->amount();
642+
boost::shared_ptr<QuantExt::CapFlooredAverageONIndexedCouponPricer> pricer =
643+
boost::dynamic_pointer_cast<QuantExt::CapFlooredAverageONIndexedCouponPricer>(
644+
tmp->pricer());
645+
if (pricer && (tmp->fixingDate() > asof)) {
646+
if (tmp->isCapped()) {
647+
caps.push_back(tmp->cap());
648+
const Rate effectiveCap = tmp->effectiveCap();
649+
effectiveCaps.push_back(effectiveCap);
650+
capletVols.push_back(
651+
pricer->capletVolatility()->volatility(tmp->fixingDate(), effectiveCap));
652+
capletAmounts.push_back(pricer->capletRate(effectiveCap) * coupon->accrualPeriod() *
653+
coupon->nominal());
654+
}
655+
if (tmp->isFloored()) {
656+
floors.push_back(tmp->floor());
657+
const Rate effectiveFloor = tmp->effectiveFloor();
658+
effectiveFloors.push_back(effectiveFloor);
659+
floorletVols.push_back(
660+
pricer->capletVolatility()->volatility(tmp->fixingDate(), effectiveFloor));
661+
floorletAmounts.push_back(pricer->floorletRate(effectiveFloor) *
662+
coupon->accrualPeriod() * coupon->nominal());
663+
}
664+
}
665+
666+
} else if (auto tmp = boost::dynamic_pointer_cast<QuantExt::CappedFlooredAverageBMACoupon>(c)) {
667+
tmp->deepUpdate();
668+
tmp->amount();
669+
boost::shared_ptr<QuantExt::CapFlooredAverageBMACouponPricer> pricer =
670+
boost::dynamic_pointer_cast<QuantExt::CapFlooredAverageBMACouponPricer>(
671+
tmp->pricer());
672+
if (pricer && (tmp->fixingDate() > asof)) {
673+
if (tmp->isCapped()) {
674+
caps.push_back(tmp->cap());
675+
const Rate effectiveCap = tmp->effectiveCap();
676+
effectiveCaps.push_back(effectiveCap);
677+
capletVols.push_back(
678+
pricer->capletVolatility()->volatility(tmp->fixingDate(), effectiveCap));
679+
capletAmounts.push_back(pricer->capletRate(effectiveCap) * coupon->accrualPeriod() *
680+
coupon->nominal());
681+
}
682+
if (tmp->isFloored()) {
683+
floors.push_back(tmp->floor());
684+
const Rate effectiveFloor = tmp->effectiveFloor();
685+
effectiveFloors.push_back(effectiveFloor);
686+
floorletVols.push_back(
687+
pricer->capletVolatility()->volatility(tmp->fixingDate(), effectiveFloor));
688+
floorletAmounts.push_back(pricer->floorletRate(effectiveFloor) *
689+
coupon->accrualPeriod() * coupon->nominal());
690+
}
580691
}
581692
}
582693
}

0 commit comments

Comments
 (0)