Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
ascot.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2020 Quaternion Risk Management Ltd
3
4 This file is part of ORE, a free-software/open-source library
5 for transparent pricing and risk analysis - http://opensourcerisk.org
6
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
12 This program is distributed on the basis that it will form a useful
13 contribution to risk analytics and model standardisation, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
16*/
17
20
22
23#include <ql/cashflows/cashflows.hpp>
24
25#include <boost/lexical_cast.hpp>
26
27namespace ore {
28namespace data {
29
30using namespace QuantLib;
31using namespace QuantExt;
32
33std::map<AssetClass, std::set<std::string>>
34Ascot::underlyingIndices(const QuantLib::ext::shared_ptr<ReferenceDataManager>& referenceDataManager) const {
35 return bond_.underlyingIndices(referenceDataManager);
36}
37
38void Ascot::build(const QuantLib::ext::shared_ptr<ore::data::EngineFactory>& engineFactory) {
39 DLOG("Ascot::build() called for trade " << id());
40
41 // ISDA taxonomy
42 additionalData_["isdaAssetClass"] = string("Credit");
43 additionalData_["isdaBaseProduct"] = string("Exotic");
44 additionalData_["isdaSubProduct"] = string("Other");
45 additionalData_["isdaTransaction"] = string("");
46
47 // build underlying convertible bond
48 bond_.reset();
49 // we need to do set the id manually because it otherwise remains blank
50 bond_.id() = id() + "_Bond";
51 bond_.build(engineFactory);
52 requiredFixings_.addData(bond_.requiredFixings());
53 QuantLib::ext::shared_ptr<QuantExt::ConvertibleBond2> cb =
54 QuantLib::ext::dynamic_pointer_cast<QuantExt::ConvertibleBond2>(bond_.instrument()->qlInstrument());
55
56 // check option fields
57 Exercise::Type exerciseType = parseExerciseType(optionData_.style());
58 QL_REQUIRE(exerciseType == Exercise::American, "expected American exercise type");
59 QL_REQUIRE(optionData_.exerciseDates().size() == 1,
60 "Ascot::build(): exactly one option date required, found " << optionData_.exerciseDates().size());
61 Date exerciseDate = parseDate(optionData_.exerciseDates().back());
62 QuantLib::ext::shared_ptr<Exercise> exercise = QuantLib::ext::make_shared<AmericanExercise>(exerciseDate);
63 Option::Type type = parseOptionType(optionData_.callPut());
64
65 // build funding leg
66 // Payer should be false,
67 // i.e. the swap is entered from the viewpoint of the asset swap buyer
68 QL_REQUIRE(fundingLegData_.isPayer() == false, "expected isPayer == false for funding leg");
69 Leg fundingLeg;
70
71 auto builder = QuantLib::ext::dynamic_pointer_cast<AscotEngineBuilder>(engineFactory->builder("Ascot"));
72 auto configuration = builder->configuration(MarketContext::pricing);
73 auto legBuilder = engineFactory->legBuilder(fundingLegData_.legType());
74 fundingLeg = legBuilder->buildLeg(fundingLegData_, engineFactory, requiredFixings_, configuration);
75
76 QL_REQUIRE(builder, "Ascot::build(): could not cast to AscotBuilder, this is unexpected");
77
78 auto qlAscot =
79 QuantLib::ext::make_shared<QuantExt::Ascot>(type, exercise, bond_.data().bondData().bondNotional(), cb, fundingLeg);
80 qlAscot->setPricingEngine(builder->engine(id(), bond_.data().bondData().currency()));
81 setSensitivityTemplate(*builder);
82
83 Real multiplier = (parsePositionType(optionData_.longShort()) == Position::Long ? 1.0 : -1.0);
84 instrument_ =
85 QuantLib::ext::shared_ptr<ore::data::InstrumentWrapper>(new ore::data::VanillaInstrument(qlAscot, multiplier));
86
87 npvCurrency_ = notionalCurrency_ = bond_.notionalCurrency();
88 legs_ = {cb->cashflows()};
89 legCurrencies_ = {npvCurrency_};
90 legPayers_ = {parsePositionType(optionData_.longShort()) == Position::Long};
91
92 notional_ = bond_.data().bondData().bondNotional();
93 maturity_ = bond_.maturity();
94}
95
96void Ascot::fromXML(XMLNode* node) {
97 Trade::fromXML(node);
98 XMLNode* dataNode = XMLUtils::getChildNode(node, "AscotData");
99 QL_REQUIRE(dataNode, "AscotData node not found");
100
101 ConvertibleBondData bondData;
102 bondData.fromXML(XMLUtils::getChildNode(dataNode, "ConvertibleBondData"));
103 bond_ = ConvertibleBond(envelope(), bondData);
104
105 optionData_.fromXML(XMLUtils::getChildNode(dataNode, "OptionData"));
106
107 XMLNode* tmpNode = XMLUtils::getChildNode(dataNode, "ReferenceSwapData");
108 QL_REQUIRE(tmpNode, "ReferenceSwapData node not found");
109 XMLNode* legNode = XMLUtils::getChildNode(tmpNode, "LegData");
110 QL_REQUIRE(legNode, "LegData node not found");
111 fundingLegData_.fromXML(legNode);
112}
113
114XMLNode* Ascot::toXML(XMLDocument& doc) const {
115 XMLNode* node = Trade::toXML(doc);
116 XMLNode* dataNode = doc.allocNode("AscotData");
117 XMLUtils::appendNode(node, dataNode);
118
119 ConvertibleBondData d = bond_.data();
120 XMLUtils::appendNode(dataNode, d.toXML(doc));
121 XMLUtils::appendNode(dataNode, optionData_.toXML(doc));
122
123 XMLNode* fundingDataNode = doc.allocNode("ReferenceSwapData");
124 XMLUtils::appendNode(dataNode, fundingDataNode);
125 XMLUtils::appendNode(fundingDataNode, fundingLegData_.toXML(doc));
126
127 return node;
128}
129
130} // namespace data
131} // namespace ore
Ascot (or Convertible Bond Option) trade data model and serialization.
const Leg & fundingLeg() const
ext::shared_ptr< ConvertibleBond2 > bond_
ext::shared_ptr< Exercise > exercise()
std::map< AssetClass, std::set< std::string > > underlyingIndices(const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceDataManager=nullptr) const override
Definition: ascot.cpp:34
void fromXML(ore::data::XMLNode *node) override
ore::data::XMLNode * toXML(ore::data::XMLDocument &doc) const override
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
Exercise::Type parseExerciseType(const std::string &s)
Convert text to QuantLib::Exercise::Type.
Definition: parsers.cpp:466
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
Option::Type parseOptionType(const std::string &s)
Convert text to QuantLib::Option::Type.
Definition: parsers.cpp:481
@ data
Definition: log.hpp:77
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Map text representations to QuantLib/QuantExt types.