35#include <ql/experimental/coupons/strippedcapflooredcoupon.hpp>
36#include <ql/instruments/capfloor.hpp>
37#include <ql/instruments/compositeinstrument.hpp>
38#include <ql/instruments/cpicapfloor.hpp>
39#include <ql/instruments/inflationcapfloor.hpp>
42#include <boost/make_shared.hpp>
49void CapFloor::build(
const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory) {
51 DLOG(
"CapFloor::build() called for trade " <<
id() <<
", leg type is " <<
legData_.
legType());
62 "CapFloor build error, LegType must be Floating, CMS, DurationAdjustedCMS, CMSSpread, CPI or YY");
64 QL_REQUIRE(
caps_.size() > 0 ||
floors_.size() > 0,
"CapFloor build error, no cap rates or floor rates provided");
65 QuantLib::CapFloor::Type capFloorType;
67 capFloorType = QuantLib::CapFloor::Cap;
68 }
else if (
caps_.size() == 0) {
69 capFloorType = QuantLib::CapFloor::Floor;
71 capFloorType = QuantLib::CapFloor::Collar;
75 QuantLib::ext::shared_ptr<EngineBuilder> builder;
76 std::string underlyingIndex;
77 QuantLib::ext::shared_ptr<QuantLib::Instrument> qlInstrument;
87 QuantLib::ext::shared_ptr<FloatingLegData> floatData =
89 QL_REQUIRE(floatData,
"Wrong LegType, expected Floating, got " <<
legData_.
legType());
90 underlyingIndex = floatData->index();
91 Handle<IborIndex> hIndex =
93 QL_REQUIRE(!hIndex.empty(),
"Could not find ibor index " << underlyingIndex <<
" in market.");
94 QuantLib::ext::shared_ptr<IborIndex> index = hIndex.currentLink();
95 bool isBma = QuantLib::ext::dynamic_pointer_cast<QuantExt::BMAIndexWrapper>(index) !=
nullptr;
96 bool isOis = QuantLib::ext::dynamic_pointer_cast<QuantExt::OvernightIndex>(index) !=
nullptr;
98 QL_REQUIRE(floatData->caps().empty() && floatData->floors().empty(),
99 "CapFloor build error, Floating leg section must not have caps and floors");
101 if (!floatData->hasSubPeriods() || isOis || isBma) {
107 QuantLib::ext::shared_ptr<FloatingLegData> tmpFloatData = QuantLib::ext::make_shared<FloatingLegData>(*floatData);
108 tmpFloatData->floors() =
floors_;
109 tmpFloatData->caps() =
caps_;
110 tmpFloatData->nakedOption() =
true;
112 legs_.push_back(engineFactory->legBuilder(tmpLegData.
legType())
119 QuantLib::ext::make_shared<QuantLib::Swap>(
legs_, std::vector<bool>{!
floors_.empty() && !
caps_.empty()});
120 if (engineFactory->engineData()->hasProduct(
"Swap")) {
121 builder = engineFactory->builder(
"Swap");
122 QuantLib::ext::shared_ptr<SwapEngineBuilderBase> swapBuilder =
123 QuantLib::ext::dynamic_pointer_cast<SwapEngineBuilderBase>(builder);
124 QL_REQUIRE(swapBuilder,
"No Builder found for Swap " <<
id());
128 qlInstrument->setPricingEngine(
129 QuantLib::ext::make_shared<DiscountingSwapEngine>(engineFactory->market()->discountCurve(
legData_.
currency())));
137 ALOG(
"CapFloor trade " <<
id() <<
" on sub periods Ibor (index = '" << underlyingIndex
138 <<
"') built, will ignore sub periods feature");
145 "The number of floor rates provided does not match the number of schedule periods");
148 if (
caps_.size() > 1) {
150 "The number of cap rates provided does not match the number of schedule periods");
157 if (
caps_.size() == 1)
161 qlInstrument = QuantLib::ext::make_shared<QuantLib::CapFloor>(capFloorType,
legs_[0],
caps_,
floors_);
163 QuantLib::ext::shared_ptr<CapFloorEngineBuilder> capFloorBuilder =
164 QuantLib::ext::dynamic_pointer_cast<CapFloorEngineBuilder>(builder);
165 qlInstrument->setPricingEngine(capFloorBuilder->engine(underlyingIndex));
168 maturity_ = QuantLib::ext::dynamic_pointer_cast<QuantLib::CapFloor>(qlInstrument)->maturityDate();
172 builder = engineFactory->builder(
"Swap");
174 QuantLib::ext::shared_ptr<CMSLegData> cmsData = QuantLib::ext::dynamic_pointer_cast<CMSLegData>(
legData_.
concreteLegData());
175 QL_REQUIRE(cmsData,
"Wrong LegType, expected CMS");
177 underlyingIndex = cmsData->swapIndex();
178 Handle<SwapIndex> hIndex =
180 QL_REQUIRE(!hIndex.empty(),
"Could not find swap index " << underlyingIndex <<
" in market.");
182 QuantLib::ext::shared_ptr<SwapIndex> index = hIndex.currentLink();
185 QuantLib::ext::shared_ptr<CMSLegData> tmpFloatData = QuantLib::ext::make_shared<CMSLegData>(*cmsData);
186 tmpFloatData->floors() =
floors_;
187 tmpFloatData->caps() =
caps_;
188 tmpFloatData->nakedOption() =
true;
190 legs_.push_back(engineFactory->legBuilder(tmpLegData.
legType())
196 qlInstrument = QuantLib::ext::make_shared<QuantLib::Swap>(
legs_, std::vector<bool>{!
floors_.empty() && !
caps_.empty()});
197 if (engineFactory->engineData()->hasProduct(
"Swap")) {
198 builder = engineFactory->builder(
"Swap");
199 QuantLib::ext::shared_ptr<SwapEngineBuilderBase> swapBuilder =
200 QuantLib::ext::dynamic_pointer_cast<SwapEngineBuilderBase>(builder);
201 QL_REQUIRE(swapBuilder,
"No Builder found for Swap " <<
id());
205 qlInstrument->setPricingEngine(
206 QuantLib::ext::make_shared<DiscountingSwapEngine>(engineFactory->market()->discountCurve(
legData_.
currency())));
212 QL_REQUIRE(cmsData,
"Wrong LegType, expected DurationAdjustedCmsLegData");
214 auto tmpCmsData = QuantLib::ext::make_shared<DurationAdjustedCmsLegData>(*cmsData);
215 tmpCmsData->floors() =
floors_;
216 tmpCmsData->caps() =
caps_;
217 tmpCmsData->nakedOption() =
true;
219 legs_.push_back(engineFactory->legBuilder(tmpLegData.
legType())
225 qlInstrument = QuantLib::ext::make_shared<QuantLib::Swap>(
legs_, std::vector<bool>{!
floors_.empty() && !
caps_.empty()});
226 if (engineFactory->engineData()->hasProduct(
"Swap")) {
227 builder = engineFactory->builder(
"Swap");
228 QuantLib::ext::shared_ptr<SwapEngineBuilderBase> swapBuilder =
229 QuantLib::ext::dynamic_pointer_cast<SwapEngineBuilderBase>(builder);
230 QL_REQUIRE(swapBuilder,
"No Builder found for Swap " <<
id());
234 qlInstrument->setPricingEngine(
235 QuantLib::ext::make_shared<DiscountingSwapEngine>(engineFactory->market()->discountCurve(
legData_.
currency())));
239 builder = engineFactory->builder(
"Swap");
240 QuantLib::ext::shared_ptr<CMSSpreadLegData> cmsSpreadData =
242 QL_REQUIRE(cmsSpreadData,
"Wrong LegType, expected CMSSpread");
244 QuantLib::ext::shared_ptr<CMSSpreadLegData> tmpFloatData = QuantLib::ext::make_shared<CMSSpreadLegData>(*cmsSpreadData);
245 tmpFloatData->floors() =
floors_;
246 tmpFloatData->caps() =
caps_;
247 tmpFloatData->nakedOption() =
true;
249 legs_.push_back(engineFactory->legBuilder(tmpLegData.
legType())
255 qlInstrument = QuantLib::ext::make_shared<QuantLib::Swap>(
legs_, std::vector<bool>{!
floors_.empty() && !
caps_.empty()});
256 if (engineFactory->engineData()->hasProduct(
"Swap")) {
257 builder = engineFactory->builder(
"Swap");
258 QuantLib::ext::shared_ptr<SwapEngineBuilderBase> swapBuilder =
259 QuantLib::ext::dynamic_pointer_cast<SwapEngineBuilderBase>(builder);
260 QL_REQUIRE(swapBuilder,
"No Builder found for Swap " <<
id());
264 qlInstrument->setPricingEngine(
265 QuantLib::ext::make_shared<DiscountingSwapEngine>(engineFactory->market()->discountCurve(
legData_.
currency())));
269 DLOG(
"CPI CapFloor Type " << capFloorType <<
" ID " <<
id());
271 builder = engineFactory->builder(
"CpiCapFloor");
273 QuantLib::ext::shared_ptr<CPILegData> cpiData = QuantLib::ext::dynamic_pointer_cast<CPILegData>(
legData_.
concreteLegData());
274 QL_REQUIRE(cpiData,
"Wrong LegType, expected CPI");
276 underlyingIndex = cpiData->index();
277 Handle<ZeroInflationIndex> zeroIndex = engineFactory->market()->zeroInflationIndex(
286 const string& start = cpiData->startDate();
287 if (schedule.size() < 2) {
288 QL_REQUIRE(!start.empty(),
"Only one schedule date, a 'StartDate' must be given.");
290 }
else if (!start.empty()) {
291 DLOG(
"Schedule with more than 2 dates was provided. The first schedule date "
292 << io::iso_date(schedule.dates().front()) <<
" is used as the start date. The 'StartDate' of " << start
294 startDate = schedule.dates().front();
297 Real baseCPI = cpiData->baseCPI();
299 QuantLib::ext::shared_ptr<InflationSwapConvention> cpiSwapConvention =
nullptr;
301 auto inflationConventions = InstrumentConventions::instance().conventions()->get(
304 if (inflationConventions.first)
305 cpiSwapConvention = QuantLib::ext::dynamic_pointer_cast<InflationSwapConvention>(inflationConventions.second);
307 Period observationLag;
308 if (cpiData->observationLag().empty()) {
309 QL_REQUIRE(cpiSwapConvention,
"observationLag is not specified in legData and couldn't find convention for "
311 <<
". Please add field to trade xml or add convention");
312 DLOG(
"Build CPI Leg and use observation lag from standard inflationswap convention");
313 observationLag = cpiSwapConvention->observationLag();
315 observationLag =
parsePeriod(cpiData->observationLag());
318 CPI::InterpolationType interpolationMethod;
319 if (cpiData->interpolation().empty()) {
320 QL_REQUIRE(cpiSwapConvention,
"observationLag is not specified in legData and couldn't find convention for "
322 <<
". Please add field to trade xml or add convention");
323 DLOG(
"Build CPI Leg and use observation lag from standard inflationswap convention");
324 interpolationMethod = cpiSwapConvention->interpolated() ? CPI::Linear : CPI::Flat;
329 Calendar cal = zeroIndex->fixingCalendar();
330 BusinessDayConvention conv = Unadjusted;
332 QL_REQUIRE(!zeroIndex.empty(),
"Zero Inflation Index is empty");
339 "The number of floor rates provided does not match the number of schedule periods");
342 if (
caps_.size() > 1) {
344 "The number of cap rates provided does not match the number of schedule periods");
351 if (
caps_.size() == 1)
354 QuantLib::ext::shared_ptr<CpiCapFloorEngineBuilder> capFloorBuilder =
355 QuantLib::ext::dynamic_pointer_cast<CpiCapFloorEngineBuilder>(builder);
358 qlInstrument = QuantLib::ext::make_shared<CompositeInstrument>();
360 for (Size i = 0; i <
legs_[0].size(); ++i) {
361 DLOG(
"Create composite " << i);
362 Real nominal, gearing;
364 QuantLib::ext::shared_ptr<CPICoupon> coupon = QuantLib::ext::dynamic_pointer_cast<CPICoupon>(
legs_[0][i]);
365 QuantLib::ext::shared_ptr<CPICashFlow> cashflow = QuantLib::ext::dynamic_pointer_cast<CPICashFlow>(
legs_[0][i]);
367 nominal = coupon->nominal();
368 gearing = coupon->fixedRate() * coupon->accrualPeriod();
369 paymentDate = coupon->date();
370 }
else if (cashflow) {
371 nominal = cashflow->notional();
373 paymentDate = cashflow->date();
375 QL_FAIL(
"Failed to interpret CPI flow");
378 if (capFloorType == QuantLib::CapFloor::Cap || capFloorType == QuantLib::CapFloor::Collar) {
379 QuantLib::ext::shared_ptr<CPICapFloor> capfloor = QuantLib::ext::make_shared<CPICapFloor>(
380 Option::Call, nominal, startDate, baseCPI, paymentDate, cal, conv, cal, conv,
caps_[i], zeroIndex,
381 observationLag, interpolationMethod);
382 capfloor->setPricingEngine(capFloorBuilder->engine(underlyingIndex));
384 QuantLib::ext::dynamic_pointer_cast<QuantLib::CompositeInstrument>(qlInstrument)->add(capfloor, gearing);
388 if (capFloorType == QuantLib::CapFloor::Floor || capFloorType == QuantLib::CapFloor::Collar) {
390 Real sign = capFloorType == QuantLib::CapFloor::Floor ? 1.0 : -1.0;
391 QuantLib::ext::shared_ptr<CPICapFloor> capfloor = QuantLib::ext::make_shared<CPICapFloor>(
392 Option::Put, nominal, startDate, baseCPI, paymentDate, cal, conv, cal, conv,
floors_[i], zeroIndex,
393 observationLag, interpolationMethod);
394 capfloor->setPricingEngine(capFloorBuilder->engine(underlyingIndex));
396 QuantLib::ext::dynamic_pointer_cast<QuantLib::CompositeInstrument>(qlInstrument)->add(capfloor, sign * gearing);
402 builder = engineFactory->builder(
"YYCapFloor");
404 QuantLib::ext::shared_ptr<YoYLegData> yyData = QuantLib::ext::dynamic_pointer_cast<YoYLegData>(
legData_.
concreteLegData());
405 QL_REQUIRE(yyData,
"Wrong LegType, expected YY");
407 underlyingIndex = yyData->index();
408 Handle<YoYInflationIndex> yoyIndex;
411 engineFactory->market()->yoyInflationIndex(underlyingIndex, builder->configuration(
MarketContext::pricing));
415 if (yoyIndex.empty()) {
416 Handle<ZeroInflationIndex> zeroIndex = engineFactory->market()->zeroInflationIndex(
418 QL_REQUIRE(!zeroIndex.empty(),
"Could not find inflation index (of type either zero or yoy) "
419 << underlyingIndex <<
" in market.");
420 yoyIndex = Handle<YoYInflationIndex>(QuantLib::ext::make_shared<QuantExt::YoYInflationIndexWrapper>(
421 zeroIndex.currentLink(),
false));
429 "The number of floor rates provided does not match the number of schedule periods");
432 if (
caps_.size() > 1) {
434 "The number of cap rates provided does not match the number of schedule periods");
441 if (
caps_.size() == 1)
445 if (capFloorType == QuantLib::CapFloor::Cap) {
446 qlInstrument = QuantLib::ext::shared_ptr<YoYInflationCapFloor>(
new YoYInflationCap(
legs_[0],
caps_));
447 }
else if (capFloorType == QuantLib::CapFloor::Floor) {
448 qlInstrument = QuantLib::ext::shared_ptr<YoYInflationCapFloor>(
new YoYInflationFloor(
legs_[0],
floors_));
449 }
else if (capFloorType == QuantLib::CapFloor::Collar) {
450 qlInstrument = QuantLib::ext::shared_ptr<YoYInflationCapFloor>(
451 new YoYInflationCapFloor(QuantLib::YoYInflationCapFloor::Collar,
legs_[0],
caps_,
floors_));
453 QL_FAIL(
"unknown YoYInflation cap/floor type");
456 QuantLib::ext::shared_ptr<YoYCapFloorEngineBuilder> capFloorBuilder =
457 QuantLib::ext::dynamic_pointer_cast<YoYCapFloorEngineBuilder>(builder);
458 qlInstrument->setPricingEngine(capFloorBuilder->engine(underlyingIndex));
463 maturity_ = QuantLib::ext::dynamic_pointer_cast<QuantLib::YoYInflationCapFloor>(qlInstrument)->maturityDate();
470 QL_REQUIRE(
legs_.size() == 1,
"internal error, expected one leg in cap floor builder, got " <<
legs_.size());
480 std::vector<QuantLib::ext::shared_ptr<Instrument>> additionalInstruments;
481 std::vector<Real> additionalMultipliers;
488 QuantLib::ext::make_shared<VanillaInstrument>(qlInstrument, multiplier, additionalInstruments, additionalMultipliers);
492 for (
auto const& l :
legs_)
495 Date startDate = Date::maxDate();
496 for (
auto const& l :
legs_) {
498 startDate = std::min(startDate, l.front()->date());
499 QuantLib::ext::shared_ptr<Coupon> coupon = QuantLib::ext::dynamic_pointer_cast<Coupon>(l.front());
501 startDate = std::min(startDate, coupon->accrualStartDate());
510 Date asof = Settings::instance().evaluationDate();
516 QuantLib::ext::shared_ptr<CashFlow> flow =
legs_[0][j];
518 if (flow->date() > asof) {
519 QuantLib::ext::shared_ptr<Coupon> coupon = QuantLib::ext::dynamic_pointer_cast<Coupon>(flow);
524 }
catch (std::exception& e) {
525 ALOG(
"current notional could not be determined for trade " <<
id()
526 <<
", set to zero: " << e.what());
530 QuantLib::ext::shared_ptr<FloatingRateCoupon> frc = QuantLib::ext::dynamic_pointer_cast<FloatingRateCoupon>(flow);
539 QuantLib::ext::shared_ptr<Coupon> coupon = QuantLib::ext::dynamic_pointer_cast<Coupon>(
legs_[0][0]);
544 }
catch (std::exception& e) {
545 ALOG(
"original nominal could not be determined for trade " <<
id() <<
", set to zero: " << e.what());
551 vector<Real> amounts;
552 vector<Date> paymentDates;
553 vector<Real> currentNotionals;
555 vector<Date> fixingDates;
556 vector<Rate> indexFixings;
557 vector<Spread> spreads;
559 vector<Rate> effectiveCaps;
560 vector<Volatility> capletVols;
561 vector<Volatility> effectiveCapletVols;
562 vector<Real> capletAmounts;
564 vector<Rate> effectiveFloors;
565 vector<Volatility> floorletVols;
566 vector<Volatility> effectiveFloorletVols;
567 vector<Real> floorletAmounts;
570 if (!
legs_.empty()) {
571 for (
const auto& flow :
legs_[0]) {
573 if (flow->date() > asof) {
574 amounts.push_back(flow->amount());
575 paymentDates.push_back(flow->date());
576 QuantLib::ext::shared_ptr<Coupon> coupon = QuantLib::ext::dynamic_pointer_cast<Coupon>(flow);
578 currentNotionals.push_back(coupon->nominal());
579 rates.push_back(coupon->rate());
580 QuantLib::ext::shared_ptr<FloatingRateCoupon> frc =
581 QuantLib::ext::dynamic_pointer_cast<FloatingRateCoupon>(flow);
583 fixingDates.push_back(frc->fixingDate());
586 if (
auto on = QuantLib::ext::dynamic_pointer_cast<QuantExt::AverageONIndexedCoupon>(frc)) {
587 indexFixings.push_back((on->rate() - on->spread()) / on->gearing());
588 }
else if (
auto on = QuantLib::ext::dynamic_pointer_cast<QuantExt::OvernightIndexedCoupon>(frc)) {
589 indexFixings.push_back((on->rate() - on->effectiveSpread()) / on->gearing());
591 QuantLib::ext::dynamic_pointer_cast<QuantExt::CappedFlooredOvernightIndexedCoupon>(
593 indexFixings.push_back((c->underlying()->rate() - c->underlying()->effectiveSpread()) /
594 c->underlying()->gearing());
596 QuantLib::ext::dynamic_pointer_cast<QuantExt::CappedFlooredAverageONIndexedCoupon>(
598 indexFixings.push_back((c->underlying()->rate() - c->underlying()->spread()) /
599 c->underlying()->gearing());
602 else if (
auto c = QuantLib::ext::dynamic_pointer_cast<QuantLib::AverageBMACoupon>(frc)) {
603 indexFixings.push_back((c->rate() - c->spread()) / c->gearing());
605 QuantLib::ext::dynamic_pointer_cast<QuantExt::CappedFlooredAverageBMACoupon>(frc)) {
606 indexFixings.push_back((c->underlying()->rate() - c->underlying()->spread()) /
607 c->underlying()->gearing());
608 }
else if (
auto sp = QuantLib::ext::dynamic_pointer_cast<QuantExt::SubPeriodsCoupon1>(frc))
609 indexFixings.push_back((sp->rate() - sp->spread()) / sp->gearing());
612 indexFixings.push_back(frc->indexFixing());
615 spreads.push_back(frc->spread());
619 QuantLib::ext::shared_ptr<CashFlow> c = flow;
620 if (
auto strippedCfc = QuantLib::ext::dynamic_pointer_cast<StrippedCappedFlooredCoupon>(flow)) {
621 c = strippedCfc->underlying();
624 if (
auto cfc = QuantLib::ext::dynamic_pointer_cast<CappedFlooredCoupon>(c)) {
628 QuantLib::ext::shared_ptr<IborCouponPricer> pricer =
629 QuantLib::ext::dynamic_pointer_cast<IborCouponPricer>(cfc->pricer());
630 if (pricer && (cfc->fixingDate() > asof)) {
633 if (cfc->isCapped()) {
634 caps.push_back(cfc->cap());
635 const Rate effectiveCap = cfc->effectiveCap();
636 effectiveCaps.push_back(effectiveCap);
637 capletVols.push_back(
638 pricer->capletVolatility()->volatility(cfc->fixingDate(), effectiveCap));
639 capletAmounts.push_back(pricer->capletRate(effectiveCap) *
640 coupon->accrualPeriod() * coupon->nominal());
642 if (cfc->isFloored()) {
643 floors.push_back(cfc->floor());
644 const Rate effectiveFloor = cfc->effectiveFloor();
645 effectiveFloors.push_back(effectiveFloor);
646 floorletVols.push_back(
647 pricer->capletVolatility()->volatility(cfc->fixingDate(), effectiveFloor));
648 floorletAmounts.push_back(pricer->floorletRate(effectiveFloor) *
649 coupon->accrualPeriod() * coupon->nominal());
652 }
else if (
auto tmp =
653 QuantLib::ext::dynamic_pointer_cast<QuantExt::CappedFlooredOvernightIndexedCoupon>(
657 QuantLib::ext::shared_ptr<QuantExt::CappedFlooredOvernightIndexedCouponPricer> pricer =
658 QuantLib::ext::dynamic_pointer_cast<QuantExt::CappedFlooredOvernightIndexedCouponPricer>(
660 if (pricer && (tmp->fixingDate() > asof)) {
661 if (tmp->isCapped()) {
662 caps.push_back(tmp->cap());
663 const Rate effectiveCap = tmp->effectiveCap();
664 effectiveCaps.push_back(effectiveCap);
665 capletVols.push_back(
666 pricer->capletVolatility()->volatility(tmp->fixingDate(), effectiveCap));
667 capletAmounts.push_back(pricer->capletRate(effectiveCap) *
668 coupon->accrualPeriod() * coupon->nominal());
669 effectiveCapletVols.push_back(tmp->effectiveCapletVolatility());
671 if (tmp->isFloored()) {
672 floors.push_back(tmp->floor());
673 const Rate effectiveFloor = tmp->effectiveFloor();
674 effectiveFloors.push_back(effectiveFloor);
675 floorletVols.push_back(
676 pricer->capletVolatility()->volatility(tmp->fixingDate(), effectiveFloor));
677 floorletAmounts.push_back(pricer->floorletRate(effectiveFloor) *
678 coupon->accrualPeriod() * coupon->nominal());
679 effectiveFloorletVols.push_back(tmp->effectiveFloorletVolatility());
682 }
else if (
auto tmp =
683 QuantLib::ext::dynamic_pointer_cast<QuantExt::CappedFlooredAverageONIndexedCoupon>(
687 QuantLib::ext::shared_ptr<QuantExt::CapFlooredAverageONIndexedCouponPricer> pricer =
688 QuantLib::ext::dynamic_pointer_cast<QuantExt::CapFlooredAverageONIndexedCouponPricer>(
690 if (pricer && (tmp->fixingDate() > asof)) {
691 if (tmp->isCapped()) {
692 caps.push_back(tmp->cap());
693 const Rate effectiveCap = tmp->effectiveCap();
694 effectiveCaps.push_back(effectiveCap);
695 capletVols.push_back(
696 pricer->capletVolatility()->volatility(tmp->fixingDate(), effectiveCap));
697 capletAmounts.push_back(pricer->capletRate(effectiveCap) *
698 coupon->accrualPeriod() * coupon->nominal());
699 effectiveCapletVols.push_back(tmp->effectiveCapletVolatility());
701 if (tmp->isFloored()) {
702 floors.push_back(tmp->floor());
703 const Rate effectiveFloor = tmp->effectiveFloor();
704 effectiveFloors.push_back(effectiveFloor);
705 floorletVols.push_back(
706 pricer->capletVolatility()->volatility(tmp->fixingDate(), effectiveFloor));
707 floorletAmounts.push_back(pricer->floorletRate(effectiveFloor) *
708 coupon->accrualPeriod() * coupon->nominal());
709 effectiveFloorletVols.push_back(tmp->effectiveFloorletVolatility());
713 }
else if (
auto tmp =
714 QuantLib::ext::dynamic_pointer_cast<QuantExt::CappedFlooredAverageBMACoupon>(c)) {
717 QuantLib::ext::shared_ptr<QuantExt::CapFlooredAverageBMACouponPricer> pricer =
718 QuantLib::ext::dynamic_pointer_cast<QuantExt::CapFlooredAverageBMACouponPricer>(
720 if (pricer && (tmp->fixingDate() > asof)) {
721 if (tmp->isCapped()) {
722 caps.push_back(tmp->cap());
723 const Rate effectiveCap = tmp->effectiveCap();
724 effectiveCaps.push_back(effectiveCap);
725 capletVols.push_back(
726 pricer->capletVolatility()->volatility(tmp->fixingDate(), effectiveCap));
727 capletAmounts.push_back(pricer->capletRate(effectiveCap) *
728 coupon->accrualPeriod() * coupon->nominal());
729 effectiveCapletVols.push_back(tmp->effectiveCapletVolatility());
731 if (tmp->isFloored()) {
732 floors.push_back(tmp->floor());
733 const Rate effectiveFloor = tmp->effectiveFloor();
734 effectiveFloors.push_back(effectiveFloor);
735 floorletVols.push_back(
736 pricer->capletVolatility()->volatility(tmp->fixingDate(), effectiveFloor));
737 floorletAmounts.push_back(pricer->floorletRate(effectiveFloor) *
738 coupon->accrualPeriod() * coupon->nominal());
739 effectiveFloorletVols.push_back(tmp->effectiveFloorletVolatility());
756 if (
caps.size() > 0) {
771 }
catch (std::exception& e) {
772 ALOG(
"error getting additional data for capfloor trade " <<
id() <<
". " << e.what());
builder that returns an engine to price a cap or floor on IBOR instrument
Engine builder for Swaps.
Ibor cap, floor or collar trade data model and serialization.
const vector< double > & floors() const
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
const vector< double > & caps() const
virtual void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
const std::map< std::string, boost::any > & additionalData() const override
returns all additional data returned by the trade once built
Serializable object holding leg data.
const string & currency() const
const ScheduleData & schedule() const
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
const string & legType() const
QuantLib::ext::shared_ptr< LegAdditionalData > concreteLegData() const
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
std::vector< bool > legPayers_
std::vector< string > legCurrencies_
std::vector< QuantLib::Leg > legs_
virtual void fromXML(XMLNode *node) override
Date addPremiums(std::vector< QuantLib::ext::shared_ptr< Instrument > > &instruments, std::vector< Real > &multipliers, const Real tradeMultiplier, const PremiumData &premiumData, const Real premiumMultiplier, const Currency &tradeCurrency, const QuantLib::ext::shared_ptr< EngineFactory > &factory, const string &configuration)
void setSensitivityTemplate(const EngineBuilder &builder)
virtual XMLNode * toXML(XMLDocument &doc) const override
RequiredFixings requiredFixings_
QuantLib::ext::shared_ptr< InstrumentWrapper > instrument_
std::map< std::string, boost::any > additionalData_
Small XML Document wrapper class.
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
static vector< Real > getChildrenValuesAsDoubles(XMLNode *node, const string &names, const string &name, bool mandatory=false)
static void addChildren(XMLDocument &doc, XMLNode *n, const string &names, const string &name, const vector< T > &values)
static string getChildValue(XMLNode *node, const string &name, bool mandatory=false, const string &defaultValue=string())
static XMLNode * getChildNode(XMLNode *n, const string &name="")
static XMLNode * addChild(XMLDocument &doc, XMLNode *n, const string &name)
static void appendNode(XMLNode *parent, XMLNode *child)
leg data for duration adjusted cms
Logic for calculating required fixing dates on legs.
Date parseDate(const string &s)
Convert std::string to QuantLib::Date.
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
Position::Type parsePositionType(const std::string &s)
Convert text to QuantLib::Position::Type.
QuantLib::CPI::InterpolationType parseObservationInterpolation(const std::string &s)
Convert string to observation interpolation.
Period parsePeriod(const string &s)
Convert text to QuantLib::Period.
leg data model and serialization
Classes and functions for log message handling.
#define DLOG(text)
Logging Macro (Level = Debug)
#define ALOG(text)
Logging Macro (Level = Alert)
Real currentNotional(const Leg &leg)
void addToRequiredFixings(const QuantLib::Leg &leg, const QuantLib::ext::shared_ptr< FixingDateGetter > &fixingDateGetter)
Size size(const ValueType &v)
Real originalNotional(const Leg &leg)
Leg makeYoYLeg(const LegData &data, const QuantLib::ext::shared_ptr< InflationIndex > &index, const QuantLib::ext::shared_ptr< EngineFactory > &engineFactory, const QuantLib::Date &openEndDateReplacement)
std::string to_string(const LocationInfo &l)
Leg makeCPILeg(const LegData &data, const QuantLib::ext::shared_ptr< ZeroInflationIndex > &index, const QuantLib::ext::shared_ptr< EngineFactory > &engineFactory, const QuantLib::Date &openEndDateReplacement)
Leg makeIborLeg(const LegData &data, const QuantLib::ext::shared_ptr< IborIndex > &index, const QuantLib::ext::shared_ptr< EngineFactory > &engineFactory, const bool attachPricer, const QuantLib::Date &openEndDateReplacement)
Schedule makeSchedule(const ScheduleDates &data)
Serializable Credit Default Swap.
builder that returns an engine to price a CPI cap or floor
Engine builder for year-on-year inflation caps/floors.
string conversion utilities