Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
pairwisevarianceswap.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
19/*! \file ored/portfolio/pairwisevarianceswap.hpp
20\brief pairwise variance swap representation
21\ingroup tradedata
22*/
23
25
27#include <qle/instruments/pairwisevarianceswap.hpp>
28
30
31using namespace QuantLib;
32
33namespace ore {
34namespace data {
35
36void PairwiseVarSwap::build(const QuantLib::ext::shared_ptr<ore::data::EngineFactory>& engineFactory) {
37
38 // Build schedules
39 ScheduleBuilder scheduleBuilder;
40
41 Schedule valuationSchedule;
42 scheduleBuilder.add(valuationSchedule, valuationSchedule_);
43
44 Schedule laggedValuationSchedule;
45 ScheduleData laggedValuationScheduleData =
48 : ScheduleData(ScheduleDerived(valuationSchedule_.name(), "NullCalendar", "Unadjusted", "1D"));
49 scheduleBuilder.add(laggedValuationSchedule, laggedValuationScheduleData);
50
51 scheduleBuilder.makeSchedules();
52
53 // For the PairwiseVarSwap::toXML() to return an entry for LaggedValuationSchedule
54 laggedValuationSchedule_ = laggedValuationScheduleData;
55
56 const Currency ccy = parseCurrency(currency_);
57 const Position::Type longShort = parsePositionType(longShort_);
58
59 QL_REQUIRE(valuationSchedule.dates().size() == laggedValuationSchedule.dates().size(),
60 "Trade " << id()
61 << " ValuationSchedule and LaggedValuationSchedule must have the same number of dates.");
62
63 const Date settlementDate = parseDate(settlementDate_);
64
65 QL_REQUIRE(basketStrike_ > 0 && !close_enough(basketStrike_, 0.0),
66 "Trade " << id() << ": PairwiseVarSwap::build() basket strike must be positive (" << basketStrike_
67 << ")");
68 QL_REQUIRE(basketNotional_ >= 0.0,
69 "Trade " << id() << ": PairwiseVarSwap::build() basket notional must be non-negative (" << notional_
70 << ")");
71
72 QuantLib::ext::shared_ptr<QuantExt::PairwiseVarianceSwap> pairwiseVarSwap(new QuantExt::PairwiseVarianceSwap(
75 laggedValuationSchedule, settlementDate));
76
77 // Pricing Engine
78 QuantLib::ext::shared_ptr<ore::data::EngineBuilder> builder = engineFactory->builder(tradeType_);
79 QL_REQUIRE(builder, "No builder found for " << tradeType_);
80 QuantLib::ext::shared_ptr<PairwiseVarSwapEngineBuilder> pairwiseVarSwapBuilder =
81 QuantLib::ext::dynamic_pointer_cast<PairwiseVarSwapEngineBuilder>(builder);
82
83 pairwiseVarSwap->setPricingEngine(pairwiseVarSwapBuilder->engine(
84 name(0), name(1), ccy, laggedValuationSchedule.dates().back(), assetClassUnderlyings()));
85 setSensitivityTemplate(*pairwiseVarSwapBuilder);
86
87 // set up other Trade details
88 instrument_ = QuantLib::ext::shared_ptr<ore::data::InstrumentWrapper>(new ore::data::VanillaInstrument(pairwiseVarSwap));
89
92 maturity_ = settlementDate;
93
94 // add required fixings
95 requiredFixings_.addFixingDates(valuationSchedule.dates(), indexNames_[0], maturity_);
96 requiredFixings_.addFixingDates(laggedValuationSchedule.dates(), indexNames_[0], maturity_);
97 requiredFixings_.addFixingDates(valuationSchedule.dates(), indexNames_[1], maturity_);
98 requiredFixings_.addFixingDates(laggedValuationSchedule.dates(), indexNames_[1], maturity_);
99}
100
102 Trade::fromXML(node);
103 XMLNode* vNode = XMLUtils::getChildNode(node, tradeType() + "Data");
104 longShort_ = XMLUtils::getChildValue(vNode, "LongShort", true);
105
106 XMLNode* underlyingsNode = XMLUtils::getChildNode(vNode, "Underlyings");
107 QL_REQUIRE(underlyingsNode, "Trade " << id() << ": Must provide an Underlyings node");
108
109 // We use "Value" sub-nodes here for backward compatibility with the scripted pairwise variance swap
110 const string underlyingNodeName = "Value";
111 auto underlyings = XMLUtils::getChildrenNodes(underlyingsNode, underlyingNodeName);
112 QL_REQUIRE(underlyings.size() == 2,
113 "Trade " << id() << ": Must provide two \"Value\" sub-nodes in the Underlyings node");
114
115 // Build underlyings - not using the usual UnderlyingBuilder here again for compatibility with the scripted version
116 string uVal, uName, acString;
117 vector<AssetClass> assetClasses;
118 AssetClass ac;
119 for (auto const& u : underlyings) {
120 uVal = XMLUtils::getNodeValue(u);
121 if (boost::starts_with(uVal, "COMM-")) {
122 ac = AssetClass::COM;
123 acString = "Commodity";
124 uName = uVal.substr(5);
125 } else if (boost::starts_with(uVal, "EQ-")) {
126 ac = AssetClass::EQ;
127 acString = "Equity";
128 uName = uVal.substr(3);
129 } else if (boost::starts_with(uVal, "FX-")) {
130 ac = AssetClass::FX;
131 acString = "FX";
132 uName = uVal.substr(3);
133 } else {
134 QL_FAIL("Unsupported underlying type for " << uVal);
135 }
136
137 indexNames_.push_back(uVal);
138 QuantLib::ext::shared_ptr<ore::data::Underlying> underlying(new ore::data::Underlying(acString, uName, 1.0));
139 assetClasses.push_back(ac);
140 underlyings_.push_back(underlying);
141 }
142
143 QL_REQUIRE(assetClasses[0] == assetClasses[1],
144 "Trade " << id() << ": Both underlyings must belong to the same asset class.");
145 assetClassUnderlyings_ = assetClasses[0];
146
147 underlyingStrikes_ = XMLUtils::getChildrenValuesAsDoubles(vNode, "UnderlyingStrikes", "Value", true);
148 underlyingNotionals_ = XMLUtils::getChildrenValuesAsDoubles(vNode, "UnderlyingNotionals", "Value", true);
149 basketNotional_ = XMLUtils::getChildValueAsDouble(vNode, "BasketNotional", true);
150 basketStrike_ = XMLUtils::getChildValueAsDouble(vNode, "BasketStrike", true);
151 settlementDate_ = XMLUtils::getChildValue(vNode, "SettlementDate", true);
152 currency_ = XMLUtils::getChildValue(vNode, "PayCcy", true);
153
154 // Optional parameters
155 accrualLag_ = XMLUtils::getChildValueAsInt(vNode, "AccrualLag", false, 1);
156 payoffLimit_ = XMLUtils::getChildValueAsDouble(vNode, "PayoffLimit", false, 0.0);
157 cap_ = XMLUtils::getChildValueAsDouble(vNode, "Cap", false, 0.0);
158 floor_ = XMLUtils::getChildValueAsDouble(vNode, "Floor", false, 0.0);
159
160 XMLNode* valuationSchedule = XMLUtils::getChildNode(vNode, "ValuationSchedule");
161 QL_REQUIRE(valuationSchedule, "Trade " << id() << ": Must provide a \"ValuationSchedule\" node");
162 valuationSchedule_.fromXML(valuationSchedule);
163
164 // If valuation schedule is derived (from lagged valuation schedule), the offset must be negative
167 QL_REQUIRE(parsePeriod(s.shift()) <= -1 * Days,
168 "Trade " << id() << " Shift value for ValutionSchedule must be at least -1D or less");
169 }
170 }
171
172 XMLNode* laggedValuationSchedule = XMLUtils::getChildNode(vNode, "LaggedValuationSchedule");
173 if (laggedValuationSchedule) {
174 laggedValuationSchedule_.fromXML(laggedValuationSchedule);
175 // If lagged valuation schedule is derived (from valuation schedule), the offset must be positive
178 QL_REQUIRE(parsePeriod(s.shift()) >= 1 * Days,
179 "Trade " << id()
180 << " Shift value for LaggedValuationSchedule must be at least 1D or greater");
181 }
182 }
183 } else {
184 // Defaulting will be dealt with later in PairwiseVarSwap::build()
186 }
187}
188
190 XMLNode* node = Trade::toXML(doc);
191 XMLNode* vNode = doc.allocNode(tradeType() + "Data");
192
193 XMLUtils::appendNode(node, vNode);
194 XMLUtils::addChild(doc, vNode, "LongShort", longShort_);
195 XMLNode* underlyingsNode = doc.allocNode("Underlyings");
196 XMLNode* underlyingStrikesNode = doc.allocNode("UnderlyingStrikes");
197 XMLNode* underlyingNotionalsNode = doc.allocNode("UnderlyingNotionals");
198 for (int i = 0; i < 2; i++) {
199 XMLUtils::addChild(doc, underlyingsNode, "Value", indexNames_[i]);
200 XMLUtils::addChild(doc, underlyingStrikesNode, "Value", underlyingStrikes_[i]);
201 XMLUtils::addChild(doc, underlyingNotionalsNode, "Value", underlyingNotionals_[i]);
202 }
203 XMLUtils::appendNode(vNode, underlyingsNode);
204 XMLUtils::appendNode(vNode, underlyingStrikesNode);
205 XMLUtils::appendNode(vNode, underlyingNotionalsNode);
206 XMLUtils::addChild(doc, vNode, "BasketNotional", basketNotional_);
207 XMLUtils::addChild(doc, vNode, "BasketStrike", basketStrike_);
208 XMLNode* valuationSchedule = valuationSchedule_.toXML(doc);
209 XMLUtils::appendNode(vNode, valuationSchedule);
210 XMLUtils::setNodeName(doc, valuationSchedule, "ValuationSchedule");
211 XMLNode* laggedValuationSchedule = laggedValuationSchedule_.toXML(doc);
212 XMLUtils::appendNode(vNode, laggedValuationSchedule);
213 XMLUtils::setNodeName(doc, laggedValuationSchedule, "LaggedValuationSchedule");
214 XMLUtils::addChild(doc, vNode, "AccrualLag", accrualLag_);
215 XMLUtils::addChild(doc, vNode, "PayoffLimit", payoffLimit_);
216 XMLUtils::addChild(doc, vNode, "Cap", cap_);
217 XMLUtils::addChild(doc, vNode, "Floor", floor_);
218 XMLUtils::addChild(doc, vNode, "SettlementDate", settlementDate_);
219 XMLUtils::addChild(doc, vNode, "PayCcy", currency_);
220
221 return node;
222}
223
224std::map<AssetClass, std::set<std::string>>
225EqPairwiseVarSwap::underlyingIndices(const QuantLib::ext::shared_ptr<ReferenceDataManager>& referenceDataManager) const {
226 return {{AssetClass::EQ, std::set<std::string>({name(0), name(1)})}};
227}
228
229} // namespace data
230} // namespace ore
std::map< AssetClass, std::set< std::string > > underlyingIndices(const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceDataManager=nullptr) const override
Add underlying Equity names.
vector< QuantLib::ext::shared_ptr< Underlying > > underlyings_
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
const vector< QuantLib::ext::shared_ptr< Underlying > > & underlyings() const
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
void addFixingDates(const std::vector< std::pair< QuantLib::Date, bool > > &fixingDates, const std::string &indexName, const QuantLib::Date &payDate=Date::maxDate(), const bool alwaysAddIfPaysOnSettlement=false)
void makeSchedules(const QuantLib::Date &openEndDateReplacement=QuantLib::Null< QuantLib::Date >())
Definition: schedule.cpp:214
void add(QuantLib::Schedule &schedule, const ScheduleData &scheduleData)
Definition: schedule.cpp:209
Serializable schedule data.
Definition: schedule.hpp:202
const vector< ScheduleDerived > & derived() const
Definition: schedule.hpp:230
bool hasData() const
Check if has any dates/rules/derived schedules.
Definition: schedule.hpp:223
virtual void fromXML(XMLNode *node) override
Definition: schedule.cpp:179
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: schedule.cpp:198
const bool & hasDerived() const
Definition: schedule.hpp:232
const string & name() const
Definition: schedule.hpp:231
Serializable object holding Derived schedule data.
Definition: schedule.hpp:157
string npvCurrency_
Definition: trade.hpp:201
QuantLib::Real notional_
Definition: trade.hpp:202
virtual void fromXML(XMLNode *node) override
Definition: trade.cpp:34
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
const string & tradeType() const
Definition: trade.hpp:133
Class to hold Underlyings.
Definition: underlying.hpp:37
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 vector< Real > getChildrenValuesAsDoubles(XMLNode *node, const string &names, const string &name, bool mandatory=false)
Definition: xmlutils.cpp:319
static vector< XMLNode * > getChildrenNodes(XMLNode *node, const string &name)
Returns all the children with a given name.
Definition: xmlutils.cpp:428
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 string getNodeValue(XMLNode *node)
Get a node's value.
Definition: xmlutils.cpp:489
static int getChildValueAsInt(XMLNode *node, const string &name, bool mandatory=false, int defaultValue=0)
Definition: xmlutils.cpp:291
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
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
Period parsePeriod(const string &s)
Convert text to QuantLib::Period.
Definition: parsers.cpp:171
@ data
Definition: log.hpp:77
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
Serializable Credit Default Swap.
Definition: namespaces.docs:23
pairwise variance swap representation
Map text representations to QuantLib/QuantExt types.
Reference data model and serialization.
string name