Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
equityeuropeanbarrieroption.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2020 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 ORE is free software: you can redistribute it and/or modify it
8 under the terms of the Modified BSD License. You should have received a
9 copy of the license along with this program.
10 The license is also available online at <http://opensourcerisk.org>
11 This program is distributed on the basis that it will form a useful
12 contribution to risk analytics and model standardisation, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
15*/
16
24
25#include <ql/errors.hpp>
26#include <ql/exercise.hpp>
27#include <ql/instruments/barriertype.hpp>
28#include <ql/instruments/compositeinstrument.hpp>
29#include <ql/instruments/vanillaoption.hpp>
30
31#include <boost/make_shared.hpp>
32
33using namespace QuantLib;
34
35namespace ore {
36namespace data {
37
38void EquityEuropeanBarrierOption::build(const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory) {
39
40 // ISDA taxonomy
41 additionalData_["isdaAssetClass"] = string("Equity");
42 additionalData_["isdaBaseProduct"] = string("Other");
43 additionalData_["isdaSubProduct"] = string("Price Return Basic Performance");
44 // skip the transaction level mapping for now
45 additionalData_["isdaTransaction"] = string("");
46
47 const QuantLib::ext::shared_ptr<Market> market = engineFactory->market();
48
49 // Only European Single Barrier supported for now
50 QL_REQUIRE(option_.style() == "European", "Option Style unknown: " << option_.style());
51 QL_REQUIRE(option_.exerciseDates().size() == 1, "Invalid number of exercise dates");
52 QL_REQUIRE(barrier_.levels().size() == 1, "Invalid number of barrier levels");
53 QL_REQUIRE(barrier_.style().empty() || barrier_.style() == "European", "Only european barrier style suppported");
54 QL_REQUIRE(tradeActions().empty(), "TradeActions not supported for FxEuropeanBarrierOption");
55
57
58 Currency ccy = parseCurrencyWithMinors(currency_);
59 // Set the strike currency - if we have a minor currency, convert the strike
60 if (!strikeCurrency_.empty())
62 else if (strike_.currency().empty())
64
65 Real level = barrier_.levels()[0].value();
66 Real rebate = barrier_.rebate() / quantity_;
67 QL_REQUIRE(rebate >= 0, "Rebate must be non-negative");
68
69 Option::Type type = parseOptionType(option_.callPut());
70
71 // Exercise
72 Date expiryDate = parseDate(option_.exerciseDates().front());
73 QuantLib::ext::shared_ptr<Exercise> exercise = QuantLib::ext::make_shared<EuropeanExercise>(expiryDate);
74
75 Barrier::Type barrierType = parseBarrierType(barrier_.type());
76
77 // Payoff - European Option with strike K
78 QuantLib::ext::shared_ptr<StrikedTypePayoff> payoffVanillaK(new PlainVanillaPayoff(type, strike_.value()));
79 // Payoff - European Option with strike B
80 QuantLib::ext::shared_ptr<StrikedTypePayoff> payoffVanillaB(new PlainVanillaPayoff(type, level));
81 // Payoff - Digital Option with barrier B payoff abs(B - K)
82 QuantLib::ext::shared_ptr<StrikedTypePayoff> payoffDigital(new CashOrNothingPayoff(type, level, fabs(level - strike_.value())));
83
84 QuantLib::ext::shared_ptr<Instrument> digital = QuantLib::ext::make_shared<VanillaOption>(payoffDigital, exercise);
85 QuantLib::ext::shared_ptr<Instrument> vanillaK = QuantLib::ext::make_shared<VanillaOption>(payoffVanillaK, exercise);
86 QuantLib::ext::shared_ptr<Instrument> vanillaB = QuantLib::ext::make_shared<VanillaOption>(payoffVanillaB, exercise);
87
88 QuantLib::ext::shared_ptr<StrikedTypePayoff> rebatePayoff;
89 if (barrierType == Barrier::Type::UpIn || barrierType == Barrier::Type::DownOut) {
90 // Payoff - Up&Out / Down&In Digital Option with barrier B payoff rebate
91 rebatePayoff = QuantLib::ext::make_shared<CashOrNothingPayoff>(Option::Put, level, rebate);
92 } else if (barrierType == Barrier::Type::UpOut || barrierType == Barrier::Type::DownIn) {
93 // Payoff - Up&In / Down&Out Digital Option with barrier B payoff rebate
94 rebatePayoff = QuantLib::ext::make_shared<CashOrNothingPayoff>(Option::Call, level, rebate);
95 }
96 QuantLib::ext::shared_ptr<Instrument> rebateInstrument = QuantLib::ext::make_shared<VanillaOption>(rebatePayoff, exercise);
97
98 // set pricing engines
99 QuantLib::ext::shared_ptr<EngineBuilder> builder = engineFactory->builder("EquityOption");
100 QL_REQUIRE(builder, "No builder found for EquityOption");
101 QuantLib::ext::shared_ptr<EquityEuropeanOptionEngineBuilder> eqOptBuilder =
102 QuantLib::ext::dynamic_pointer_cast<EquityEuropeanOptionEngineBuilder>(builder);
103
104 builder = engineFactory->builder("EquityDigitalOption");
105 QL_REQUIRE(builder, "No builder found for EquityDigitalOption");
106 QuantLib::ext::shared_ptr<EquityDigitalOptionEngineBuilder> eqDigitalOptBuilder =
107 QuantLib::ext::dynamic_pointer_cast<EquityDigitalOptionEngineBuilder>(builder);
108
109 digital->setPricingEngine(eqDigitalOptBuilder->engine(assetName_, ccy));
110 vanillaK->setPricingEngine(eqOptBuilder->engine(assetName_, ccy, expiryDate));
111 vanillaB->setPricingEngine(eqOptBuilder->engine(assetName_, ccy, expiryDate));
112 rebateInstrument->setPricingEngine(eqDigitalOptBuilder->engine(assetName_, ccy));
113 setSensitivityTemplate(*eqDigitalOptBuilder);
114
115 QuantLib::ext::shared_ptr<CompositeInstrument> qlInstrument = QuantLib::ext::make_shared<CompositeInstrument>();
116 qlInstrument->add(rebateInstrument);
117 if (type == Option::Call) {
118 if (barrierType == Barrier::Type::UpIn || barrierType == Barrier::Type::DownOut) {
119 if (level > strike_.value()) {
120 qlInstrument->add(vanillaB);
121 qlInstrument->add(digital);
122 } else {
123 qlInstrument->add(vanillaK);
124 }
125 } else if (barrierType == Barrier::Type::UpOut || barrierType == Barrier::Type::DownIn) {
126 if (level > strike_.value()) {
127 qlInstrument->add(vanillaK);
128 qlInstrument->add(vanillaB, -1);
129 qlInstrument->add(digital, -1);
130 } else {
131 // empty
132 }
133 } else {
134 QL_FAIL("Unknown Barrier Type: " << barrierType);
135 }
136 } else if (type == Option::Put) {
137 if (barrierType == Barrier::Type::UpIn || barrierType == Barrier::Type::DownOut) {
138 if (level > strike_.value()) {
139 // empty
140 } else {
141 qlInstrument->add(vanillaK);
142 qlInstrument->add(vanillaB, -1);
143 qlInstrument->add(digital, -1);
144 }
145 } else if (barrierType == Barrier::Type::UpOut || barrierType == Barrier::Type::DownIn) {
146 if (level > strike_.value()) {
147 qlInstrument->add(vanillaK);
148 } else {
149 qlInstrument->add(vanillaB);
150 qlInstrument->add(digital);
151 }
152 } else {
153 QL_FAIL("Unknown Barrier Type: " << barrierType);
154 }
155 }
156
157 // Add additional premium payments
158 Position::Type positionType = parsePositionType(option_.longShort());
159 Real bsInd = (positionType == QuantLib::Position::Long ? 1.0 : -1.0);
160
161 std::vector<QuantLib::ext::shared_ptr<Instrument>> additionalInstruments;
162 std::vector<Real> additionalMultipliers;
163 Date lastPremiumDate =
164 addPremiums(additionalInstruments, additionalMultipliers, quantity_ * bsInd, option_.premiumData(), -bsInd, ccy,
165 engineFactory, eqOptBuilder->configuration(MarketContext::pricing));
166
167 instrument_ = QuantLib::ext::shared_ptr<InstrumentWrapper>(
168 new VanillaInstrument(qlInstrument, quantity_ * bsInd, additionalInstruments, additionalMultipliers));
169
170 npvCurrency_ = ccy.code();
173 maturity_ = std::max(lastPremiumDate, expiryDate);
174
175 additionalData_["quantity"] = quantity_;
176 additionalData_["strike"] = strike_.value();
177 additionalData_["strikeCurrency"] = strike_.currency();
178}
179
181 Trade::fromXML(node);
182 XMLNode* eqNode = XMLUtils::getChildNode(node, "EquityEuropeanBarrierOptionData");
183 QL_REQUIRE(eqNode, "No EquityEuropeanBarrierOptionData Node");
184 option_.fromXML(XMLUtils::getChildNode(eqNode, "OptionData"));
185 XMLNode* tmp = XMLUtils::getChildNode(eqNode, "Underlying");
186 if (!tmp)
187 tmp = XMLUtils::getChildNode(eqNode, "Name");
189 currency_ = XMLUtils::getChildValue(eqNode, "Currency", true);
190
191 strike_.fromXML(eqNode);
192 strikeCurrency_ = XMLUtils::getChildValue(eqNode, "StrikeCurrency", false);
193 if (!strikeCurrency_.empty())
194 WLOG("EquityOption::fromXML: node StrikeCurrency is deprecated, please us StrikeData node");
195
196 barrier_.fromXML(XMLUtils::getChildNode(eqNode, "BarrierData"));
197 quantity_ = XMLUtils::getChildValueAsDouble(eqNode, "Quantity", true);
198}
199
201 XMLNode* node = Trade::toXML(doc);
202 XMLNode* eqNode = doc.allocNode("EquityEuropeanBarrierOptionData");
203 XMLUtils::appendNode(node, eqNode);
204
205 XMLUtils::appendNode(eqNode, option_.toXML(doc));
206 XMLUtils::appendNode(eqNode, barrier_.toXML(doc));
208 XMLUtils::addChild(doc, eqNode, "Currency", currency_);
209 XMLUtils::appendNode(eqNode, strike_.toXML(doc));
210 if (!strikeCurrency_.empty())
211 XMLUtils::addChild(doc, eqNode, "StrikeCurrency", strikeCurrency_);
212
213 XMLUtils::addChild(doc, eqNode, "Quantity", quantity_);
214
215 return node;
216}
217} // namespace data
218} // namespace oreplus
Engine builder for equity options.
const std::string & type() const
Definition: barrierdata.hpp:46
virtual void fromXML(ore::data::XMLNode *node) override
Definition: barrierdata.cpp:25
double rebate() const
Definition: barrierdata.hpp:47
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
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
Build QuantLib/QuantExt instrument, link pricing engine.
const string & equityName() const
EquityUnderlying equityUnderlying_
void fromXML(XMLNode *node) override
Definition: underlying.cpp:81
XMLNode * toXML(XMLDocument &doc) const override
Definition: underlying.cpp:102
const string & callPut() const
Definition: optiondata.hpp:71
const string & longShort() const
Definition: optiondata.hpp:70
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 PremiumData & premiumData() const
Definition: optiondata.hpp:83
const vector< string > & exerciseDates() const
Definition: optiondata.hpp:76
TradeActions & tradeActions()
Set the trade actions.
Definition: trade.hpp:126
string npvCurrency_
Definition: trade.hpp:201
QuantLib::Real notional_
Definition: trade.hpp:202
virtual void fromXML(XMLNode *node) override
Definition: trade.cpp:34
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
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: trade.cpp:46
QuantLib::ext::shared_ptr< InstrumentWrapper > instrument_
Definition: trade.hpp:197
string notionalCurrency_
Definition: trade.hpp:203
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
Vanilla Instrument Wrapper.
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 XMLNode * addChild(XMLDocument &doc, XMLNode *n, const string &name)
Definition: xmlutils.cpp:181
static void appendNode(XMLNode *parent, XMLNode *child)
Definition: xmlutils.cpp:406
Pricing Engine Factory.
EQ European Barrier Option data model and serialization.
Equity Option data model and serialization.
Currency parseCurrencyWithMinors(const string &s)
Convert text to QuantLib::Currency.
Definition: parsers.cpp:310
Date parseDate(const string &s)
Convert std::string to QuantLib::Date.
Definition: parsers.cpp:51
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
Classes and functions for log message handling.
@ data
Definition: log.hpp:77
#define WLOG(text)
Logging Macro (Level = Warning)
Definition: log.hpp:550
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Map text representations to QuantLib/QuantExt types.