Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
bestentryoption.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2022 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
25
26namespace ore {
27namespace data {
28
29void BestEntryOption::build(const QuantLib::ext::shared_ptr<EngineFactory>& factory) {
30
31 // set script parameters
32
33 clear();
35
36 // clang-format off
37
38 static const std::string script =
39 "NUMBER payoff, initialIndex, triggerEvent, strikeIndexObs, strikeIndexLevel, d, resetMinValue;\n"
40 "\n"
41 "triggerEvent = 0;\n"
42 "\n"
43 "strikeIndexLevel = Underlying(StrikeDate);\n"
44 "\n"
45 "resetMinValue = strikeIndexLevel * ResetMinimum;\n"
46 "\n"
47 "strikeIndexObs = Underlying(StrikeObservationDates[1]);\n"
48 "\n"
49 "FOR d IN (1, SIZE(StrikeObservationDates), 1) DO\n"
50 " IF Underlying(StrikeObservationDates[d]) < TriggerLevel * strikeIndexLevel THEN\n"
51 " triggerEvent = 1;\n"
52 " strikeIndexObs = min(strikeIndexObs, Underlying(StrikeObservationDates[d]));\n"
53 " END;\n"
54 "END;\n"
55 "\n"
56 "IF triggerEvent == 1 THEN\n"
57 " initialIndex = max(ResetMinimum * strikeIndexLevel, strikeIndexObs);\n"
58 "ELSE\n"
59 " initialIndex = strikeIndexLevel;\n"
60 "END;\n"
61 "\n"
62 "IF Underlying(ExpiryDate) > Strike * initialIndex THEN\n"
63 " payoff = LongShort * Notional * Multiplier * min(Cap, max(0, (Underlying(ExpiryDate) - initialIndex)/initialIndex));\n"
64 "ELSE\n"
65 " payoff = -1* LongShort * Notional * (Strike * initialIndex - Underlying(ExpiryDate))/initialIndex;\n"
66 "END;\n"
67 "\n"
68 "Option = PAY(payoff, ExpiryDate, SettlementDate, Currency) - PAY(Premium, PremiumDate, PremiumDate, Currency);\n";
69
70 // clang-format on
71
72 numbers_.emplace_back("Number", "Notional", notional_);
73 numbers_.emplace_back("Number", "Multiplier", !multiplier_.empty() ? multiplier_ : "1");
74 numbers_.emplace_back("Number", "Cap", cap_);
75 numbers_.emplace_back("Number", "ResetMinimum", resetMinimum_);
76
77 numbers_.emplace_back("Number", "Strike", strike_);
78
79 numbers_.emplace_back("Number", "LongShort", longShort_ == "Long" ? "1" : "-1");
80
81 numbers_.emplace_back("Number", "TriggerLevel", triggerLevel_);
82
83 events_.emplace_back("ExpiryDate", expiryDate_);
85 "Expiry date must be before settlement date");
86
87 currencies_.emplace_back("Currency", "Currency", currency_);
88 numbers_.emplace_back("Number", "Premium", !premium_.empty() ? premium_ : "0");
89 events_.emplace_back("PremiumDate", !premiumDate_.empty() ? premiumDate_ : settlementDate_);
90
91 events_.emplace_back("SettlementDate", settlementDate_);
92 events_.emplace_back("StrikeDate", strikeDate_);
93 QL_REQUIRE(parseDate(strikeDate_) < parseDate(expiryDate_), "Strike date must be before expiry date");
94
96 events_.emplace_back("StrikeObservationDates", observationDates_);
97 }
98
99 // set product tag
100
101 productTag_ = "SingleAssetOption({AssetClass})";
102
103 // set script
104
105 script_[""] = ScriptedTradeScriptData(script, "Option",
106 {{"initialIndex", "initialIndex"}, {"strikeIndexLevel", "strikeIndexLevel"},
107 {"payoffAmount", "payoff"}, {"resetMinimumValue", "resetMinValue"},
108 {"lowestStrikeObs", "strikeIndexObs"},
109 {"Cap", "Cap"},
110 {"TriggerEvent", "triggerEvent"}},
111 {});
112
113 // build trade
114
115 ScriptedTrade::build(factory);
116}
117
120
121 // asset class set in the base class already
122 std::string assetClass = boost::any_cast<std::string>(additionalData_["isdaAssetClass"]);
123 if (assetClass == "Equity") {
124 additionalData_["isdaBaseProduct"] = string("Other");
125 additionalData_["isdaSubProduct"] = string("Price Return Basic Performance");
126 } else if (assetClass == "Commodity") {
127 // isda taxonomy missing for this class, using the same as equity
128 additionalData_["isdaBaseProduct"] = string("Other");
129 additionalData_["isdaSubProduct"] = string("Price Return Basic Performance");
130 } else if (assetClass == "Foreign Exchange") {
131 additionalData_["isdaBaseProduct"] = string("Complex Exotic");
132 additionalData_["isdaSubProduct"] = string("Generic");
133 } else {
134 WLOG("ISDA taxonomy incomplete for trade " << id());
135 }
136 additionalData_["isdaTransaction"] = string("");
137}
138
139void BestEntryOption::initIndices() { indices_.emplace_back("Index", "Underlying", scriptedIndexName(underlying_)); }
140
142 Trade::fromXML(node);
143 XMLNode* tradeDataNode = XMLUtils::getChildNode(node, tradeType() + "Data");
144 QL_REQUIRE(tradeDataNode, "BestEntryOptionData node not found");
145 longShort_ = XMLUtils::getChildValue(tradeDataNode, "LongShort", true);
146 notional_ = XMLUtils::getChildValue(tradeDataNode, "Notional", true);
147 multiplier_ = XMLUtils::getChildValue(tradeDataNode, "Multiplier", false);
148 strike_ = XMLUtils::getChildValue(tradeDataNode, "Strike", true);
149 cap_ = XMLUtils::getChildValue(tradeDataNode, "Cap", true);
150 triggerLevel_ = XMLUtils::getChildValue(tradeDataNode, "TriggerLevel", true);
151 resetMinimum_ = XMLUtils::getChildValue(tradeDataNode, "ResetMinimum", true);
152 currency_ = XMLUtils::getChildValue(tradeDataNode, "Currency", true);
153
154 XMLNode* underlying = XMLUtils::getChildNode(tradeDataNode, "Underlying");
155 QL_REQUIRE(underlying, "Underlying node not found");
156
157 UnderlyingBuilder underlyingBuilder;
158 underlyingBuilder.fromXML(underlying);
159 underlying_ = underlyingBuilder.underlying();
160
161 XMLNode* observationNode = XMLUtils::getChildNode(tradeDataNode, "StrikeObservationDates");
162 QL_REQUIRE(observationNode, "No strike observation dates provided");
163 observationDates_.fromXML(observationNode);
164
165 expiryDate_ = XMLUtils::getChildValue(tradeDataNode, "ExpiryDate", true);
166 settlementDate_ = XMLUtils::getChildValue(tradeDataNode, "SettlementDate");
167 strikeDate_ = XMLUtils::getChildValue(tradeDataNode, "StrikeDate", true);
168 premium_ = XMLUtils::getChildValue(tradeDataNode, "Premium", false);
169 premiumDate_ = XMLUtils::getChildValue(tradeDataNode, "PremiumDate", false);
170 currency_ = XMLUtils::getChildValue(tradeDataNode, "Currency", true);
171
172 initIndices();
173}
174
176 XMLNode* node = Trade::toXML(doc);
177 XMLNode* tradeNode = doc.allocNode(tradeType() + "Data");
178 XMLUtils::appendNode(node, tradeNode);
179 XMLUtils::addChild(doc, tradeNode, "LongShort", longShort_);
180 XMLUtils::addChild(doc, tradeNode, "Notional", notional_);
181 XMLUtils::addChild(doc, tradeNode, "Multiplier", multiplier_);
182 XMLUtils::addChild(doc, tradeNode, "Strike", strike_);
183 XMLUtils::addChild(doc, tradeNode, "Cap", cap_);
184 XMLUtils::addChild(doc, tradeNode, "TriggerLevel", triggerLevel_);
185 XMLUtils::addChild(doc, tradeNode, "ResetMinimum", resetMinimum_);
186
187 XMLUtils::appendNode(tradeNode, underlying_->toXML(doc));
188
189 XMLNode* observationNode = observationDates_.toXML(doc);
190 XMLUtils::setNodeName(doc, observationNode, "StrikeObservationDates");
191 XMLUtils::appendNode(tradeNode, observationNode);
192
193 XMLUtils::addChild(doc, tradeNode, "ExpiryDate", expiryDate_);
194 XMLUtils::addChild(doc, tradeNode, "StrikeDate", strikeDate_);
195 XMLUtils::addChild(doc, tradeNode, "Currency", currency_);
196 XMLUtils::addChild(doc, tradeNode, "Premium", premium_);
197 XMLUtils::addChild(doc, tradeNode, "PremiumDate", premiumDate_);
198 XMLUtils::addChild(doc, tradeNode, "SettlementDate", settlementDate_);
199
200 return node;
201}
202
203} // namespace data
204} // namespace ore
std::string strike_
void initIndices()
std::string resetMinimum_
void setIsdaTaxonomyFields() override
std::string currency_
std::string strikeDate_
std::string longShort_
std::string triggerLevel_
std::string cap_
void fromXML(XMLNode *node) override
QuantLib::ext::shared_ptr< Underlying > underlying_
XMLNode * toXML(XMLDocument &doc) const override
std::string premiumDate_
ScheduleData observationDates_
std::string premium_
std::string multiplier_
std::string settlementDate_
std::string notional_
std::string expiryDate_
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
bool hasData() const
Check if has any dates/rules/derived schedules.
Definition: schedule.hpp:223
virtual void fromXML(XMLNode *node) override
Definition: schedule.cpp:179
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: schedule.cpp:198
const std::map< std::string, ScriptedTradeScriptData > & script() const
std::vector< ScriptedTradeEventData > events_
std::vector< ScriptedTradeValueTypeData > currencies_
std::vector< ScriptedTradeValueTypeData > indices_
virtual void setIsdaTaxonomyFields()
std::vector< ScriptedTradeValueTypeData > numbers_
std::map< std::string, ScriptedTradeScriptData > script_
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
virtual void fromXML(XMLNode *node) override
Definition: trade.cpp:34
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: trade.cpp:46
const string & tradeType() const
Definition: trade.hpp:133
std::map< std::string, boost::any > additionalData_
Definition: trade.hpp:224
const QuantLib::ext::shared_ptr< Underlying > & underlying()
Definition: underlying.hpp:266
void fromXML(XMLNode *node) override
Definition: underlying.cpp:305
Small XML Document wrapper class.
Definition: xmlutils.hpp:65
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
Definition: xmlutils.cpp:132
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 void setNodeName(XMLDocument &doc, XMLNode *node, const string &name)
Definition: xmlutils.cpp:478
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
Date parseDate(const string &s)
Convert std::string to QuantLib::Date.
Definition: parsers.cpp:51
@ data
Definition: log.hpp:77
#define WLOG(text)
Logging Macro (Level = Warning)
Definition: log.hpp:550
QL_DEPRECATED_ENABLE_WARNING std::string scriptedIndexName(const QuantLib::ext::shared_ptr< Underlying > &underlying)
Definition: utilities.cpp:614
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Map text representations to QuantLib/QuantExt types.
trade schedule data model and serialization
some utility functions
string conversion utilities