Skip to content

Commit 16e971f

Browse files
rolandlichtersjenkins
authored andcommitted
QPR-12263 move formula based coupon into ore
1 parent 3df563f commit 16e971f

28 files changed

Lines changed: 2493 additions & 3 deletions

OREAnalytics/orea/engine/xvaenginecg.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
1717
*/
1818

19-
/*! \file engine/xvacgengine.hpp
19+
/*! \file orea/engine/xvaenginecg.hpp
2020
\brief xva engine using cg infrastructure
2121
\ingroup engine
2222
*/

OREData/ored/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ portfolio/builders/equityforward.cpp
158158
portfolio/builders/equityfuturesoption.cpp
159159
portfolio/builders/equityoption.cpp
160160
portfolio/builders/equitytouchoption.cpp
161+
portfolio/builders/formulabasedcoupon.cpp
161162
portfolio/builders/forwardbond.cpp
162163
portfolio/builders/fxasianoption.cpp
163164
portfolio/builders/fxbarrieroption.cpp
@@ -227,6 +228,9 @@ portfolio/equitytouchoption.cpp
227228
portfolio/europeanoptionbarrier.cpp
228229
portfolio/failedtrade.cpp
229230
portfolio/fixingdates.cpp
231+
portfolio/formulabasedindexbuilder.cpp
232+
portfolio/formulabasedlegbuilder.cpp
233+
portfolio/formulabasedlegdata.cpp
230234
portfolio/forwardbond.cpp
231235
portfolio/forwardrateagreement.cpp
232236
portfolio/fxaverageforward.cpp
@@ -340,6 +344,7 @@ utilities/currencyparser.cpp
340344
utilities/dategrid.cpp
341345
utilities/fileio.cpp
342346
utilities/flowanalysis.cpp
347+
utilities/formulaparser.cpp
343348
utilities/indexnametranslator.cpp
344349
utilities/indexparser.cpp
345350
utilities/inflationstartdate.cpp
@@ -525,6 +530,7 @@ portfolio/builders/equityforward.hpp
525530
portfolio/builders/equityfuturesoption.hpp
526531
portfolio/builders/equityoption.hpp
527532
portfolio/builders/equitytouchoption.hpp
533+
portfolio/builders/formulabasedcoupon.hpp
528534
portfolio/builders/forwardbond.hpp
529535
portfolio/builders/fxasianoption.hpp
530536
portfolio/builders/fxbarrieroption.hpp
@@ -597,6 +603,9 @@ portfolio/equitytouchoption.hpp
597603
portfolio/europeanoptionbarrier.hpp
598604
portfolio/failedtrade.hpp
599605
portfolio/fixingdates.hpp
606+
portfolio/formulabasedindexbuilder.hpp
607+
portfolio/formulabasedlegbuilder.hpp
608+
portfolio/formulabasedlegdata.hpp
600609
portfolio/forwardbond.hpp
601610
portfolio/forwardrateagreement.hpp
602611
portfolio/fxaverageforward.hpp
@@ -722,6 +731,7 @@ utilities/currencyhedgedequityindexdecomposition.hpp
722731
utilities/currencyparser.hpp
723732
utilities/dategrid.hpp
724733
utilities/fileio.hpp
734+
utilities/formulaparser.hpp
725735
utilities/flowanalysis.hpp
726736
utilities/indexnametranslator.hpp
727737
utilities/indexparser.hpp
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
Copyright (C) 2018 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+
#include <ored/portfolio/builders/formulabasedcoupon.hpp>
20+
#include <qle/cashflows/mcgaussianformulabasedcouponpricer.hpp>
21+
22+
#include <ql/math/matrixutilities/pseudosqrt.hpp>
23+
24+
#include <boost/algorithm/string.hpp>
25+
#include <boost/make_shared.hpp>
26+
27+
#include <ored/configuration/correlationcurveconfig.hpp>
28+
29+
#include <ored/utilities/indexparser.hpp>
30+
#include <ored/utilities/parsers.hpp>
31+
32+
#include <boost/algorithm/string.hpp>
33+
34+
#include <qle/termstructures/flatcorrelation.hpp>
35+
36+
namespace ore {
37+
namespace data {
38+
39+
boost::shared_ptr<FloatingRateCouponPricer> FormulaBasedCouponPricerBuilder::engineImpl(
40+
const std::string& paymentCcy,
41+
const std::map<std::string, boost::shared_ptr<QuantLib::IborCouponPricer>>& iborPricers,
42+
const std::map<std::string, boost::shared_ptr<QuantLib::CmsCouponPricer>>& cmsPricers,
43+
const std::map<std::string, boost::shared_ptr<InterestRateIndex>>& indexMaps) {
44+
45+
// MC parameters
46+
auto samples = parseInteger(engineParameters_.at("Samples"));
47+
auto seed = parseInteger(engineParameters_.at("Seed"));
48+
auto useSobol = parseBool(engineParameters_.at("Sobol"));
49+
SalvagingAlgorithm::Type salvaging = parseBool(engineParameters_.at("SalvageCorrelationMatrix"))
50+
? SalvagingAlgorithm::Spectral
51+
: SalvagingAlgorithm::None;
52+
53+
// build fx vol map
54+
std::map<std::string, Handle<BlackVolTermStructure>> fxVols;
55+
for (auto const& i : indexMaps) {
56+
std::string indexCcy = i.second->currency().code();
57+
if (indexCcy != paymentCcy) {
58+
fxVols[indexCcy] = (market_->fxVol(paymentCcy + indexCcy, configuration(MarketContext::pricing)));
59+
}
60+
}
61+
62+
// build correlation map (index-index or index-FX)
63+
// Index/Index correlation
64+
std::map<std::pair<std::string, std::string>, Handle<QuantExt::CorrelationTermStructure>> correlation;
65+
std::string fxSource = modelParameters_.at("FXSource");
66+
std::string index1, index2, indexQL1, indexQL2;
67+
68+
for (auto it1 = indexMaps.begin(); it1 != std::prev(indexMaps.end(), 1); it1++) {
69+
index1 = it1->first;
70+
indexQL1 = it1->second->name();
71+
for (auto it2 = std::next(it1, 1); it2 != indexMaps.end(); it2++) {
72+
index2 = it2->first;
73+
indexQL2 = it2->second->name();
74+
QuantLib::Handle<QuantExt::CorrelationTermStructure> corrCurve(
75+
boost::make_shared<FlatCorrelation>(0, NullCalendar(), 0.0, Actual365Fixed()));
76+
try {
77+
corrCurve = market_->correlationCurve(index1, index2, configuration(MarketContext::pricing));
78+
} catch (...) {
79+
WLOG("no correlation curve found for " << index1 << ", " << index2
80+
<< " found, fall back to zero correlation.");
81+
}
82+
correlation[std::make_pair(indexQL1, indexQL2)] = corrCurve;
83+
}
84+
}
85+
86+
std::string index, indexQL, indexCcy, fxIndex;
87+
for (auto const& it : indexMaps) {
88+
index = it.first;
89+
indexQL = it.second->name();
90+
std::vector<std::string> result;
91+
boost::split(result, index, boost::is_any_of("-"));
92+
indexCcy = result[0];
93+
if (indexCcy != paymentCcy) {
94+
fxIndex = "FX-" + fxSource + "-" + indexCcy + "-" + paymentCcy;
95+
QuantLib::Handle<QuantExt::CorrelationTermStructure> corrCurve(
96+
boost::make_shared<FlatCorrelation>(0, NullCalendar(), 0.0, Actual365Fixed()));
97+
try {
98+
corrCurve = market_->correlationCurve(index, fxIndex, configuration(MarketContext::pricing));
99+
} catch (...) {
100+
WLOG("no correlation curve found for " << index << ", " << fxIndex
101+
<< " found, fall back to zero correlation.");
102+
}
103+
correlation[std::make_pair(indexQL, "FX")] = corrCurve;
104+
}
105+
}
106+
107+
auto discount = market_->discountCurve(paymentCcy, configuration(MarketContext::pricing));
108+
return boost::make_shared<QuantExt::MCGaussianFormulaBasedCouponPricer>(
109+
paymentCcy, iborPricers, cmsPricers, fxVols, correlation, discount, samples, seed, useSobol, salvaging);
110+
}
111+
112+
} // namespace data
113+
} // namespace ore
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
Copyright (C) 2018 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+
#pragma once
20+
21+
#include <ored/portfolio/builders/cachingenginebuilder.hpp>
22+
#include <ored/portfolio/enginefactory.hpp>
23+
#include <ql/cashflows/couponpricer.hpp>
24+
25+
namespace ore {
26+
namespace data {
27+
28+
using namespace QuantExt;
29+
using namespace QuantLib;
30+
31+
class FormulaBasedCouponPricerBuilder
32+
: public ore::data::CachingCouponPricerBuilder<
33+
std::string, const std::string&, const std::map<std::string, boost::shared_ptr<QuantLib::IborCouponPricer>>&,
34+
const std::map<std::string, boost::shared_ptr<QuantLib::CmsCouponPricer>>&,
35+
const std::map<std::string, boost::shared_ptr<QuantLib::InterestRateIndex>>&> {
36+
public:
37+
FormulaBasedCouponPricerBuilder() : CachingEngineBuilder("BrigoMercurio", "MC", {"FormulaBasedCoupon"}) {}
38+
39+
protected:
40+
virtual std::string
41+
keyImpl(const std::string& paymentCcy, const std::map<std::string, boost::shared_ptr<QuantLib::IborCouponPricer>>&,
42+
const std::map<std::string, boost::shared_ptr<QuantLib::CmsCouponPricer>>&,
43+
const std::map<std::string, boost::shared_ptr<QuantLib::InterestRateIndex>>& indexMaps) override {
44+
std::string key = paymentCcy;
45+
for (auto const& i : indexMaps) {
46+
key += ":" + i.first;
47+
}
48+
return key;
49+
}
50+
virtual boost::shared_ptr<FloatingRateCouponPricer>
51+
engineImpl(const std::string& paymentCcy,
52+
const std::map<std::string, boost::shared_ptr<QuantLib::IborCouponPricer>>& iborPricers,
53+
const std::map<std::string, boost::shared_ptr<QuantLib::CmsCouponPricer>>& cmsPricers,
54+
const std::map<std::string, boost::shared_ptr<QuantLib::InterestRateIndex>>& indexMaps) override;
55+
};
56+
57+
} // namespace data
58+
} // namespace ore
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
Copyright (C) 2018 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+
#include <ored/portfolio/formulabasedindexbuilder.hpp>
20+
#include <ored/utilities/formulaparser.hpp>
21+
22+
#include <ored/utilities/indexparser.hpp>
23+
24+
#include <ql/time/calendars/jointcalendar.hpp>
25+
#include <ql/time/calendars/nullcalendar.hpp>
26+
27+
#include <boost/make_shared.hpp>
28+
29+
namespace ore {
30+
namespace data {
31+
32+
boost::shared_ptr<QuantExt::FormulaBasedIndex>
33+
makeFormulaBasedIndex(const std::string& formula, const boost::shared_ptr<ore::data::Market> market,
34+
const std::string& configuration,
35+
std::map<std::string, boost::shared_ptr<QuantLib::InterestRateIndex>>& indexMaps,
36+
const Calendar& fixingCalendar) {
37+
38+
indexMaps.clear();
39+
std::vector<boost::shared_ptr<QuantLib::InterestRateIndex>> indices;
40+
std::vector<std::string> variables;
41+
QuantExt::CompiledFormula compiledFormula = parseFormula(formula, variables);
42+
Calendar fixCal = NullCalendar();
43+
for (auto const& v : variables) {
44+
boost::shared_ptr<InterestRateIndex> index;
45+
boost::shared_ptr<IborIndex> dummyIborIndex;
46+
if (ore::data::tryParseIborIndex(v, dummyIborIndex)) {
47+
index = *market->iborIndex(v, configuration);
48+
} else {
49+
// if it is not an ibor index, we know it must be a swap index
50+
index = *market->swapIndex(v, configuration);
51+
}
52+
QL_REQUIRE(index != nullptr, "makeFormulaBasedIndex("
53+
<< formula << "): variable \"" << v
54+
<< "\" could not resolved as an ibor or swap index in the given market");
55+
indices.push_back(index);
56+
fixCal = JointCalendar(fixCal, index->fixingCalendar());
57+
indexMaps[v] = index;
58+
}
59+
60+
boost::shared_ptr<QuantExt::FormulaBasedIndex> fbi = boost::make_shared<QuantExt::FormulaBasedIndex>(
61+
"FormulaBasedIndex", indices, compiledFormula, fixingCalendar == Calendar() ? fixCal : fixingCalendar);
62+
return fbi;
63+
}
64+
65+
} // namespace data
66+
} // namespace ore
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
Copyright (C) 2018 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/formulabasedindexbuilder.hpp
20+
\brief formula based index builder
21+
\ingroup portfolio
22+
*/
23+
24+
#pragma once
25+
26+
#include <qle/indexes/formulabasedindex.hpp>
27+
28+
#include <ored/configuration/conventions.hpp>
29+
#include <ored/marketdata/market.hpp>
30+
31+
namespace ore {
32+
namespace data {
33+
using namespace QuantLib;
34+
35+
/*! builds a formula based index using the ibor and swap indices in the given market, the fixing
36+
calendar is the joint holiday calendar of all constituents of the resulting index */
37+
boost::shared_ptr<QuantExt::FormulaBasedIndex>
38+
makeFormulaBasedIndex(const std::string& formula, const boost::shared_ptr<ore::data::Market> market,
39+
const std::string& configuration,
40+
std::map<std::string, boost::shared_ptr<QuantLib::InterestRateIndex>>& indexMaps,
41+
const Calendar& fixingCalendar = Calendar());
42+
43+
} // namespace data
44+
} // namespace ore
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
Copyright (C) 2018 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+
#include <ored/portfolio/formulabasedlegbuilder.hpp>
20+
21+
#include <ored/portfolio/formulabasedindexbuilder.hpp>
22+
#include <ored/portfolio/formulabasedlegdata.hpp>
23+
namespace ore {
24+
namespace data {
25+
26+
Leg FormulaBasedLegBuilder::buildLeg(const LegData& data, const boost::shared_ptr<EngineFactory>& engineFactory,
27+
RequiredFixings& requiredFixings, const string& configuration,
28+
const QuantLib::Date& openEndDateReplacement, const bool useXbsCurves) const {
29+
auto formulaData = boost::dynamic_pointer_cast<FormulaBasedLegData>(data.concreteLegData());
30+
QL_REQUIRE(formulaData, "Wrong LegType, expected Formula");
31+
string formula = formulaData->formulaBasedIndex();
32+
Calendar cal;
33+
if (formulaData->fixingCalendar() != "")
34+
cal = parseCalendar(formulaData->fixingCalendar());
35+
std::map<std::string, boost::shared_ptr<QuantLib::InterestRateIndex>> indexMaps;
36+
auto formulaIndex =
37+
makeFormulaBasedIndex(formula, engineFactory->market(), configuration, indexMaps, cal);
38+
Leg result = makeFormulaBasedLeg(data, formulaIndex, engineFactory, indexMaps, openEndDateReplacement);
39+
// add required fixing dates
40+
for (auto const& m : indexMaps) {
41+
for (auto const& c : result) {
42+
auto f = boost::dynamic_pointer_cast<FloatingRateCoupon>(c);
43+
QL_REQUIRE(f != nullptr, "expected FloatingRateCoupon in FormulaBasedLegBuilder");
44+
requiredFixings.addFixingDate(f->fixingDate(), m.first, f->date(), false);
45+
}
46+
}
47+
return result;
48+
}
49+
50+
} // namespace data
51+
} // namespace ore

0 commit comments

Comments
 (0)