Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
enginefactory.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016-2022 Quaternion Risk Management Ltd
3 Copyright (C) 2021 Skandinaviska Enskilda Banken AB (publ)
4 All rights reserved.
5
6 This file is part of ORE, a free-software/open-source library
7 for transparent pricing and risk analysis - http://opensourcerisk.org
8
9 ORE is free software: you can redistribute it and/or modify it
10 under the terms of the Modified BSD License. You should have received a
11 copy of the license along with this program.
12 The license is also available online at <http://opensourcerisk.org>
13
14 This program is distributed on the basis that it will form a useful
15 contribution to risk analytics and model standardisation, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
22
23#include <boost/make_shared.hpp>
24#include <boost/algorithm/string/join.hpp>
25
26#include <ql/errors.hpp>
27
28namespace ore {
29namespace data {
30
31namespace {
32std::string getParameter(const std::map<std::string, std::string>& m, const std::string& p,
33 const std::vector<std::string>& qs, const bool mandatory, const std::string& defaultValue) {
34 // first look for p_q if one or several qualifiers are given
35 for (auto const& q : qs) {
36 if (!q.empty()) {
37 auto r = m.find(p + "_" + q);
38 if (r != m.end())
39 return r->second;
40 }
41 }
42 // no qualifier given, or fall back on p because p_q was not found
43 auto r = m.find(p);
44 if (r != m.end()) {
45 return r->second;
46 }
47 // if parameter is mandatory throw, otherwise return the default value
48 if (mandatory) {
49 QL_FAIL("parameter " << p << " not found (qualifier list was \"" << boost::algorithm::join(qs, ", ") << "\")");
50 }
51 return defaultValue;
52}
53} // namespace
54
55std::string EngineBuilder::engineParameter(const std::string& p, const std::vector<std::string>& qualifiers,
56 const bool mandatory, const std::string& defaultValue) const {
57 return getParameter(engineParameters_, p, qualifiers, mandatory, defaultValue);
58}
59
60std::string EngineBuilder::modelParameter(const std::string& p, const std::vector<std::string>& qualifiers,
61 const bool mandatory, const std::string& defaultValue) const {
62 return getParameter(modelParameters_, p, qualifiers, mandatory, defaultValue);
63}
64
65void EngineBuilderFactory::addEngineBuilder(const std::function<QuantLib::ext::shared_ptr<EngineBuilder>()>& builder,
66 const bool allowOverwrite) {
67 boost::unique_lock<boost::shared_mutex> lock(mutex_);
68 auto tmp = builder();
69 auto key = make_tuple(tmp->model(), tmp->engine(), tmp->tradeTypes());
70 auto it = std::remove_if(engineBuilderBuilders_.begin(), engineBuilderBuilders_.end(),
71 [&key](std::function<QuantLib::ext::shared_ptr<EngineBuilder>()>& b) {
72 auto tmp = b();
73 return key == std::make_tuple(tmp->model(), tmp->engine(), tmp->tradeTypes());
74 });
75 QL_REQUIRE(it == engineBuilderBuilders_.end() || allowOverwrite,
76 "EngineBuilderFactory::addEngineBuilder(" << tmp->model() << "/" << tmp->engine() << "/"
77 << boost::algorithm::join(tmp->tradeTypes(), ",")
78 << "): builder for given key already exists.");
80 engineBuilderBuilders_.push_back(builder);
81}
82
84 const std::function<QuantLib::ext::shared_ptr<EngineBuilder>(const QuantLib::ext::shared_ptr<QuantExt::CrossAssetModel>& cam,
85 const std::vector<Date>& grid)>& builder,
86 const bool allowOverwrite) {
87 boost::unique_lock<boost::shared_mutex> lock(mutex_);
88 auto tmp = builder(nullptr, {});
89 auto key = make_tuple(tmp->model(), tmp->engine(), tmp->tradeTypes());
90 auto it = std::remove_if(
92 [&key](std::function<QuantLib::ext::shared_ptr<EngineBuilder>(const QuantLib::ext::shared_ptr<QuantExt::CrossAssetModel>& cam,
93 const std::vector<Date>& grid)>& b) {
94 auto tmp = b(nullptr, {});
95 return key == std::make_tuple(tmp->model(), tmp->engine(), tmp->tradeTypes());
96 });
97 QL_REQUIRE(it == amcEngineBuilderBuilders_.end() || allowOverwrite,
98 "EngineBuilderFactory::addAmcEngineBuilder(" << tmp->model() << "/" << tmp->engine() << "/"
99 << boost::algorithm::join(tmp->tradeTypes(), ",")
100 << "): builder for given key already exists.");
101 amcEngineBuilderBuilders_.erase(it, amcEngineBuilderBuilders_.end());
102 amcEngineBuilderBuilders_.push_back(builder);
103}
104
106 const std::function<QuantLib::ext::shared_ptr<EngineBuilder>(const QuantLib::ext::shared_ptr<ore::data::ModelCG>& model,
107 const std::vector<Date>& grid)>& builder,
108 const bool allowOverwrite) {
109 boost::unique_lock<boost::shared_mutex> lock(mutex_);
110 auto tmp = builder(nullptr, {});
111 auto key = make_tuple(tmp->model(), tmp->engine(), tmp->tradeTypes());
112 auto it = std::remove_if(
114 [&key](std::function<QuantLib::ext::shared_ptr<EngineBuilder>(const QuantLib::ext::shared_ptr<ore::data::ModelCG>& model,
115 const std::vector<Date>& grid)>& b) {
116 auto tmp = b(nullptr, {});
117 return key == std::make_tuple(tmp->model(), tmp->engine(), tmp->tradeTypes());
118 });
119 QL_REQUIRE(it == amcCgEngineBuilderBuilders_.end() || allowOverwrite,
120 "EngineBuilderFactory::addAmcCgEngineBuilder(" << tmp->model() << "/" << tmp->engine() << "/"
121 << boost::algorithm::join(tmp->tradeTypes(), ",")
122 << "): builder for given key already exists.");
123 amcCgEngineBuilderBuilders_.erase(it, amcCgEngineBuilderBuilders_.end());
124 amcCgEngineBuilderBuilders_.push_back(builder);
125}
126
127void EngineBuilderFactory::addLegBuilder(const std::function<QuantLib::ext::shared_ptr<LegBuilder>()>& builder,
128 const bool allowOverwrite) {
129 boost::unique_lock<boost::shared_mutex> lock(mutex_);
130 auto key = builder()->legType();
131 auto it =
132 std::remove_if(legBuilderBuilders_.begin(), legBuilderBuilders_.end(),
133 [&key](std::function<QuantLib::ext::shared_ptr<LegBuilder>()>& b) { return key == b()->legType(); });
134 QL_REQUIRE(it == legBuilderBuilders_.end() || allowOverwrite,
135 "EngineBuilderFactory::addLegBuilder(" << key << "): builder for given key already exists.");
137 legBuilderBuilders_.push_back(builder);
138}
139
140std::vector<QuantLib::ext::shared_ptr<EngineBuilder>> EngineBuilderFactory::generateEngineBuilders() const {
141 boost::shared_lock<boost::shared_mutex> lock(mutex_);
142 std::vector<QuantLib::ext::shared_ptr<EngineBuilder>> result;
143 for (auto const& b : engineBuilderBuilders_)
144 result.push_back(b());
145 return result;
146}
147
148std::vector<QuantLib::ext::shared_ptr<EngineBuilder>>
149EngineBuilderFactory::generateAmcEngineBuilders(const QuantLib::ext::shared_ptr<QuantExt::CrossAssetModel>& cam,
150 const std::vector<Date>& grid) const {
151 boost::shared_lock<boost::shared_mutex> lock(mutex_);
152 std::vector<QuantLib::ext::shared_ptr<EngineBuilder>> result;
153 for (auto const& b : amcEngineBuilderBuilders_)
154 result.push_back(b(cam, grid));
155 return result;
156}
157
158std::vector<QuantLib::ext::shared_ptr<EngineBuilder>>
159EngineBuilderFactory::generateAmcCgEngineBuilders(const QuantLib::ext::shared_ptr<ore::data::ModelCG>& model,
160 const std::vector<Date>& grid) const {
161 boost::shared_lock<boost::shared_mutex> lock(mutex_);
162 std::vector<QuantLib::ext::shared_ptr<EngineBuilder>> result;
163 for (auto const& b : amcCgEngineBuilderBuilders_)
164 result.push_back(b(model, grid));
165 return result;
166}
167
168std::vector<QuantLib::ext::shared_ptr<LegBuilder>> EngineBuilderFactory::generateLegBuilders() const {
169 boost::shared_lock<boost::shared_mutex> lock(mutex_);
170 std::vector<QuantLib::ext::shared_ptr<LegBuilder>> result;
171 for (auto const& b : legBuilderBuilders_)
172 result.push_back(b());
173 return result;
174}
175
176EngineFactory::EngineFactory(const QuantLib::ext::shared_ptr<EngineData>& engineData, const QuantLib::ext::shared_ptr<Market>& market,
177 const map<MarketContext, string>& configurations,
178 const QuantLib::ext::shared_ptr<ReferenceDataManager>& referenceData,
179 const IborFallbackConfig& iborFallbackConfig,
180 const std::vector<QuantLib::ext::shared_ptr<EngineBuilder>> extraEngineBuilders,
181 const bool allowOverwrite)
182 : market_(market), engineData_(engineData), configurations_(configurations), referenceData_(referenceData),
183 iborFallbackConfig_(iborFallbackConfig) {
184 LOG("Building EngineFactory");
185
187 addExtraBuilders(extraEngineBuilders, {}, allowOverwrite);
188}
189
190void EngineFactory::registerBuilder(const QuantLib::ext::shared_ptr<EngineBuilder>& builder, const bool allowOverwrite) {
191 const string& modelName = builder->model();
192 const string& engineName = builder->engine();
193 auto key = make_tuple(modelName, engineName, builder->tradeTypes());
194 if (allowOverwrite)
195 builders_.erase(key);
196 QL_REQUIRE(builders_.insert(make_pair(key, builder)).second,
197 "EngineFactory: duplicate engine builder for (" << modelName << "/" << engineName << "/"
198 << boost::algorithm::join(builder->tradeTypes(), ",")
199 << ") - this is an internal error.");
200}
201
202QuantLib::ext::shared_ptr<EngineBuilder> EngineFactory::builder(const string& tradeType) {
203 // Check that we have a model/engine for tradetype
204 QL_REQUIRE(engineData_->hasProduct(tradeType),
205 "No Pricing Engine configuration was provided for trade type " << tradeType);
206
207 // Find a builder for the model/engine/tradeType
208 const string& model = engineData_->model(tradeType);
209 const string& engine = engineData_->engine(tradeType);
210 typedef pair<tuple<string, string, set<string>>, QuantLib::ext::shared_ptr<EngineBuilder>> map_type;
211 auto pred = [&model, &engine, &tradeType](const map_type& v) -> bool {
212 const set<string>& types = std::get<2>(v.first);
213 return std::get<0>(v.first) == model && std::get<1>(v.first) == engine &&
214 std::find(types.begin(), types.end(), tradeType) != types.end();
215 };
216 auto it = std::find_if(builders_.begin(), builders_.end(), pred);
217 QL_REQUIRE(it != builders_.end(), "No EngineBuilder for " << model << "/" << engine << "/" << tradeType);
218 QL_REQUIRE(std::find_if(std::next(it, 1), builders_.end(), pred) == builders_.end(),
219 "Ambiguous EngineBuilder for " << model << "/" << engine << "/" << tradeType);
220
221 QuantLib::ext::shared_ptr<EngineBuilder> builder = it->second;
222 string effectiveTradeType = tradeType;
223 if(auto db = QuantLib::ext::dynamic_pointer_cast<DelegatingEngineBuilder>(builder))
224 effectiveTradeType = db->effectiveTradeType();
225
226 builder->init(market_, configurations_, engineData_->modelParameters(effectiveTradeType),
227 engineData_->engineParameters(effectiveTradeType), engineData_->globalParameters());
228
229 return builder;
230}
231
232void EngineFactory::registerLegBuilder(const QuantLib::ext::shared_ptr<LegBuilder>& legBuilder, const bool allowOverwrite) {
233 if (allowOverwrite)
234 legBuilders_.erase(legBuilder->legType());
235 QL_REQUIRE(legBuilders_.insert(make_pair(legBuilder->legType(), legBuilder)).second,
236 "EngineFactory duplicate leg builder for '" << legBuilder->legType()
237 << "' - this is an internal error.");
238}
239
240QuantLib::ext::shared_ptr<LegBuilder> EngineFactory::legBuilder(const string& legType) {
241 auto it = legBuilders_.find(legType);
242 QL_REQUIRE(it != legBuilders_.end(), "No LegBuilder for " << legType);
243 return it->second;
244}
245
246set<std::pair<string, QuantLib::ext::shared_ptr<QuantExt::ModelBuilder>>> EngineFactory::modelBuilders() const {
247 set<std::pair<string, QuantLib::ext::shared_ptr<QuantExt::ModelBuilder>>> res;
248 for (auto const& b : builders_) {
249 res.insert(b.second->modelBuilders().begin(), b.second->modelBuilders().end());
250 }
251 return res;
252}
253
255 for(auto const& b: EngineBuilderFactory::instance().generateEngineBuilders())
257 for(auto const& b: EngineBuilderFactory::instance().generateLegBuilders())
259}
260
261void EngineFactory::addExtraBuilders(const std::vector<QuantLib::ext::shared_ptr<EngineBuilder>> extraEngineBuilders,
262 const std::vector<QuantLib::ext::shared_ptr<LegBuilder>> extraLegBuilders,
263 const bool allowOverwrite) {
264
265 if (extraEngineBuilders.size() > 0) {
266 DLOG("adding " << extraEngineBuilders.size() << " extra engine builders");
267 for (auto eb : extraEngineBuilders)
268 registerBuilder(eb, allowOverwrite);
269 }
270 if (extraLegBuilders.size() > 0) {
271 DLOG("adding " << extraLegBuilders.size() << " extra leg builders");
272 for (auto elb : extraLegBuilders)
273 registerLegBuilder(elb, allowOverwrite);
274 }
275}
276
277} // namespace data
278} // namespace ore
std::vector< std::function< QuantLib::ext::shared_ptr< LegBuilder >()> > legBuilderBuilders_
void addEngineBuilder(const std::function< QuantLib::ext::shared_ptr< EngineBuilder >()> &builder, const bool allowOverwrite=false)
std::vector< QuantLib::ext::shared_ptr< EngineBuilder > > generateAmcEngineBuilders(const QuantLib::ext::shared_ptr< QuantExt::CrossAssetModel > &cam, const std::vector< Date > &grid) const
void addAmcEngineBuilder(const std::function< QuantLib::ext::shared_ptr< EngineBuilder >(const QuantLib::ext::shared_ptr< QuantExt::CrossAssetModel > &cam, const std::vector< Date > &grid)> &builder, const bool allowOverwrite=false)
std::vector< QuantLib::ext::shared_ptr< EngineBuilder > > generateEngineBuilders() const
std::vector< QuantLib::ext::shared_ptr< LegBuilder > > generateLegBuilders() const
void addAmcCgEngineBuilder(const std::function< QuantLib::ext::shared_ptr< EngineBuilder >(const QuantLib::ext::shared_ptr< ore::data::ModelCG > &model, const std::vector< Date > &grid)> &builder, const bool allowOverwrite=false)
std::vector< std::function< QuantLib::ext::shared_ptr< EngineBuilder >()> > engineBuilderBuilders_
std::vector< std::function< QuantLib::ext::shared_ptr< EngineBuilder >(const QuantLib::ext::shared_ptr< QuantExt::CrossAssetModel > &cam, const std::vector< Date > &grid)> > amcEngineBuilderBuilders_
std::vector< QuantLib::ext::shared_ptr< EngineBuilder > > generateAmcCgEngineBuilders(const QuantLib::ext::shared_ptr< ore::data::ModelCG > &model, const std::vector< Date > &grid) const
std::vector< std::function< QuantLib::ext::shared_ptr< EngineBuilder >(const QuantLib::ext::shared_ptr< ore::data::ModelCG > &model, const std::vector< Date > &grid)> > amcCgEngineBuilderBuilders_
void addLegBuilder(const std::function< QuantLib::ext::shared_ptr< LegBuilder >()> &builder, const bool allowOverwrite=false)
map< string, string > engineParameters_
std::string modelParameter(const std::string &p, const std::vector< std::string > &qualifiers={}, const bool mandatory=true, const std::string &defaultValue="") const
std::string engineParameter(const std::string &p, const std::vector< std::string > &qualifiers={}, const bool mandatory=true, const std::string &defaultValue="") const
map< string, string > modelParameters_
QuantLib::ext::shared_ptr< Market > market_
QuantLib::ext::shared_ptr< EngineBuilder > builder(const string &tradeType)
Get a builder by trade type.
map< string, QuantLib::ext::shared_ptr< LegBuilder > > legBuilders_
QuantLib::ext::shared_ptr< LegBuilder > legBuilder(const string &legType)
Get a leg builder by leg type.
QuantLib::ext::shared_ptr< EngineData > engineData_
set< std::pair< string, QuantLib::ext::shared_ptr< QuantExt::ModelBuilder > > > modelBuilders() const
return model builders
void addDefaultBuilders()
Add a set of default engine and leg builders.
EngineFactory(const QuantLib::ext::shared_ptr< EngineData > &data, const QuantLib::ext::shared_ptr< Market > &market, const map< MarketContext, string > &configurations=std::map< MarketContext, string >(), const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceData=nullptr, const IborFallbackConfig &iborFallbackConfig=IborFallbackConfig::defaultConfig(), const std::vector< QuantLib::ext::shared_ptr< EngineBuilder > > extraEngineBuilders={}, const bool allowOverwrite=false)
Create an engine factory.
map< MarketContext, string > configurations_
void addExtraBuilders(const std::vector< QuantLib::ext::shared_ptr< EngineBuilder > > extraEngineBuilders, const std::vector< QuantLib::ext::shared_ptr< LegBuilder > > extraLegBuilders, const bool allowOverwrite=false)
Add a set of default engine and leg builders, overwrite existing builders with same key if specified.
map< tuple< string, string, set< string > >, QuantLib::ext::shared_ptr< EngineBuilder > > builders_
void registerBuilder(const QuantLib::ext::shared_ptr< EngineBuilder > &builder, const bool allowOverwrite=false)
Register a builder with the factory.
void registerLegBuilder(const QuantLib::ext::shared_ptr< LegBuilder > &legBuilder, const bool allowOverwrite=false)
Register a leg builder with the factory.
Pricing Engine Factory.
Classes and functions for log message handling.
@ data
Definition: log.hpp:77
#define LOG(text)
Logging Macro (Level = Notice)
Definition: log.hpp:552
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
boost::bimap< std::string, TRS::FundingData::NotionalType > types
Definition: trs.cpp:783
Serializable Credit Default Swap.
Definition: namespaces.docs:23