Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
fxdigitaloption.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2017 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>
23#include <ql/errors.hpp>
24#include <ql/exercise.hpp>
25#include <ql/instruments/compositeinstrument.hpp>
26#include <ql/instruments/payoffs.hpp>
27#include <ql/instruments/vanillaoption.hpp>
28
29using namespace QuantLib;
30
31namespace ore {
32namespace data {
33
34void FxDigitalOption::build(const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory) {
35
36 // ISDA taxonomy
37 additionalData_["isdaAssetClass"] = string("Foreign Exchange");
38 additionalData_["isdaBaseProduct"] = string("Simple Exotic");
39 additionalData_["isdaSubProduct"] = string("Digital");
40 additionalData_["isdaTransaction"] = string("");
41
42 additionalData_["payoffAmount"] = payoffAmount_;
43 additionalData_["payoffCurrency"] = payoffCurrency_;
44
45 // Only European Vanilla supported for now
46 QL_REQUIRE(option_.style() == "European", "Option Style unknown: " << option_.style());
47 QL_REQUIRE(option_.exerciseDates().size() == 1, "Invalid number of exercise dates");
48 QL_REQUIRE(option_.payoffAtExpiry() == true, "PayoffAtExpiry must be True for FxDigitalOption");
49 QL_REQUIRE(tradeActions().empty(), "TradeActions not supported for FxDigitalOption");
50 QL_REQUIRE(strike_ > 0.0 && strike_ != Null<Real>(), "Invalid strike " << strike_);
51
52 Currency domCcy = parseCurrency(domesticCurrency_);
53 Currency forCcy = parseCurrency(foreignCurrency_);
54
55 // Payoff Type
56 Option::Type type = parseOptionType(option_.callPut());
57
58 // Handle PayoffCurrency, we might have to flip the trade here
59 Real strike = strike_;
60 bool flipResults = false;
61 if (payoffCurrency_ == "") {
62 DLOG("PayoffCurrency defaulting to " << domesticCurrency_ << " for FxDigitalOption " << id());
63 } else if (payoffCurrency_ == foreignCurrency_) {
64 // Invert the trade, switch dom and for and flip Put/Call
65 strike = 1.0 / strike;
66 std::swap(domCcy, forCcy);
67 type = type == Option::Call ? Option::Put : Option::Call;
68 flipResults = true;
69 } else if (payoffCurrency_ != domesticCurrency_) {
70 QL_FAIL("Invalid Payoff currency (" << payoffCurrency_ << ") for FxDigitalOption " << forCcy << domCcy);
71 }
72 DLOG("Setting up FxDigitalOption with strike " << strike << " foreign " << forCcy << " domestic " << domCcy);
73
74 // Set up the CashOrNothing
75 QuantLib::ext::shared_ptr<StrikedTypePayoff> payoff(new CashOrNothingPayoff(type, strike, payoffAmount_));
76
77 npvCurrency_ = domCcy.code(); // don't use domesticCurrency_ as it might be flipped
80
81 // Exercise
82 Date expiryDate = parseDate(option_.exerciseDates().front());
83 QuantLib::ext::shared_ptr<Exercise> exercise = QuantLib::ext::make_shared<EuropeanExercise>(expiryDate);
84 maturity_ = std::max(option_.premiumData().latestPremiumDate(), expiryDate);
85
86 // QL does not have an FXDigitalOption, so we add a vanilla one here and wrap
87 // it in a composite.
88 QuantLib::ext::shared_ptr<Instrument> vanilla = QuantLib::ext::make_shared<VanillaOption>(payoff, exercise);
89
90 // set pricing engines
91 QuantLib::ext::shared_ptr<EngineBuilder> builder = engineFactory->builder(tradeType_);
92 QL_REQUIRE(builder, "No builder found for " << tradeType_);
93 QuantLib::ext::shared_ptr<FxDigitalOptionEngineBuilder> fxOptBuilder =
94 QuantLib::ext::dynamic_pointer_cast<FxDigitalOptionEngineBuilder>(builder);
95 vanilla->setPricingEngine(fxOptBuilder->engine(forCcy, domCcy, flipResults));
96 setSensitivityTemplate(*fxOptBuilder);
97
98 Position::Type positionType = parsePositionType(option_.longShort());
99 Real bsInd = (positionType == QuantLib::Position::Long ? 1.0 : -1.0);
100 Real mult = bsInd;
101
102 std::vector<QuantLib::ext::shared_ptr<Instrument>> additionalInstruments;
103 std::vector<Real> additionalMultipliers;
104 addPremiums(additionalInstruments, additionalMultipliers, mult, option_.premiumData(), -bsInd, domCcy,
105 engineFactory, fxOptBuilder->configuration(MarketContext::pricing));
106
107 instrument_ = QuantLib::ext::shared_ptr<InstrumentWrapper>(
108 new VanillaInstrument(vanilla, mult, additionalInstruments, additionalMultipliers));
109}
110
112 Trade::fromXML(node);
113 XMLNode* fxNode = XMLUtils::getChildNode(node, "FxDigitalOptionData");
114 QL_REQUIRE(fxNode, "No FxDigitalOptionData Node");
115 option_.fromXML(XMLUtils::getChildNode(fxNode, "OptionData"));
116 strike_ = XMLUtils::getChildValueAsDouble(fxNode, "Strike", true);
117 payoffCurrency_ = XMLUtils::getChildValue(fxNode, "PayoffCurrency", false);
118 payoffAmount_ = XMLUtils::getChildValueAsDouble(fxNode, "PayoffAmount", true);
119 foreignCurrency_ = XMLUtils::getChildValue(fxNode, "ForeignCurrency", true);
120 domesticCurrency_ = XMLUtils::getChildValue(fxNode, "DomesticCurrency", true);
121}
122
124 XMLNode* node = Trade::toXML(doc);
125 XMLNode* fxNode = doc.allocNode("FxDigitalOptionData");
126 XMLUtils::appendNode(node, fxNode);
127
128 XMLUtils::appendNode(fxNode, option_.toXML(doc));
129 XMLUtils::addChild(doc, fxNode, "Strike", strike_);
130 XMLUtils::addChild(doc, fxNode, "PayoffCurrency", payoffCurrency_);
131 XMLUtils::addChild(doc, fxNode, "PayoffAmount", payoffAmount_);
132 XMLUtils::addChild(doc, fxNode, "ForeignCurrency", foreignCurrency_);
133 XMLUtils::addChild(doc, fxNode, "DomesticCurrency", domesticCurrency_);
134
135 return node;
136}
137} // namespace data
138} // namespace oreplus
Engine builder for FX Options.
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 & 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 bool & payoffAtExpiry() const
Definition: optiondata.hpp:75
const PremiumData & premiumData() const
Definition: optiondata.hpp:83
const vector< string > & exerciseDates() const
Definition: optiondata.hpp:76
QuantLib::Date latestPremiumDate() const
Definition: premiumdata.cpp:28
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
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
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.
FX Digital Option data model and serialization.
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
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 DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
Serializable Credit Default Swap.
Definition: namespaces.docs:23