Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
List of all members
CommodityCurve Class Reference

#include <ored/marketdata/commoditycurve.hpp>

+ Collaboration diagram for CommodityCurve:

Public Member Functions

Constructors
 CommodityCurve ()
 Default constructor. More...
 
 CommodityCurve (const QuantLib::Date &asof, const CommodityCurveSpec &spec, const Loader &loader, const CurveConfigurations &curveConfigs, const FXTriangulation &fxSpots=FXTriangulation(), const std::map< std::string, QuantLib::ext::shared_ptr< YieldCurve > > &yieldCurves={}, const std::map< std::string, QuantLib::ext::shared_ptr< CommodityCurve > > &commodityCurves={}, bool const buildCalibrationInfo=false)
 Detailed constructor. More...
 

Inspectors

using Helper = QuantLib::BootstrapHelper< QuantExt::PriceTermStructure >
 Add the instruments relating to a priceSegment to instruments. More...
 
CommodityCurveSpec spec_
 
QuantLib::ext::shared_ptr< QuantExt::PriceTermStructurecommodityPriceCurve_
 
QuantLib::ext::shared_ptr< QuantExt::CommodityIndexcommodityIndex_
 
QuantLib::ext::shared_ptr< CommodityCurveCalibrationInfocalibrationInfo_
 
QuantLib::Real commoditySpot_
 Store the commodity spot value with Null<Real>() indicating that none has been provided. More...
 
QuantLib::Real onValue_
 Store the overnight value if any. More...
 
QuantLib::Real tnValue_
 Store the tomorrow next value if any. More...
 
bool regexQuotes_
 Populated with true if the quotes are configured via a wildcard. More...
 
std::string interpolationMethod_
 Store the interpolation method. More...
 
QuantLib::DayCounter dayCounter_
 Store the curve's day counter. More...
 
const CommodityCurveSpecspec () const
 
QuantLib::ext::shared_ptr< QuantExt::PriceTermStructurecommodityPriceCurve () const
 
QuantLib::ext::shared_ptr< QuantExt::CommodityIndexcommodityIndex () const
 
QuantLib::ext::shared_ptr< CommodityCurveCalibrationInfocalibrationInfo () const
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
void buildBasisPriceCurve (const QuantLib::Date &asof, const CommodityCurveConfig &config, const QuantLib::Handle< QuantExt::PriceTermStructure > &basePts, const Loader &loader)
 Build commodity basis price curve. More...
 
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. More...
 
std::vector< QuantLib::ext::shared_ptr< CommodityForwardQuote > > getQuotes (const QuantLib::Date &asof, const std::string &, const std::vector< std::string > &quotes, const Loader &loader, bool filter=false)
 Get the configured quotes. If filter is true, remove tenor based quotes and quotes with expiry before asof. More...
 
template<template< class > class CurveType, typename... Args>
void populateCurve (Args... args)
 Method for populating the price curve. More...
 
void addInstruments (const QuantLib::Date &asof, const Loader &loader, const std::string &configId, const std::string &currency, const PriceSegment &priceSegment, const std::map< std::string, QuantLib::ext::shared_ptr< CommodityCurve > > &commodityCurves, std::map< QuantLib::Date, QuantLib::ext::shared_ptr< Helper > > &instruments)
 
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. More...
 

Detailed Description

Definition at line 43 of file commoditycurve.hpp.

Member Typedef Documentation

◆ Helper

using Helper = QuantLib::BootstrapHelper<QuantExt::PriceTermStructure>
private

Add the instruments relating to a priceSegment to instruments.

Definition at line 128 of file commoditycurve.hpp.

Constructor & Destructor Documentation

◆ CommodityCurve() [1/2]

Default constructor.

Definition at line 108 of file commoditycurve.cpp.

109 : commoditySpot_(Null<Real>()), onValue_(Null<Real>()), tnValue_(Null<Real>()), regexQuotes_(false) {}
QuantLib::Real onValue_
Store the overnight value if any.
QuantLib::Real tnValue_
Store the tomorrow next value if any.
bool regexQuotes_
Populated with true if the quotes are configured via a wildcard.
QuantLib::Real commoditySpot_
Store the commodity spot value with Null<Real>() indicating that none has been provided.

◆ CommodityCurve() [2/2]

CommodityCurve ( const QuantLib::Date &  asof,
const CommodityCurveSpec spec,
const Loader loader,
const CurveConfigurations curveConfigs,
const FXTriangulation fxSpots = FXTriangulation(),
const std::map< std::string, QuantLib::ext::shared_ptr< YieldCurve > > &  yieldCurves = {},
const std::map< std::string, QuantLib::ext::shared_ptr< CommodityCurve > > &  commodityCurves = {},
bool const  buildCalibrationInfo = false 
)

Detailed constructor.

Member Function Documentation

◆ spec()

const CommodityCurveSpec & spec ( ) const

Definition at line 61 of file commoditycurve.hpp.

61{ return spec_; }
CommodityCurveSpec spec_

◆ commodityPriceCurve()

QuantLib::ext::shared_ptr< QuantExt::PriceTermStructure > commodityPriceCurve ( ) const

Definition at line 62 of file commoditycurve.hpp.

62{ return commodityPriceCurve_; }
QuantLib::ext::shared_ptr< QuantExt::PriceTermStructure > commodityPriceCurve_

◆ commodityIndex()

QuantLib::ext::shared_ptr< QuantExt::CommodityIndex > commodityIndex ( ) const

Definition at line 63 of file commoditycurve.hpp.

63{ return commodityIndex_; }
QuantLib::ext::shared_ptr< QuantExt::CommodityIndex > commodityIndex_

◆ calibrationInfo()

QuantLib::ext::shared_ptr< CommodityCurveCalibrationInfo > calibrationInfo ( ) const

Definition at line 64 of file commoditycurve.hpp.

64{ return calibrationInfo_; }
QuantLib::ext::shared_ptr< CommodityCurveCalibrationInfo > calibrationInfo_

◆ populateData()

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 
)
private

Populate data with dates and prices from the loader.

Definition at line 194 of file commoditycurve.cpp.

195 {
196
197 // Some default conventions for building the commodity curve
198 Period spotTenor = 2 * Days;
199 Real pointsFactor = 1.0;
200
201 Calendar cal = parseCalendar(config->currency());
202 bool spotRelative = true;
203 BusinessDayConvention bdc = Following;
204 bool outright = true;
205
206 QuantLib::ext::shared_ptr<Conventions> conventions = InstrumentConventions::instance().conventions();
207
208 // Overwrite the default conventions if the commodity curve config provides explicit 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");
213 auto convention =
214 QuantLib::ext::dynamic_pointer_cast<CommodityForwardConvention>(conventions->get(config->conventionsId()));
215 QL_REQUIRE(convention, "Convention " << config->conventionsId() << " not of expected type CommodityConvention");
216
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();
224 }
225
226 // Commodity spot quote if provided by the configuration
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");
231 } else {
232 auto spot = loader.get(config->commoditySpotQuoteId(), asof)->quote();
233 commoditySpot_ = spot->value();
234 data[spotDate] = spot;
235 }
236
237 // Add the forward quotes to the curve data
238 for (auto& q : getQuotes(asof, config->curveID(), config->fwdQuotes(), loader)) {
239
240 // We add ON and TN quotes after this loop if they are given and not outright quotes
241 TLOG("Commodity Forward Price found for quote: " << q->name());
242 Date expiry;
243 Real value = q->quote()->value();
244 if (!q->tenorBased()) {
245 expiry = q->expiryDate();
246 add(asof, expiry, value, data, outright, pointsFactor);
247 } else {
248 if (q->startTenor() == boost::none) {
249 expiry = cal.advance(spotRelative ? spotDate : asof, q->tenor(), bdc);
250 add(asof, expiry, value, data, outright, pointsFactor);
251 } else {
252 if (*q->startTenor() == 0 * Days && q->tenor() == 1 * Days) {
253 onValue_ = q->quote()->value();
254 if (outright)
255 add(asof, asof, value, data, outright);
256 } else if (*q->startTenor() == 1 * Days && q->tenor() == 1 * Days) {
257 tnValue_ = q->quote()->value();
258 if (outright) {
259 expiry = cal.advance(asof, 1 * Days, bdc);
260 add(asof, expiry, value, data, outright);
261 }
262 } else {
263 expiry = cal.advance(cal.advance(asof, *q->startTenor(), bdc), q->tenor(), bdc);
264 add(asof, expiry, value, data, outright, pointsFactor);
265 }
266 }
267 }
268 }
269
270 // Deal with ON and TN if quotes are not outright quotes
271 if (spotTenor == 2 * Days && tnValue_ != Null<Real>() && !outright) {
272 add(asof, cal.advance(asof, 1 * Days, bdc), -tnValue_, data, outright, pointsFactor);
273 if (onValue_ != Null<Real>()) {
274 add(asof, asof, -onValue_ - tnValue_, data, outright, pointsFactor);
275 }
276 }
277
278 // Some logging and checks
279 LOG("Read " << data.size() << " quotes for commodity curve " << config->curveID());
280 if (!regexQuotes_) {
281 QL_REQUIRE(data.size() == config->quotes().size(), "Found " << data.size() << " quotes, but "
282 << config->quotes().size()
283 << " quotes given in config " << config->curveID());
284 } else {
285 QL_REQUIRE(data.size() > 0,
286 "Regular expression specified in commodity config " << config->curveID() << " but no quotes read");
287 }
288}
std::vector< QuantLib::ext::shared_ptr< CommodityForwardQuote > > getQuotes(const QuantLib::Date &asof, const std::string &, const std::vector< std::string > &quotes, 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.
SafeStack< ValueType > value
Calendar parseCalendar(const string &s)
Convert text to QuantLib::Calendar.
Definition: parsers.cpp:157
@ data
Definition: log.hpp:77
#define LOG(text)
Logging Macro (Level = Notice)
Definition: log.hpp:552
#define TLOG(text)
Logging Macro (Level = Data)
Definition: log.hpp:556
+ Here is the call graph for this function:

◆ add()

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 
)
private

Add node to price curve data with check for duplicate expiry dates.

Definition at line 290 of file commoditycurve.cpp.

291 {
292
293 if (expiry < asof)
294 return;
295
296 if (data.find(expiry) != data.end()) {
297 WLOG("building " << spec_.name() << ": skipping duplicate expiry " << io::iso_date(expiry));
298 return;
299 }
300
301 if (!outright) {
302 QL_REQUIRE(commoditySpot_ != Null<Real>(), "Can't use forward points without a commodity spot value");
303 value = commoditySpot_ + value / pointsFactor;
304 }
305
306 data[expiry] = Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(value));
307}
string name() const
returns the unique curve name
Definition: curvespec.hpp:78
#define WLOG(text)
Logging Macro (Level = Warning)
Definition: log.hpp:550
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ buildCurve()

void buildCurve ( const QuantLib::Date &  asof,
const std::map< QuantLib::Date, QuantLib::Handle< QuantLib::Quote > > &  data,
const QuantLib::ext::shared_ptr< CommodityCurveConfig > &  config 
)
private

Build price curve using the curve data.

Definition at line 309 of file commoditycurve.cpp.

310 {
311
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);
319 }
320
321 // Build the curve using the data
322 populateCurve<InterpolatedPriceCurve>(asof, curveDates, curvePrices, dayCounter_,
323 parseCurrency(config->currency()));
324}
QuantLib::DayCounter dayCounter_
Store the curve's day counter.
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
Definition: parsers.cpp:290
+ Here is the call graph for this function:

◆ buildCrossCurrencyPriceCurve()

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 
)
private

Build cross currency commodity price curve.

Definition at line 326 of file commoditycurve.cpp.

330 {
331
332 // Look up the required base price curve in the commodityCurves map
333 // We pass in the commodity curve ID only in the member basePriceCurveId of config e.g. PM:XAUUSD.
334 // But, the map commodityCurves is keyed on the spec name e.g. Commodity/USD/PM:XAUUSD
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());
340
341 // Look up the two yield curves in the yieldCurves map
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());
347
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());
353
354 // Get the FX spot rate, number of units of this currency per unit of base currency
355 Handle<Quote> fxSpot = fxSpots.getQuote(baseConfig->currency() + config->currency());
356
357 // Populate the commodityPriceCurve_ member
358 commodityPriceCurve_ = QuantLib::ext::make_shared<CrossCurrencyPriceTermStructure>(
359 asof, QuantLib::Handle<PriceTermStructure>(commIt->second->commodityPriceCurve()), fxSpot,
360 baseYtsIt->second->handle(), ytsIt->second->handle(), parseCurrency(config->currency()));
361}
+ Here is the call graph for this function:

◆ buildBasisPriceCurve()

void buildBasisPriceCurve ( const QuantLib::Date &  asof,
const CommodityCurveConfig config,
const QuantLib::Handle< QuantExt::PriceTermStructure > &  basePts,
const Loader loader 
)
private

Build commodity basis price curve.

Definition at line 363 of file commoditycurve.cpp.

364 {
365
366 LOG("CommodityCurve: start building commodity basis curve.");
367
368 QL_REQUIRE(!basePts.empty() && basePts.currentLink() != nullptr,
369 "Internal error: Can not build commodityBasisCurve '" << config.curveID() << "'without empty baseCurve");
370
371 QuantLib::ext::shared_ptr<Conventions> conventions = InstrumentConventions::instance().conventions();
372
373 // We need to have commodity future conventions for both the base curve and the basis curve
374 QL_REQUIRE(conventions->has(config.conventionsId()), "Commodity conventions " << config.conventionsId()
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);
382
383 QL_REQUIRE(conventions->has(config.baseConventionsId()),
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);
391
392 // Construct the commodity index.
393 auto baseIndex = parseCommodityIndex(baseConvention->id(), false, basePts);
394
395
396 // Sort the configured quotes on expiry dates
397 // Ignore tenor based quotes i.e. we expect an explicit expiry date and log a warning if the expiry date does not
398 // match our own calculated expiry date based on the basis conventions.
399 map<Date, Handle<Quote>> basisData;
400 for (auto& q : getQuotes(asof, config.curveID(), config.fwdQuotes(), loader, true)) {
401
402 QL_REQUIRE(basisData.find(q->expiryDate()) == basisData.end(), "Found duplicate quote, "
403 << q->name() << ", for expiry date "
404 << io::iso_date(q->expiryDate()) << ".");
405
406 basisData[q->expiryDate()] = q->quote();
407 TLOG("Using quote " << q->name() << " in commodity basis curve.");
408
409 // We expect the expiry date in the quotes to match our calculated expiry date. The code will work if it does
410 // not but we log a warning in this case.
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()) << ".");
415 }
416 }
417
418 if (basisConvention->isAveraging()) {
419 // We are building a curve that will be used to return an average price.
420 if (!baseConvention->isAveraging() && config.averageBase()) {
421 DLOG("Creating a CommodityAverageBasisPriceCurve.");
422 populateCurve<CommodityAverageBasisPriceCurve>(asof, basisData, basisFec, baseIndex, baseFec,
423 config.addBasis(), config.priceAsHistFixing());
424 } else {
425 // Either 1) base convention is not averaging and config.averageBase() is false or 2) the base convention
426 // is averaging. Either way, we build a CommodityBasisPriceCurve.
427 DLOG("Creating a CommodityBasisPriceCurve for an average price curve.");
428 populateCurve<CommodityBasisPriceCurve>(asof, basisData, basisFec, baseIndex, baseFec,
429 config.addBasis(), config.monthOffset(), config.priceAsHistFixing());
430 }
431 } else {
432 // We are building a curve that will be used to return a price on a single date.
433 QL_REQUIRE(!baseConvention->isAveraging(), "A commodity basis curve with non-averaging"
434 << " basis and averaging base is not valid.");
435
436 populateCurve<CommodityBasisPriceCurve>(asof, basisData, basisFec, baseIndex, baseFec, config.addBasis(),
437 config.monthOffset(), config.priceAsHistFixing());
438 }
439
440 LOG("CommodityCurve: finished building commodity basis curve.");
441}
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
QuantLib::ext::shared_ptr< QuantExt::CommodityIndex > parseCommodityIndex(const string &name, bool hasPrefix, const Handle< PriceTermStructure > &ts, const Calendar &cal, const bool enforceFutureIndex)
+ Here is the call graph for this function:

◆ buildPiecewiseCurve()

void buildPiecewiseCurve ( const QuantLib::Date &  asof,
const CommodityCurveConfig config,
const Loader loader,
const std::map< std::string, QuantLib::ext::shared_ptr< CommodityCurve > > &  commodityCurves 
)
private

Build commodity piecewise price curve.

Definition at line 447 of file commoditycurve.cpp.

448 {
449
450 LOG("CommodityCurve: start building commodity piecewise curve.");
451
452 // We store the instruments in a map. The key is the instrument's pillar date. The segments are ordered in
453 // priority so if we encounter the same pillar date later, we ignore it with a debug log.
454 map<Date, QuantLib::ext::shared_ptr<Helper>> mpInstruments;
455 const auto& priceSegments = config.priceSegments();
456 QL_REQUIRE(!priceSegments.empty(), "CommodityCurve: need at least one price segment to build piecewise curve.");
457 for (const auto& kv : priceSegments) {
458 if (kv.second.type() != PriceSegment::Type::OffPeakPowerDaily) {
459 addInstruments(asof, loader, config.curveID(), config.currency(), kv.second,
460 commodityCurves, mpInstruments);
461 } else {
462 addOffPeakPowerInstruments(asof, loader, config.curveID(), kv.second, mpInstruments);
463 }
464 }
465
466 // Populate the vector of helpers.
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);
471 }
472
473 // Use bootstrap configuration if provided.
474 BootstrapConfig bc;
475 if (config.bootstrapConfig()) {
476 bc = *config.bootstrapConfig();
477 }
478 Real acc = bc.accuracy();
479 Real globalAcc = bc.globalAccuracy();
480 bool noThrow = bc.dontThrow();
481 Size maxAttempts = bc.maxAttempts();
482 Real maxF = bc.maxFactor();
483 Real minF = bc.minFactor();
484 Size noThrowSteps = bc.dontThrowSteps();
485
486 // Create curve based on interpolation method provided.
487 Currency ccy = parseCurrency(config.currency());
488 if (interpolationMethod_ == "Linear") {
489 BS<Crv<Linear>> bs(acc, globalAcc, noThrow, maxAttempts, maxF, minF, noThrowSteps);
490 commodityPriceCurve_ = QuantLib::ext::make_shared<Crv<Linear>>(asof, instruments, dayCounter_, ccy, Linear(), bs);
491 } else if (interpolationMethod_ == "LogLinear") {
492 BS<Crv<QuantLib::LogLinear>> bs(acc, globalAcc, noThrow, maxAttempts, maxF, minF, noThrowSteps);
493 commodityPriceCurve_ = QuantLib::ext::make_shared<Crv<QuantLib::LogLinear>>(asof, instruments,
494 dayCounter_, ccy, QuantLib::LogLinear(), bs);
495 } else if (interpolationMethod_ == "Cubic") {
496 BS<Crv<QuantLib::Cubic>> bs(acc, globalAcc, noThrow, maxAttempts, maxF, minF, noThrowSteps);
497 commodityPriceCurve_ = QuantLib::ext::make_shared<Crv<QuantLib::Cubic>>(asof, instruments,
498 dayCounter_, ccy, QuantLib::Cubic(), bs);
499 } else if (interpolationMethod_ == "LinearFlat") {
500 BS<Crv<QuantExt::LinearFlat>> bs(acc, globalAcc, noThrow, maxAttempts, maxF, minF, noThrowSteps);
501 commodityPriceCurve_ = QuantLib::ext::make_shared<Crv<QuantExt::LinearFlat>>(asof, instruments,
503 } else if (interpolationMethod_ == "LogLinearFlat") {
504 BS<Crv<QuantExt::LogLinearFlat>> bs(acc, globalAcc, noThrow, maxAttempts, maxF, minF, noThrowSteps);
505 commodityPriceCurve_ = QuantLib::ext::make_shared<Crv<QuantExt::LogLinearFlat>>(asof, instruments,
507 } else if (interpolationMethod_ == "CubicFlat") {
508 BS<Crv<QuantExt::CubicFlat>> bs(acc, globalAcc, noThrow, maxAttempts, maxF, minF, noThrowSteps);
509 commodityPriceCurve_ = QuantLib::ext::make_shared<Crv<QuantExt::CubicFlat>>(asof, instruments,
510 dayCounter_, ccy, QuantExt::CubicFlat(), bs);
511 } else if (interpolationMethod_ == "BackwardFlat") {
512 BS<Crv<BackwardFlat>> bs(acc, globalAcc, noThrow, maxAttempts, maxF, minF, noThrowSteps);
513 commodityPriceCurve_ = QuantLib::ext::make_shared<Crv<BackwardFlat>>(asof, instruments,
514 dayCounter_, ccy, BackwardFlat(), bs);
515 } else {
516 QL_FAIL("The interpolation method, " << interpolationMethod_ << ", is not supported.");
517 }
518
519 LOG("CommodityCurve: finished building commodity piecewise curve.");
520}
std::string interpolationMethod_
Store the interpolation method.
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 addInstruments(const QuantLib::Date &asof, const Loader &loader, const std::string &configId, const std::string &currency, const PriceSegment &priceSegment, const std::map< std::string, QuantLib::ext::shared_ptr< CommodityCurve > > &commodityCurves, std::map< QuantLib::Date, QuantLib::ext::shared_ptr< Helper > > &instruments)
+ Here is the call graph for this function:

◆ getQuotes()

vector< QuantLib::ext::shared_ptr< CommodityForwardQuote > > getQuotes ( const QuantLib::Date &  asof,
const std::string &  ,
const std::vector< std::string > &  quotes,
const Loader loader,
bool  filter = false 
)
private

Get the configured quotes. If filter is true, remove tenor based quotes and quotes with expiry before asof.

Definition at line 523 of file commoditycurve.cpp.

524 {
525
526 LOG("CommodityCurve: start getting configured commodity quotes.");
527
528 // Check if we are using a regular expression to select the quotes for the curve. If we are, the quotes should
529 // contain exactly one element.
530 auto wildcard = getUniqueWildcard(quotes);
531 regexQuotes_ = wildcard != boost::none;
532
533 std::set<QuantLib::ext::shared_ptr<MarketDatum>> data;
534 if (wildcard) {
535 data = loader.get(*wildcard, asof);
536 } else {
537 std::ostringstream ss;
539 Wildcard w(ss.str());
540 data = loader.get(w, asof);
541 }
542
543 // Add the relevant forward quotes to the result vector
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 << "'");
547
548 // Only looking for quotes on asof date, with quote type PRICE and instrument type commodity forward
549
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");
552
553 if (!wildcard) {
554 vector<string>::const_iterator it =
555 find(quotes.begin(), quotes.end(), q->name());
556 if (it == quotes.end())
557 continue;
558 }
559
560 // If filter is true, remove tenor based quotes and quotes with expiry before asof.
561 if (filter) {
562 if (q->tenorBased()) {
563 TLOG("Skipping tenor based quote, " << q->name() << ".");
564 continue;
565 }
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));
569 continue;
570 }
571 }
572
573 // If we make it here, the quote is relevant.
574 result.push_back(q);
575 TLOG("Added quote " << q->name() << ".");
576 }
577
578 LOG("CommodityCurve: finished getting configured commodity quotes.");
579
580 return result;
581}
SafeStack< Filter > filter
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
Definition: wildcard.hpp:65
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ populateCurve()

void populateCurve ( Args...  args)
private

Method for populating the price curve.

Definition at line 140 of file commoditycurve.hpp.

140 {
141
142 if (interpolationMethod_ == "Linear") {
143 commodityPriceCurve_ = QuantLib::ext::make_shared<CurveType<QuantLib::Linear>>(args...);
144 } else if (interpolationMethod_ == "LogLinear") {
145 commodityPriceCurve_ = QuantLib::ext::make_shared<CurveType<QuantLib::LogLinear>>(args...);
146 } else if (interpolationMethod_ == "Cubic") {
147 commodityPriceCurve_ = QuantLib::ext::make_shared<CurveType<QuantLib::Cubic>>(args...);
148 } else if (interpolationMethod_ == "Hermite") {
149 commodityPriceCurve_ = QuantLib::ext::make_shared<CurveType<QuantLib::Cubic>>(
150 args..., QuantLib::Cubic(QuantLib::CubicInterpolation::Parabolic));
151 } else if (interpolationMethod_ == "LinearFlat") {
152 commodityPriceCurve_ = QuantLib::ext::make_shared<CurveType<QuantExt::LinearFlat>>(args...);
153 } else if (interpolationMethod_ == "LogLinearFlat") {
154 commodityPriceCurve_ = QuantLib::ext::make_shared<CurveType<QuantExt::LogLinearFlat>>(args...);
155 } else if (interpolationMethod_ == "CubicFlat") {
156 commodityPriceCurve_ = QuantLib::ext::make_shared<CurveType<QuantExt::CubicFlat>>(args...);
157 } else if (interpolationMethod_ == "HermiteFlat") {
158 commodityPriceCurve_ = QuantLib::ext::make_shared<CurveType<QuantExt::HermiteFlat>>(args...);
159 } else if (interpolationMethod_ == "BackwardFlat") {
160 commodityPriceCurve_ = QuantLib::ext::make_shared<CurveType<QuantLib::BackwardFlat>>(args...);
161 } else {
162 QL_FAIL("The interpolation method, " << interpolationMethod_ << ", is not supported.");
163 }
164}

◆ addInstruments()

void addInstruments ( const QuantLib::Date &  asof,
const Loader loader,
const std::string &  configId,
const std::string &  currency,
const PriceSegment priceSegment,
const std::map< std::string, QuantLib::ext::shared_ptr< CommodityCurve > > &  commodityCurves,
std::map< QuantLib::Date, QuantLib::ext::shared_ptr< Helper > > &  instruments 
)
private

Definition at line 583 of file commoditycurve.cpp.

586 {
587
588 using PST = PriceSegment::Type;
589 using AD = CommodityFutureConvention::AveragingData;
590 PST type = priceSegment.type();
591
592 // Pre-populate some variables if averaging segment.
593 QuantLib::ext::shared_ptr<Conventions> conventions = InstrumentConventions::instance().conventions();
594 QuantLib::ext::shared_ptr<CommodityFutureConvention> convention;
595 AD ad;
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) {
599
600 // Get the associated averaging commodity future convention.
601 convention = QuantLib::ext::dynamic_pointer_cast<CommodityFutureConvention>(
602 conventions->get(priceSegment.conventionsId()));
603 QL_REQUIRE(convention, "Convention " << priceSegment.conventionsId() <<
604 " not of expected type CommodityFutureConvention.");
605
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.");
609
610 // The commodity index for which we are building a price curve.
611 index = parseCommodityIndex(ad.commodityName(), false);
612
613 // If referencing a future, we need conventions for the underlying future that is being averaged.
614 if (type == PST::AveragingFuture || type == PST::AveragingOffPeakPower) {
615
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);
621
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() << ").");
626 }
627 }
628
629 }
630
631 // Pre-populate some variables if the price segment is AveragingOffPeakPower.
632 QuantLib::ext::shared_ptr<CommodityIndex> peakIndex;
633 Natural peakHoursPerDay = 16;
634 Calendar peakCalendar;
635 if (type == PST::AveragingOffPeakPower) {
636
637 // Look up the peak price curve in the commodityCurves map
638 const string& ppId = priceSegment.peakPriceCurveId();
639 QL_REQUIRE(!ppId.empty(), "CommodityCurve: AveragingOffPeakPower segment in " <<
640 " curve configuration " << configId << " does not provide a peak price curve ID.");
641 CommodityCurveSpec ccSpec(currency, ppId);
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());
646
647 // Create the daily peak price index linked to the peak price term structure.
648 peakIndex = parseCommodityIndex(ppId, false, peakPts);
649
650 // Calendar defining the peak business days.
651 peakCalendar = parseCalendar(priceSegment.peakPriceCalendar());
652
653 // Look up the conventions for the peak price commodity to determine peak hours per day.
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();
658 }
659 }
660 }
661
662 // Get the relevant quotes
663 auto quotes = getQuotes(asof, configId, priceSegment.quotes(), loader, true);
664
665 // Add an instrument for each relevant quote.
666 for (const auto& quote : quotes) {
667
668 const Date& expiry = quote->expiryDate();
669 switch (type) {
670 case PST::Future:
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);
677 } else {
678 TLOG("Skipping quote, " << quote->name() << ", because its expiry date, " <<
679 io::iso_date(expiry) << ", is already in the instrument set.");
680 }
681 break;
682
683 // An averaging future referencing an underlying future or spot. Setup is similar.
684 case PST::AveragingFuture:
685 case PST::AveragingSpot:
686 case PST::AveragingOffPeakPower: {
687
688 // Determine the calculation period.
689 using ADCP = AD::CalculationPeriod;
690 Date start;
691 Date end;
692 if (ad.period() == ADCP::ExpiryToExpiry) {
693
694 auto fec = QuantLib::ext::make_shared<ConventionsBasedFutureExpiry>(*convention);
695 end = fec->nextExpiry(true, expiry);
696 if (end != 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.");
699 }
700 start = fec->priorExpiry(false, end) + 1;
701
702 } else if (ad.period() == ADCP::PreviousMonth) {
703
704 end = Date::endOfMonth(expiry - 1 * Months);
705 start = Date(1, end.month(), end.year());
706 }
707
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);
713 } else {
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());
718 }
719
720 // Only add to instruments if an instrument with the same pillar date is not there already.
721 Date pillar = helper->pillarDate();
722 if (instruments.count(pillar) == 0) {
723 instruments[pillar] = helper;
724 } else {
725 TLOG("Skipping quote, " << quote->name() << ", because an instrument with its pillar date, " <<
726 io::iso_date(pillar) << ", is already in the instrument set.");
727 }
728 break;
729 }
730
731 default:
732 QL_FAIL("CommodityCurve: unrecognised price segment type.");
733 break;
734 }
735 }
736}
Type
Type of price segment being represented, i.e. type of instrument in the price segment.
CommodityFutureConvention::AveragingData::CalculationPeriod ADCP
Definition: parsers.cpp:1135
PriceSegment::Type PST
Definition: parsers.cpp:1157
QuantLib::BootstrapHelper< QuantLib::OptionletVolatilityStructure > helper
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ addOffPeakPowerInstruments()

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 
)
private

Special method to add instruments when the priceSegment is OffPeakPowerDaily.

Definition at line 738 of file commoditycurve.cpp.

739 {
740
741 // Check that we have been called with the expected segment type.
742 using PST = PriceSegment::Type;
743 QL_REQUIRE(priceSegment.type() == PST::OffPeakPowerDaily, "Expecting a price segment type of OffPeakPowerDaily.");
744
745 QuantLib::ext::shared_ptr<Conventions> conventions = InstrumentConventions::instance().conventions();
746
747 // Check we have a commodity future convention for the price segment.
748 const string& convId = priceSegment.conventionsId();
749 auto p = conventions->get(convId, Convention::Type::CommodityFuture);
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);
753
754 // Check that the commodity future convention has off-peak information for the name.
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();
761
762 // Check that the price segment has off-peak daily section.
763 const auto& opd = priceSegment.offPeakDaily();
764 QL_REQUIRE(opd, "The OffPeakPowerDaily price segment for curve configuration " << configId <<
765 " should have an OffPeakDaily section.");
766
767 // Get all the peak and off-peak quotes that we have and store them in a map. The map key is the expiry date and
768 // the map value is a pair of values the first being the off-peak value for that expiry and the second being the
769 // peak value for that expiry. We only need the peak portion to form the quote on peakCalendar holidays. We need
770 // the off-peak portion always.
771 map<Date, pair<Real, Real>> quotes;
772
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());
779 } else {
780 TLOG("Adding off-peak quote " << q->name() << ": " << io::iso_date(expiry) << "," << value);
781 quotes[expiry] = make_pair(value, Null<Real>());
782 }
783 }
784
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());
794 } else {
795 TLOG("Adding peak quote " << q->name() << ": " << io::iso_date(expiry) << "," << value);
796 it->second.second = value;
797 }
798 }
799
800 // Now, use the quotes to create the future instruments in the curve.
801 for (const auto& kv : quotes) {
802
803 // If the expiry is already in the instrument set, we skip it.
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.");
807 continue;
808 }
809
810 // If the expiry is equal to the asof, we add fixings.
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.");
817 } else {
818 // Add the off-peak and if necessary peak fixing
819 addMarketFixing(oppIdxData->offPeakIndex(), expiry, kv.second.first);
820 if (peakCalendar.isHoliday(expiry))
821 addMarketFixing(oppIdxData->peakIndex(), expiry, kv.second.second);
822 }
823 continue;
824 }
825
826 // Determine the quote that we will use in the future instrument for this expiry.
827 Real quote = 0.0;
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.");
832 continue;
833 } else {
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 << ").");
838 }
839 } else {
840 quote = kv.second.first;
841 TLOG("The quote on business day " << io::iso_date(expiry) << " is the off-peak value " << quote << ".");
842 }
843
844 // Add the future helper for this expiry.
845 instruments[expiry] = QuantLib::ext::make_shared<FuturePriceHelper>(quote, expiry);
846
847 }
848}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Data Documentation

◆ spec_

CommodityCurveSpec spec_
private

Definition at line 68 of file commoditycurve.hpp.

◆ commodityPriceCurve_

QuantLib::ext::shared_ptr<QuantExt::PriceTermStructure> commodityPriceCurve_
private

Definition at line 69 of file commoditycurve.hpp.

◆ commodityIndex_

QuantLib::ext::shared_ptr<QuantExt::CommodityIndex> commodityIndex_
private

Definition at line 70 of file commoditycurve.hpp.

◆ calibrationInfo_

QuantLib::ext::shared_ptr<CommodityCurveCalibrationInfo> calibrationInfo_
private

Definition at line 71 of file commoditycurve.hpp.

◆ commoditySpot_

QuantLib::Real commoditySpot_
private

Store the commodity spot value with Null<Real>() indicating that none has been provided.

Definition at line 74 of file commoditycurve.hpp.

◆ onValue_

QuantLib::Real onValue_
private

Store the overnight value if any.

Definition at line 77 of file commoditycurve.hpp.

◆ tnValue_

QuantLib::Real tnValue_
private

Store the tomorrow next value if any.

Definition at line 80 of file commoditycurve.hpp.

◆ regexQuotes_

bool regexQuotes_
private

Populated with true if the quotes are configured via a wildcard.

Definition at line 83 of file commoditycurve.hpp.

◆ interpolationMethod_

std::string interpolationMethod_
private

Store the interpolation method.

Definition at line 86 of file commoditycurve.hpp.

◆ dayCounter_

QuantLib::DayCounter dayCounter_
private

Store the curve's day counter.

Definition at line 89 of file commoditycurve.hpp.