Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
equityoutperformanceoption.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
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
20
25
31
33
34#include <ql/errors.hpp>
35#include <ql/exercise.hpp>
36#include <ql/instruments/barrieroption.hpp>
37
38#include <boost/make_shared.hpp>
39
40using namespace QuantLib;
41
42namespace ore {
43namespace data {
44
46 const string& currency, Real notional, const QuantLib::ext::shared_ptr<ore::data::Underlying>& underlying1,
47 const QuantLib::ext::shared_ptr<ore::data::Underlying>& underlying2,
48 Real initialPrice1, Real initialPrice2, Real strike, const string& initialPriceCurrency1, const string& initialPriceCurrency2,
49 Real knockInPrice, Real knockOutPrice, string fxIndex1, string fxIndex2)
50 : Trade("EquityOutperformanceOption", env), option_(option), currency_(currency), amount_(notional),
51 underlying1_(underlying1), underlying2_(underlying2), initialPrice1_(initialPrice1), initialPrice2_(initialPrice2),
52 strikeReturn_(strike), knockInPrice_(knockInPrice), knockOutPrice_(knockOutPrice), initialPriceCurrency1_(initialPriceCurrency1),
53 initialPriceCurrency2_(initialPriceCurrency2), fxIndex1_(fxIndex1), fxIndex2_(fxIndex2) {
54 }
55
56void EquityOutperformanceOption::build(const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory) {
57
58 const QuantLib::ext::shared_ptr<Market> market = engineFactory->market();
59
60 // Only European exercise supported for now
61 QL_REQUIRE(option_.style() == "European", "Option Style unknown: " << option_.style());
62 QL_REQUIRE(option_.exerciseDates().size() == 1, "Invalid number of excercise dates");
63 Currency ccy = parseCurrency(currency_);
64
65 QuantLib::ext::shared_ptr<QuantExt::FxIndex> fxIndex1 = nullptr;
66 QuantLib::ext::shared_ptr<QuantExt::FxIndex> fxIndex2 = nullptr;
67
69 if (initialPriceCurrency1_ != "") {
72
73 auto eqCurve1 = *engineFactory->market()->equityCurve(name1());
74 Currency eqCurrency1 = eqCurve1->currency();
75
76 // if the initialPrice differs from the equity price
77 if (ccy1 != eqCurrency1) {
78 QL_REQUIRE(!fxIndex1_.empty(), "FX settlement index must be specified: " << ccy1 << " " << eqCurrency1 << " " << fxIndex1_);
79 fxIndex1 = buildFxIndex(fxIndex1_, eqCurrency1.code(), ccy1.code(), engineFactory->market(),
80 engineFactory->configuration(MarketContext::pricing));
81 }
82 }
83
85 if (initialPriceCurrency2_ != "") {
88
89 auto eqCurve2 = *engineFactory->market()->equityCurve(name2());
90 Currency eqCurrency2 = eqCurve2->currency();
91
92 // if the initialPrice differs from the equity price
93 if (ccy2 != eqCurrency2) {
94 QL_REQUIRE(!fxIndex2_.empty(), "FX settlement index must be specified");
95 fxIndex2 = buildFxIndex(fxIndex2_, eqCurrency2.code(), ccy2.code(), engineFactory->market(),
96 engineFactory->configuration(MarketContext::pricing));
97 }
98 }
99
100 Date valuationDate = parseDate(option_.exerciseDates().front());
101 QuantLib::ext::shared_ptr<Exercise> exercise;
102 exercise = QuantLib::ext::make_shared<EuropeanExercise>(valuationDate);
103
104 Option::Type optionType = parseOptionType(option_.callPut());
105 QuantLib::ext::shared_ptr<Instrument> inst = QuantLib::ext::make_shared<QuantExt::OutperformanceOption>(exercise, optionType, strikeReturn_, initialPrice1, initialPrice2, amount_, knockInPrice_, knockOutPrice_, fxIndex1, fxIndex2);
106
107 QuantLib::ext::shared_ptr<EngineBuilder> builder = engineFactory->builder(tradeType_);
108 QL_REQUIRE(builder, "No builder found for " << tradeType_);
109 QuantLib::ext::shared_ptr<EquityOutperformanceOptionEngineBuilder> eqOptBuilder = QuantLib::ext::dynamic_pointer_cast<EquityOutperformanceOptionEngineBuilder>(builder);
110
111 inst->setPricingEngine(eqOptBuilder->engine(name1(), name2(), ccy));
112 setSensitivityTemplate(*eqOptBuilder);
113
114 // Add additional premium payments
115 Position::Type positionType = parsePositionType(option_.longShort());
116 Real bsInd = (positionType == QuantLib::Position::Long ? 1.0 : -1.0);
117 Real mult = bsInd;
118
119 std::vector<QuantLib::ext::shared_ptr<Instrument>> additionalInstruments;
120 std::vector<Real> additionalMultipliers;
121 Date lastPremiumDate = addPremiums(additionalInstruments, additionalMultipliers, mult, option_.premiumData(),
122 -bsInd, ccy, engineFactory, eqOptBuilder->configuration(MarketContext::pricing));
123
124 instrument_ = QuantLib::ext::shared_ptr<InstrumentWrapper>(new VanillaInstrument(inst, mult, additionalInstruments, additionalMultipliers));
126 maturity_ = std::max(lastPremiumDate, std::max(maturity_, valuationDate));
129}
130
132 Trade::fromXML(node);
133 XMLNode* eqNode = XMLUtils::getChildNode(node, "EquityOutperformanceOptionData");
134 QL_REQUIRE(eqNode, "No EquityOutperformanceOptionData Node");
135 option_.fromXML(XMLUtils::getChildNode(eqNode, "OptionData"));
136 knockInPrice_ = Null<Real>();
137 if (XMLUtils::getChildNode(eqNode, "KnockInPrice")) {
138 knockInPrice_ = XMLUtils::getChildValueAsDouble(eqNode, "KnockInPrice", true);
139 }
140 knockOutPrice_ = Null<Real>();
141 if (XMLUtils::getChildNode(eqNode, "KnockOutPrice")) {
142 knockOutPrice_ = XMLUtils::getChildValueAsDouble(eqNode, "KnockOutPrice", true);
143 }
144
145 currency_ = XMLUtils::getChildValue(eqNode, "Currency", true);
146 amount_ = XMLUtils::getChildValueAsDouble(eqNode, "Notional", true);
147
148 XMLNode* tmp1 = XMLUtils::getChildNode(eqNode, "Underlying1");
149 if (!tmp1)
150 tmp1 = XMLUtils::getChildNode(eqNode, "Name1");
151 UnderlyingBuilder underlyingBuilder1("Underlying1", "Name1");
152 underlyingBuilder1.fromXML(tmp1);
153 underlying1_ = underlyingBuilder1.underlying();
154
155 XMLNode* fxt1 = XMLUtils::getChildNode(eqNode, "InitialPriceFXTerms1");
156 if (fxt1)
157 fxIndex1_ = XMLUtils::getChildValue(fxt1, "FXIndex", true);
158
159 XMLNode* tmp2 = XMLUtils::getChildNode(eqNode, "Underlying2");
160 if (!tmp2)
161 tmp2 = XMLUtils::getChildNode(eqNode, "Name2");
162 UnderlyingBuilder underlyingBuilder2("Underlying2", "Name2");
163 underlyingBuilder2.fromXML(tmp2);
164 underlying2_ = underlyingBuilder2.underlying();
165
166 XMLNode* fxt2 = XMLUtils::getChildNode(eqNode, "InitialPriceFXTerms2");
167 if (fxt2)
168 fxIndex2_ = XMLUtils::getChildValue(fxt2, "FXIndex", true);
169
170 initialPrice1_ = XMLUtils::getChildValueAsDouble(eqNode, "InitialPrice1", true);
171 initialPrice2_ = XMLUtils::getChildValueAsDouble(eqNode, "InitialPrice2", true);
172
173 tmp1 = XMLUtils::getChildNode(eqNode, "InitialPriceCurrency1");
174 if (tmp1)
175 initialPriceCurrency1_ = XMLUtils::getChildValue(eqNode, "InitialPriceCurrency1", true);
176 tmp2 = XMLUtils::getChildNode(eqNode, "InitialPriceCurrency2");
177 if (tmp2)
178 initialPriceCurrency2_ = XMLUtils::getChildValue(eqNode, "InitialPriceCurrency2", true);
179 strikeReturn_ = XMLUtils::getChildValueAsDouble(eqNode, "StrikeReturn", true);
180
181}
182
184 XMLNode* node = Trade::toXML(doc);
185 XMLNode* eqNode = doc.allocNode("EquityOutperformanceOptionData");
186 XMLUtils::appendNode(node, eqNode);
187 XMLUtils::appendNode(eqNode, option_.toXML(doc));
188
189 XMLUtils::addChild(doc, eqNode, "Currency", currency_);
190 XMLUtils::addChild(doc, eqNode, "Notional", amount_);
191
192 XMLUtils::appendNode(eqNode, underlying1_->toXML(doc));
193 XMLUtils::appendNode(eqNode, underlying2_->toXML(doc));
194
195 XMLUtils::addChild(doc, eqNode, "InitialPrice1", initialPrice1_);
196 XMLUtils::addChild(doc, eqNode, "InitialPrice2", initialPrice2_);
197 if (initialPriceCurrency1_ != "")
198 XMLUtils::addChild(doc, eqNode, "InitialPriceCurrency1", initialPriceCurrency1_);
199 if (initialPriceCurrency2_ != "")
200 XMLUtils::addChild(doc, eqNode, "InitialPriceCurrency2", initialPriceCurrency2_);
201 XMLUtils::addChild(doc, eqNode, "StrikeReturn", strikeReturn_);
202 if (knockInPrice_ != Null<Real>())
203 XMLUtils::addChild(doc, eqNode, "KnockInPrice", knockInPrice_);
204 if (knockOutPrice_ != Null<Real>())
205 XMLUtils::addChild(doc, eqNode, "KnockOutPrice", knockOutPrice_);
206
207 if (fxIndex1_ != "") {
208 XMLNode* fxNode = doc.allocNode("InitialPriceFXTerms1");
209 XMLUtils::addChild(doc, fxNode, "FXIndex", fxIndex1_);
210 XMLUtils::appendNode(eqNode, fxNode);
211 }
212
213 if (fxIndex2_ != "") {
214 XMLNode* fxNode = doc.allocNode("InitialPriceFXTerms2");
215 XMLUtils::addChild(doc, fxNode, "FXIndex", fxIndex2_);
216 XMLUtils::appendNode(eqNode, fxNode);
217 }
218
219 return node;
220}
221
222} // namespace data
223} // namespace ore
Wrapper for option instruments, tracks whether option has been exercised or not.
Serializable object holding generic trade data, reporting dimensions.
Definition: envelope.hpp:51
QuantLib::ext::shared_ptr< ore::data::Underlying > underlying2_
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
QuantLib::ext::shared_ptr< ore::data::Underlying > underlying1_
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
Build QuantLib/QuantExt instrument, link pricing engine.
Serializable object holding option data.
Definition: optiondata.hpp:42
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
Trade base class.
Definition: trade.hpp:55
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
string tradeType_
Definition: trade.hpp:196
QuantLib::ext::shared_ptr< InstrumentWrapper > instrument_
Definition: trade.hpp:197
string notionalCurrency_
Definition: trade.hpp:203
const QuantLib::ext::shared_ptr< Underlying > & underlying()
Definition: underlying.hpp:266
void fromXML(XMLNode *node) override
Definition: underlying.cpp:305
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
Real amount_
Pricing Engine Factory.
EQ Outperformance 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
QuantLib::Real convertMinorToMajorCurrency(const std::string &s, QuantLib::Real value)
Convert a value from a minor ccy to major.
Definition: parsers.cpp:324
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
Definition: parsers.cpp:290
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
Map text representations to QuantLib/QuantExt types.
leg data model and serialization
Classes and functions for log message handling.
@ data
Definition: log.hpp:77
market data related utilties
QuantLib::ext::shared_ptr< QuantExt::FxIndex > buildFxIndex(const string &fxIndex, const string &domestic, const string &foreign, const QuantLib::ext::shared_ptr< Market > &market, const string &configuration, bool useXbsCurves)
Definition: marketdata.cpp:137
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Map text representations to QuantLib/QuantExt types.
Trade Factory.