Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
commodityforward.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2018 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19#include <boost/make_shared.hpp>
20
21#include <ql/errors.hpp>
23
30
33using namespace QuantLib;
34using namespace std;
35
36namespace ore {
37namespace data {
38
39CommodityForward::CommodityForward() : Trade("CommodityForward"), quantity_(0.0), strike_(0.0) {}
40
41CommodityForward::CommodityForward(const Envelope& envelope, const string& position, const string& commodityName,
42 const string& currency, Real quantity, const string& maturityDate, Real strike)
43 : Trade("CommodityForward", envelope), position_(position), commodityName_(commodityName), currency_(currency),
44 quantity_(quantity), maturityDate_(maturityDate), strike_(strike),
45 fixingDate_(Date()), fxIndex_(""), payCcy_(currency){}
46
47CommodityForward::CommodityForward(const Envelope& envelope, const string& position, const string& commodityName,
48 const string& currency, Real quantity, const string& maturityDate, Real strike,
49 const Date& futureExpiryDate, const boost::optional<bool>& physicallySettled,
50 const Date& paymentDate)
51 : Trade("CommodityForward", envelope), position_(position), commodityName_(commodityName), currency_(currency),
52 quantity_(quantity), maturityDate_(maturityDate), strike_(strike), isFuturePrice_(true),
53 futureExpiryDate_(futureExpiryDate), physicallySettled_(physicallySettled), paymentDate_(paymentDate),
54 fixingDate_(Date()), fxIndex_(""), payCcy_(currency) {}
55
56CommodityForward::CommodityForward(const Envelope& envelope, const string& position, const string& commodityName,
57 const string& currency, Real quantity, const string& maturityDate, Real strike,
58 const Period& futureExpiryOffset, const Calendar& offsetCalendar,
59 const boost::optional<bool>& physicallySettled,
60 const Date& paymentDate)
61 : Trade("CommodityForward", envelope), position_(position), commodityName_(commodityName), currency_(currency),
62 quantity_(quantity), maturityDate_(maturityDate), strike_(strike), isFuturePrice_(true),
63 futureExpiryOffset_(futureExpiryOffset), offsetCalendar_(offsetCalendar), physicallySettled_(physicallySettled),
64 paymentDate_(paymentDate),
65 fixingDate_(Date()), fxIndex_(""), payCcy_(currency){}
66
67void CommodityForward::build(const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory) {
68
69 // ISDA taxonomy
70 additionalData_["isdaAssetClass"] = string("Commodity");
71 additionalData_["isdaBaseProduct"] = string("Forward");
72 additionalData_["isdaSubProduct"] = string("Price Return Basic Performance");
73 // skip the transaction level mapping for now
74 additionalData_["isdaTransaction"] = string("");
75
76 // Create the underlying commodity index for the forward
77 const QuantLib::ext::shared_ptr<Market>& market = engineFactory->market();
78 QuantLib::ext::shared_ptr<QuantExt::FxIndex> fxIndex = nullptr;
79
80 npvCurrency_ = fixingDate_ == Date() ? currency_ : payCcy_;
81
82 // notional_ = strike_ * quantity_;
83 notional_ = strike_ * quantity_;
84 notionalCurrency_ = currency_;
85
86 additionalData_["quantity"] = quantity_;
87 additionalData_["strike"] = strike_;
88 additionalData_["strikeCurrency"] = currency_;
89 if (fixingDate_ != Date()) {
90 additionalData_["settlementCurrency"] = payCcy_;
91 additionalData_["fixingDate"] = fixingDate_;
92 additionalData_["fxIndex"] = fxIndex;
93 }
94
95 maturity_ = parseDate(maturityDate_);
96 auto index = *market->commodityIndex(commodityName_, engineFactory->configuration(MarketContext::pricing));
97 bool isFutureAccordingToConventions = InstrumentConventions::instance().conventions()->has(commodityName_, Convention::Type::CommodityFuture);
98
99 // adjust the maturity date if not a valid fixing date for the index
100 maturity_ = index->fixingCalendar().adjust(maturity_, Preceding);
101
102 if ((isFuturePrice_ && *isFuturePrice_) || isFutureAccordingToConventions) {
103
104 // Get the commodity index from the market.
105 index = *market->commodityIndex(commodityName_, engineFactory->configuration(MarketContext::pricing));
106
107 // May have been given an explicit future expiry date or an offset and calendar or neither.
108 Date expiryDate = maturity_;
109 if (futureExpiryDate_ != Date()) {
110 expiryDate = futureExpiryDate_;
111 } else if (futureExpiryOffset_ != Period()) {
112 Calendar cal = offsetCalendar_.empty() ? NullCalendar() : offsetCalendar_;
113 expiryDate = cal.advance(maturity_, futureExpiryOffset_);
114 }
115
116 // Clone the index with the relevant expiry date.
117 index = index->clone(expiryDate);
118 }
119
121 bool physicallySettled = true;
123 // If cash settled and given a payment date that is not greater than the maturity date, set it equal to the
124 // maturity date and log a warning to continue processing.
125 physicallySettled = false;
126 if (paymentDate_ != Date() && paymentDate_ < maturity_) {
127 WLOG("Commodity forward " << id() << " has payment date (" << io::iso_date(paymentDate_) <<
128 ") before the maturity date (" << io::iso_date(maturity_) << "). Setting payment date" <<
129 " equal to the maturity date.");
130 paymentDate = maturity_;
131 }
132 } else {
133 // If physically settled and given a payment date, log a warning that it is ignored.
134 if (paymentDate_ != Date()) {
135 WLOG("Commodity forward " << id() << " supplies a payment date (" << io::iso_date(paymentDate_) <<
136 ") but is physically settled. The payment date is ignored.");
137 paymentDate = Date();
138 }
139 }
140
141 // add required commodity fixing
142 DLOG("commodity forward " << id() << " paymentDate is " << paymentDate);
143 requiredFixings_.addFixingDate(maturity_, index->name(),
144 paymentDate == Date() ? maturity_ : paymentDate);
145
146 // Create the commodity forward instrument
147 Currency currency = parseCurrency(currency_);
148 Position::Type position = parsePositionType(position_);
149 auto payCcy = Currency();
150 if(!fxIndex_.empty()){
152 requiredFixings_.addFixingDate( fixingDate_, fxIndex_, paymentDate);
153 fxIndex = buildFxIndex(fxIndex_, currency.code(), payCcy.code(), engineFactory->market(),
154 engineFactory->configuration(MarketContext::pricing));
155 npvCurrency_ = payCcy_;
156 }
157 QuantLib::ext::shared_ptr<Instrument> commodityForward = QuantLib::ext::make_shared<QuantExt::CommodityForward>(
160
161 // Pricing engine
162 QuantLib::ext::shared_ptr<EngineBuilder> builder = engineFactory->builder(tradeType_);
163 QL_REQUIRE(builder, "No builder found for " << tradeType_);
164 QuantLib::ext::shared_ptr<CommodityForwardEngineBuilder> commodityForwardEngineBuilder =
165 QuantLib::ext::dynamic_pointer_cast<CommodityForwardEngineBuilder>(builder);
166 commodityForward->setPricingEngine(commodityForwardEngineBuilder->engine(currency)); // the engine accounts for NDF if settlement data are present
167 setSensitivityTemplate(*commodityForwardEngineBuilder);
168
169 // set up other Trade details
170 instrument_ = QuantLib::ext::make_shared<VanillaInstrument>(commodityForward);
171}
172
173Real CommodityForward::notional() const { return notional_; }
174
175std::map<AssetClass, std::set<std::string>>
176CommodityForward::underlyingIndices(const QuantLib::ext::shared_ptr<ReferenceDataManager>& referenceDataManager) const {
177 return {{AssetClass::COM, std::set<std::string>({commodityName_})}};
178}
179
180void CommodityForward::fromXML(XMLNode* node) {
181
182 Trade::fromXML(node);
183 XMLNode* commodityDataNode = XMLUtils::getChildNode(node, "CommodityForwardData");
184
185 position_ = XMLUtils::getChildValue(commodityDataNode, "Position", true);
186 commodityName_ = XMLUtils::getChildValue(commodityDataNode, "Name", true);
187 currency_ = XMLUtils::getChildValue(commodityDataNode, "Currency", true);
188 quantity_ = XMLUtils::getChildValueAsDouble(commodityDataNode, "Quantity", true);
189 maturityDate_ = XMLUtils::getChildValue(commodityDataNode, "Maturity", true);
190 strike_ = XMLUtils::getChildValueAsDouble(commodityDataNode, "Strike", true);
191
192 isFuturePrice_ = boost::none;
193 if (XMLNode* n = XMLUtils::getChildNode(commodityDataNode, "IsFuturePrice"))
194 isFuturePrice_ = parseBool(XMLUtils::getNodeValue(n));
195
196 futureExpiryDate_ = Date();
197 if (XMLNode* n = XMLUtils::getChildNode(commodityDataNode, "FutureExpiryDate"))
198 futureExpiryDate_ = parseDate(XMLUtils::getNodeValue(n));
199
200 // If not given an explicit future expiry date, check for offset and calendar.
201 if (futureExpiryDate_ == Date()) {
202 futureExpiryOffset_ = Period();
203 if (XMLNode* n = XMLUtils::getChildNode(commodityDataNode, "FutureExpiryOffset"))
204 futureExpiryOffset_ = parsePeriod(XMLUtils::getNodeValue(n));
205
206 offsetCalendar_ = Calendar();
207 if (XMLNode* n = XMLUtils::getChildNode(commodityDataNode, "FutureExpiryOffsetCalendar"))
208 offsetCalendar_ = parseCalendar(XMLUtils::getNodeValue(n));
209 }
210
211 physicallySettled_ = boost::none;
212 if (XMLNode* n = XMLUtils::getChildNode(commodityDataNode, "PhysicallySettled"))
213 physicallySettled_ = parseBool(XMLUtils::getNodeValue(n));
214
215 paymentDate_ = Date();
216 if (XMLNode* n = XMLUtils::getChildNode(commodityDataNode, "PaymentDate"))
217 paymentDate_ = parseDate(XMLUtils::getNodeValue(n));
218
219 if (XMLNode* settlementDataNode = XMLUtils::getChildNode(commodityDataNode, "SettlementData")) {
220 // this node is used to provide data for NDF. This includes a fixing date, a settlement currency and the
221 // quote/settlement fx index.
222 payCcy_ = XMLUtils::getChildValue(settlementDataNode, "PayCurrency", true);
223 fxIndex_ = XMLUtils::getChildValue(settlementDataNode, "FXIndex", true);
224 fixingDate_ = parseDate(XMLUtils::getChildValue(settlementDataNode, "FixingDate", true));
225 }
226}
227
228XMLNode* CommodityForward::toXML(XMLDocument& doc) const {
229
230 XMLNode* node = Trade::toXML(doc);
231 XMLNode* commodityDataNode = doc.allocNode("CommodityForwardData");
232 XMLUtils::appendNode(node, commodityDataNode);
233
234 XMLUtils::addChild(doc, commodityDataNode, "Position", position_);
235 XMLUtils::addChild(doc, commodityDataNode, "Maturity", maturityDate_);
236 XMLUtils::addChild(doc, commodityDataNode, "Name", commodityName_);
237 XMLUtils::addChild(doc, commodityDataNode, "Currency", currency_);
238 XMLUtils::addChild(doc, commodityDataNode, "Strike", strike_);
239 XMLUtils::addChild(doc, commodityDataNode, "Quantity", quantity_);
240
241 if (isFuturePrice_)
242 XMLUtils::addChild(doc, commodityDataNode, "IsFuturePrice", *isFuturePrice_);
243
244 if (futureExpiryDate_ != Date())
245 XMLUtils::addChild(doc, commodityDataNode, "FutureExpiryDate", to_string(futureExpiryDate_));
246
247 if (futureExpiryOffset_ != Period())
248 XMLUtils::addChild(doc, commodityDataNode, "FutureExpiryOffset", to_string(futureExpiryOffset_));
249
250 if (offsetCalendar_ != Calendar())
251 XMLUtils::addChild(doc, commodityDataNode, "FutureExpiryOffsetCalendar", to_string(offsetCalendar_));
252
254 XMLUtils::addChild(doc, commodityDataNode, "PhysicallySettled", *physicallySettled_);
255
256 if (paymentDate_ != Date())
257 XMLUtils::addChild(doc, commodityDataNode, "PaymentDate", to_string(paymentDate_));
258
259 if(fixingDate_!=Date()){ //NDF
260 XMLNode* settlementDataNode = doc.allocNode("SettlementData");
261 XMLUtils::appendNode(commodityDataNode, settlementDataNode);
262 XMLUtils::addChild(doc, settlementDataNode, "PayCurrency", payCcy_);
263 XMLUtils::addChild(doc, settlementDataNode, "FXIndex", fxIndex_);
264 XMLUtils::addChild(doc, settlementDataNode, "FixingDate", to_string(fixingDate_));
265 }
266
267 return node;
268}
269
270} // namespace data
271} // namespace ore
Engine builder for commodity forward.
const boost::shared_ptr< CommodityIndex > & index() const
QuantLib::Currency currency_
QuantLib::Date paymentDate_
QuantLib::Position::Type position() const
boost::shared_ptr< QuantExt::FxIndex > fxIndex() const
const QuantLib::Currency & currency() const
const QuantLib::Date & paymentDate() const
boost::shared_ptr< FxIndex > fxIndex_
QuantLib::Position::Type position_
QuantLib::Date maturityDate_
Currency payCcy() const
bool physicallySettled() const
CommodityForward()
Default constructor.
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
Serializable object holding generic trade data, reporting dimensions.
Definition: envelope.hpp:51
Trade base class.
Definition: trade.hpp:55
Small XML Document wrapper class.
Definition: xmlutils.hpp:65
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
Definition: xmlutils.cpp:132
Pricing Engine Factory.
Calendar parseCalendar(const string &s)
Convert text to QuantLib::Calendar.
Definition: parsers.cpp:157
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
Period parsePeriod(const string &s)
Convert text to QuantLib::Period.
Definition: parsers.cpp:171
bool parseBool(const string &s)
Convert text to bool.
Definition: parsers.cpp:144
@ data
Definition: log.hpp:77
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
#define WLOG(text)
Logging Macro (Level = Warning)
Definition: log.hpp:550
market data related utilties
An implementation of the Market class that stores the required objects in maps.
std::string to_string(const LocationInfo &l)
Definition: ast.cpp:28
QuantLib::ext::shared_ptr< QuantExt::FxIndex > buildFxIndex(const string &fxIndex, const string &domestic, const string &foreign, const QuantLib::ext::shared_ptr< Market > &market, const string &configuration, bool useXbsCurves)
Definition: marketdata.cpp:137
Serializable Credit Default Swap.
Definition: namespaces.docs:23
string conversion utilities