Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
windowbarrieroption.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2023 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
23
24#include <boost/lexical_cast.hpp>
25
26namespace ore {
27namespace data {
28
29// clang-format off
30
31static const std::string window_barrier_script =
32 "REQUIRE BarrierType == 1 OR BarrierType == 2 OR BarrierType == 3 OR BarrierType == 4;\n"
33 "\n"
34 "NUMBER i, Payoff, TriggerProbability, ExerciseProbability, isUp, currentNotional;\n"
35 "\n"
36 "IF BarrierType == 1 OR BarrierType == 3 THEN\n"
37 " TriggerProbability = BELOWPROB(Underlying, StartDate, EndDate, BarrierLevel);\n"
38 "ELSE\n"
39 " TriggerProbability = ABOVEPROB(Underlying, StartDate, EndDate, BarrierLevel);\n"
40 "END;\n"
41 "\n"
42 "Payoff = Quantity * PutCall * (Underlying(Expiry) - Strike);\n"
43 "IF Payoff > 0.0 THEN\n"
44 " IF BarrierType == 1 OR BarrierType == 2 THEN\n"
45 " Option = PAY(Payoff * TriggerProbability, Expiry, Settlement, PayCcy);\n"
46 " ExerciseProbability = TriggerProbability;\n"
47 " ELSE\n"
48 " Option = PAY(Payoff * (1 - TriggerProbability), Expiry, Settlement, PayCcy);\n"
49 " ExerciseProbability = (1 - TriggerProbability);\n"
50 " END;\n"
51 "END;\n"
52 "\n"
53 "Option = LongShort * Option;\n"
54 "currentNotional = Quantity * Strike;\n";
55
56// clang-format on
57
58void WindowBarrierOption::build(const QuantLib::ext::shared_ptr<EngineFactory>& factory) {
59
60 // set script parameters
61
62 clear();
64
65 if (strike_.currency().empty())
67
68 currencies_.emplace_back("Currency", "PayCcy", currency_);
69 numbers_.emplace_back("Number", "Quantity", fixingAmount_);
70 numbers_.emplace_back("Number", "Strike", boost::lexical_cast<std::string>(strike_.value()));
71 events_.emplace_back("StartDate", startDate_);
72 events_.emplace_back("EndDate", endDate_);
73
74 auto positionType = parsePositionType(optionData_.longShort());
75 numbers_.emplace_back("Number", "LongShort", positionType == Position::Long ? "1" : "-1");
76 numbers_.emplace_back("Number", "PutCall",
77 parseOptionType(optionData_.callPut()) == Option::Type::Call ? "1" : "-1");
78
79 QL_REQUIRE(optionData_.exerciseDates().size() == 1, "WindowBarrierOption: one exercise date required, got " << optionData_.exerciseDates().size());
80 events_.emplace_back("Expiry", optionData_.exerciseDates().front());
81
82 std::string settlementDate = optionData_.exerciseDates().front();
84 QL_REQUIRE(optionData_.paymentData()->dates().size() == 1,
85 "WindowBarrierOption: exactly one payment date required under PaymentData/Dates/Date");
86 }
87 events_.emplace_back("Settlement", settlementDate);
88
89 std::string barrierType;
90 QL_REQUIRE(barrier_.style().empty() || barrier_.style() == "American",
91 "expected barrier style American, got " << barrier_.style());
92 QL_REQUIRE(barrier_.levels().size() == 1,
93 "WindowBarrierOption: exactly one barrier level required, got " << barrier_.levels().size());
94 if (barrier_.type() == "UpAndOut")
95 barrierType = "4";
96 else if (barrier_.type() == "UpAndIn")
97 barrierType = "2";
98 else if (barrier_.type() == "DownAndOut")
99 barrierType = "3";
100 else if (barrier_.type() == "DownAndIn")
101 barrierType = "1";
102 else {
103 QL_FAIL("WindowBarrierOption: invalid barrier level " << barrier_.type());
104 }
105 numbers_.emplace_back("Number", "BarrierType", barrierType);
106 numbers_.emplace_back("Number", "BarrierLevel", boost::lexical_cast<std::string>(barrier_.levels().front().value()));
107
108 // set product tag
109
110 productTag_ = "SingleAssetOption({AssetClass})";
111
112 // set script
113
115 window_barrier_script, "Option",
116 {{"currentNotional", "currentNotional"},
117 {"notionalCurrency", "PayCcy"},
118 {"TriggerProbability", "TriggerProbability"},
119 {"ExerciseProbability", "ExerciseProbability"}},
120 {}, {}, {ScriptedTradeScriptData::CalibrationData("Underlying", {"Strike", "BarrierLevel"})});
121
122 // build trade
123
124 ScriptedTrade::build(factory, optionData_.premiumData(), positionType == QuantLib::Position::Long ? -1.0 : 1.0);
125
126 additionalData_["isdaTransaction"] = string("");
127}
128
131
132 // ISDA taxonomy, asset class set in the base class build
133 // asset class set in the base class already
134 std::string assetClass = boost::any_cast<std::string>(additionalData_["isdaAssetClass"]);
135 if (assetClass == "Equity") {
136 additionalData_["isdaBaseProduct"] = string("Other");
137 additionalData_["isdaSubProduct"] = string("Price Return Basic Performance");
138 } else if (assetClass == "Commodity") {
139 // isda taxonomy missing for this class, using the same as equity
140 additionalData_["isdaBaseProduct"] = string("Other");
141 additionalData_["isdaSubProduct"] = string("Price Return Basic Performance");
142 } else if (assetClass == "Foreign Exchange") {
143 additionalData_["isdaBaseProduct"] = string("Exotic");
144 additionalData_["isdaSubProduct"] = string("Target");
145 } else {
146 WLOG("ISDA taxonomy incomplete for trade " << id());
147 }
148}
149
151 indices_.emplace_back("Index", "Underlying", scriptedIndexName(underlying_));
152}
153
155 Trade::fromXML(node);
156 XMLNode* dataNode = XMLUtils::getChildNode(node, tradeType() + "Data");
157 QL_REQUIRE(dataNode, tradeType() + "Data node not found");
158 fixingAmount_ = XMLUtils::getChildValue(dataNode, "FixingAmount");
159
160 currency_ = XMLUtils::getChildValue(dataNode, "Currency");
161 strike_.fromXML(dataNode, true, false);
162
163 XMLNode* tmp = XMLUtils::getChildNode(dataNode, "Underlying");
164 if (!tmp)
165 tmp = XMLUtils::getChildNode(dataNode, "Name");
166 UnderlyingBuilder underlyingBuilder;
167 underlyingBuilder.fromXML(tmp);
168 underlying_ = underlyingBuilder.underlying();
169
170 optionData_.fromXML(XMLUtils::getChildNode(dataNode, "OptionData"));
171 startDate_ = XMLUtils::getChildValue(dataNode, "StartDate");
172 endDate_ = XMLUtils::getChildValue(dataNode, "EndDate");
173
174 auto barrierNode = XMLUtils::getChildNode(dataNode, "BarrierData");
175 QL_REQUIRE(barrierNode, "No BarrierData node");
176 barrier_.fromXML(barrierNode);
177 initIndices();
178}
179
181 XMLNode* node = Trade::toXML(doc);
182 XMLNode* dataNode = doc.allocNode(tradeType() + "Data");
183 XMLUtils::appendNode(node, dataNode);
184 XMLUtils::addChild(doc, dataNode, "FixingAmount", fixingAmount_);
185 XMLUtils::addChild(doc, dataNode, "Currency", currency_);
186
187 XMLUtils::appendNode(dataNode, strike_.toXML(doc));
188
189 XMLUtils::appendNode(dataNode, underlying_->toXML(doc));
190 XMLUtils::appendNode(dataNode, optionData_.toXML(doc));
191 XMLUtils::addChild(doc, dataNode, "StartDate", startDate_);
192 XMLUtils::addChild(doc, dataNode, "EndDate", endDate_);
193 XMLUtils::appendNode(dataNode, barrier_.toXML(doc));
194
195 return node;
196}
197
198} // namespace data
199} // namespace ore
const std::string & type() const
Definition: barrierdata.hpp:46
virtual void fromXML(ore::data::XMLNode *node) override
Definition: barrierdata.cpp:25
virtual ore::data::XMLNode * toXML(ore::data::XMLDocument &doc) const override
Definition: barrierdata.cpp:49
std::vector< ore::data::TradeBarrier > levels() const
Definition: barrierdata.hpp:50
const std::string & style() const
Definition: barrierdata.hpp:51
const string & callPut() const
Definition: optiondata.hpp:71
const string & longShort() const
Definition: optiondata.hpp:70
virtual void fromXML(XMLNode *node) override
Definition: optiondata.cpp:32
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: optiondata.cpp:86
const boost::optional< OptionPaymentData > & paymentData() const
Definition: optiondata.hpp:93
const PremiumData & premiumData() const
Definition: optiondata.hpp:83
const vector< string > & exerciseDates() const
Definition: optiondata.hpp:76
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
XMLNode * toXML(XMLDocument &doc) const
Definition: tradestrike.cpp:86
void setCurrency(const std::string &currency)
void fromXML(XMLNode *node, const bool isRequired=true, const bool allowYieldStrike=false)
Definition: tradestrike.cpp:50
std::string currency()
QuantLib::Real value() const
const QuantLib::ext::shared_ptr< Underlying > & underlying()
Definition: underlying.hpp:266
void fromXML(XMLNode *node) override
Definition: underlying.cpp:305
void fromXML(XMLNode *node) override
QuantLib::ext::shared_ptr< Underlying > underlying_
XMLNode * toXML(XMLDocument &doc) const override
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
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 XMLNode * addChild(XMLDocument &doc, XMLNode *n, const string &name)
Definition: xmlutils.cpp:181
static void appendNode(XMLNode *parent, XMLNode *child)
Definition: xmlutils.cpp:406
Position::Type parsePositionType(const std::string &s)
Convert text to QuantLib::Position::Type.
Definition: parsers.cpp:404
Option::Type parseOptionType(const std::string &s)
Convert text to QuantLib::Option::Type.
Definition: parsers.cpp:481
@ 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.
some utility functions
string conversion utilities
window barrier option - wrapper for scripted trade