Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
equitytouchoption.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
17#include <boost/make_shared.hpp>
26#include <ql/errors.hpp>
27#include <ql/exercise.hpp>
28#include <ql/instruments/barrieroption.hpp>
29#include <ql/instruments/compositeinstrument.hpp>
30#include <ql/instruments/swap.hpp>
31#include <ql/instruments/vanillaoption.hpp>
33
34using namespace QuantLib;
35
36namespace ore {
37namespace data {
38
40 const EquityUnderlying& equityUnderlying, string payoffCurrency,
41 double payoffAmount, string startDate, string calendar, string eqIndex)
42 : ore::data::Trade("EquityTouchOption", env),
43 EquitySingleAssetDerivative("", env, equityUnderlying), option_(option), barrier_(barrier),
44 startDate_(startDate), calendar_(calendar), eqIndex_(eqIndex), payoffAmount_(payoffAmount),
45 payoffCurrency_(payoffCurrency) {
46 Barrier::Type barrierType = parseBarrierType(barrier_.type());
47 switch (barrierType) {
48 case Barrier::DownIn:
49 case Barrier::UpIn:
50 type_ = "One-Touch";
51 break;
52 case Barrier::DownOut:
53 case Barrier::UpOut:
54 type_ = "No-Touch";
55 break;
56 default:
57 QL_FAIL("unknown barrier type");
58 }
59}
60
61void EquityTouchOption::build(const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory) {
62
63 // ISDA taxonomy
64 additionalData_["isdaAssetClass"] = string("Equity");
65 additionalData_["isdaBaseProduct"] = string("Other");
66 additionalData_["isdaSubProduct"] = string("Price Return Basic Performance");
67 // skip the transaction level mapping for now
68 additionalData_["isdaTransaction"] = string("");
69
70 Date today = Settings::instance().evaluationDate();
71 const QuantLib::ext::shared_ptr<Market> market = engineFactory->market();
72
73 // Parse trade data
74 string assetName = equityName();
75 Currency ccy = parseCurrency(payoffCurrency_);
76 Real level = barrier_.levels()[0].value();
77 Date expiryDate = parseDate(option_.exerciseDates().front());
78 Barrier::Type barrierType = parseBarrierType(barrier_.type());
79 Option::Type type;
80 if (barrierType == Barrier::DownIn || barrierType == Barrier::DownOut)
81 type = Option::Type::Put;
82 else
83 type = Option::Type::Call;
84 bool payoffAtExpiry = option_.payoffAtExpiry();
85 Real rebate = barrier_.rebate();
86 Position::Type positionType = parsePositionType(option_.longShort());
87 Date start = ore::data::parseDate(startDate_);
88
89 QL_REQUIRE(tradeActions().empty(), "TradeActions not supported for EquityOption");
90 QL_REQUIRE(option_.exerciseDates().size() == 1, "Invalid number of exercise dates");
91 QL_REQUIRE(barrier_.levels().size() == 1, "Double barriers not supported for EquityTouchOptions");
92 QL_REQUIRE(barrier_.style().empty() || barrier_.style() == "American", "Only american barrier style suppported");
93 QL_REQUIRE(rebate == 0, "Rebates not supported for EquityTouchOptions");
94 QL_REQUIRE(payoffAtExpiry == true || barrierType == Barrier::Type::DownIn || barrierType == Barrier::Type::UpIn,
95 "Payoff at hit not supported for EquityNoTouchOptions");
96
97 // create payoff and exercise, as well as leg of underlying instrument
98 QuantLib::ext::shared_ptr<StrikedTypePayoff> payoff(new CashOrNothingPayoff(type, level, 1.0));
99 Leg leg;
100
101 leg.push_back(QuantLib::ext::shared_ptr<CashFlow>(new SimpleCashFlow(1.0, expiryDate)));
102
103 QuantLib::ext::shared_ptr<Exercise> exercise = QuantLib::ext::make_shared<AmericanExercise>(expiryDate, payoffAtExpiry);
104
105 QuantLib::ext::shared_ptr<Instrument> barrier = QuantLib::ext::make_shared<VanillaOption>(payoff, exercise);
106 QuantLib::ext::shared_ptr<Instrument> underlying = QuantLib::ext::make_shared<Swap>(Leg(), leg);
107
108 QL_REQUIRE(eqIndex_ != "", "No eqIndex provided");
109 QL_REQUIRE(calendar_ != "", "No calendar provided");
110
111 QuantLib::ext::shared_ptr<QuantExt::EquityIndex2> eqIndex = parseEquityIndex(eqIndex_);
112
113 // check if the barrier has been triggered already
114 bool triggered = false;
115 Calendar cal = eqIndex->fixingCalendar();
116 if (startDate_ != "" && start < today) {
117
118 Date d = start;
119
120 while (d < today && !triggered) {
121
122 Real fixing = eqIndex->pastFixing(d);
123
124 if (fixing == 0.0 || fixing == Null<Real>()) {
125 ALOG("Got invalid Equity fixing for index " << eqIndex_ << " on " << d
126 << "Skipping this date, assuming no trigger");
127 } else {
128 triggered = checkBarrier(fixing, barrierType, level);
129 }
130
131 d = cal.advance(d, 1, Days);
132 }
133 }
134
135 // set pricing engines
136 QuantLib::ext::shared_ptr<EngineBuilder> builder = engineFactory->builder(tradeType_);
137 QL_REQUIRE(builder, "No builder found for " << tradeType_);
138 QuantLib::ext::shared_ptr<EquityTouchOptionEngineBuilder> eqTouchOptBuilder =
139 QuantLib::ext::dynamic_pointer_cast<EquityTouchOptionEngineBuilder>(builder);
140 barrier->setPricingEngine(eqTouchOptBuilder->engine(assetName, ccy, type_));
141 setSensitivityTemplate(*eqTouchOptBuilder);
142 if (type_ == "One-Touch") {
143 // if a one-touch option is triggered it becomes a simple forward cashflow
144 // which we price as a swap
145 builder = engineFactory->builder("Swap");
146 QL_REQUIRE(builder, "No builder found for Swap");
147 QuantLib::ext::shared_ptr<SwapEngineBuilderBase> swapBuilder =
148 QuantLib::ext::dynamic_pointer_cast<SwapEngineBuilderBase>(builder);
149 underlying->setPricingEngine(swapBuilder->engine(ccy, std::string(), std::string()));
150 }
151
152 bool isLong = (positionType == Position::Long) ? true : false;
153
154 std::vector<QuantLib::ext::shared_ptr<Instrument>> additionalInstruments;
155 std::vector<Real> additionalMultipliers;
156 Date lastPremiumDate = addPremiums(
157 additionalInstruments, additionalMultipliers, (isLong ? 1.0 : -1.0) * payoffAmount_, option_.premiumData(),
158 isLong ? -1.0 : 1.0, ccy, engineFactory, builder->configuration(MarketContext::pricing));
159
160 Handle<Quote> spot = market->equitySpot(assetName);
161 instrument_ = QuantLib::ext::make_shared<SingleBarrierOptionWrapper>(
162 barrier, isLong, expiryDate, false, underlying, barrierType, spot, level, rebate, ccy, start, eqIndex, cal, payoffAmount_,
163 payoffAmount_, additionalInstruments, additionalMultipliers);
167 maturity_ = std::max(lastPremiumDate, expiryDate);
168
169 if (start != Date()) {
170 for (Date d = start; d <= expiryDate; d = cal.advance(d, 1 * Days))
172 }
173
174 additionalData_["payoffAmount"] = payoffAmount_;
175 additionalData_["payoffCurrency"] = payoffCurrency_;
176}
177
178bool EquityTouchOption::checkBarrier(Real spot, Barrier::Type type, Real barrier) {
179 switch (type) {
180 case Barrier::DownIn:
181 case Barrier::DownOut:
182 return spot <= barrier;
183 case Barrier::UpIn:
184 case Barrier::UpOut:
185 return spot >= barrier;
186 default:
187 QL_FAIL("unknown barrier type " << type);
188 }
189}
190
192 Trade::fromXML(node);
193 XMLNode* eqNode = XMLUtils::getChildNode(node, "EquityTouchOptionData");
194 QL_REQUIRE(eqNode, "No EquityOptionData Node");
195 option_.fromXML(XMLUtils::getChildNode(eqNode, "OptionData"));
196 barrier_.fromXML(XMLUtils::getChildNode(eqNode, "BarrierData"));
197 Barrier::Type barrierType = parseBarrierType(barrier_.type());
198 switch (barrierType) {
199 case Barrier::DownIn:
200 case Barrier::UpIn:
201 type_ = "One-Touch";
202 break;
203 case Barrier::DownOut:
204 case Barrier::UpOut:
205 type_ = "No-Touch";
206 break;
207 default:
208 QL_FAIL("unknown barrier type");
209 }
210
211 XMLNode* tmp = XMLUtils::getChildNode(eqNode, "Underlying");
212 if (!tmp)
213 tmp = XMLUtils::getChildNode(eqNode, "Name");
215 payoffAmount_ = XMLUtils::getChildValueAsDouble(eqNode, "PayoffAmount", true);
216 payoffCurrency_ = XMLUtils::getChildValue(eqNode, "PayoffCurrency", true);
217 startDate_ = XMLUtils::getChildValue(eqNode, "StartDate", false);
218 calendar_ = XMLUtils::getChildValue(eqNode, "Calendar", false);
219 eqIndex_ = XMLUtils::getChildValue(eqNode, "EQIndex", false);
220}
221
223 XMLNode* node = Trade::toXML(doc);
224 XMLNode* eqNode = doc.allocNode("EquityTouchOptionData");
225 XMLUtils::appendNode(node, eqNode);
226 XMLUtils::appendNode(eqNode, option_.toXML(doc));
227 XMLUtils::appendNode(eqNode, barrier_.toXML(doc));
229 XMLUtils::addChild(doc, eqNode, "PayoffCurrency", payoffCurrency_);
230 XMLUtils::addChild(doc, eqNode, "PayoffAmount", payoffAmount_);
231 if (startDate_ != "")
232 XMLUtils::addChild(doc, eqNode, "StartDate", startDate_);
233 if (eqIndex_ != "")
234 XMLUtils::addChild(doc, eqNode, "EQIndex", eqIndex_);
235 if (calendar_ != "")
236 XMLUtils::addChild(doc, eqNode, "Calendar", calendar_);
237
238 return node;
239}
240
241} // namespace data
242} // namespace oreplus
Wrapper for option instruments, tracks whether option has been exercised or not.
Engine builder for Swaps.
Serializable obejct holding barrier data.
Definition: barrierdata.hpp:34
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
Serializable object holding generic trade data, reporting dimensions.
Definition: envelope.hpp:51
Base class for all single asset Equity Derivaties.
const BarrierData & barrier() const
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
const string & type() const
bool checkBarrier(Real spot, Barrier::Type type, Real level)
EquityTouchOption()
Default constructor.
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
Build QuantLib/QuantExt instrument, link pricing engine.
const string & eqIndex() const
void fromXML(XMLNode *node) override
Definition: underlying.cpp:81
XMLNode * toXML(XMLDocument &doc) const override
Definition: underlying.cpp:102
Serializable object holding option data.
Definition: optiondata.hpp:42
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 bool & payoffAtExpiry() const
Definition: optiondata.hpp:75
const PremiumData & premiumData() const
Definition: optiondata.hpp:83
const vector< string > & exerciseDates() const
Definition: optiondata.hpp:76
void addFixingDate(const QuantLib::Date &fixingDate, const std::string &indexName, const QuantLib::Date &payDate=Date::maxDate(), const bool alwaysAddIfPaysOnSettlement=false, const bool mandatoryFixing=true)
Trade base class.
Definition: trade.hpp:55
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
string tradeType_
Definition: trade.hpp:196
RequiredFixings requiredFixings_
Definition: trade.hpp:223
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
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 One-Touch/No-Touch Option data model and serialization.
QuantLib::ext::shared_ptr< QuantExt::EquityIndex2 > parseEquityIndex(const string &s)
Convert std::string (e.g SP5) to QuantExt::EquityIndex.
Date parseDate(const string &s)
Convert std::string to QuantLib::Date.
Definition: parsers.cpp:51
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
Barrier::Type parseBarrierType(const std::string &s)
Convert std::string to QuantLib::BarrierType.
Definition: parsers.cpp:1042
Map text representations to QuantLib/QuantExt types.
Classes and functions for log message handling.
@ data
Definition: log.hpp:77
#define ALOG(text)
Logging Macro (Level = Alert)
Definition: log.hpp:544
Calendar calendar
Definition: utilities.cpp:441
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Map text representations to QuantLib/QuantExt types.