Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Public Member Functions | List of all members
CommodityOptionStrip Class Reference

#include <ored/portfolio/commodityoptionstrip.hpp>

+ Inheritance diagram for CommodityOptionStrip:
+ Collaboration diagram for CommodityOptionStrip:

Public Member Functions

 CommodityOptionStrip ()
 
 CommodityOptionStrip (const ore::data::Envelope &envelope, const ore::data::LegData &legData, const std::vector< QuantLib::Position::Type > &callPositions, const std::vector< QuantLib::Real > &callStrikes, const std::vector< QuantLib::Position::Type > &putPositions, const std::vector< QuantLib::Real > &putStrikes, QuantLib::Real premium=0.0, const std::string &premiumCurrency="", const QuantLib::Date &premiumPayDate=QuantLib::Date(), const std::string &style="", const std::string &settlement="", const BarrierData &callBarrierData={}, const BarrierData &putBarrierData={}, const std::string &fxIndex="", const bool isDigital=false, Real payoffPerUnit=0.0)
 
void build (const QuantLib::ext::shared_ptr< ore::data::EngineFactory > &engineFactory) override
 Implement the build method. More...
 
std::map< ore::data::AssetClass, std::set< std::string > > underlyingIndices (const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceDataManager=nullptr) const override
 Add underlying Commodity names. More...
 
Inspectors
const ore::data::LegDatalegData () const
 
const std::vector< QuantLib::Position::Type > & callPositions () const
 
const std::vector< QuantLib::Real > & callStrikes () const
 
const std::vector< QuantLib::Position::Type > & putPositions () const
 
const std::vector< QuantLib::Real > & putStrikes () const
 
const PremiumDatapremiumDate () const
 
const std::string & style () const
 
const std::string & settlement () const
 
const std::string & fxIndex () const
 
const BarrierDatacallBarrierData () const
 
const BarrierDataputBarrierData () const
 
const bool isDigital () const
 
const Real payoffPerUnit () const
 
Serialisation
virtual void fromXML (ore::data::XMLNode *node) override
 
virtual ore::data::XMLNodetoXML (ore::data::XMLDocument &doc) const override
 
- Public Member Functions inherited from Trade
 Trade ()
 Default constructor. More...
 
 Trade (const string &tradeType, const Envelope &env=Envelope(), const TradeActions &ta=TradeActions())
 Base class constructor. More...
 
virtual ~Trade ()
 Default destructor. More...
 
virtual void build (const QuantLib::ext::shared_ptr< EngineFactory > &)=0
 
virtual std::map< std::string, RequiredFixings::FixingDatesfixings (const QuantLib::Date &settlementDate=QuantLib::Date()) const
 
const RequiredFixingsrequiredFixings () const
 
virtual std::map< AssetClass, std::set< std::string > > underlyingIndices (const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceDataManager=nullptr) const
 
void reset ()
 Reset trade, clear all base class data. This does not reset accumulated timings for this trade. More...
 
void resetPricingStats (const std::size_t numberOfPricings=0, const boost::timer::nanosecond_type cumulativePricingTime=0)
 Reset accumulated timings to given values. More...
 
string & id ()
 Set the trade id. More...
 
void setEnvelope (const Envelope &envelope)
 Set the envelope with counterparty and portfolio info. More...
 
void setAdditionalData (const std::map< std::string, boost::any > &additionalData)
 
TradeActionstradeActions ()
 Set the trade actions. More...
 
const string & id () const
 
const string & tradeType () const
 
const Envelopeenvelope () const
 
const set< string > & portfolioIds () const
 
const TradeActionstradeActions () const
 
const QuantLib::ext::shared_ptr< InstrumentWrapper > & instrument () const
 
const std::vector< QuantLib::Leg > & legs () const
 
const std::vector< string > & legCurrencies () const
 
const std::vector< bool > & legPayers () const
 
const string & npvCurrency () const
 
virtual QuantLib::Real notional () const
 Return the current notional in npvCurrency. See individual sub-classes for the precise definition. More...
 
virtual string notionalCurrency () const
 
const Date & maturity () const
 
virtual bool isExpired (const Date &d)
 
const string & issuer () const
 
template<typename T >
additionalDatum (const std::string &tag) const
 returns any additional datum. More...
 
virtual const std::map< std::string, boost::any > & additionalData () const
 returns all additional data returned by the trade once built More...
 
const std::string & sensitivityTemplate () const
 
void validate () const
 Utility to validate that everything that needs to be set in this base class is actually set. More...
 
boost::timer::nanosecond_type getCumulativePricingTime () const
 Get cumulative timing spent on pricing. More...
 
std::size_t getNumberOfPricings () const
 Get number of pricings. More...
 
- Public Member Functions inherited from XMLSerializable
virtual ~XMLSerializable ()
 
virtual void fromXML (XMLNode *node)=0
 
virtual XMLNodetoXML (XMLDocument &doc) const =0
 
void fromFile (const std::string &filename)
 
void toFile (const std::string &filename) const
 
void fromXMLString (const std::string &xml)
 Parse from XML string. More...
 
std::string toXMLString () const
 Parse from XML string. More...
 

Trade

ore::data::LegData legData_
 
std::vector< QuantLib::Position::Type > callPositions_
 
std::vector< QuantLib::Real > callStrikes_
 
std::vector< QuantLib::Position::Type > putPositions_
 
std::vector< QuantLib::Real > putStrikes_
 
PremiumData premiumData_
 
std::string style_
 
std::string settlement_
 
BarrierData callBarrierData_
 
BarrierData putBarrierData_
 
std::string fxIndex_
 
bool isDigital_
 
Real unaryPayoff_
 
QuantLib::ext::shared_ptr< CommodityFloatingLegDatacommLegData_
 
bool hasCashflows () const override
 
void buildAPOs (const QuantLib::Leg &leg, const QuantLib::ext::shared_ptr< ore::data::EngineFactory > &engineFactory)
 Build an average price option strip. More...
 
void buildStandardOptions (const QuantLib::Leg &leg, const QuantLib::ext::shared_ptr< ore::data::EngineFactory > &engineFactory)
 Build a standard option strip. More...
 
void check (QuantLib::Size numberPeriods) const
 Perform checks before building. More...
 

Additional Inherited Members

- Protected Member Functions inherited from Trade
Date addPremiums (std::vector< QuantLib::ext::shared_ptr< Instrument > > &instruments, std::vector< Real > &multipliers, const Real tradeMultiplier, const PremiumData &premiumData, const Real premiumMultiplier, const Currency &tradeCurrency, const QuantLib::ext::shared_ptr< EngineFactory > &factory, const string &configuration)
 
void setLegBasedAdditionalData (const Size legNo, Size resultLegId=Null< Size >()) const
 
void setSensitivityTemplate (const EngineBuilder &builder)
 
void setSensitivityTemplate (const std::string &id)
 
- Protected Attributes inherited from Trade
string tradeType_
 
QuantLib::ext::shared_ptr< InstrumentWrapperinstrument_
 
std::vector< QuantLib::Leg > legs_
 
std::vector< string > legCurrencies_
 
std::vector< boollegPayers_
 
string npvCurrency_
 
QuantLib::Real notional_
 
string notionalCurrency_
 
Date maturity_
 
string issuer_
 
string sensitivityTemplate_
 
bool sensitivityTemplateSet_ = false
 
std::size_t savedNumberOfPricings_ = 0
 
boost::timer::nanosecond_type savedCumulativePricingTime_ = 0
 
RequiredFixings requiredFixings_
 
std::map< std::string, boost::any > additionalData_
 

Detailed Description

Serializable Commodity option strip

Definition at line 38 of file commodityoptionstrip.hpp.

Constructor & Destructor Documentation

◆ CommodityOptionStrip() [1/2]

Definition at line 40 of file commodityoptionstrip.hpp.

40: ore::data::Trade("CommodityOptionStrip") {}
Trade base class.
Definition: trade.hpp:55

◆ CommodityOptionStrip() [2/2]

CommodityOptionStrip ( const ore::data::Envelope envelope,
const ore::data::LegData legData,
const std::vector< QuantLib::Position::Type > &  callPositions,
const std::vector< QuantLib::Real > &  callStrikes,
const std::vector< QuantLib::Position::Type > &  putPositions,
const std::vector< QuantLib::Real > &  putStrikes,
QuantLib::Real  premium = 0.0,
const std::string &  premiumCurrency = "",
const QuantLib::Date &  premiumPayDate = QuantLib::Date(),
const std::string &  style = "",
const std::string &  settlement = "",
const BarrierData callBarrierData = {},
const BarrierData putBarrierData = {},
const std::string &  fxIndex = "",
const bool  isDigital = false,
Real  payoffPerUnit = 0.0 
)

Member Function Documentation

◆ build()

void build ( const QuantLib::ext::shared_ptr< ore::data::EngineFactory > &  engineFactory)
override

Implement the build method.

Definition at line 84 of file commodityoptionstrip.cpp.

84 {
85
86 reset();
87
88 DLOG("CommodityOptionStrip::build() called for trade " << id());
89
90 // ISDA taxonomy, assuming Commodity follows the Equity template
91 additionalData_["isdaAssetClass"] = std::string("Commodity");
92 additionalData_["isdaBaseProduct"] = std::string("Option");
93 additionalData_["isdaSubProduct"] = std::string("Price Return Basic Performance");
94 // skip the transaction level mapping for now
95 additionalData_["isdaTransaction"] = std::string();
96
98
99 // Check that the leg data is of type CommodityFloating
100 auto conLegData = legData_.concreteLegData();
101 commLegData_ = QuantLib::ext::dynamic_pointer_cast<CommodityFloatingLegData>(conLegData);
102 QL_REQUIRE(commLegData_, "CommodityOptionStrip leg data should be of type CommodityFloating");
103 if(!commLegData_->fxIndex().empty())
104 fxIndex_= commLegData_->fxIndex();
105 // Build the commodity floating leg data
106 auto legBuilder = engineFactory->legBuilder(legData_.legType());
107 auto cflb = QuantLib::ext::dynamic_pointer_cast<CommodityFloatingLegBuilder>(legBuilder);
108 QL_REQUIRE(cflb, "Expected a CommodityFloatingLegBuilder for leg type " << legData_.legType());
109 Leg leg =
110 cflb->buildLeg(legData_, engineFactory, requiredFixings_, engineFactory->configuration(MarketContext::pricing));
111
112 // Perform checks
113 check(leg.size());
114
115 // We update the notional_ in either buildAPOs or buildStandardOptions below.
116 notional_ = Null<Real>();
117
118 // Build the strip of option trades
120
121 if (commLegData_->isAveraged() && !cflb->allAveraging()) {
122 buildAPOs(leg, engineFactory);
123 } else {
124 buildStandardOptions(leg, engineFactory);
125 }
126
127 // Add leg to legs_ so that fixings method can work.
128 legs_.push_back(leg);
129 legPayers_.push_back(false);
130 legCurrencies_.push_back(npvCurrency_);
131}
void buildAPOs(const QuantLib::Leg &leg, const QuantLib::ext::shared_ptr< ore::data::EngineFactory > &engineFactory)
Build an average price option strip.
QuantLib::ext::shared_ptr< CommodityFloatingLegData > commLegData_
void buildStandardOptions(const QuantLib::Leg &leg, const QuantLib::ext::shared_ptr< ore::data::EngineFactory > &engineFactory)
Build a standard option strip.
const string & currency() const
Definition: legdata.hpp:873
const string & legType() const
Definition: legdata.hpp:890
QuantLib::ext::shared_ptr< LegAdditionalData > concreteLegData() const
Definition: legdata.hpp:891
string npvCurrency_
Definition: trade.hpp:201
std::vector< bool > legPayers_
Definition: trade.hpp:200
std::vector< string > legCurrencies_
Definition: trade.hpp:199
std::vector< QuantLib::Leg > legs_
Definition: trade.hpp:198
QuantLib::Real notional_
Definition: trade.hpp:202
RequiredFixings requiredFixings_
Definition: trade.hpp:223
void reset()
Reset trade, clear all base class data. This does not reset accumulated timings for this trade.
Definition: trade.cpp:130
string notionalCurrency_
Definition: trade.hpp:203
std::map< std::string, boost::any > additionalData_
Definition: trade.hpp:224
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
+ Here is the call graph for this function:

◆ underlyingIndices()

std::map< ore::data::AssetClass, std::set< std::string > > underlyingIndices ( const QuantLib::ext::shared_ptr< ReferenceDataManager > &  referenceDataManager = nullptr) const
overridevirtual

Add underlying Commodity names.

Reimplemented from Trade.

Definition at line 134 of file commodityoptionstrip.cpp.

134 {
135 std::map<ore::data::AssetClass, std::set<std::string>> result;
136
137 set<string> indices = legData_.indices();
138 for (auto ind : indices) {
139 QuantLib::ext::shared_ptr<Index> index = parseIndex(ind);
140 // only handle commodity
141 if (auto ci = QuantLib::ext::dynamic_pointer_cast<QuantExt::CommodityIndex>(index)) {
142 result[ore::data::AssetClass::COM].insert(ci->name());
143 }
144 }
145 return result;
146}
const std::set< std::string > & indices() const
Definition: legdata.hpp:892
QuantLib::ext::shared_ptr< Index > parseIndex(const string &s)
Convert std::string to QuantLib::Index.
+ Here is the call graph for this function:

◆ legData()

const ore::data::LegData & legData ( ) const

Definition at line 64 of file commodityoptionstrip.hpp.

64{ return legData_; }

◆ callPositions()

const std::vector< QuantLib::Position::Type > & callPositions ( ) const

Definition at line 65 of file commodityoptionstrip.hpp.

65{ return callPositions_; }
std::vector< QuantLib::Position::Type > callPositions_

◆ callStrikes()

const std::vector< QuantLib::Real > & callStrikes ( ) const

Definition at line 66 of file commodityoptionstrip.hpp.

66{ return callStrikes_; }
std::vector< QuantLib::Real > callStrikes_

◆ putPositions()

const std::vector< QuantLib::Position::Type > & putPositions ( ) const

Definition at line 67 of file commodityoptionstrip.hpp.

67{ return putPositions_; }
std::vector< QuantLib::Position::Type > putPositions_

◆ putStrikes()

const std::vector< QuantLib::Real > & putStrikes ( ) const

Definition at line 68 of file commodityoptionstrip.hpp.

68{ return putStrikes_; }
std::vector< QuantLib::Real > putStrikes_

◆ premiumDate()

const PremiumData & premiumDate ( ) const

Definition at line 69 of file commodityoptionstrip.hpp.

◆ style()

const std::string & style ( ) const

Definition at line 70 of file commodityoptionstrip.hpp.

+ Here is the caller graph for this function:

◆ settlement()

const std::string & settlement ( ) const

Definition at line 71 of file commodityoptionstrip.hpp.

+ Here is the caller graph for this function:

◆ fxIndex()

const std::string & fxIndex ( ) const

Definition at line 72 of file commodityoptionstrip.hpp.

72{ return fxIndex_; }

◆ callBarrierData()

const BarrierData & callBarrierData ( ) const

Definition at line 73 of file commodityoptionstrip.hpp.

◆ putBarrierData()

const BarrierData & putBarrierData ( ) const

Definition at line 74 of file commodityoptionstrip.hpp.

◆ isDigital()

const bool isDigital ( ) const

Definition at line 75 of file commodityoptionstrip.hpp.

+ Here is the caller graph for this function:

◆ payoffPerUnit()

const Real payoffPerUnit ( ) const

Definition at line 76 of file commodityoptionstrip.hpp.

+ Here is the caller graph for this function:

◆ fromXML()

void fromXML ( ore::data::XMLNode node)
overridevirtual

Reimplemented from Trade.

Definition at line 148 of file commodityoptionstrip.cpp.

148 {
149
150 Trade::fromXML(node);
151
152 XMLNode* stripNode = XMLUtils::getChildNode(node, "CommodityOptionStripData");
153 QL_REQUIRE(stripNode, "No CommodityOptionStripData Node");
154
155 legData_.fromXML(XMLUtils::getChildNode(stripNode, "LegData"));
156
157 if (XMLNode* n = XMLUtils::getChildNode(stripNode, "Calls")) {
158 vector<string> ls = XMLUtils::getChildrenValues(n, "LongShorts", "LongShort", false);
159 callPositions_ = parseVectorOfValues<Position::Type>(ls, &parsePositionType);
160 callStrikes_ = XMLUtils::getChildrenValuesAsDoubles(n, "Strikes", "Strike", false);
161 if (XMLNode* n2 = XMLUtils::getChildNode(n, "BarrierData")) {
163 }
164 }
165
166 if (XMLNode* n = XMLUtils::getChildNode(stripNode, "Puts")) {
167 vector<string> ls = XMLUtils::getChildrenValues(n, "LongShorts", "LongShort", false);
168 putPositions_ = parseVectorOfValues<Position::Type>(ls, &parsePositionType);
169 putStrikes_ = XMLUtils::getChildrenValuesAsDoubles(n, "Strikes", "Strike", false);
170 if (XMLNode* n2 = XMLUtils::getChildNode(n, "BarrierData")) {
172 }
173 }
174 premiumData_.fromXML(stripNode);
175 style_ = "";
176 if (XMLNode* n = XMLUtils::getChildNode(stripNode, "Style"))
178
179 settlement_ = "";
180 if (XMLNode* n = XMLUtils::getChildNode(stripNode, "Settlement"))
182
183 isDigital_ = false;
184 if (XMLNode* n = XMLUtils::getChildNode(stripNode, "IsDigital") )
186 if (isDigital_) {
187 XMLNode* n = XMLUtils::getChildNode(stripNode, "PayoffPerUnit");
188 QL_REQUIRE(n, "A strip of commodity digital options requires PayoffPerUnit node");
190 }
191}
virtual void fromXML(ore::data::XMLNode *node) override
Definition: barrierdata.cpp:25
virtual void fromXML(XMLNode *node) override
Definition: legdata.cpp:759
virtual void fromXML(XMLNode *node) override
Definition: premiumdata.cpp:37
virtual void fromXML(XMLNode *node) override
Definition: trade.cpp:34
static vector< Real > getChildrenValuesAsDoubles(XMLNode *node, const string &names, const string &name, bool mandatory=false)
Definition: xmlutils.cpp:319
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 vector< string > getChildrenValues(XMLNode *node, const string &names, const string &name, bool mandatory=false)
Definition: xmlutils.cpp:306
Position::Type parsePositionType(const std::string &s)
Convert text to QuantLib::Position::Type.
Definition: parsers.cpp:404
bool parseBool(const string &s)
Convert text to bool.
Definition: parsers.cpp:144
Real parseReal(const string &s)
Convert text to Real.
Definition: parsers.cpp:112
+ Here is the call graph for this function:

◆ toXML()

XMLNode * toXML ( ore::data::XMLDocument doc) const
overridevirtual

Reimplemented from Trade.

Definition at line 193 of file commodityoptionstrip.cpp.

193 {
194
195 XMLNode* node = Trade::toXML(doc);
196
197 XMLNode* stripNode = doc.allocNode("CommodityOptionStripData");
198 XMLUtils::appendNode(node, stripNode);
199
200 XMLUtils::appendNode(stripNode, legData_.toXML(doc));
201
202 if (!callStrikes_.empty()) {
203 XMLNode* callsNode = doc.allocNode("Calls");
204 XMLUtils::addChildren(doc, callsNode, "LongShorts", "LongShort", strPositions(callPositions_));
205 XMLUtils::addChildren(doc, callsNode, "Strikes", "Strike", callStrikes_);
208 }
209 XMLUtils::appendNode(stripNode, callsNode);
210 }
211
212 if (!putStrikes_.empty()) {
213 XMLNode* putsNode = doc.allocNode("Puts");
214 XMLUtils::addChildren(doc, putsNode, "LongShorts", "LongShort", strPositions(putPositions_));
215 XMLUtils::addChildren(doc, putsNode, "Strikes", "Strike", putStrikes_);
218 }
219 XMLUtils::appendNode(stripNode, putsNode);
220 }
221
222 // These are all optional, really they should be grouped here
223 if (!premiumData_.premiumData().empty())
224 XMLUtils::appendNode(stripNode, premiumData_.toXML(doc));
225
226 if (!style_.empty())
227 XMLUtils::addChild(doc, stripNode, "Style", style_);
228
229 if (!settlement_.empty())
230 XMLUtils::addChild(doc, stripNode, "Settlement", settlement_);
231
232 if (isDigital_){
233 XMLUtils::addChild(doc, stripNode, "IsDigital", isDigital_);
234 XMLUtils::addChild(doc, stripNode, "PayoffPerUnit", unaryPayoff_);
235 }
236 return node;
237}
virtual ore::data::XMLNode * toXML(ore::data::XMLDocument &doc) const override
Definition: barrierdata.cpp:49
bool initialized() const
Definition: barrierdata.hpp:52
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: legdata.cpp:856
const std::vector< PremiumDatum > & premiumData() const
Definition: premiumdata.hpp:57
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: premiumdata.cpp:76
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: trade.cpp:46
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
Definition: xmlutils.cpp:132
static void addChildren(XMLDocument &doc, XMLNode *n, const string &names, const string &name, const vector< T > &values)
Definition: xmlutils.cpp:502
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
+ Here is the call graph for this function:

◆ hasCashflows()

bool hasCashflows ( ) const
overridevirtual

Utility method indicating if the trade has cashflows for the cashflow report. The default implementation returns true so that a trade is automatically considered when cashflows are being written. To prevent a trade from being asked for its cashflows, the method can be overridden to return false.

Reimplemented from Trade.

Definition at line 87 of file commodityoptionstrip.hpp.

87{ return false; }

◆ buildAPOs()

void buildAPOs ( const QuantLib::Leg &  leg,
const QuantLib::ext::shared_ptr< ore::data::EngineFactory > &  engineFactory 
)
private

Build an average price option strip.

Definition at line 239 of file commodityoptionstrip.cpp.

239 {
240
241 // If style is set and not European, log a warning.
242 if (!style_.empty() && style_ != "European") {
243 WLOG("Style should be European when the commodity option strip is a strip of APOs. Ignoring style "
244 << style_ << " and proceeding as if European.");
245 }
246
247 // If settlement is set and not Cash, log a warning. Physical settlement for APOs does not make sense.
248 if (!settlement_.empty() && settlement_ != "Cash") {
249 WLOG("Settlement should be Cash when the commodity option strip is a strip of APOs. Ignoring settlement "
250 << settlement_ << " and proceeding as if Cash.");
251 }
252
253
254 // Populate these with the call/put options requested in each period
255 vector<QuantLib::ext::shared_ptr<Instrument>> additionalInstruments;
256 vector<Real> additionalMultipliers;
257
258 for (Size i = 0; i < leg.size(); i++) {
259 auto cf = QuantLib::ext::dynamic_pointer_cast<CommodityIndexedAverageCashFlow>(leg[i]);
260 QL_REQUIRE(cf, "Expected a CommodityIndexedAverageCashFlow while building APO");
261
262 // Populate call and/or put data at this leg period
263 vector<TempOptionData> tempData;
264 Date exerciseDate = cf->indices().rbegin()->first;
265 vector<string> strExerciseDate = {to_string(exerciseDate)};
266 maturity_ = maturity_ == Date() ? cf->date() : max(maturity_, cf->date());
267 string stemId = id() + "_" + strExerciseDate[0] + "_";
268 if (!callStrikes_.empty()) {
269 Position::Type position = callPositions_.size() == 1 ? callPositions_[0] : callPositions_[i];
270 Real strike = callStrikes_.size() == 1 ? callStrikes_[0] : callStrikes_[i];
271 string id = stemId + "call";
272 tempData.push_back({"Call", position, strike, id});
273 }
274 if (!putStrikes_.empty()) {
275 Position::Type position = putPositions_.size() == 1 ? putPositions_[0] : putPositions_[i];
276 Real strike = putStrikes_.size() == 1 ? putStrikes_[0] : putStrikes_[i];
277 string id = stemId + "put";
278 tempData.push_back({"Put", position, strike, id});
279 }
280
281 // Each CommodityAveragePriceOption is set up to go through the commodity floating leg builder which for
282 // averaging cashflows includes the start date on the first coupon in the leg and includes the end date on
283 // the last coupon in the leg. Only one coupon in each of the cases here so need to do this manually here.
284 Date start = cf->indices().begin()->first;
285
286 // Build a commodity APO for the call and/or put in this period
287
288 for (const auto& tempDatum : tempData) {
289 QuantLib::ext::shared_ptr<Trade> commOption;
290 OptionData optionData(to_string(tempDatum.position), tempDatum.type, "European", true, strExerciseDate);
291 if (!isDigital()) {
292 commOption = QuantLib::ext::make_shared<CommodityAveragePriceOption>(
293 envelope(), optionData, cf->quantity(), tempDatum.strike, legData_.currency(), commLegData_->name(),
294 commLegData_->priceType(), to_string(start), to_string(cf->endDate()), legData_.paymentCalendar(),
296 to_string(cf->date()), cf->gearing(), cf->spread(), cf->quantityFrequency(),
298 commLegData_->deliveryRollDays(), true,
299 tempDatum.type == "Call" ? callBarrierData_ : putBarrierData_, fxIndex_);
300 } else {
301 auto undCcy = cf->index()->priceCurve()->currency();
302 QL_REQUIRE(undCcy.code() == legData_.currency(),
303 "Strips of commodity digital options do not support intra-currency trades yet.");
304 commOption = QuantLib::ext::make_shared<CommodityDigitalAveragePriceOption>(
305 envelope(), optionData, tempDatum.strike, cf->quantity() * payoffPerUnit(),
306 legData_.currency(), commLegData_->name(), commLegData_->priceType(), to_string(start),
308 legData_.paymentConvention(), commLegData_->pricingCalendar(), to_string(cf->date()),
309 cf->gearing(), cf->spread(), cf->quantityFrequency(),
311 commLegData_->deliveryRollDays(), true,
312 tempDatum.type == "Call" ? callBarrierData_ : putBarrierData_, fxIndex_);
313 }
314 commOption->id() = tempDatum.id;
315 commOption->build(engineFactory);
316 QuantLib::ext::shared_ptr<InstrumentWrapper> instWrapper = commOption->instrument();
317 setSensitivityTemplate(commOption->sensitivityTemplate());
318 additionalInstruments.push_back(instWrapper->qlInstrument());
319 additionalMultipliers.push_back(instWrapper->multiplier());
320
321 // Update the notional_ each time. It will hold the notional of the last instrument which is arbitrary
322 // but reasonable as this is the instrument that we use as the main instrument below.
323 notional_ = commOption->notional();
324
325 if (!fxIndex_.empty()) { // if fx is applied, the notional is still quoted in the domestic ccy
326 auto underlyingCcy = QuantLib::ext::dynamic_pointer_cast<CommodityIndexedAverageCashFlow>(leg[0])->index()->priceCurve()->currency();
327 notionalCurrency_ = underlyingCcy.code();
328 }
329 }
330 }
331
332 QL_REQUIRE(additionalInstruments.size() > 0, "Expected commodity APO strip to have at least one instrument");
333
334 // Take the last option and multiplier as the main instrument
335 auto qlInst = additionalInstruments.back();
336 auto qlInstMult = additionalMultipliers.back();
337 additionalInstruments.pop_back();
338 additionalMultipliers.pop_back();
339
340 // Possibly add a premium to the additional instruments and multipliers
341 // We expect here that the fee already has the correct sign
342
343 maturity_ = std::max(maturity_, addPremiums(additionalInstruments, additionalMultipliers, qlInstMult, premiumData_,
344 1.0, parseCurrency(legData_.currency()), engineFactory, ""));
345
346 // Create the Trade's instrument wrapper
348 QuantLib::ext::make_shared<VanillaInstrument>(qlInst, qlInstMult, additionalInstruments, additionalMultipliers);
349}
const string & paymentConvention() const
Definition: legdata.hpp:878
const std::string & paymentCalendar() const
Definition: legdata.hpp:889
const string & paymentLag() const
Definition: legdata.hpp:886
Serializable object holding option data.
Definition: optiondata.hpp:42
Date addPremiums(std::vector< QuantLib::ext::shared_ptr< Instrument > > &instruments, std::vector< Real > &multipliers, const Real tradeMultiplier, const PremiumData &premiumData, const Real premiumMultiplier, const Currency &tradeCurrency, const QuantLib::ext::shared_ptr< EngineFactory > &factory, const string &configuration)
Definition: trade.cpp:58
void setSensitivityTemplate(const EngineBuilder &builder)
Definition: trade.cpp:295
string & id()
Set the trade id.
Definition: trade.hpp:118
const Envelope & envelope() const
Definition: trade.hpp:135
QuantLib::ext::shared_ptr< InstrumentWrapper > instrument_
Definition: trade.hpp:197
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
Definition: parsers.cpp:290
#define WLOG(text)
Logging Macro (Level = Warning)
Definition: log.hpp:550
RandomVariable max(RandomVariable x, const RandomVariable &y)
std::string to_string(const LocationInfo &l)
Definition: ast.cpp:28
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ buildStandardOptions()

void buildStandardOptions ( const QuantLib::Leg &  leg,
const QuantLib::ext::shared_ptr< ore::data::EngineFactory > &  engineFactory 
)
private

Build a standard option strip.

Definition at line 351 of file commodityoptionstrip.cpp.

351 {
352
353 QL_REQUIRE(!callBarrierData_.initialized(), "Commodity APO: standard option does not support barriers");
354 QL_REQUIRE(!putBarrierData_.initialized(), "Commodity APO: standard option does not support barriers");
355
356 // Set style and settlement
357 string style = style_.empty() ? "European" : style_;
358 string settlement = settlement_.empty() ? "Cash" : settlement_;
359
360 // Set automatic exercise to true for cash settlement.
361 bool automaticExercise = settlement == "Cash";
362
363 // Populate these with the call/put options requested in each period
364 vector<QuantLib::ext::shared_ptr<Instrument>> additionalInstruments;
365 vector<Real> additionalMultipliers;
366
367 for (Size i = 0; i < leg.size(); i++) {
368
369 auto cf = QuantLib::ext::dynamic_pointer_cast<CommodityIndexedCashFlow>(leg[i]);
370 QL_REQUIRE(cf, "Expected a CommodityIndexedCashFlow while building standard option");
371
372 // Exercise date is the pricing date.
373 Date exerciseDate = cf->pricingDate();
374 vector<string> strExerciseDate = {to_string(exerciseDate)};
375
376 // If cash settlement and European, create the OptionPaymentData for the OptionData block below.
377 boost::optional<OptionPaymentData> paymentData = boost::none;
378 if (settlement == "Cash" && style == "European") {
379
380 Date paymentDate = cf->date();
381 vector<string> strPaymentDate = {to_string(paymentDate)};
382 paymentData = OptionPaymentData(strPaymentDate);
383
384 // Update the maturity - cash-settled strip, it is the maximum payment date.
385 maturity_ = maturity_ == Date() ? paymentDate : max(maturity_, paymentDate);
386
387 } else {
388 // Update the maturity - physically-settled strip or American, it is the maximum
389 // exercise date (no deferred delivery for Physical implemented yet).
390 maturity_ = maturity_ == Date() ? exerciseDate : max(maturity_, exerciseDate);
391 }
392
393 // Populate call and/or put data at this leg period
394 vector<TempOptionData> tempData;
395 string stemId = id() + "_" + strExerciseDate[0] + "_";
396 if (!callStrikes_.empty()) {
397 Position::Type position = callPositions_.size() == 1 ? callPositions_[0] : callPositions_[i];
398 Real strike = callStrikes_.size() == 1 ? callStrikes_[0] : callStrikes_[i];
399 string id = stemId + "call";
400 tempData.push_back({"Call", position, strike, id});
401 }
402 if (!putStrikes_.empty()) {
403 Position::Type position = putPositions_.size() == 1 ? putPositions_[0] : putPositions_[i];
404 Real strike = putStrikes_.size() == 1 ? putStrikes_[0] : putStrikes_[i];
405 string id = stemId + "put";
406 tempData.push_back({"Put", position, strike, id});
407 }
408
409 // Build a commodity option for the call and/or put in this period
410 for (const auto& tempDatum : tempData) {
411
412 // Check that gearing, strike and spread make sense
413 QL_REQUIRE(cf->gearing() > 0.0, "Gearing (" << cf->gearing() << ") should be positive.");
414 QL_REQUIRE(cf->spread() < tempDatum.strike || QuantLib::close_enough(cf->spread(), tempDatum.strike),
415 "Spread (" << cf->spread() << ") should be less than strike (" << tempDatum.strike << ").");
416
417 TradeStrike effectiveStrike(TradeStrike::Type::Price, (tempDatum.strike - cf->spread()) / cf->gearing());
418 Real effectiveQuantity = cf->gearing() * cf->periodQuantity();
419
420 OptionData optionData(to_string(tempDatum.position), tempDatum.type, style, false, strExerciseDate,
421 settlement, "", PremiumData(), {}, {}, "", "", "", {}, {}, "", "", "", "", "",
422 automaticExercise, boost::none, paymentData);
423
424
425 QuantLib::ext::shared_ptr<Trade> commOption;
426 if(!isDigital()) {
427 commOption = QuantLib::ext::make_shared<CommodityOption>(
428 envelope(), optionData, commLegData_->name(), legData_.currency(), effectiveQuantity,
429 effectiveStrike, cf->useFuturePrice(), cf->index()->expiryDate());
430 } else {
431 auto undCcy = cf->index()->priceCurve()->currency();
432 QL_REQUIRE(undCcy.code() == legData_.currency(), "Strips of commodity digital options do not support intra-currency trades yet.");
433 commOption = QuantLib::ext::make_shared<CommodityDigitalOption>(
434 envelope(), optionData, commLegData_->name(), legData_.currency(), effectiveStrike.value(), effectiveQuantity*payoffPerUnit(),
435 cf->useFuturePrice(), cf->index()->expiryDate());
436 }
437 commOption->id() = tempDatum.id;
438 commOption->build(engineFactory);
439 QuantLib::ext::shared_ptr<InstrumentWrapper> instWrapper = commOption->instrument();
440 setSensitivityTemplate(commOption->sensitivityTemplate());
441 additionalInstruments.push_back(instWrapper->qlInstrument());
442 additionalMultipliers.push_back(instWrapper->multiplier());
443
444 // Update the notional_ each time. It will hold the notional of the last instrument which is arbitrary
445 // but reasonable as this is the instrument that we use as the main instrument below.
446 notional_ = commOption->notional();
447 }
448 }
449
450 QL_REQUIRE(additionalInstruments.size() > 0, "Expected commodity option strip to have at least one instrument");
451
452 // Take the last option and multiplier as the main instrument
453 auto qlInst = additionalInstruments.back();
454 auto qlInstMult = additionalMultipliers.back();
455 additionalInstruments.pop_back();
456 additionalMultipliers.pop_back();
457
458 // Possibly add a premium to the additional instruments and multipliers
459 // We expect here that the fee already has the correct sign
460 maturity_ = std::max(maturity_, addPremiums(additionalInstruments, additionalMultipliers, qlInstMult, premiumData_,
461 1.0, parseCurrency(legData_.currency()), engineFactory, ""));
462 DLOG("Option premium added for commodity option strip " << id());
463
464 // Create the Trade's instrument wrapper
466 QuantLib::ext::make_shared<VanillaInstrument>(qlInst, qlInstMult, additionalInstruments, additionalMultipliers);
467}
const std::string & settlement() const
const std::string & style() const
Serializable object holding premium data.
Definition: premiumdata.hpp:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ check()

void check ( QuantLib::Size  numberPeriods) const
private

Perform checks before building.

Definition at line 469 of file commodityoptionstrip.cpp.

469 {
470
471 QL_REQUIRE(numberPeriods > 0, "Expected at least one period in the commodity option strip");
472 QL_REQUIRE(!callStrikes_.empty() || !putStrikes_.empty(), "Need at least one call or put to build a strip");
473
474 if (!callStrikes_.empty()) {
475 QL_REQUIRE(callStrikes_.size() == 1 || callStrikes_.size() == numberPeriods,
476 "The number of "
477 << "call strikes (" << callStrikes_.size() << ") should be 1 or equal to "
478 << "the number of periods in the strip (" << numberPeriods << ")");
479 QL_REQUIRE(callPositions_.size() == 1 || callPositions_.size() == numberPeriods,
480 "The number of position "
481 << "flags provided with the call strikes (" << callPositions_.size()
482 << ") should be 1 or equal to "
483 << "the number of periods in the strip (" << numberPeriods << ")");
484 }
485
486 if (!putStrikes_.empty()) {
487 QL_REQUIRE(putStrikes_.size() == 1 || putStrikes_.size() == numberPeriods,
488 "The number of "
489 << "put strikes (" << putStrikes_.size() << ") should be 1 or equal to "
490 << "the number of periods in the strip (" << numberPeriods << ")");
491 QL_REQUIRE(putPositions_.size() == 1 || putPositions_.size() == numberPeriods,
492 "The number of position "
493 << "flags provided with the put strikes (" << putPositions_.size()
494 << ") should be 1 or equal to "
495 << "the number of periods in the strip (" << numberPeriods << ")");
496 }
497}

Member Data Documentation

◆ legData_

ore::data::LegData legData_
private

Definition at line 91 of file commodityoptionstrip.hpp.

◆ callPositions_

std::vector<QuantLib::Position::Type> callPositions_
private

Definition at line 92 of file commodityoptionstrip.hpp.

◆ callStrikes_

std::vector<QuantLib::Real> callStrikes_
private

Definition at line 93 of file commodityoptionstrip.hpp.

◆ putPositions_

std::vector<QuantLib::Position::Type> putPositions_
private

Definition at line 94 of file commodityoptionstrip.hpp.

◆ putStrikes_

std::vector<QuantLib::Real> putStrikes_
private

Definition at line 95 of file commodityoptionstrip.hpp.

◆ premiumData_

PremiumData premiumData_
private

Definition at line 96 of file commodityoptionstrip.hpp.

◆ style_

std::string style_
private

Definition at line 97 of file commodityoptionstrip.hpp.

◆ settlement_

std::string settlement_
private

Definition at line 98 of file commodityoptionstrip.hpp.

◆ callBarrierData_

BarrierData callBarrierData_
private

Definition at line 99 of file commodityoptionstrip.hpp.

◆ putBarrierData_

BarrierData putBarrierData_
private

Definition at line 100 of file commodityoptionstrip.hpp.

◆ fxIndex_

std::string fxIndex_
private

Definition at line 101 of file commodityoptionstrip.hpp.

◆ isDigital_

bool isDigital_
private

Definition at line 102 of file commodityoptionstrip.hpp.

◆ unaryPayoff_

Real unaryPayoff_
private

Definition at line 103 of file commodityoptionstrip.hpp.

◆ commLegData_

QuantLib::ext::shared_ptr<CommodityFloatingLegData> commLegData_
private

Definition at line 105 of file commodityoptionstrip.hpp.