Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
europeanoptionbarrier.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2021 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
22
23namespace ore {
24namespace data {
25
26void EuropeanOptionBarrier::build(const QuantLib::ext::shared_ptr<EngineFactory>& factory) {
27
28 // set script parameters
29
30 clear();
32
33 events_.emplace_back("PremiumDate", premiumDate_);
34 events_.emplace_back("OptionExpiry", optionExpiry_);
35 events_.emplace_back("SettlementDate", settlementDate_);
36 if (barrierStyle_ == "American")
37 events_.emplace_back("BarrierSchedule", barrierSchedule_);
38 else
39 events_.emplace_back("BarrierSchedule", optionExpiry_);
40
41 numbers_.emplace_back("Number", "Quantity", quantity_);
42 numbers_.emplace_back("Number", "Strike", strike_);
43 numbers_.emplace_back("Number", "PremiumAmount", premiumAmount_);
44 numbers_.emplace_back("Number", "BarrierLevel", barrierLevel_);
45
46 Barrier::Type barrierType = parseBarrierType(barrierType_);
47 string barrierTypeVal;
48 if (barrierType == Barrier::Type::DownIn)
49 barrierTypeVal = "1";
50 else if (barrierType == Barrier::Type::UpIn)
51 barrierTypeVal = "2";
52 else if (barrierType == Barrier::Type::DownOut)
53 barrierTypeVal = "3";
54 else if (barrierType == Barrier::Type::UpOut)
55 barrierTypeVal = "4";
56 else
57 QL_FAIL("Unknown Barrier Type: " << barrierType);
58 numbers_.emplace_back("Number", "BarrierType", barrierTypeVal);
59
60 numbers_.emplace_back("Number", "BarrierStyle", barrierStyle_ == "American" ? "1" : "-1");
61
62 Option::Type putCall = parseOptionType(putCall_);
63 numbers_.emplace_back("Number", "PutCall", putCall == Option::Call ? "1" : "-1");
64
65 Position::Type longShort = parsePositionType(longShort_);
66 numbers_.emplace_back("Number", "LongShort", longShort == Position::Long ? "1" : "-1");
67
68 currencies_.emplace_back("Currency", "PremiumCurrency", premiumCurrency_);
69 currencies_.emplace_back("Currency", "PayCcy", payCcy_);
70
71 // check underlying types
72 QL_REQUIRE(optionUnderlying_->type() == "Equity" || optionUnderlying_->type() == "Commodity" ||
73 optionUnderlying_->type() == "FX" || optionUnderlying_->type() == "InterestRate",
74 "Underlying type " << optionUnderlying_->type() << " not supported");
75 QL_REQUIRE(barrierUnderlying_->type() == "Equity" || barrierUnderlying_->type() == "Commodity" ||
76 barrierUnderlying_->type() == "FX" || barrierUnderlying_->type() == "InterestRate",
77 "Underlying type " << barrierUnderlying_->type() << " not supported");
78
79 // set product tag accordingly
80 if (optionUnderlying_->type() == "InterestRate" && barrierUnderlying_->type() == "InterestRate")
81 productTag_ = "MultiUnderlyingIrOption";
82 else if (optionUnderlying_->type() == "InterestRate" || barrierUnderlying_->type() == "InterestRate")
83 productTag_ = "IrHybrid({AssetClass})";
84 else
85 productTag_ = "MultiAssetOption({AssetClass})";
86
87 LOG("ProductTag=" << productTag_);
88
89 // set script
90 script_ = {
91 {"",
93 " REQUIRE Quantity >= 0;\n"
94 " REQUIRE PremiumDate <= SettlementDate;\n"
95 " REQUIRE OptionExpiry <= SettlementDate;\n"
96 "\n"
97 " NUMBER barrierFixing, finalPrice, exercisePayoff, premium;\n"
98 " NUMBER notKnocked, factor, currentNotional, exerciseProbability;\n"
99 "\n"
100 " notKnocked = 1;\n"
101 "\n"
102 " IF BarrierStyle == -1 THEN\n"
103 " barrierFixing = BarrierUnderlying(OptionExpiry);\n"
104 " finalPrice = OptionUnderlying(OptionExpiry);\n"
105 "\n"
106 " IF {BarrierType == 1 AND barrierFixing <= BarrierLevel}\n"
107 " OR {BarrierType == 2 AND barrierFixing >= BarrierLevel}\n"
108 " OR {BarrierType == 3 AND barrierFixing > BarrierLevel}\n"
109 " OR {BarrierType == 4 AND barrierFixing < BarrierLevel} THEN\n"
110 " exercisePayoff = LOGPAY(LongShort * Quantity * max(0, PutCall * (finalPrice - Strike)),\n"
111 " OptionExpiry, SettlementDate, PayCcy, 1, ExercisePayoff);\n"
112 " END;\n"
113 "\n"
114 " ELSE\n"
115 " NUMBER d;\n"
116 " FOR d IN (2, SIZE(BarrierSchedule), 1) DO\n"
117 " IF BarrierType == 1 OR BarrierType == 3 THEN\n"
118 " notKnocked = notKnocked * (1 - BELOWPROB(BarrierUnderlying, BarrierSchedule[d-1],\n"
119 " BarrierSchedule[d], BarrierLevel));\n"
120 " ELSE\n"
121 " notKnocked = notKnocked * (1 - ABOVEPROB(BarrierUnderlying, BarrierSchedule[d-1],\n"
122 " BarrierSchedule[d], BarrierLevel));\n"
123 " END;\n"
124 " END;\n"
125 "\n"
126 " IF BarrierType == 1 OR BarrierType == 2 THEN\n"
127 " factor = 1 - notKnocked;\n"
128 " ELSE\n"
129 " factor = notKnocked;\n"
130 " END;\n"
131 "\n"
132 " finalPrice = OptionUnderlying(OptionExpiry);\n"
133 " exercisePayoff = LOGPAY(Quantity * factor * max(0, PutCall * (finalPrice - Strike)),\n"
134 " OptionExpiry, SettlementDate, PayCcy, 1, ExercisePayoff);\n"
135 " END;\n"
136 "\n"
137 " premium = LOGPAY(Quantity * PremiumAmount, PremiumDate,\n"
138 " PremiumDate, PremiumCurrency, 0, Premium);\n"
139 "\n"
140 " IF exercisePayoff != 0 THEN\n"
141 " exerciseProbability = 1;\n"
142 " END;\n"
143 "\n"
144 " currentNotional = Quantity * Strike;"
145 " Option = LongShort * (exercisePayoff - premium);\n",
146 //
147 "Option",
148 {{"ExerciseProbability", "exerciseProbability"},
149 {"currentNotional", "currentNotional"},
150 {"notionalCurrency", "PayCcy"}},
151 {})}};
152
153 // build trade
154
155 ScriptedTrade::build(factory);
156}
157
159 indices_.emplace_back("Index", "OptionUnderlying", scriptedIndexName(optionUnderlying_));
160 indices_.emplace_back("Index", "BarrierUnderlying", scriptedIndexName(barrierUnderlying_));
161}
162
164 Trade::fromXML(node);
165 XMLNode* tradeDataNode = XMLUtils::getChildNode(node, "EuropeanOptionBarrierData");
166 QL_REQUIRE(tradeDataNode, "EuropeanOptionBarrierData node not found");
167 quantity_ = XMLUtils::getChildValue(tradeDataNode, "Quantity", true);
168 putCall_ = XMLUtils::getChildValue(tradeDataNode, "PutCall", true);
169 longShort_ = XMLUtils::getChildValue(tradeDataNode, "LongShort", true);
170 strike_ = XMLUtils::getChildValue(tradeDataNode, "Strike", true);
171 premiumAmount_ = XMLUtils::getChildValue(tradeDataNode, "PremiumAmount", true);
172 premiumCurrency_ = XMLUtils::getChildValue(tradeDataNode, "PremiumCurrency", true);
173 premiumDate_ = XMLUtils::getChildValue(tradeDataNode, "PremiumDate", true);
174 optionExpiry_ = XMLUtils::getChildValue(tradeDataNode, "OptionExpiry", true);
175
176 XMLNode* tmp = XMLUtils::getChildNode(tradeDataNode, "OptionUnderlying");
177 if (!tmp)
178 tmp = XMLUtils::getChildNode(tradeDataNode, "Name");
179 UnderlyingBuilder optionUnderlyingBuilder("OptionUnderlying", "Name");
180 optionUnderlyingBuilder.fromXML(tmp);
181 optionUnderlying_ = optionUnderlyingBuilder.underlying();
182
183 tmp = XMLUtils::getChildNode(tradeDataNode, "BarrierUnderlying");
184 if (!tmp)
185 tmp = XMLUtils::getChildNode(tradeDataNode, "Name");
186 UnderlyingBuilder barrierUnderlyingBuilder("BarrierUnderlying", "Name");
187 barrierUnderlyingBuilder.fromXML(tmp);
188 barrierUnderlying_ = barrierUnderlyingBuilder.underlying();
189
190 barrierLevel_ = XMLUtils::getChildValue(tradeDataNode, "BarrierLevel", true);
191 barrierType_ = XMLUtils::getChildValue(tradeDataNode, "BarrierType", true);
192
193 barrierStyle_ = XMLUtils::getChildValue(tradeDataNode, "BarrierStyle", true);
194 QL_REQUIRE(barrierStyle_ == "American" || barrierStyle_ == "European",
195 "Barrier style " << barrierStyle_ << " not supported");
196 if (barrierStyle_ == "American") {
197 QL_REQUIRE(XMLUtils::getChildNode(tradeDataNode, "BarrierSchedule"), "Missing BarrierSchedule node.");
198 barrierSchedule_.fromXML(XMLUtils::getChildNode(tradeDataNode, "BarrierSchedule"));
199 }
200
201 settlementDate_ = XMLUtils::getChildValue(tradeDataNode, "SettlementDate", true);
202 payCcy_ = XMLUtils::getChildValue(tradeDataNode, "PayCcy", true);
203
204 initIndices();
205}
206
208 XMLNode* node = Trade::toXML(doc);
209 XMLNode* tradeNode = doc.allocNode("EuropeanOptionBarrierData");
210 XMLUtils::appendNode(node, tradeNode);
211 XMLUtils::addChild(doc, tradeNode, "Quantity", quantity_);
212 XMLUtils::addChild(doc, tradeNode, "PutCall", putCall_);
213 XMLUtils::addChild(doc, tradeNode, "LongShort", longShort_);
214 XMLUtils::addChild(doc, tradeNode, "Strike", strike_);
215 XMLUtils::addChild(doc, tradeNode, "PremiumAmount", premiumAmount_);
216 XMLUtils::addChild(doc, tradeNode, "PremiumCurrency", premiumCurrency_);
217 XMLUtils::addChild(doc, tradeNode, "PremiumDate", premiumDate_);
218 XMLUtils::addChild(doc, tradeNode, "OptionExpiry", optionExpiry_);
219 XMLUtils::appendNode(tradeNode, optionUnderlying_->toXML(doc));
220 XMLUtils::appendNode(tradeNode, barrierUnderlying_->toXML(doc));
221 XMLUtils::addChild(doc, tradeNode, "BarrierLevel", barrierLevel_);
222 XMLUtils::addChild(doc, tradeNode, "BarrierType", barrierType_);
223 XMLUtils::addChild(doc, tradeNode, "BarrierStyle", barrierStyle_);
224 if (barrierStyle_ == "American") {
225 XMLNode* tmp = barrierSchedule_.toXML(doc);
226 XMLUtils::setNodeName(doc, tmp, "BarrierSchedule");
227 XMLUtils::appendNode(tradeNode, tmp);
228 }
229 XMLUtils::addChild(doc, tradeNode, "SettlementDate", settlementDate_);
230 XMLUtils::addChild(doc, tradeNode, "PayCcy", payCcy_);
231 return node;
232}
233
234} // namespace data
235} // namespace ore
QuantLib::ext::shared_ptr< Underlying > barrierUnderlying_
QuantLib::ext::shared_ptr< Underlying > optionUnderlying_
void fromXML(XMLNode *node) override
XMLNode * toXML(XMLDocument &doc) const override
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
virtual void fromXML(XMLNode *node) override
Definition: schedule.cpp:179
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: schedule.cpp:198
std::vector< ScriptedTradeEventData > events_
std::vector< ScriptedTradeValueTypeData > currencies_
std::vector< ScriptedTradeValueTypeData > indices_
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 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
European option with barrier wrapper for scripted trade.
Position::Type parsePositionType(const std::string &s)
Convert text to QuantLib::Position::Type.
Definition: parsers.cpp:404
Barrier::Type parseBarrierType(const std::string &s)
Convert std::string to QuantLib::BarrierType.
Definition: parsers.cpp:1042
Option::Type parseOptionType(const std::string &s)
Convert text to QuantLib::Option::Type.
Definition: parsers.cpp:481
@ data
Definition: log.hpp:77
#define LOG(text)
Logging Macro (Level = Notice)
Definition: log.hpp:552
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