29#include <ql/cashflows/cashflows.hpp>
47 LOG(
"CommoditySwap::build() called for trade " <<
id());
52 additionalData_[
"isdaSubProduct"] = string(
"Price Return Basic Performance");
65 const QuantLib::ext::shared_ptr<Market> market = engineFactory->market();
66 QuantLib::ext::shared_ptr<EngineBuilder> builder = engineFactory->builder(
"CommoditySwap");
67 QuantLib::ext::shared_ptr<CommoditySwapEngineBuilder> engineBuilder =
68 QuantLib::ext::dynamic_pointer_cast<CommoditySwapEngineBuilder>(builder);
78 map<string, Leg> floatingLegs;
80 for (Size t = 0; t <
legData_.size(); t++) {
81 const auto& legDatum =
legData_.at(t);
83 const string& type = legDatum.legType();
84 if (type ==
"CommodityFixed")
88 buildLeg(engineFactory, legDatum, configuration);
92 if (
auto cfld = QuantLib::ext::dynamic_pointer_cast<CommodityFloatingLegData>(legDatum.concreteLegData())) {
93 floatingLegs[cfld->tag()] =
legs_.back();
98 for (Size t = 0; t <
legData_.size(); t++) {
99 const auto& legDatum =
legData_.at(t);
102 auto effLegDatum = legDatum;
104 const string& type = effLegDatum.legType();
105 if (type !=
"CommodityFixed")
109 auto cfld = QuantLib::ext::dynamic_pointer_cast<CommodityFixedLegData>(effLegDatum.concreteLegData());
110 QL_REQUIRE(cfld,
"CommodityFixed leg should have valid CommodityFixedLegData");
111 if (cfld->quantities().empty()) {
113 auto it = floatingLegs.find(cfld->tag());
114 QL_REQUIRE(it != floatingLegs.end(),
"Did not find a commodity floating leg corresponding to the" <<
115 " fixed leg with tag '" << cfld->tag() <<
"' from which to take the quantities.");
117 const Leg& leg = it->second;
118 vector<Real> quantities;
119 quantities.reserve(leg.size());
120 for (
const auto& cf : leg) {
123 if (
auto cicf = QuantLib::ext::dynamic_pointer_cast<CommodityIndexedCashFlow>(ucf)) {
124 quantities.push_back(cicf->periodQuantity());
125 }
else if (
auto ciacf = QuantLib::ext::dynamic_pointer_cast<CommodityIndexedAverageCashFlow>(ucf)) {
126 quantities.push_back(ciacf->periodQuantity());
128 QL_FAIL(
"Expected a commodity indexed cashflow while building commodity fixed" <<
129 " leg quantities for trade " <<
id() <<
".");
133 cfld->setQuantities(quantities);
136 if (effLegDatum.paymentDates().empty() &&
138 auto it = floatingLegs.find(cfld->tag());
139 QL_REQUIRE(it != floatingLegs.end(),
140 "Did not find a commodity floating leg correpsonding to the fixed leg with tag '"
141 << cfld->tag() <<
"' from which to take the payment dates.");
143 for(
auto const& cf: it->second) {
146 effLegDatum.paymentDates() = tmp;
150 buildLeg(engineFactory, effLegDatum, configuration);
151 legsIdx.push_back(t);
156 vector<bool> legPayersTmp;
157 vector<string> legCurrenciesTmp;
158 for (
const Size idx : legsIdx) {
159 legsTmp.push_back(
legs_.at(idx));
168 auto swap = QuantLib::ext::make_shared<QuantLib::Swap>(
legs_,
legPayers_);
170 swap->setPricingEngine(engine);
172 instrument_ = QuantLib::ext::make_shared<VanillaInstrument>(swap);
178 Date asof = Settings::instance().evaluationDate();
179 QuantLib::ext::shared_ptr<QuantLib::Swap> swap = QuantLib::ext::dynamic_pointer_cast<QuantLib::Swap>(
instrument_->qlInstrument());
180 for (Size i = 0; i < numLegs; ++i) {
188 ALOG(
"commodity swap underlying instrument not set, skip leg npv reporting");
189 for (Size j = 0; j <
legs_[i].size(); ++j) {
190 QuantLib::ext::shared_ptr<CashFlow> flow =
legs_[i][j];
191 if (flow->date() > asof) {
192 std::string label = legID +
":" + std::to_string(j + 1);
194 QuantLib::ext::shared_ptr<CommodityIndexedCashFlow> indexedFlow =
198 additionalData_[
"periodQuantity[" + label +
"]"] = indexedFlow->periodQuantity();
200 if (indexedFlow->isAveragingFrontMonthCashflow(asof)) {
201 std::vector<Real> priceVec;
202 std::vector<std::string> indexVec;
203 std::vector<Date> indexExpiryVec, pricingDateVec;
204 double averagePrice = 0;
205 for (
const auto& pd : indexedFlow->spotAveragingPricingDates()) {
207 auto index = indexedFlow->index();
208 auto pricingDate = indexedFlow->lastPricingDate();
209 indexVec.push_back(index->name());
210 indexExpiryVec.push_back(index->expiryDate());
211 pricingDateVec.push_back(pd);
212 priceVec.push_back(index->fixing(pricingDate));
213 averagePrice += priceVec.back();
216 auto index = indexedFlow->spotIndex();
217 indexVec.push_back(index->name());
218 indexExpiryVec.push_back(index->expiryDate());
219 pricingDateVec.push_back(pd);
220 priceVec.push_back(index->fixing(pd));
221 averagePrice += priceVec.back();
224 averagePrice /= indexedFlow->spotAveragingPricingDates().size();
232 additionalData_[
"index[" + label +
"]"] = indexedFlow->index()->name();
233 additionalData_[
"indexExpiry[" + label +
"]"] = indexedFlow->index()->expiryDate();
234 additionalData_[
"price[" + label +
"]"] = indexedFlow->index()->fixing(indexedFlow->pricingDate());
239 QuantLib::ext::shared_ptr<CommodityIndexedAverageCashFlow> indexedAvgFlow =
241 if (indexedAvgFlow) {
242 additionalData_[
"quantity[" + label +
"]"] = indexedAvgFlow->quantity();
243 additionalData_[
"periodQuantity[" + label +
"]"] = indexedAvgFlow->periodQuantity();
245 std::vector<Real> priceVec;
246 std::vector<std::string> indexVec;
247 std::vector<Date> indexExpiryVec, pricingDateVec;
248 double averagePrice = 0;
249 for (
const auto& kv : indexedAvgFlow->indices()) {
250 indexVec.push_back(kv.second->name());
251 indexExpiryVec.push_back(kv.second->expiryDate());
252 pricingDateVec.push_back(kv.first);
253 priceVec.push_back(kv.second->fixing(kv.first));
254 averagePrice += priceVec.back();
256 averagePrice /= indexedAvgFlow->indices().size();
265 Real flowAmount = 0.0;
267 flowAmount = flow->amount();
268 }
catch (std::exception& e) {
269 ALOG(
"flow amount could not be determined for trade " <<
id() <<
", set to zero: " << e.what());
276 QuantLib::ext::shared_ptr<Coupon> coupon = QuantLib::ext::dynamic_pointer_cast<Coupon>(
legs_[i][0]);
280 catch(std::exception& e) {
281 ALOG(
"original nominal could not be determined for trade " <<
id() <<
", set to zero: " << e.what());
291 Date asof = Settings::instance().evaluationDate();
292 Real currentAmount = Null<Real>();
295 for (Size i = 0; i <
legs_.size(); ++i) {
296 for (Size j = 0; j <
legs_[i].size(); ++j) {
297 QuantLib::ext::shared_ptr<CashFlow> flow =
legs_[i][j];
299 if (flow->date() > asof) {
300 if (currentAmount == Null<Real>())
301 currentAmount = flow->amount();
303 currentAmount = std::max(currentAmount, flow->amount());
309 if (currentAmount != Null<Real>()) {
310 return currentAmount;
312 ALOG(
"Error retrieving current notional for commodity swap " <<
id() <<
" as of " << io::iso_date(asof));
317std::map<AssetClass, std::set<std::string>>
320 std::map<AssetClass, std::set<std::string>> result;
323 set<string> indices = ld.indices();
324 for (
auto ind : indices) {
325 QuantLib::ext::shared_ptr<Index> index =
parseIndex(ind);
327 if (
auto ci = QuantLib::ext::dynamic_pointer_cast<QuantExt::CommodityIndex>(index)) {
336 DLOG(
"CommoditySwap::fromXML called");
341 QL_REQUIRE(swapNode,
"No SwapData Node");
344 for (Size i = 0; i < nodes.size(); i++) {
346 ld->fromXML(nodes[i]);
355 for (Size i = 0; i <
legData_.size(); i++)
361 QL_REQUIRE(
legData_.size() >= 2,
"Expected at least two commodity legs but found " <<
legData_.size());
363 for (
const auto& legDatum :
legData_) {
364 QL_REQUIRE(legDatum.currency() == ccy,
"Cross currency commodity swaps are not supported");
369 const LegData& legDatum,
const string& configuration) {
371 auto legBuilder = ef->legBuilder(legDatum.
legType());
372 Leg leg = legBuilder->buildLeg(legDatum, ef,
requiredFixings_, configuration);
373 legs_.push_back(leg);
Engine builder for commodity swaps.
void buildLeg(const QuantLib::ext::shared_ptr< ore::data::EngineFactory > &ef, const ore::data::LegData &legDatum, const std::string &configuration)
std::vector< ore::data::LegData > legData_
virtual void fromXML(ore::data::XMLNode *node) override
QuantLib::Real notional() const override
Return the current notional in npvCurrency. See individual sub-classes for the precise definition.
virtual ore::data::XMLNode * toXML(ore::data::XMLDocument &doc) const override
QuantLib::ext::shared_ptr< ore::data::LegData > createLegData() const
void build(const QuantLib::ext::shared_ptr< ore::data::EngineFactory > &) override
std::map< ore::data::AssetClass, std::set< std::string > > underlyingIndices(const QuantLib::ext::shared_ptr< ore::data::ReferenceDataManager > &referenceDataManager=nullptr) const override
Add underlying Commodity names.
const std::map< std::string, boost::any > & additionalData() const override
returns all additional data returned by the trade once built
Serializable object holding leg data.
const string & currency() const
const string & legType() const
std::vector< bool > legPayers_
std::vector< string > legCurrencies_
std::vector< QuantLib::Leg > legs_
virtual void fromXML(XMLNode *node) override
void setSensitivityTemplate(const EngineBuilder &builder)
virtual XMLNode * toXML(XMLDocument &doc) const override
RequiredFixings requiredFixings_
QuantLib::ext::shared_ptr< InstrumentWrapper > instrument_
void reset()
Reset trade, clear all base class data. This does not reset accumulated timings for this trade.
std::map< std::string, boost::any > additionalData_
Small XML Document wrapper class.
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
static vector< XMLNode * > getChildrenNodes(XMLNode *node, const string &name)
Returns all the children with a given name.
static XMLNode * getChildNode(XMLNode *n, const string &name="")
static void appendNode(XMLNode *parent, XMLNode *child)
leg data for commodity leg types
Commodity Swap data model and serialization.
Logic for calculating required fixing dates on legs.
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
QuantLib::ext::shared_ptr< Index > parseIndex(const string &s)
Convert std::string to QuantLib::Index.
leg data model and serialization
Classes and functions for log message handling.
#define LOG(text)
Logging Macro (Level = Notice)
#define DLOG(text)
Logging Macro (Level = Debug)
#define ALOG(text)
Logging Macro (Level = Alert)
boost::shared_ptr< CashFlow > unpackIndexWrappedCashFlow(const boost::shared_ptr< CashFlow > &c)
RandomVariable max(RandomVariable x, const RandomVariable &y)
Size size(const ValueType &v)
Real originalNotional(const Leg &leg)
std::string to_string(const LocationInfo &l)
Serializable Credit Default Swap.
Map text representations to QuantLib/QuantExt types.
trade schedule data model and serialization
string conversion utilities