Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
commodityoption.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
20
21#include <boost/make_shared.hpp>
22
23#include <ql/errors.hpp>
24#include <ql/exercise.hpp>
25#include <ql/instruments/compositeinstrument.hpp>
26#include <ql/instruments/vanillaoption.hpp>
28
32
33using namespace std;
34using namespace QuantLib;
37
38namespace ore {
39namespace data {
40
42
43CommodityOption::CommodityOption(const Envelope& env, const OptionData& optionData, const string& commodityName,
44 const string& currency, Real quantity, TradeStrike strike,
45 const boost::optional<bool>& isFuturePrice, const Date& futureExpiryDate)
46 : VanillaOptionTrade(env, AssetClass::COM, optionData, commodityName, currency, quantity, strike),
47 isFuturePrice_(isFuturePrice), futureExpiryDate_(futureExpiryDate) {
48 tradeType_ = "CommodityOption";
49}
50
51void CommodityOption::build(const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory) {
52
53 // ISDA taxonomy, assuming Commodity follows the Equity template
54 additionalData_["isdaAssetClass"] = std::string("Commodity");
55 additionalData_["isdaBaseProduct"] = std::string("Option");
56 additionalData_["isdaSubProduct"] = std::string("Price Return Basic Performance");
57 // skip the transaction level mapping for now
58 additionalData_["isdaTransaction"] = std::string("");
59
60 additionalData_["quantity"] = quantity_;
61 additionalData_["strike"] = strike_.value();
62 additionalData_["strikeCurrency"] = currency_;
63
64 // Checks
65 QL_REQUIRE((strike_.value() > 0) || close_enough(strike_.value(),0.0), "Commodity option requires a non-negative strike");
66 if (close_enough(strike_.value(), 0.0)) {
67 strike_.setValue(0.0);
68 }
69
70 // This is called in VanillaOptionTrade::build(), but we want to call it first here,
71 // in case the build fails before it reaches VanillaOptionTrade::build()
73
74 // Populate the index_ in case the option is automatic exercise.
75 // Intentionally use null calendar because we will ask for index value on the expiry date without adjustment.
76 const QuantLib::ext::shared_ptr<Market>& market = engineFactory->market();
77 index_ = *market->commodityIndex(assetName_, engineFactory->configuration(MarketContext::pricing));
79
80 // Assume future price if isFuturePrice_ is not explicitly set or if it is and true.
81
82 auto index = *market->commodityIndex(assetName_, engineFactory->configuration(MarketContext::pricing));
83
84 // If we are given an explicit future contract expiry date, use it, otherwise use option's expiry.
85 Date expiryDate;
86 if (futureExpiryDate_ != Date()) {
87 expiryDate = futureExpiryDate_;
88 } else {
89 // Get the expiry date of the option. This is the expiry date of the commodity future index.
90 const vector<string>& expiryDates = option_.exerciseDates();
91 QL_REQUIRE(expiryDates.size() == 1,
92 "Expected exactly one expiry date for CommodityOption but got " << expiryDates.size() << ".");
93 expiryDate = parseDate(expiryDates[0]);
94 }
95
96 // Clone the index with the relevant expiry date.
97 index_ = index->clone(expiryDate);
98
99 // Set the VanillaOptionTrade forwardDate_ if the index is a CommodityFuturesIndex - we possibly still have a
100 // CommoditySpotIndex at this point so check. Also, will only work for European exercise.
101 auto et = parseExerciseType(option_.style());
102 if (et == Exercise::European && QuantLib::ext::dynamic_pointer_cast<CommodityFuturesIndex>(index_)) {
103 forwardDate_ = expiryDate;
104 }
105
106 }
107
108 VanillaOptionTrade::build(engineFactory);
109
110 // LOG the volatility if the trade expiry date is in the future.
111 if (expiryDate_ > Settings::instance().evaluationDate()) {
112 DLOG("Implied vol for " << tradeType_ << " on " << assetName_ << " with expiry " << expiryDate_
113 << " and strike " << strike_.value() << " is "
114 << market->commodityVolatility(assetName_)->blackVol(expiryDate_, strike_.value()));
115 }
116}
117
118std::map<AssetClass, std::set<std::string>>
119CommodityOption::underlyingIndices(const QuantLib::ext::shared_ptr<ReferenceDataManager>& referenceDataManager) const {
120 return {{AssetClass::COM, std::set<std::string>({assetName_})}};
121}
122
124
125 Trade::fromXML(node);
126
127 XMLNode* commodityNode = XMLUtils::getChildNode(node, "CommodityOptionData");
128 QL_REQUIRE(commodityNode, "A commodity option needs a 'CommodityOptionData' node");
129
130 option_.fromXML(XMLUtils::getChildNode(commodityNode, "OptionData"));
131
132 assetName_ = XMLUtils::getChildValue(commodityNode, "Name", true);
133 currency_ = XMLUtils::getChildValue(commodityNode, "Currency", true);
134 strike_.fromXML(commodityNode);
135 quantity_ = XMLUtils::getChildValueAsDouble(commodityNode, "Quantity", true);
136
137 isFuturePrice_ = boost::none;
138 if (XMLNode* n = XMLUtils::getChildNode(commodityNode, "IsFuturePrice"))
140
141 futureExpiryDate_ = Date();
142 if (XMLNode* n = XMLUtils::getChildNode(commodityNode, "FutureExpiryDate"))
144}
145
147
148 XMLNode* node = Trade::toXML(doc);
149
150 XMLNode* eqNode = doc.allocNode("CommodityOptionData");
151 XMLUtils::appendNode(node, eqNode);
152
153 XMLUtils::appendNode(eqNode, option_.toXML(doc));
154
155 XMLUtils::addChild(doc, eqNode, "Name", assetName_);
156 XMLUtils::addChild(doc, eqNode, "Currency", currency_);
157 XMLUtils::appendNode(eqNode, strike_.toXML(doc));
158 XMLUtils::addChild(doc, eqNode, "Quantity", quantity_);
159
160 if (isFuturePrice_)
161 XMLUtils::addChild(doc, eqNode, "IsFuturePrice", *isFuturePrice_);
162
163 if (futureExpiryDate_ != Date())
164 XMLUtils::addChild(doc, eqNode, "FutureExpiryDate", to_string(futureExpiryDate_));
165
166 return node;
167}
168
169} // namespace data
170} // namespace ore
std::map< AssetClass, std::set< std::string > > underlyingIndices(const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceDataManager=nullptr) const override
Add underlying Commodity names.
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
void build(const QuantLib::ext::shared_ptr< EngineFactory > &engineFactory) override
Build underlying instrument and link pricing engine.
CommodityOption()
Default constructor.
boost::optional< bool > isFuturePrice_
Serializable object holding generic trade data, reporting dimensions.
Definition: envelope.hpp:51
Serializable object holding option data.
Definition: optiondata.hpp:42
const string & style() const
Definition: optiondata.hpp:74
virtual void fromXML(XMLNode *node) override
Definition: optiondata.cpp:32
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: optiondata.cpp:86
const vector< string > & exerciseDates() const
Definition: optiondata.hpp:76
virtual void fromXML(XMLNode *node) override
Definition: trade.cpp:34
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: trade.cpp:46
string tradeType_
Definition: trade.hpp:196
std::map< std::string, boost::any > additionalData_
Definition: trade.hpp:224
XMLNode * toXML(XMLDocument &doc) const
Definition: tradestrike.cpp:86
void fromXML(XMLNode *node, const bool isRequired=true, const bool allowYieldStrike=false)
Definition: tradestrike.cpp:50
QuantLib::Real value() const
void setValue(const QuantLib::Real &value)
Serializable Vanilla Option.
QuantLib::Date expiryDate_
Store the option expiry date.
QuantLib::Date forwardDate_
Store the (optional) forward date.
QuantLib::ext::shared_ptr< QuantLib::Index > index_
An index is needed if the option is to be automatically exercised on expiry.
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
Build QuantLib/QuantExt instrument, link pricing engine.
Small XML Document wrapper class.
Definition: xmlutils.hpp:65
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
Definition: xmlutils.cpp:132
static Real getChildValueAsDouble(XMLNode *node, const string &name, bool mandatory=false, double defaultValue=0.0)
Definition: xmlutils.cpp:286
static string getChildValue(XMLNode *node, const string &name, bool mandatory=false, const string &defaultValue=string())
Definition: xmlutils.cpp:277
static XMLNode * getChildNode(XMLNode *n, const string &name="")
Definition: xmlutils.cpp:387
static string getNodeValue(XMLNode *node)
Get a node's value.
Definition: xmlutils.cpp:489
static XMLNode * addChild(XMLDocument &doc, XMLNode *n, const string &name)
Definition: xmlutils.cpp:181
static void appendNode(XMLNode *parent, XMLNode *child)
Definition: xmlutils.cpp:406
Commodity option representation.
Pricing Engine Factory.
Exercise::Type parseExerciseType(const std::string &s)
Convert text to QuantLib::Exercise::Type.
Definition: parsers.cpp:466
Date parseDate(const string &s)
Convert std::string to QuantLib::Date.
Definition: parsers.cpp:51
bool parseBool(const string &s)
Convert text to bool.
Definition: parsers.cpp:144
Classes and functions for log message handling.
@ data
Definition: log.hpp:77
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
std::string to_string(const LocationInfo &l)
Definition: ast.cpp:28
Serializable Credit Default Swap.
Definition: namespaces.docs:23
string conversion utilities