20#include <boost/algorithm/string.hpp>
35#include <ql/time/calendars/weekendsonly.hpp>
36#include <ql/time/date.hpp>
53using QuantLib::BootstrapHelper;
77using QuantLib::io::iso_date;
80void addMarketFixing(
const string& idxConvId,
const Date& expiry, Real
value) {
81 QuantLib::ext::shared_ptr<Conventions> conventions = ore::data::InstrumentConventions::instance().conventions();
82 auto p = conventions->
get(idxConvId, Convention::Type::CommodityFuture);
85 idx = idx->clone(expiry);
86 if (idx->isValidFixingDate(expiry)) {
88 idx->addFixing(expiry,
value);
89 TLOG(
"Added fixing (" << iso_date(expiry) <<
"," << idx->name() <<
"," <<
value <<
").");
90 }
catch (
const Error& e) {
91 TLOG(
"Failed to add fixing (" << iso_date(expiry) <<
"," << idx->name() <<
"," <<
92 value <<
"): " << e.what());
95 TLOG(
"Failed to add fixing (" << iso_date(expiry) <<
"," << idx->name() <<
"," <<
96 value <<
") because " << iso_date(expiry) <<
" is not a valid fixing date.");
99 TLOG(
"Failed to add fixing because no commodity future convention for " << idxConvId <<
".");
108CommodityCurve::CommodityCurve()
109 : commoditySpot_(Null<Real>()), onValue_(Null<Real>()), tnValue_(Null<Real>()), regexQuotes_(false) {}
114 const map<
string, QuantLib::ext::shared_ptr<YieldCurve>>& yieldCurves,
115 const map<
string, QuantLib::ext::shared_ptr<CommodityCurve>>& commodityCurves,
116 bool const buildCalibrationInfo)
117 : spec_(spec), commoditySpot_(Null<Real>()), onValue_(Null<Real>()), tnValue_(Null<Real>()), regexQuotes_(false) {
124 interpolationMethod_ = config->interpolationMethod().empty() ?
"Linear" : config->interpolationMethod();
129 map<Date, Handle<Quote>>
data;
141 DLOG(
"Looking for base price curve with id, " << config->basePriceCurveId() <<
", and spec, " << ccSpec
143 auto itCc = commodityCurves.find(ccSpec.name());
144 QL_REQUIRE(itCc != commodityCurves.end(),
"Can't find price curve with id " << config->basePriceCurveId());
145 auto pts = Handle<PriceTermStructure>(itCc->second->commodityPriceCurve());
157 QuantLib::ext::shared_ptr<CommodityCurveConfig> baseConfig =
158 curveConfigs.commodityCurveConfig(config->basePriceCurveId());
174 if (buildCalibrationInfo) {
175 auto calInfo = QuantLib::ext::make_shared<CommodityCurveCalibrationInfo>();
182 calInfo->pillarDates.emplace_back(d);
187 }
catch (std::exception& e) {
188 QL_FAIL(
"commodity curve building failed: " << e.what());
190 QL_FAIL(
"commodity curve building failed: unknown error");
195 const QuantLib::ext::shared_ptr<CommodityCurveConfig>& config,
const Loader& loader) {
198 Period spotTenor = 2 * Days;
199 Real pointsFactor = 1.0;
202 bool spotRelative =
true;
203 BusinessDayConvention bdc = Following;
204 bool outright =
true;
206 QuantLib::ext::shared_ptr<Conventions> conventions = InstrumentConventions::instance().conventions();
209 if (!config->conventionsId().empty()) {
210 QL_REQUIRE(conventions->has(config->conventionsId()),
211 "Commodity conventions " << config->conventionsId() <<
" requested by commodity config "
212 << config->curveID() <<
" not found");
214 QuantLib::ext::dynamic_pointer_cast<CommodityForwardConvention>(conventions->get(config->conventionsId()));
215 QL_REQUIRE(convention,
"Convention " << config->conventionsId() <<
" not of expected type CommodityConvention");
217 spotTenor = convention->spotDays() * Days;
218 pointsFactor = convention->pointsFactor();
219 if (!convention->strAdvanceCalendar().empty())
220 cal = convention->advanceCalendar();
221 spotRelative = convention->spotRelative();
222 bdc = convention->bdc();
223 outright = convention->outright();
227 Date spotDate = cal.advance(asof, spotTenor);
228 if (config->commoditySpotQuoteId().empty()) {
229 QL_REQUIRE(outright,
"If the commodity forward quotes are not outright,"
230 <<
" a commodity spot quote needs to be configured");
232 auto spot = loader.
get(config->commoditySpotQuoteId(), asof)->quote();
234 data[spotDate] = spot;
238 for (
auto& q :
getQuotes(asof, config->curveID(), config->fwdQuotes(), loader)) {
241 TLOG(
"Commodity Forward Price found for quote: " << q->name());
243 Real
value = q->quote()->value();
244 if (!q->tenorBased()) {
245 expiry = q->expiryDate();
248 if (q->startTenor() == boost::none) {
249 expiry = cal.advance(spotRelative ? spotDate : asof, q->tenor(), bdc);
252 if (*q->startTenor() == 0 * Days && q->tenor() == 1 * Days) {
256 }
else if (*q->startTenor() == 1 * Days && q->tenor() == 1 * Days) {
259 expiry = cal.advance(asof, 1 * Days, bdc);
263 expiry = cal.advance(cal.advance(asof, *q->startTenor(), bdc), q->tenor(), bdc);
271 if (spotTenor == 2 * Days &&
tnValue_ != Null<Real>() && !outright) {
272 add(asof, cal.advance(asof, 1 * Days, bdc), -
tnValue_,
data, outright, pointsFactor);
279 LOG(
"Read " <<
data.size() <<
" quotes for commodity curve " << config->curveID());
281 QL_REQUIRE(
data.size() == config->quotes().size(),
"Found " <<
data.size() <<
" quotes, but "
282 << config->quotes().size()
283 <<
" quotes given in config " << config->curveID());
285 QL_REQUIRE(
data.size() > 0,
286 "Regular expression specified in commodity config " << config->curveID() <<
" but no quotes read");
296 if (
data.find(expiry) !=
data.end()) {
297 WLOG(
"building " <<
spec_.
name() <<
": skipping duplicate expiry " << io::iso_date(expiry));
302 QL_REQUIRE(
commoditySpot_ != Null<Real>(),
"Can't use forward points without a commodity spot value");
306 data[expiry] = Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(
value));
310 const QuantLib::ext::shared_ptr<CommodityCurveConfig>& config) {
312 vector<Date> curveDates;
313 curveDates.reserve(
data.size());
314 vector<Handle<Quote>> curvePrices;
315 curvePrices.reserve(
data.size());
316 for (
auto const& datum :
data) {
317 curveDates.push_back(datum.first);
318 curvePrices.push_back(datum.second);
322 populateCurve<InterpolatedPriceCurve>(asof, curveDates, curvePrices,
dayCounter_,
327 const Date& asof,
const QuantLib::ext::shared_ptr<CommodityCurveConfig>& config,
328 const QuantLib::ext::shared_ptr<CommodityCurveConfig>& baseConfig,
const FXTriangulation& fxSpots,
329 const map<
string, QuantLib::ext::shared_ptr<YieldCurve>>& yieldCurves,
330 const map<
string, QuantLib::ext::shared_ptr<CommodityCurve>>& commodityCurves) {
335 auto commIt = commodityCurves.find(
CommodityCurveSpec(baseConfig->currency(), baseConfig->curveID()).
name());
336 QL_REQUIRE(commIt != commodityCurves.end(),
"Could not find base commodity curve with id "
337 << baseConfig->curveID()
338 <<
" required in the building of commodity curve with id "
339 << config->curveID());
342 auto baseYtsIt = yieldCurves.find(
YieldCurveSpec(baseConfig->currency(), config->baseYieldCurveId()).
name());
343 QL_REQUIRE(baseYtsIt != yieldCurves.end(),
344 "Could not find base yield curve with id "
345 << config->baseYieldCurveId() <<
" and currency " << baseConfig->currency()
346 <<
" required in the building of commodity curve with id " << config->curveID());
348 auto ytsIt = yieldCurves.find(
YieldCurveSpec(config->currency(), config->yieldCurveId()).
name());
349 QL_REQUIRE(ytsIt != yieldCurves.end(),
"Could not find yield curve with id "
350 << config->yieldCurveId() <<
" and currency " << config->currency()
351 <<
" required in the building of commodity curve with id "
352 << config->curveID());
355 Handle<Quote> fxSpot = fxSpots.
getQuote(baseConfig->currency() + config->currency());
359 asof, QuantLib::Handle<PriceTermStructure>(commIt->second->commodityPriceCurve()), fxSpot,
360 baseYtsIt->second->handle(), ytsIt->second->handle(),
parseCurrency(config->currency()));
364 const Handle<PriceTermStructure>& basePts,
const Loader& loader) {
366 LOG(
"CommodityCurve: start building commodity basis curve.");
368 QL_REQUIRE(!basePts.empty() && basePts.currentLink() !=
nullptr,
369 "Internal error: Can not build commodityBasisCurve '" << config.
curveID() <<
"'without empty baseCurve");
371 QuantLib::ext::shared_ptr<Conventions> conventions = InstrumentConventions::instance().conventions();
375 <<
" requested by commodity config "
376 << config.
curveID() <<
" not found");
377 auto basisConvention =
378 QuantLib::ext::dynamic_pointer_cast<CommodityFutureConvention>(conventions->get(config.
conventionsId()));
379 QL_REQUIRE(basisConvention,
380 "Convention " << config.
conventionsId() <<
" not of expected type CommodityFutureConvention");
381 auto basisFec = QuantLib::ext::make_shared<ConventionsBasedFutureExpiry>(*basisConvention);
384 "Commodity conventions " << config.
baseConventionsId() <<
" requested by commodity config "
385 << config.
curveID() <<
" not found");
386 auto baseConvention =
387 QuantLib::ext::dynamic_pointer_cast<CommodityFutureConvention>(conventions->get(config.
baseConventionsId()));
388 QL_REQUIRE(baseConvention,
389 "Convention " << config.
baseConventionsId() <<
" not of expected type CommodityFutureConvention");
390 auto baseFec = QuantLib::ext::make_shared<ConventionsBasedFutureExpiry>(*baseConvention);
399 map<Date, Handle<Quote>> basisData;
402 QL_REQUIRE(basisData.find(q->expiryDate()) == basisData.end(),
"Found duplicate quote, "
403 << q->name() <<
", for expiry date "
404 << io::iso_date(q->expiryDate()) <<
".");
406 basisData[q->expiryDate()] = q->quote();
407 TLOG(
"Using quote " << q->name() <<
" in commodity basis curve.");
411 Date calcExpiry = basisFec->nextExpiry(
true, q->expiryDate());
412 if (calcExpiry != q->expiryDate()) {
413 WLOG(
"Calculated expiry date, " << io::iso_date(calcExpiry) <<
", does not equal quote's expiry date "
414 << io::iso_date(q->expiryDate()) <<
".");
418 if (basisConvention->isAveraging()) {
420 if (!baseConvention->isAveraging() && config.
averageBase()) {
421 DLOG(
"Creating a CommodityAverageBasisPriceCurve.");
422 populateCurve<CommodityAverageBasisPriceCurve>(asof, basisData, basisFec, baseIndex, baseFec,
427 DLOG(
"Creating a CommodityBasisPriceCurve for an average price curve.");
428 populateCurve<CommodityBasisPriceCurve>(asof, basisData, basisFec, baseIndex, baseFec,
433 QL_REQUIRE(!baseConvention->isAveraging(),
"A commodity basis curve with non-averaging"
434 <<
" basis and averaging base is not valid.");
436 populateCurve<CommodityBasisPriceCurve>(asof, basisData, basisFec, baseIndex, baseFec, config.
addBasis(),
440 LOG(
"CommodityCurve: finished building commodity basis curve.");
448 const Loader& loader,
const map<
string, QuantLib::ext::shared_ptr<CommodityCurve>>& commodityCurves) {
450 LOG(
"CommodityCurve: start building commodity piecewise curve.");
454 map<Date, QuantLib::ext::shared_ptr<Helper>> mpInstruments;
456 QL_REQUIRE(!priceSegments.empty(),
"CommodityCurve: need at least one price segment to build piecewise curve.");
457 for (
const auto& kv : priceSegments) {
460 commodityCurves, mpInstruments);
467 vector<QuantLib::ext::shared_ptr<Helper>> instruments;
468 instruments.reserve(mpInstruments.size());
469 for (
const auto& kv : mpInstruments) {
470 instruments.push_back(kv.second);
489 BS<Crv<Linear>> bs(acc, globalAcc, noThrow, maxAttempts, maxF, minF, noThrowSteps);
505 commodityPriceCurve_ = QuantLib::ext::make_shared<Crv<QuantExt::LogLinearFlat>>(asof, instruments,
519 LOG(
"CommodityCurve: finished building commodity piecewise curve.");
522vector<QuantLib::ext::shared_ptr<CommodityForwardQuote>>
526 LOG(
"CommodityCurve: start getting configured commodity quotes.");
533 std::set<QuantLib::ext::shared_ptr<MarketDatum>>
data;
535 data = loader.
get(*wildcard, asof);
537 std::ostringstream ss;
544 vector<QuantLib::ext::shared_ptr<CommodityForwardQuote>> result;
545 for (
const auto& md :
data) {
546 QL_REQUIRE(md->asofDate() == asof,
"MarketDatum asofDate '" << md->asofDate() <<
"' <> asof '" << asof <<
"'");
550 QuantLib::ext::shared_ptr<CommodityForwardQuote> q = QuantLib::ext::dynamic_pointer_cast<CommodityForwardQuote>(md);
551 QL_REQUIRE(q,
"Internal error: could not downcast MarketDatum '" << md->name() <<
"' to CommodityForwardQuote");
554 vector<string>::const_iterator it =
555 find(quotes.begin(), quotes.end(), q->name());
556 if (it == quotes.end())
562 if (q->tenorBased()) {
563 TLOG(
"Skipping tenor based quote, " << q->name() <<
".");
566 if (q->expiryDate() < asof) {
567 TLOG(
"Skipping quote because its expiry date, " << io::iso_date(q->expiryDate())
568 <<
", is before the market date " << io::iso_date(asof));
575 TLOG(
"Added quote " << q->name() <<
".");
578 LOG(
"CommodityCurve: finished getting configured commodity quotes.");
584 const string& currency,
const PriceSegment& priceSegment,
585 const map<
string, QuantLib::ext::shared_ptr<CommodityCurve>>& commodityCurves,
586 map<Date, QuantLib::ext::shared_ptr<Helper>>& instruments) {
590 PST type = priceSegment.
type();
593 QuantLib::ext::shared_ptr<Conventions> conventions = InstrumentConventions::instance().conventions();
594 QuantLib::ext::shared_ptr<CommodityFutureConvention> convention;
596 QuantLib::ext::shared_ptr<CommodityIndex> index;
597 QuantLib::ext::shared_ptr<FutureExpiryCalculator> uFec;
598 if (type == PST::AveragingFuture || type == PST::AveragingSpot || type == PST::AveragingOffPeakPower) {
601 convention = QuantLib::ext::dynamic_pointer_cast<CommodityFutureConvention>(
603 QL_REQUIRE(convention,
"Convention " << priceSegment.
conventionsId() <<
604 " not of expected type CommodityFutureConvention.");
606 ad = convention->averagingData();
607 QL_REQUIRE(!ad.empty(),
"CommodityCurve: convention " << convention->id() <<
608 " should have non-empty averaging data for piecewise price curve construction.");
614 if (type == PST::AveragingFuture || type == PST::AveragingOffPeakPower) {
616 auto uConvention = QuantLib::ext::dynamic_pointer_cast<CommodityFutureConvention>(
617 conventions->get(ad.conventionsId()));
618 QL_REQUIRE(uConvention,
"Convention " << priceSegment.
conventionsId() <<
619 " not of expected type CommodityFutureConvention.");
620 uFec = QuantLib::ext::make_shared<ConventionsBasedFutureExpiry>(*uConvention);
622 if (ad.dailyExpiryOffset() != Null<Natural>() && ad.dailyExpiryOffset() > 0) {
623 QL_REQUIRE(uConvention->contractFrequency() == Daily,
"CommodityCurve: the averaging data has" <<
624 " a positive DailyExpiryOffset (" << ad.dailyExpiryOffset() <<
") but the underlying future" <<
625 " contract frequency is not daily (" << uConvention->contractFrequency() <<
").");
632 QuantLib::ext::shared_ptr<CommodityIndex> peakIndex;
633 Natural peakHoursPerDay = 16;
634 Calendar peakCalendar;
635 if (type == PST::AveragingOffPeakPower) {
639 QL_REQUIRE(!ppId.empty(),
"CommodityCurve: AveragingOffPeakPower segment in " <<
640 " curve configuration " << configId <<
" does not provide a peak price curve ID.");
642 DLOG(
"Looking for peak price curve with id, " << ppId <<
", and spec, " << ccSpec <<
".");
643 auto itCc = commodityCurves.find(ccSpec.
name());
644 QL_REQUIRE(itCc != commodityCurves.end(),
"Can't find peak price curve with id " << ppId);
645 auto peakPts = Handle<PriceTermStructure>(itCc->second->commodityPriceCurve());
654 if (conventions->has(ppId)) {
655 auto peakConvention = QuantLib::ext::dynamic_pointer_cast<CommodityFutureConvention>(conventions->get(ppId));
656 if (peakConvention && peakConvention->hoursPerDay() != Null<Natural>()) {
657 peakHoursPerDay = peakConvention->hoursPerDay();
663 auto quotes =
getQuotes(asof, configId, priceSegment.
quotes(), loader,
true);
666 for (
const auto& quote : quotes) {
668 const Date& expiry = quote->expiryDate();
671 if (expiry == asof) {
672 TLOG(
"Quote " << quote->name() <<
" has expiry date " << io::iso_date(expiry) <<
" equal to asof" <<
673 " so not adding to instruments. Attempt to add as fixing instead.");
674 addMarketFixing(priceSegment.
conventionsId(), expiry, quote->quote()->value());
675 }
else if (instruments.count(expiry) == 0) {
676 instruments[expiry] = QuantLib::ext::make_shared<FuturePriceHelper>(quote->quote(), expiry);
678 TLOG(
"Skipping quote, " << quote->name() <<
", because its expiry date, " <<
679 io::iso_date(expiry) <<
", is already in the instrument set.");
684 case PST::AveragingFuture:
685 case PST::AveragingSpot:
686 case PST::AveragingOffPeakPower: {
689 using ADCP = AD::CalculationPeriod;
692 if (ad.period() == ADCP::ExpiryToExpiry) {
694 auto fec = QuantLib::ext::make_shared<ConventionsBasedFutureExpiry>(*convention);
695 end = fec->nextExpiry(
true, expiry);
697 WLOG(
"Calculated expiry date, " << io::iso_date(end) <<
", does not equal quote's expiry date "
698 << io::iso_date(expiry) <<
". Proceed with quote's expiry.");
700 start = fec->priorExpiry(
false, end) + 1;
702 }
else if (ad.period() == ADCP::PreviousMonth) {
704 end = Date::endOfMonth(expiry - 1 * Months);
705 start = Date(1, end.month(), end.year());
708 QuantLib::ext::shared_ptr<Helper>
helper;
709 if (type == PST::AveragingOffPeakPower) {
710 TLOG(
"Building average off-peak power helper from quote, " << quote->name() <<
".");
711 helper = QuantLib::ext::make_shared<AverageOffPeakPowerHelper>(quote->quote(), index, start,
712 end, uFec, peakIndex, peakCalendar, peakHoursPerDay);
714 TLOG(
"Building average future price helper from quote, " << quote->name() <<
".");
715 helper = QuantLib::ext::make_shared<AverageFuturePriceHelper>(quote->quote(), index, start, end, uFec,
716 ad.pricingCalendar(), ad.deliveryRollDays(), ad.futureMonthOffset(), ad.useBusinessDays(),
717 ad.dailyExpiryOffset());
721 Date pillar =
helper->pillarDate();
722 if (instruments.count(pillar) == 0) {
723 instruments[pillar] =
helper;
725 TLOG(
"Skipping quote, " << quote->name() <<
", because an instrument with its pillar date, " <<
726 io::iso_date(pillar) <<
", is already in the instrument set.");
732 QL_FAIL(
"CommodityCurve: unrecognised price segment type.");
739 const PriceSegment& priceSegment, map<Date, QuantLib::ext::shared_ptr<Helper>>& instruments) {
743 QL_REQUIRE(priceSegment.
type() == PST::OffPeakPowerDaily,
"Expecting a price segment type of OffPeakPowerDaily.");
745 QuantLib::ext::shared_ptr<Conventions> conventions = InstrumentConventions::instance().conventions();
750 QL_REQUIRE(p.first,
"Could not get conventions with id " << convId <<
" for OffPeakPowerDaily price segment" <<
751 " in curve configuration " << configId <<
".");
752 auto convention = QuantLib::ext::dynamic_pointer_cast<CommodityFutureConvention>(p.second);
755 const auto& oppIdxData = convention->offPeakPowerIndexData();
756 QL_REQUIRE(oppIdxData,
"Conventions with id " << convId <<
" for OffPeakPowerDaily price segment" <<
757 " should have an OffPeakPowerIndexData section.");
758 Real offPeakHours = oppIdxData->offPeakHours();
759 TLOG(
"Off-peak hours is " << offPeakHours);
760 const Calendar& peakCalendar = oppIdxData->peakCalendar();
764 QL_REQUIRE(opd,
"The OffPeakPowerDaily price segment for curve configuration " << configId <<
765 " should have an OffPeakDaily section.");
771 map<Date, pair<Real, Real>> quotes;
773 auto opqs =
getQuotes(asof, configId, opd->offPeakQuotes(), loader,
true);
774 for (
const auto& q : opqs) {
775 Real
value = q->quote()->value();
776 Date expiry = q->expiryDate();
777 if (quotes.count(expiry) != 0) {
778 TLOG(
"Already have off-peak quote with expiry " << io::iso_date(expiry) <<
" so skipping " << q->name());
780 TLOG(
"Adding off-peak quote " << q->name() <<
": " << io::iso_date(expiry) <<
"," <<
value);
781 quotes[expiry] = make_pair(
value, Null<Real>());
785 auto pqs =
getQuotes(asof, configId, opd->peakQuotes(), loader,
true);
786 for (
const auto& q : pqs) {
787 Real
value = q->quote()->value();
788 Date expiry = q->expiryDate();
789 auto it = quotes.find(expiry);
790 if (it == quotes.end()) {
791 TLOG(
"Have no off-peak quote with expiry " << io::iso_date(expiry) <<
" so skipping " << q->name());
792 }
else if (it->second.second != Null<Real>()) {
793 TLOG(
"Already have a peak quote with expiry " << io::iso_date(expiry) <<
" so skipping " << q->name());
795 TLOG(
"Adding peak quote " << q->name() <<
": " << io::iso_date(expiry) <<
"," <<
value);
796 it->second.second =
value;
801 for (
const auto& kv : quotes) {
804 const Date& expiry = kv.first;
805 if (instruments.count(expiry) != 0) {
806 TLOG(
"Skipping expiry " << io::iso_date(expiry) <<
" because it is already in the instrument set.");
811 if (expiry == asof) {
812 TLOG(
"The off-peak power expiry date " << io::iso_date(expiry) <<
" is equal to asof" <<
813 " so not adding to instruments. Attempt to add fixing(s) instead.");
814 if (peakCalendar.isHoliday(expiry) && kv.second.second == Null<Real>()) {
815 DLOG(
"The peak portion of the quote on holiday " << io::iso_date(expiry) <<
816 " is missing so can't add fixings.");
819 addMarketFixing(oppIdxData->offPeakIndex(), expiry, kv.second.first);
820 if (peakCalendar.isHoliday(expiry))
821 addMarketFixing(oppIdxData->peakIndex(), expiry, kv.second.second);
828 if (peakCalendar.isHoliday(expiry)) {
829 Real peakValue = kv.second.second;
830 if (peakValue == Null<Real>()) {
831 DLOG(
"The peak portion of the quote on holiday " << io::iso_date(expiry) <<
" is missing so skip.");
834 Real offPeakValue = kv.second.first;
835 quote = (offPeakHours * offPeakValue + (24.0 - offPeakHours) * peakValue) / 24.0;
836 TLOG(
"The quote on holiday " << io::iso_date(expiry) <<
" is " << quote <<
". (off-peak,peak) is" <<
837 " (" << offPeakValue <<
"," << peakValue <<
").");
840 quote = kv.second.first;
841 TLOG(
"The quote on business day " << io::iso_date(expiry) <<
" is the off-peak value " << quote <<
".");
845 instruments[expiry] = QuantLib::ext::make_shared<FuturePriceHelper>(quote, expiry);
QuantLib::Real maxFactor() const
QuantLib::Size dontThrowSteps() const
QuantLib::Real globalAccuracy() const
QuantLib::Real accuracy() const
QuantLib::Real minFactor() const
QuantLib::Size maxAttempts() const
Commodity curve configuration.
const std::string & conventionsId() const
const std::string & currency() const
bool priceAsHistFixing() const
const std::map< unsigned short, PriceSegment > & priceSegments() const
const boost::optional< BootstrapConfig > & bootstrapConfig() const
const vector< string > & fwdQuotes() const
QuantLib::Natural monthOffset() const
const std::string & baseConventionsId() const
std::string interpolationMethod_
Store the interpolation method.
QuantLib::ext::shared_ptr< QuantExt::CommodityIndex > commodityIndex_
QuantLib::ext::shared_ptr< QuantExt::PriceTermStructure > commodityPriceCurve_
QuantLib::ext::shared_ptr< CommodityCurveCalibrationInfo > calibrationInfo_
QuantLib::Real onValue_
Store the overnight value if any.
void buildCurve(const QuantLib::Date &asof, const std::map< QuantLib::Date, QuantLib::Handle< QuantLib::Quote > > &data, const QuantLib::ext::shared_ptr< CommodityCurveConfig > &config)
Build price curve using the curve data.
CommodityCurve()
Default constructor.
void buildPiecewiseCurve(const QuantLib::Date &asof, const CommodityCurveConfig &config, const Loader &loader, const std::map< std::string, QuantLib::ext::shared_ptr< CommodityCurve > > &commodityCurves)
Build commodity piecewise price curve.
void buildCrossCurrencyPriceCurve(const QuantLib::Date &asof, const QuantLib::ext::shared_ptr< CommodityCurveConfig > &config, const QuantLib::ext::shared_ptr< CommodityCurveConfig > &baseConfig, const FXTriangulation &fxSpots, const std::map< std::string, QuantLib::ext::shared_ptr< YieldCurve > > &yieldCurves, const std::map< std::string, QuantLib::ext::shared_ptr< CommodityCurve > > &commodityCurves)
Build cross currency commodity price curve.
std::vector< QuantLib::ext::shared_ptr< CommodityForwardQuote > > getQuotes(const QuantLib::Date &asof, const std::string &, const std::vector< std::string > "es, const Loader &loader, bool filter=false)
Get the configured quotes. If filter is true, remove tenor based quotes and quotes with expiry before...
void add(const QuantLib::Date &asof, const QuantLib::Date &expiry, QuantLib::Real value, std::map< QuantLib::Date, QuantLib::Handle< QuantLib::Quote > > &data, bool outright, QuantLib::Real pointsFactor=1.0)
Add node to price curve data with check for duplicate expiry dates.
QuantLib::Real tnValue_
Store the tomorrow next value if any.
bool regexQuotes_
Populated with true if the quotes are configured via a wildcard.
QuantLib::DayCounter dayCounter_
Store the curve's day counter.
void addOffPeakPowerInstruments(const QuantLib::Date &asof, const Loader &loader, const std::string &configId, const PriceSegment &priceSegment, std::map< QuantLib::Date, QuantLib::ext::shared_ptr< Helper > > &instruments)
Special method to add instruments when the priceSegment is OffPeakPowerDaily.
void populateData(std::map< QuantLib::Date, QuantLib::Handle< QuantLib::Quote > > &data, const QuantLib::Date &asof, const QuantLib::ext::shared_ptr< CommodityCurveConfig > &config, const Loader &loader)
Populate data with dates and prices from the loader.
QuantLib::Real commoditySpot_
Store the commodity spot value with Null<Real>() indicating that none has been provided.
void buildBasisPriceCurve(const QuantLib::Date &asof, const CommodityCurveConfig &config, const QuantLib::Handle< QuantExt::PriceTermStructure > &basePts, const Loader &loader)
Build commodity basis price curve.
void addInstruments(const QuantLib::Date &asof, const Loader &loader, const std::string &configId, const std::string ¤cy, const PriceSegment &priceSegment, const std::map< std::string, QuantLib::ext::shared_ptr< CommodityCurve > > &commodityCurves, std::map< QuantLib::Date, QuantLib::ext::shared_ptr< Helper > > &instruments)
Commodity curve description.
CalculationPeriod
Indicate location of calculation period relative to the future expiry date.
Abstract base class for convention objects.
Repository for currency dependent market conventions.
QuantLib::ext::shared_ptr< Convention > get(const string &id) const
const string & curveID() const
Container class for all Curve Configurations.
const std::string & curveConfigID() const
string name() const
returns the unique curve name
QuantLib::Handle< QuantLib::Quote > getQuote(const std::string &pair) const
Market data loader base class.
virtual QuantLib::ext::shared_ptr< MarketDatum > get(const std::string &name, const QuantLib::Date &d) const
get quote by its unique name, throws if not existent, override in derived classes for performance
Type
Type of price segment being represented, i.e. type of instrument in the price segment.
const std::string & peakPriceCalendar() const
const boost::optional< OffPeakDaily > & offPeakDaily() const
const std::string & peakPriceCurveId() const
const std::string & conventionsId() const
const std::vector< std::string > & quotes() const
Class for building a commodity price curve.
SafeStack< ValueType > value
SafeStack< Filter > filter
Base class for classes that perform date calculations for future contracts.
Calendar parseCalendar(const string &s)
Convert text to QuantLib::Calendar.
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
DayCounter parseDayCounter(const string &s)
Convert text to QuantLib::DayCounter.
Map text representations to QuantLib/QuantExt types.
Classes and functions for log message handling.
#define LOG(text)
Logging Macro (Level = Notice)
#define DLOG(text)
Logging Macro (Level = Debug)
#define WLOG(text)
Logging Macro (Level = Warning)
#define TLOG(text)
Logging Macro (Level = Data)
QuantLib::ext::shared_ptr< QuantExt::CommodityIndex > parseCommodityIndex(const string &name, bool hasPrefix, const Handle< PriceTermStructure > &ts, const Calendar &cal, const bool enforceFutureIndex)
boost::optional< Wildcard > getUniqueWildcard(const C &c)
checks if at most one element in C has a wild card and returns it in this case
Serializable Credit Default Swap.
QuantLib::BootstrapHelper< QuantLib::OptionletVolatilityStructure > helper
vector< string > curveConfigs
utilities for wildcard handling