Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Public Member Functions | List of all members
CapFloor Class Reference

Serializable cap, floor, collar. More...

#include <ored/portfolio/capfloor.hpp>

+ Inheritance diagram for CapFloor:
+ Collaboration diagram for CapFloor:

Public Member Functions

 CapFloor ()
 
 CapFloor (const Envelope &env, const string &longShort, const LegData &leg, const vector< double > &caps, const vector< double > &floors, const PremiumData &premiumData={})
 
virtual void build (const QuantLib::ext::shared_ptr< EngineFactory > &) override
 
const string & longShort () const
 Inspectors. More...
 
const LegDataleg () const
 
const vector< double > & caps () const
 
const vector< double > & floors () const
 
virtual void fromXML (XMLNode *node) override
 
virtual XMLNodetoXML (XMLDocument &doc) const override
 
- Public Member Functions inherited from Trade
 Trade ()
 Default constructor. More...
 
 Trade (const string &tradeType, const Envelope &env=Envelope(), const TradeActions &ta=TradeActions())
 Base class constructor. More...
 
virtual ~Trade ()
 Default destructor. More...
 
virtual void build (const QuantLib::ext::shared_ptr< EngineFactory > &)=0
 
virtual std::map< std::string, RequiredFixings::FixingDatesfixings (const QuantLib::Date &settlementDate=QuantLib::Date()) const
 
const RequiredFixingsrequiredFixings () const
 
virtual std::map< AssetClass, std::set< std::string > > underlyingIndices (const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceDataManager=nullptr) const
 
void reset ()
 Reset trade, clear all base class data. This does not reset accumulated timings for this trade. More...
 
void resetPricingStats (const std::size_t numberOfPricings=0, const boost::timer::nanosecond_type cumulativePricingTime=0)
 Reset accumulated timings to given values. More...
 
string & id ()
 Set the trade id. More...
 
void setEnvelope (const Envelope &envelope)
 Set the envelope with counterparty and portfolio info. More...
 
void setAdditionalData (const std::map< std::string, boost::any > &additionalData)
 
TradeActionstradeActions ()
 Set the trade actions. More...
 
const string & id () const
 
const string & tradeType () const
 
const Envelopeenvelope () const
 
const set< string > & portfolioIds () const
 
const TradeActionstradeActions () const
 
const QuantLib::ext::shared_ptr< InstrumentWrapper > & instrument () const
 
const std::vector< QuantLib::Leg > & legs () const
 
const std::vector< string > & legCurrencies () const
 
const std::vector< bool > & legPayers () const
 
const string & npvCurrency () const
 
virtual QuantLib::Real notional () const
 Return the current notional in npvCurrency. See individual sub-classes for the precise definition. More...
 
virtual string notionalCurrency () const
 
const Date & maturity () const
 
virtual bool isExpired (const Date &d)
 
const string & issuer () const
 
template<typename T >
additionalDatum (const std::string &tag) const
 returns any additional datum. More...
 
const std::string & sensitivityTemplate () const
 
void validate () const
 Utility to validate that everything that needs to be set in this base class is actually set. More...
 
boost::timer::nanosecond_type getCumulativePricingTime () const
 Get cumulative timing spent on pricing. More...
 
std::size_t getNumberOfPricings () const
 Get number of pricings. More...
 
- Public Member Functions inherited from XMLSerializable
virtual ~XMLSerializable ()
 
virtual void fromXML (XMLNode *node)=0
 
virtual XMLNodetoXML (XMLDocument &doc) const =0
 
void fromFile (const std::string &filename)
 
void toFile (const std::string &filename) const
 
void fromXMLString (const std::string &xml)
 Parse from XML string. More...
 
std::string toXMLString () const
 Parse from XML string. More...
 

Trade

string longShort_
 
LegData legData_
 
vector< double > caps_
 
vector< double > floors_
 
PremiumData premiumData_
 
bool hasCashflows () const override
 
const std::map< std::string, boost::any > & additionalData () const override
 returns all additional data returned by the trade once built More...
 

Additional Inherited Members

- Protected Member Functions inherited from Trade
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 setLegBasedAdditionalData (const Size legNo, Size resultLegId=Null< Size >()) const
 
void setSensitivityTemplate (const EngineBuilder &builder)
 
void setSensitivityTemplate (const std::string &id)
 
- Protected Attributes inherited from Trade
string tradeType_
 
QuantLib::ext::shared_ptr< InstrumentWrapperinstrument_
 
std::vector< QuantLib::Leg > legs_
 
std::vector< string > legCurrencies_
 
std::vector< boollegPayers_
 
string npvCurrency_
 
QuantLib::Real notional_
 
string notionalCurrency_
 
Date maturity_
 
string issuer_
 
string sensitivityTemplate_
 
bool sensitivityTemplateSet_ = false
 
std::size_t savedNumberOfPricings_ = 0
 
boost::timer::nanosecond_type savedCumulativePricingTime_ = 0
 
RequiredFixings requiredFixings_
 
std::map< std::string, boost::any > additionalData_
 

Detailed Description

Serializable cap, floor, collar.

Definition at line 37 of file capfloor.hpp.

Constructor & Destructor Documentation

◆ CapFloor() [1/2]

CapFloor ( )

Definition at line 39 of file capfloor.hpp.

39: Trade("CapFloor") {}
Trade()
Default constructor.
Definition: trade.hpp:59

◆ CapFloor() [2/2]

CapFloor ( const Envelope env,
const string &  longShort,
const LegData leg,
const vector< double > &  caps,
const vector< double > &  floors,
const PremiumData premiumData = {} 
)

Definition at line 40 of file capfloor.hpp.

41 {})
42 : Trade("CapFloor", env), longShort_(longShort), legData_(leg), caps_(caps), floors_(floors),
43 premiumData_(premiumData) {}
const vector< double > & floors() const
Definition: capfloor.hpp:52
const string & longShort() const
Inspectors.
Definition: capfloor.hpp:49
vector< double > floors_
Definition: capfloor.hpp:69
const LegData & leg() const
Definition: capfloor.hpp:50
const vector< double > & caps() const
Definition: capfloor.hpp:51
PremiumData premiumData_
Definition: capfloor.hpp:70
vector< double > caps_
Definition: capfloor.hpp:68

Member Function Documentation

◆ build()

void build ( const QuantLib::ext::shared_ptr< EngineFactory > &  )
overridevirtual

Build QuantLib/QuantExt instrument, link pricing engine. If build() is called multiple times, reset() should be called between these calls.

Implements Trade.

Definition at line 49 of file capfloor.cpp.

49 {
50
51 DLOG("CapFloor::build() called for trade " << id() << ", leg type is " << legData_.legType());
52
53 // ISDA taxonomy
54 additionalData_["isdaAssetClass"] = string("Interest Rate");
55 additionalData_["isdaBaseProduct"] = string("CapFloor");
56 additionalData_["isdaSubProduct"] = string("");
57 additionalData_["isdaTransaction"] = string("");
58
59 QL_REQUIRE((legData_.legType() == "Floating") || (legData_.legType() == "CMS") ||
60 (legData_.legType() == "DurationAdjustedCMS") || (legData_.legType() == "CMSSpread") ||
61 (legData_.legType() == "CPI") || (legData_.legType() == "YY"),
62 "CapFloor build error, LegType must be Floating, CMS, DurationAdjustedCMS, CMSSpread, CPI or YY");
63
64 QL_REQUIRE(caps_.size() > 0 || floors_.size() > 0, "CapFloor build error, no cap rates or floor rates provided");
65 QuantLib::CapFloor::Type capFloorType;
66 if (floors_.size() == 0) {
67 capFloorType = QuantLib::CapFloor::Cap;
68 } else if (caps_.size() == 0) {
69 capFloorType = QuantLib::CapFloor::Floor;
70 } else {
71 capFloorType = QuantLib::CapFloor::Collar;
72 }
73
74 legs_.clear();
75 QuantLib::ext::shared_ptr<EngineBuilder> builder;
76 std::string underlyingIndex;
77 QuantLib::ext::shared_ptr<QuantLib::Instrument> qlInstrument;
78
79 // Account for long / short multiplier. In the following we expect the qlInstrument to be set up
80 // as a long cap resp. a long floor resp. as a collar which by definition is a long cap + short floor
81 // (this is opposite to the definition of a leg with naked option = true!)
82 // The isPayer flag in the leg data is ignored.
83 Real multiplier = (parsePositionType(longShort_) == Position::Long ? 1.0 : -1.0);
84
85 if (legData_.legType() == "Floating") {
86
87 QuantLib::ext::shared_ptr<FloatingLegData> floatData =
88 QuantLib::ext::dynamic_pointer_cast<FloatingLegData>(legData_.concreteLegData());
89 QL_REQUIRE(floatData, "Wrong LegType, expected Floating, got " << legData_.legType());
90 underlyingIndex = floatData->index();
91 Handle<IborIndex> hIndex =
92 engineFactory->market()->iborIndex(underlyingIndex, engineFactory->configuration(MarketContext::pricing));
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;
97
98 QL_REQUIRE(floatData->caps().empty() && floatData->floors().empty(),
99 "CapFloor build error, Floating leg section must not have caps and floors");
100
101 if (!floatData->hasSubPeriods() || isOis || isBma) {
102 // For the cases where we support caps and floors in the regular way, we build a floating leg with
103 // the nakedOption flag set to true, this avoids maintaining all features in legs with associated
104 // coupon pricers and at the same time in the QuaantLib::CapFloor instrument and pricing engine.
105 // The only remaining unsupported case are ibor coupons with sub periods
106 LegData tmpLegData = legData_;
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;
111 tmpLegData.concreteLegData() = tmpFloatData;
112 legs_.push_back(engineFactory->legBuilder(tmpLegData.legType())
113 ->buildLeg(tmpLegData, engineFactory, requiredFixings_,
114 engineFactory->configuration(MarketContext::pricing)));
115 // if both caps and floors are given, we have to use a payer leg, since in this case
116 // the StrippedCappedFlooredCoupon used to extract the naked options assumes a long floor
117 // and a short cap while we have documented a collar to be a short floor and long cap
118 qlInstrument =
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());
125 qlInstrument->setPricingEngine(swapBuilder->engine(parseCurrency(legData_.currency()), std::string(), std::string()));
126 setSensitivityTemplate(*swapBuilder);
127 } else {
128 qlInstrument->setPricingEngine(
129 QuantLib::ext::make_shared<DiscountingSwapEngine>(engineFactory->market()->discountCurve(legData_.currency())));
130 }
131 maturity_ = CashFlows::maturityDate(legs_.front());
132 } else {
133 // For the cases where we don't have regular cap / floor support we treat the index approximately as an Ibor
134 // index and build an QuantLib::CapFloor with associated pricing engine. The only remaining case where this
135 // is done are Ibor subperiod coupons
136
137 ALOG("CapFloor trade " << id() << " on sub periods Ibor (index = '" << underlyingIndex
138 << "') built, will ignore sub periods feature");
139 builder = engineFactory->builder(tradeType_);
140 legs_.push_back(makeIborLeg(legData_, index, engineFactory));
141
142 // If a vector of cap/floor rates are provided, ensure they align with the number of schedule periods
143 if (floors_.size() > 1) {
144 QL_REQUIRE(floors_.size() == legs_[0].size(),
145 "The number of floor rates provided does not match the number of schedule periods");
146 }
147
148 if (caps_.size() > 1) {
149 QL_REQUIRE(caps_.size() == legs_[0].size(),
150 "The number of cap rates provided does not match the number of schedule periods");
151 }
152
153 // If one cap/floor rate is given, extend the vector to align with the number of schedule periods
154 if (floors_.size() == 1)
155 floors_.resize(legs_[0].size(), floors_[0]);
156
157 if (caps_.size() == 1)
158 caps_.resize(legs_[0].size(), caps_[0]);
159
160 // Create QL CapFloor instrument
161 qlInstrument = QuantLib::ext::make_shared<QuantLib::CapFloor>(capFloorType, legs_[0], caps_, floors_);
162
163 QuantLib::ext::shared_ptr<CapFloorEngineBuilder> capFloorBuilder =
164 QuantLib::ext::dynamic_pointer_cast<CapFloorEngineBuilder>(builder);
165 qlInstrument->setPricingEngine(capFloorBuilder->engine(underlyingIndex));
166 setSensitivityTemplate(*capFloorBuilder);
167
168 maturity_ = QuantLib::ext::dynamic_pointer_cast<QuantLib::CapFloor>(qlInstrument)->maturityDate();
169 }
170
171 } else if (legData_.legType() == "CMS") {
172 builder = engineFactory->builder("Swap");
173
174 QuantLib::ext::shared_ptr<CMSLegData> cmsData = QuantLib::ext::dynamic_pointer_cast<CMSLegData>(legData_.concreteLegData());
175 QL_REQUIRE(cmsData, "Wrong LegType, expected CMS");
176
177 underlyingIndex = cmsData->swapIndex();
178 Handle<SwapIndex> hIndex =
179 engineFactory->market()->swapIndex(underlyingIndex, builder->configuration(MarketContext::pricing));
180 QL_REQUIRE(!hIndex.empty(), "Could not find swap index " << underlyingIndex << " in market.");
181
182 QuantLib::ext::shared_ptr<SwapIndex> index = hIndex.currentLink();
183
184 LegData tmpLegData = legData_;
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;
189 tmpLegData.concreteLegData() = tmpFloatData;
190 legs_.push_back(engineFactory->legBuilder(tmpLegData.legType())
191 ->buildLeg(tmpLegData, engineFactory, requiredFixings_,
192 engineFactory->configuration(MarketContext::pricing)));
193 // if both caps and floors are given, we have to use a payer leg, since in this case
194 // the StrippedCappedFlooredCoupon used to extract the naked options assumes a long floor
195 // and a short cap while we have documented a collar to be a short floor and long cap
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());
202 qlInstrument->setPricingEngine(swapBuilder->engine(parseCurrency(legData_.currency()), std::string(), std::string()));
203 setSensitivityTemplate(*swapBuilder);
204 } else {
205 qlInstrument->setPricingEngine(
206 QuantLib::ext::make_shared<DiscountingSwapEngine>(engineFactory->market()->discountCurve(legData_.currency())));
207 }
208 maturity_ = CashFlows::maturityDate(legs_.front());
209
210 } else if (legData_.legType() == "DurationAdjustedCMS") {
211 auto cmsData = QuantLib::ext::dynamic_pointer_cast<DurationAdjustedCmsLegData>(legData_.concreteLegData());
212 QL_REQUIRE(cmsData, "Wrong LegType, expected DurationAdjustedCmsLegData");
213 LegData tmpLegData = legData_;
214 auto tmpCmsData = QuantLib::ext::make_shared<DurationAdjustedCmsLegData>(*cmsData);
215 tmpCmsData->floors() = floors_;
216 tmpCmsData->caps() = caps_;
217 tmpCmsData->nakedOption() = true;
218 tmpLegData.concreteLegData() = tmpCmsData;
219 legs_.push_back(engineFactory->legBuilder(tmpLegData.legType())
220 ->buildLeg(tmpLegData, engineFactory, requiredFixings_,
221 engineFactory->configuration(MarketContext::pricing)));
222 // if both caps and floors are given, we have to use a payer leg, since in this case
223 // the StrippedCappedFlooredCoupon used to extract the naked options assumes a long floor
224 // and a short cap while we have documented a collar to be a short floor and long cap
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());
231 qlInstrument->setPricingEngine(swapBuilder->engine(parseCurrency(legData_.currency()), std::string(), std::string()));
232 setSensitivityTemplate(*swapBuilder);
233 } else {
234 qlInstrument->setPricingEngine(
235 QuantLib::ext::make_shared<DiscountingSwapEngine>(engineFactory->market()->discountCurve(legData_.currency())));
236 }
237 maturity_ = CashFlows::maturityDate(legs_.front());
238 } else if (legData_.legType() == "CMSSpread") {
239 builder = engineFactory->builder("Swap");
240 QuantLib::ext::shared_ptr<CMSSpreadLegData> cmsSpreadData =
241 QuantLib::ext::dynamic_pointer_cast<CMSSpreadLegData>(legData_.concreteLegData());
242 QL_REQUIRE(cmsSpreadData, "Wrong LegType, expected CMSSpread");
243 LegData tmpLegData = legData_;
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;
248 tmpLegData.concreteLegData() = tmpFloatData;
249 legs_.push_back(engineFactory->legBuilder(tmpLegData.legType())
250 ->buildLeg(tmpLegData, engineFactory, requiredFixings_,
251 engineFactory->configuration(MarketContext::pricing)));
252 // if both caps and floors are given, we have to use a payer leg, since in this case
253 // the StrippedCappedFlooredCoupon used to extract the naked options assumes a long floor
254 // and a short cap while we have documented a collar to be a short floor and long cap
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());
261 qlInstrument->setPricingEngine(swapBuilder->engine(parseCurrency(legData_.currency()), std::string(), std::string()));
262 setSensitivityTemplate(*swapBuilder);
263 } else {
264 qlInstrument->setPricingEngine(
265 QuantLib::ext::make_shared<DiscountingSwapEngine>(engineFactory->market()->discountCurve(legData_.currency())));
266 }
267 maturity_ = CashFlows::maturityDate(legs_.front());
268 } else if (legData_.legType() == "CPI") {
269 DLOG("CPI CapFloor Type " << capFloorType << " ID " << id());
270
271 builder = engineFactory->builder("CpiCapFloor");
272
273 QuantLib::ext::shared_ptr<CPILegData> cpiData = QuantLib::ext::dynamic_pointer_cast<CPILegData>(legData_.concreteLegData());
274 QL_REQUIRE(cpiData, "Wrong LegType, expected CPI");
275
276 underlyingIndex = cpiData->index();
277 Handle<ZeroInflationIndex> zeroIndex = engineFactory->market()->zeroInflationIndex(
278 underlyingIndex, builder->configuration(MarketContext::pricing));
279
280 // the cpi leg uses the first schedule date as the start date, which only makes sense if there are at least
281 // two dates in the schedule, otherwise the only date in the schedule is the pay date of the cf and a a separate
282 // start date is expected; if both the separate start date and a schedule with more than one date is given
283 Date startDate;
284 Schedule schedule = makeSchedule(legData_.schedule());
285
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.");
289 startDate = parseDate(start);
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
293 << " is not used.");
294 startDate = schedule.dates().front();
295 }
296
297 Real baseCPI = cpiData->baseCPI();
298
299 QuantLib::ext::shared_ptr<InflationSwapConvention> cpiSwapConvention = nullptr;
300
301 auto inflationConventions = InstrumentConventions::instance().conventions()->get(
302 underlyingIndex + "_INFLATIONSWAP", Convention::Type::InflationSwap);
303
304 if (inflationConventions.first)
305 cpiSwapConvention = QuantLib::ext::dynamic_pointer_cast<InflationSwapConvention>(inflationConventions.second);
306
307 Period observationLag;
308 if (cpiData->observationLag().empty()) {
309 QL_REQUIRE(cpiSwapConvention, "observationLag is not specified in legData and couldn't find convention for "
310 << underlyingIndex
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();
314 } else {
315 observationLag = parsePeriod(cpiData->observationLag());
316 }
317
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 "
321 << underlyingIndex
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;
325 } else {
326 interpolationMethod = parseObservationInterpolation(cpiData->interpolation());
327 }
328
329 Calendar cal = zeroIndex->fixingCalendar();
330 BusinessDayConvention conv = Unadjusted; // not used in the CPI CapFloor engine
331
332 QL_REQUIRE(!zeroIndex.empty(), "Zero Inflation Index is empty");
333
334 legs_.push_back(makeCPILeg(legData_, zeroIndex.currentLink(), engineFactory));
335
336 // If a vector of cap/floor rates are provided, ensure they align with the number of schedule periods
337 if (floors_.size() > 1) {
338 QL_REQUIRE(floors_.size() == legs_[0].size(),
339 "The number of floor rates provided does not match the number of schedule periods");
340 }
341
342 if (caps_.size() > 1) {
343 QL_REQUIRE(caps_.size() == legs_[0].size(),
344 "The number of cap rates provided does not match the number of schedule periods");
345 }
346
347 // If one cap/floor rate is given, extend the vector to align with the number of schedule periods
348 if (floors_.size() == 1)
349 floors_.resize(legs_[0].size(), floors_[0]);
350
351 if (caps_.size() == 1)
352 caps_.resize(legs_[0].size(), caps_[0]);
353
354 QuantLib::ext::shared_ptr<CpiCapFloorEngineBuilder> capFloorBuilder =
355 QuantLib::ext::dynamic_pointer_cast<CpiCapFloorEngineBuilder>(builder);
356
357 // Create QL CPI CapFloor instruments and add to a composite
358 qlInstrument = QuantLib::ext::make_shared<CompositeInstrument>();
359 maturity_ = Date::minDate();
360 for (Size i = 0; i < legs_[0].size(); ++i) {
361 DLOG("Create composite " << i);
362 Real nominal, gearing;
363 Date paymentDate;
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]);
366 if (coupon) {
367 nominal = coupon->nominal();
368 gearing = coupon->fixedRate() * coupon->accrualPeriod();
369 paymentDate = coupon->date();
370 } else if (cashflow) {
371 nominal = cashflow->notional();
372 gearing = 1.0; // no gearing here
373 paymentDate = cashflow->date();
374 } else {
375 QL_FAIL("Failed to interpret CPI flow");
376 }
377
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));
383 setSensitivityTemplate(*capFloorBuilder);
384 QuantLib::ext::dynamic_pointer_cast<QuantLib::CompositeInstrument>(qlInstrument)->add(capfloor, gearing);
385 maturity_ = std::max(maturity_, capfloor->payDate());
386 }
387
388 if (capFloorType == QuantLib::CapFloor::Floor || capFloorType == QuantLib::CapFloor::Collar) {
389 // for collars we want a long cap, short floor
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));
395 setSensitivityTemplate(*capFloorBuilder);
396 QuantLib::ext::dynamic_pointer_cast<QuantLib::CompositeInstrument>(qlInstrument)->add(capfloor, sign * gearing);
397 maturity_ = std::max(maturity_, capfloor->payDate());
398 }
399 }
400
401 } else if (legData_.legType() == "YY") {
402 builder = engineFactory->builder("YYCapFloor");
403
404 QuantLib::ext::shared_ptr<YoYLegData> yyData = QuantLib::ext::dynamic_pointer_cast<YoYLegData>(legData_.concreteLegData());
405 QL_REQUIRE(yyData, "Wrong LegType, expected YY");
406
407 underlyingIndex = yyData->index();
408 Handle<YoYInflationIndex> yoyIndex;
409 // look for yoy inflation index
410 yoyIndex =
411 engineFactory->market()->yoyInflationIndex(underlyingIndex, builder->configuration(MarketContext::pricing));
412
413 // we must have either an yoy or a zero inflation index in the market, if no yoy curve, get the zero
414 // and create a yoy index from it
415 if (yoyIndex.empty()) {
416 Handle<ZeroInflationIndex> zeroIndex = engineFactory->market()->zeroInflationIndex(
417 underlyingIndex, builder->configuration(MarketContext::pricing));
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));
422 }
423
424 legs_.push_back(makeYoYLeg(legData_, yoyIndex.currentLink(), engineFactory));
425
426 // If a vector of cap/floor rates are provided, ensure they align with the number of schedule periods
427 if (floors_.size() > 1) {
428 QL_REQUIRE(floors_.size() == legs_[0].size(),
429 "The number of floor rates provided does not match the number of schedule periods");
430 }
431
432 if (caps_.size() > 1) {
433 QL_REQUIRE(caps_.size() == legs_[0].size(),
434 "The number of cap rates provided does not match the number of schedule periods");
435 }
436
437 // If one cap/floor rate is given, extend the vector to align with the number of schedule periods
438 if (floors_.size() == 1)
439 floors_.resize(legs_[0].size(), floors_[0]);
440
441 if (caps_.size() == 1)
442 caps_.resize(legs_[0].size(), caps_[0]);
443
444 // Create QL YoY Inflation CapFloor instrument
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_));
452 } else {
453 QL_FAIL("unknown YoYInflation cap/floor type");
454 }
455
456 QuantLib::ext::shared_ptr<YoYCapFloorEngineBuilder> capFloorBuilder =
457 QuantLib::ext::dynamic_pointer_cast<YoYCapFloorEngineBuilder>(builder);
458 qlInstrument->setPricingEngine(capFloorBuilder->engine(underlyingIndex));
459 setSensitivityTemplate(*capFloorBuilder);
460
461 // Wrap the QL instrument in a vanilla instrument
462
463 maturity_ = QuantLib::ext::dynamic_pointer_cast<QuantLib::YoYInflationCapFloor>(qlInstrument)->maturityDate();
464 } else {
465 QL_FAIL("Invalid legType " << legData_.legType() << " for CapFloor");
466 }
467
468 // Fill in remaining Trade member data
469
470 QL_REQUIRE(legs_.size() == 1, "internal error, expected one leg in cap floor builder, got " << legs_.size());
471
472 legCurrencies_.push_back(legData_.currency());
473 legPayers_.push_back(false); // already accounted for via the instrument multiplier
477
478 // add premiums
479
480 std::vector<QuantLib::ext::shared_ptr<Instrument>> additionalInstruments;
481 std::vector<Real> additionalMultipliers;
482 maturity_ = std::max(maturity_, addPremiums(additionalInstruments, additionalMultipliers, multiplier, premiumData_,
483 -multiplier, parseCurrency(legData_.currency()), engineFactory,
484 engineFactory->configuration(MarketContext::pricing)));
485
486 // set instrument
488 QuantLib::ext::make_shared<VanillaInstrument>(qlInstrument, multiplier, additionalInstruments, additionalMultipliers);
489
490 // axdd required fixings
491 auto fdg = QuantLib::ext::make_shared<FixingDateGetter>(requiredFixings_);
492 for (auto const& l : legs_)
493 addToRequiredFixings(l, fdg);
494
495 Date startDate = Date::maxDate();
496 for (auto const& l : legs_) {
497 if (!l.empty()) {
498 startDate = std::min(startDate, l.front()->date());
499 QuantLib::ext::shared_ptr<Coupon> coupon = QuantLib::ext::dynamic_pointer_cast<Coupon>(l.front());
500 if (coupon)
501 startDate = std::min(startDate, coupon->accrualStartDate());
502 }
503 }
504
505 additionalData_["startDate"] = to_string(startDate);
506}
const string & currency() const
Definition: legdata.hpp:873
const ScheduleData & schedule() const
Definition: legdata.hpp:874
const string & legType() const
Definition: legdata.hpp:890
QuantLib::ext::shared_ptr< LegAdditionalData > concreteLegData() const
Definition: legdata.hpp:891
string npvCurrency_
Definition: trade.hpp:201
std::vector< bool > legPayers_
Definition: trade.hpp:200
std::vector< string > legCurrencies_
Definition: trade.hpp:199
std::vector< QuantLib::Leg > legs_
Definition: trade.hpp:198
QuantLib::Real notional_
Definition: trade.hpp:202
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)
Definition: trade.cpp:58
void setSensitivityTemplate(const EngineBuilder &builder)
Definition: trade.cpp:295
string tradeType_
Definition: trade.hpp:196
RequiredFixings requiredFixings_
Definition: trade.hpp:223
QuantLib::ext::shared_ptr< InstrumentWrapper > instrument_
Definition: trade.hpp:197
string notionalCurrency_
Definition: trade.hpp:203
std::map< std::string, boost::any > additionalData_
Definition: trade.hpp:224
Date parseDate(const string &s)
Convert std::string to QuantLib::Date.
Definition: parsers.cpp:51
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
Definition: parsers.cpp:290
Position::Type parsePositionType(const std::string &s)
Convert text to QuantLib::Position::Type.
Definition: parsers.cpp:404
QuantLib::CPI::InterpolationType parseObservationInterpolation(const std::string &s)
Convert string to observation interpolation.
Definition: parsers.cpp:682
Period parsePeriod(const string &s)
Convert text to QuantLib::Period.
Definition: parsers.cpp:171
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
#define ALOG(text)
Logging Macro (Level = Alert)
Definition: log.hpp:544
Real currentNotional(const Leg &leg)
Definition: legdata.cpp:2435
void addToRequiredFixings(const QuantLib::Leg &leg, const QuantLib::ext::shared_ptr< FixingDateGetter > &fixingDateGetter)
Size size(const ValueType &v)
Definition: value.cpp:145
Leg makeYoYLeg(const LegData &data, const QuantLib::ext::shared_ptr< InflationIndex > &index, const QuantLib::ext::shared_ptr< EngineFactory > &engineFactory, const QuantLib::Date &openEndDateReplacement)
Definition: legdata.cpp:1766
std::string to_string(const LocationInfo &l)
Definition: ast.cpp:28
Leg makeCPILeg(const LegData &data, const QuantLib::ext::shared_ptr< ZeroInflationIndex > &index, const QuantLib::ext::shared_ptr< EngineFactory > &engineFactory, const QuantLib::Date &openEndDateReplacement)
Definition: legdata.cpp:1616
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)
Definition: legdata.cpp:1102
Schedule makeSchedule(const ScheduleDates &data)
Definition: schedule.cpp:263
+ Here is the call graph for this function:

◆ longShort()

const string & longShort ( ) const

Inspectors.

Definition at line 49 of file capfloor.hpp.

49{ return longShort_; }

◆ leg()

const LegData & leg ( ) const

Definition at line 50 of file capfloor.hpp.

50{ return legData_; }

◆ caps()

const vector< double > & caps ( ) const

Definition at line 51 of file capfloor.hpp.

51{ return caps_; }
+ Here is the caller graph for this function:

◆ floors()

const vector< double > & floors ( ) const

Definition at line 52 of file capfloor.hpp.

52{ return floors_; }
+ Here is the caller graph for this function:

◆ fromXML()

void fromXML ( XMLNode node)
overridevirtual

Reimplemented from Trade.

Definition at line 778 of file capfloor.cpp.

778 {
779 Trade::fromXML(node);
780 XMLNode* capFloorNode = XMLUtils::getChildNode(node, "CapFloorData");
781 longShort_ = XMLUtils::getChildValue(capFloorNode, "LongShort", true);
782 legData_.fromXML(XMLUtils::getChildNode(capFloorNode, "LegData"));
783 caps_ = XMLUtils::getChildrenValuesAsDoubles(capFloorNode, "Caps", "Cap");
784 floors_ = XMLUtils::getChildrenValuesAsDoubles(capFloorNode, "Floors", "Floor");
785 premiumData_.fromXML(capFloorNode);
786}
virtual void fromXML(XMLNode *node) override
Definition: legdata.cpp:759
virtual void fromXML(XMLNode *node) override
Definition: premiumdata.cpp:37
virtual void fromXML(XMLNode *node) override
Definition: trade.cpp:34
static vector< Real > getChildrenValuesAsDoubles(XMLNode *node, const string &names, const string &name, bool mandatory=false)
Definition: xmlutils.cpp:319
static string getChildValue(XMLNode *node, const string &name, bool mandatory=false, const string &defaultValue=string())
Definition: xmlutils.cpp:277
static XMLNode * getChildNode(XMLNode *n, const string &name="")
Definition: xmlutils.cpp:387
rapidxml::xml_node< char > XMLNode
Definition: xmlutils.hpp:60
+ Here is the call graph for this function:

◆ toXML()

XMLNode * toXML ( XMLDocument doc) const
overridevirtual

Reimplemented from Trade.

Definition at line 788 of file capfloor.cpp.

788 {
789 XMLNode* node = Trade::toXML(doc);
790 XMLNode* capFloorNode = doc.allocNode("CapFloorData");
791 XMLUtils::appendNode(node, capFloorNode);
792 XMLUtils::addChild(doc, capFloorNode, "LongShort", longShort_);
793 XMLUtils::appendNode(capFloorNode, legData_.toXML(doc));
794 XMLUtils::addChildren(doc, capFloorNode, "Caps", "Cap", caps_);
795 XMLUtils::addChildren(doc, capFloorNode, "Floors", "Floor", floors_);
796 XMLUtils::appendNode(capFloorNode, premiumData_.toXML(doc));
797 return node;
798}
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: legdata.cpp:856
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: premiumdata.cpp:76
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: trade.cpp:46
static void addChildren(XMLDocument &doc, XMLNode *n, const string &names, const string &name, const vector< T > &values)
Definition: xmlutils.cpp:502
static XMLNode * addChild(XMLDocument &doc, XMLNode *n, const string &name)
Definition: xmlutils.cpp:181
static void appendNode(XMLNode *parent, XMLNode *child)
Definition: xmlutils.cpp:406
+ Here is the call graph for this function:

◆ hasCashflows()

bool hasCashflows ( ) const
overridevirtual

Utility method indicating if the trade has cashflows for the cashflow report. The default implementation returns true so that a trade is automatically considered when cashflows are being written. To prevent a trade from being asked for its cashflows, the method can be overridden to return false.

Reimplemented from Trade.

Definition at line 60 of file capfloor.hpp.

60{ return true; }

◆ additionalData()

const std::map< std::string, boost::any > & additionalData ( ) const
overridevirtual

returns all additional data returned by the trade once built

Reimplemented from Trade.

Definition at line 508 of file capfloor.cpp.

508 {
509 // use the build time as of date to determine current notionals
510 Date asof = Settings::instance().evaluationDate();
511
512 additionalData_["legType"] = legData_.legType();
513 additionalData_["isPayer"] = legData_.isPayer();
514 additionalData_["notionalCurrency"] = legData_.currency();
515 for (Size j = 0; !legs_.empty() && j < legs_[0].size(); ++j) {
516 QuantLib::ext::shared_ptr<CashFlow> flow = legs_[0][j];
517 // pick flow with earliest future payment date on this leg
518 if (flow->date() > asof) {
519 QuantLib::ext::shared_ptr<Coupon> coupon = QuantLib::ext::dynamic_pointer_cast<Coupon>(flow);
520 if (coupon) {
521 Real currentNotional = 0;
522 try {
523 currentNotional = coupon->nominal();
524 } catch (std::exception& e) {
525 ALOG("current notional could not be determined for trade " << id()
526 << ", set to zero: " << e.what());
527 }
528 additionalData_["currentNotional"] = currentNotional;
529
530 QuantLib::ext::shared_ptr<FloatingRateCoupon> frc = QuantLib::ext::dynamic_pointer_cast<FloatingRateCoupon>(flow);
531 if (frc) {
532 additionalData_["index"] = frc->index()->name();
533 }
534 }
535 break;
536 }
537 }
538 if (!legs_.empty() && legs_[0].size() > 0) {
539 QuantLib::ext::shared_ptr<Coupon> coupon = QuantLib::ext::dynamic_pointer_cast<Coupon>(legs_[0][0]);
540 if (coupon) {
541 Real originalNotional = 0.0;
542 try {
543 originalNotional = coupon->nominal();
544 } catch (std::exception& e) {
545 ALOG("original nominal could not be determined for trade " << id() << ", set to zero: " << e.what());
546 }
547 additionalData_["originalNotional"] = originalNotional;
548 }
549 }
550
551 vector<Real> amounts;
552 vector<Date> paymentDates;
553 vector<Real> currentNotionals;
554 vector<Rate> rates;
555 vector<Date> fixingDates;
556 vector<Rate> indexFixings;
557 vector<Spread> spreads;
558 vector<Rate> caps;
559 vector<Rate> effectiveCaps;
560 vector<Volatility> capletVols;
561 vector<Volatility> effectiveCapletVols;
562 vector<Real> capletAmounts;
563 vector<Rate> floors;
564 vector<Rate> effectiveFloors;
565 vector<Volatility> floorletVols;
566 vector<Volatility> effectiveFloorletVols;
567 vector<Real> floorletAmounts;
568
569 try {
570 if (!legs_.empty()) {
571 for (const auto& flow : legs_[0]) {
572 // pick flow with earliest future payment date on this leg
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);
577 if (coupon) {
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);
582 if (frc) {
583 fixingDates.push_back(frc->fixingDate());
584
585 // indexFixing for overnight indices
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());
590 } else if (auto c =
591 QuantLib::ext::dynamic_pointer_cast<QuantExt::CappedFlooredOvernightIndexedCoupon>(
592 frc)) {
593 indexFixings.push_back((c->underlying()->rate() - c->underlying()->effectiveSpread()) /
594 c->underlying()->gearing());
595 } else if (auto c =
596 QuantLib::ext::dynamic_pointer_cast<QuantExt::CappedFlooredAverageONIndexedCoupon>(
597 frc)) {
598 indexFixings.push_back((c->underlying()->rate() - c->underlying()->spread()) /
599 c->underlying()->gearing());
600 }
601 // indexFixing for BMA and subPeriod Coupons
602 else if (auto c = QuantLib::ext::dynamic_pointer_cast<QuantLib::AverageBMACoupon>(frc)) {
603 indexFixings.push_back((c->rate() - c->spread()) / c->gearing());
604 } else if (auto c =
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());
610 else {
611 // this sets indexFixing to the last single overnight fixing
612 indexFixings.push_back(frc->indexFixing());
613 }
614
615 spreads.push_back(frc->spread());
616
617 // The below code adds cap/floor levels, vols, and amounts
618 // for capped/floored Ibor coupons and overnight coupons
619 QuantLib::ext::shared_ptr<CashFlow> c = flow;
620 if (auto strippedCfc = QuantLib::ext::dynamic_pointer_cast<StrippedCappedFlooredCoupon>(flow)) {
621 c = strippedCfc->underlying();
622 }
623
624 if (auto cfc = QuantLib::ext::dynamic_pointer_cast<CappedFlooredCoupon>(c)) {
625 // enfore coupon pricer to hold the results of the current coupon
626 cfc->deepUpdate();
627 cfc->amount();
628 QuantLib::ext::shared_ptr<IborCouponPricer> pricer =
629 QuantLib::ext::dynamic_pointer_cast<IborCouponPricer>(cfc->pricer());
630 if (pricer && (cfc->fixingDate() > asof)) {
631 // We write the vols if an Ibor coupon pricer is found and the fixing date is in the
632 // future
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());
641 }
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());
650 }
651 }
652 } else if (auto tmp =
653 QuantLib::ext::dynamic_pointer_cast<QuantExt::CappedFlooredOvernightIndexedCoupon>(
654 c)) {
655 tmp->deepUpdate();
656 tmp->amount();
657 QuantLib::ext::shared_ptr<QuantExt::CappedFlooredOvernightIndexedCouponPricer> pricer =
658 QuantLib::ext::dynamic_pointer_cast<QuantExt::CappedFlooredOvernightIndexedCouponPricer>(
659 tmp->pricer());
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());
670 }
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());
680 }
681 }
682 } else if (auto tmp =
683 QuantLib::ext::dynamic_pointer_cast<QuantExt::CappedFlooredAverageONIndexedCoupon>(
684 c)) {
685 tmp->deepUpdate();
686 tmp->amount();
687 QuantLib::ext::shared_ptr<QuantExt::CapFlooredAverageONIndexedCouponPricer> pricer =
688 QuantLib::ext::dynamic_pointer_cast<QuantExt::CapFlooredAverageONIndexedCouponPricer>(
689 tmp->pricer());
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());
700 }
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());
710 }
711 }
712
713 } else if (auto tmp =
714 QuantLib::ext::dynamic_pointer_cast<QuantExt::CappedFlooredAverageBMACoupon>(c)) {
715 tmp->deepUpdate();
716 tmp->amount();
717 QuantLib::ext::shared_ptr<QuantExt::CapFlooredAverageBMACouponPricer> pricer =
718 QuantLib::ext::dynamic_pointer_cast<QuantExt::CapFlooredAverageBMACouponPricer>(
719 tmp->pricer());
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());
730 }
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());
740 }
741 }
742 }
743 }
744 }
745 }
746 }
747 }
748
749 additionalData_["amounts"] = amounts;
750 additionalData_["paymentDates"] = paymentDates;
751 additionalData_["currentNotionals"] = currentNotionals;
752 additionalData_["rates"] = rates;
753 additionalData_["fixingDates"] = fixingDates;
754 additionalData_["indexFixings"] = indexFixings;
755 additionalData_["spreads"] = spreads;
756 if (caps.size() > 0) {
757 additionalData_["caps"] = caps;
758 additionalData_["effectiveCaps"] = effectiveCaps;
759 additionalData_["capletVols"] = capletVols;
760 additionalData_["capletAmounts"] = capletAmounts;
761 additionalData_["effectiveCapletVols"] = effectiveCapletVols;
762 }
763 if (floors.size() > 0) {
764 additionalData_["floors"] = floors;
765 additionalData_["effectiveFloors"] = effectiveFloors;
766 additionalData_["floorletVols"] = floorletVols;
767 additionalData_["floorletAmounts"] = floorletAmounts;
768 additionalData_["effectiveFloorletVols"] = effectiveFloorletVols;
769 }
770
771 } catch (std::exception& e) {
772 ALOG("error getting additional data for capfloor trade " << id() << ". " << e.what());
773 }
774
775 return additionalData_;
776}
bool isPayer() const
Definition: legdata.hpp:872
Real originalNotional(const Leg &leg)
Definition: legdata.cpp:2449
+ Here is the call graph for this function:

Member Data Documentation

◆ longShort_

string longShort_
private

Definition at line 66 of file capfloor.hpp.

◆ legData_

LegData legData_
private

Definition at line 67 of file capfloor.hpp.

◆ caps_

vector<double> caps_
private

Definition at line 68 of file capfloor.hpp.

◆ floors_

vector<double> floors_
private

Definition at line 69 of file capfloor.hpp.

◆ premiumData_

PremiumData premiumData_
private

Definition at line 70 of file capfloor.hpp.