313 {
314
315
316 auto fixedLegData = QuantLib::ext::dynamic_pointer_cast<CommodityFixedLegData>(
data.concreteLegData());
317 QL_REQUIRE(fixedLegData,
"Wrong LegType, expected CommodityFixed, got " <<
data.legType());
318
319
321 vector<Real> prices =
buildScheduledVector(fixedLegData->prices(), fixedLegData->priceDates(), schedule);
322 vector<Real> quantities =
buildScheduledVector(fixedLegData->quantities(), fixedLegData->quantityDates(), schedule);
323
324
325
326 OneDayCounter dc;
327 Leg fixedRateLeg = FixedRateLeg(schedule)
328 .withNotionals(quantities)
329 .withCouponRates(prices, dc)
330 .withPaymentAdjustment(Unadjusted)
331 .withPaymentLag(0)
332 .withPaymentCalendar(NullCalendar());
333
334
335 vector<Date> paymentDates;
336 if (!
data.paymentDates().empty()) {
337 paymentDates = parseVectorOfValues<Date>(
data.paymentDates(), &parseDate);
339 QL_REQUIRE(paymentDates.size() == fixedRateLeg.size(),
340 "Expected the number of payment dates derived from float leg with tag '"
341 << fixedLegData->tag() << "' (" << paymentDates.size()
342 << ") to equal the number of fixed price periods (" << fixedRateLeg.size()
343 << "). Are the leg schedules consistent? Should CommodityPayRelativeTo = FutureExpiryDate "
344 "be used?");
345 } else {
346 QL_REQUIRE(paymentDates.size() == fixedRateLeg.size(),
347 "Expected the number of explicit payment dates ("
348 << paymentDates.size() << ") to equal the number of fixed price periods ("
349 << fixedRateLeg.size() << ")");
350 }
351 }
352
353
354 Leg commodityFixedLeg;
355 for (Size i = 0; i < fixedRateLeg.size(); i++) {
356
357 auto cp = QuantLib::ext::dynamic_pointer_cast<FixedRateCoupon>(fixedRateLeg[i]);
358
359
360 Date pmtDate;
361 if (!paymentDates.empty()) {
362
363 Calendar paymentCalendar =
366 Period paymentLagPeriod = boost::apply_visitor(
PaymentLagPeriod(), paymentLag);
367 BusinessDayConvention paymentConvention =
369 pmtDate = paymentCalendar.advance(paymentDates[i], paymentLagPeriod, paymentConvention);
370 } else {
371
372 BusinessDayConvention bdc =
374
375 Calendar paymentCalendar =
377
380
381
383 pmtDate = cp->accrualEndDate();
385 pmtDate = cp->accrualStartDate();
387 pmtDate = fixedRateLeg.back()->date();
389 QL_FAIL("Internal error: commodity fixed leg builder can not determine payment date relative to future "
390 "expiry date, this has to be handled in the instrument builder.");
391 } else {
392 QL_FAIL("Unexpected value " << fixedLegData->commodityPayRelativeTo() << " for CommodityPayRelativeTo");
393 }
394
395
396 pmtDate = paymentCalendar.advance(pmtDate, paymentLag, bdc);
397 }
398
399
400 commodityFixedLeg.push_back(QuantLib::ext::make_shared<SimpleCashFlow>(cp->amount(), pmtDate));
401 }
402
403 applyIndexing(commodityFixedLeg, data, engineFactory, requiredFixings, openEndDateReplacement, useXbsCurves);
404 addToRequiredFixings(commodityFixedLeg, QuantLib::ext::make_shared<FixingDateGetter>(requiredFixings));
405
406 addToRequiredFixings(commodityFixedLeg, QuantLib::ext::make_shared<ore::data::FixingDateGetter>(requiredFixings));
407
408 return commodityFixedLeg;
409}
Calendar parseCalendar(const string &s)
Convert text to QuantLib::Calendar.
BusinessDayConvention parseBusinessDayConvention(const string &s)
Convert text to QuantLib::BusinessDayConvention.
PaymentLag parsePaymentLag(const string &s)
Convert text to PaymentLag.
@ CalculationPeriodStartDate
@ CalculationPeriodEndDate
void applyIndexing(Leg &leg, const LegData &data, const QuantLib::ext::shared_ptr< EngineFactory > &engineFactory, RequiredFixings &requiredFixings, const QuantLib::Date &openEndDateReplacement, const bool useXbsCurves)
void addToRequiredFixings(const QuantLib::Leg &leg, const QuantLib::ext::shared_ptr< FixingDateGetter > &fixingDateGetter)
vector< T > buildScheduledVector(const vector< T > &values, const vector< string > &dates, const Schedule &schedule, const bool checkAllValuesAppearInResult=false)
boost::variant< QuantLib::Period, QuantLib::Natural > PaymentLag
Schedule makeSchedule(const ScheduleDates &data)