19#include <boost/test/unit_test.hpp>
22#include <oret/toplevelfixture.hpp>
23#include <ql/math/comparison.hpp>
26using namespace boost::unit_test_framework;
41static const set<SensitivityRecord> records = {
42 {
"trade_001",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 3),
"6M", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -103053.46, 74.06, 0.00},
43 {
"trade_001",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 4),
"1Y", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -103053.46, 354.79, -0.03 },
44 {
"trade_001",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 3),
"6M", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -103053.46, -72.54, 0.00 },
45 {
"trade_001",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 4),
"1Y", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -103053.46, -347.52, 0.02 },
46 {
"trade_001",
false,
RiskFactorKey(RFType::FXSpot,
"CNYUSD", 0),
"spot", 0.001534,
RiskFactorKey(),
"", 0.0,
"USD", -103053.46, -50331.89, 0.00 },
47 {
"trade_001",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 3),
"6M", 0.0001,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 4),
"1Y", 0.0001,
"USD", -103053.46, 0, -0.01 },
48 {
"trade_001",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 3),
"6M", 0.0001,
RiskFactorKey(RFType::FXSpot,
"CNYUSD", 0),
"spot", 0.001534,
"USD", -103053.46, 0, 0.74 },
49 {
"trade_001",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 4),
"1Y", 0.0001,
RiskFactorKey(RFType::FXSpot,
"CNYUSD", 0),
"spot", 0.001534,
"USD", -103053.46, 0, 3.55 },
50 {
"trade_001",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 3),
"6M", 0.0001,
RiskFactorKey(RFType::DiscountCurve,
"USD", 4),
"1Y", 0.0001,
"USD", -103053.46, 0, 0.01 },
51 {
"trade_002",
false,
RiskFactorKey(RFType::DiscountCurve,
"TWD", 1),
"1M", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", 393612.36, 0.26, 0.00 },
52 {
"trade_002",
false,
RiskFactorKey(RFType::DiscountCurve,
"TWD", 2),
"3M", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", 393612.36, 14.11, 0.00 },
53 {
"trade_002",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 1),
"1M", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", 393612.36, -0.43, 0.00 },
54 {
"trade_002",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 2),
"3M", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", 393612.36, -23.32, 0.00 },
55 {
"trade_002",
false,
RiskFactorKey(RFType::FXSpot,
"TWDUSD", 0),
"spot", 0.0002,
RiskFactorKey(),
"", 0.0,
"USD", 393612.36, -6029.41, 0.00 },
56 {
"trade_003",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 1),
"1M", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -156337.99, 38.13, 0.00 },
57 {
"trade_003",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 2),
"3M", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -156337.99, 114.53, 0.00 },
58 {
"trade_003",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 1),
"1M", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -156337.99, -37.48, 0.00 },
59 {
"trade_003",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 2),
"3M", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -156337.99, -112.57, 0.00 },
60 {
"trade_003",
false,
RiskFactorKey(RFType::FXSpot,
"CNYUSD", 0),
"spot", 0.001534,
RiskFactorKey(),
"", 0.0,
"USD", -156337.99, -91345.92, 0.00 },
61 {
"trade_003",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 1),
"1M", 0.0001,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 2),
"3M", 0.0001,
"USD", -156337.99, 0, 0.00 },
62 {
"trade_003",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 1),
"1M", 0.0001,
RiskFactorKey(RFType::FXSpot,
"CNYUSD", 0),
"spot", 0.001534,
"USD", -156337.99, 0, 0.38 },
63 {
"trade_003",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 2),
"3M", 0.0001,
RiskFactorKey(RFType::FXSpot,
"CNYUSD", 0),
"spot", 0.001534,
"USD", -156337.99, 0, 1.15 },
64 {
"trade_003",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 1),
"1M", 0.0001,
RiskFactorKey(RFType::DiscountCurve,
"USD", 2),
"3M", 0.0001,
"USD", -156337.99, 0, 0.00 },
65 {
"trade_004",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 3),
"6M", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -110809.22, 27.11, 0.00 },
66 {
"trade_004",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 4),
"1Y", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -110809.22, 940.54, -0.09 },
67 {
"trade_004",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 3),
"6M", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -110809.22, -26.81, 0.00 },
68 {
"trade_004",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 4),
"1Y", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -110809.22, -930.06, 0.09 },
69 {
"trade_004",
false,
RiskFactorKey(RFType::FXSpot,
"CNYUSD", 0),
"spot", 0.001534,
RiskFactorKey(),
"", 0.0,
"USD", -110809.22, -99495.14, 0.00 },
70 {
"trade_004",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 3),
"6M", 0.0001,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 4),
"1Y", 0.0001,
"USD", -110809.22, 0, 0.00 },
71 {
"trade_004",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 3),
"6M", 0.0001,
RiskFactorKey(RFType::FXSpot,
"CNYUSD", 0),
"spot", 0.001534,
"USD", -110809.22, 0, 0.27 },
72 {
"trade_004",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 4),
"1Y", 0.0001,
RiskFactorKey(RFType::FXSpot,
"CNYUSD", 0),
"spot", 0.001534,
"USD", -110809.22, 0, 9.41 },
73 {
"trade_004",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 3),
"6M", 0.0001,
RiskFactorKey(RFType::DiscountCurve,
"USD", 4),
"1Y", 0.0001,
"USD", -110809.22, 0, 0.00 },
74 {
"trade_005",
false,
RiskFactorKey(RFType::DiscountCurve,
"TWD", 1),
"1M", 0.0001,
RiskFactorKey(),
"", 0.0,
"EUR", 393612.36, 0.26, 0.00 },
75 {
"trade_005",
false,
RiskFactorKey(RFType::DiscountCurve,
"TWD", 2),
"3M", 0.0001,
RiskFactorKey(),
"", 0.0,
"EUR", 393612.36, 14.11, 0.00 },
76 {
"trade_005",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 1),
"1M", 0.0001,
RiskFactorKey(),
"", 0.0,
"EUR", 393612.36, -0.43, 0.00 },
77 {
"trade_005",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 2),
"3M", 0.0001,
RiskFactorKey(),
"", 0.0,
"EUR", 393612.36, -23.32, 0.00 },
78 {
"trade_005",
false,
RiskFactorKey(RFType::FXSpot,
"TWDUSD", 0),
"spot", 0.0002,
RiskFactorKey(),
"", 0.0,
"EUR", 393612.36, -6029.41, 0.00 },
79 {
"trade_006",
false,
RiskFactorKey(RFType::DiscountCurve,
"TWD", 1),
"1M", 0.0001,
RiskFactorKey(),
"", 0.0,
"EUR", -393612.36, -0.26, 0.00 },
80 {
"trade_006",
false,
RiskFactorKey(RFType::DiscountCurve,
"TWD", 2),
"3M", 0.0001,
RiskFactorKey(),
"", 0.0,
"EUR", -393612.36, -14.11, 0.00 },
81 {
"trade_006",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 1),
"1M", 0.0001,
RiskFactorKey(),
"", 0.0,
"EUR", -393612.36, 0.43, 0.00 },
82 {
"trade_006",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 2),
"3M", 0.0001,
RiskFactorKey(),
"", 0.0,
"EUR", -393612.36, 23.32, 0.00 },
83 {
"trade_006",
false,
RiskFactorKey(RFType::FXSpot,
"TWDUSD", 0),
"spot", 0.0002,
RiskFactorKey(),
"", 0.0,
"EUR", -393612.36, 6029.41, 0.00 }
90 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 1),
"1M", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -156337.99, 38.13, 0 },
91 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 2),
"3M", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -156337.99, 114.53, 0 },
92 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 3),
"6M", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -213862.68, 101.17, 0 },
93 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 4),
"1Y", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -213862.68, 1295.33, -0.12 },
94 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 1),
"1M", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -156337.99, -37.48, 0 },
95 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 2),
"3M", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -156337.99, -112.57, 0 },
96 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 3),
"6M", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -213862.68, -99.35, 0 },
97 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 4),
"1Y", 0.0001,
RiskFactorKey(),
"", 0.0,
"USD", -213862.68, -1277.58, 0.11 },
98 {
"",
false,
RiskFactorKey(RFType::FXSpot,
"CNYUSD", 0),
"spot", 0.001534,
RiskFactorKey(),
"", 0.0,
"USD", -370200.67, -241172.95, 0 },
99 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 1),
"1M", 0.0001,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 2),
"3M", 0.0001,
"USD", -156337.99, 0.00, 0.00 },
100 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 1),
"1M", 0.0001,
RiskFactorKey(RFType::FXSpot,
"CNYUSD", 0),
"spot", 0.001534,
"USD", -156337.99, 0.00, 0.38 },
101 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 2),
"3M", 0.0001,
RiskFactorKey(RFType::FXSpot,
"CNYUSD", 0),
"spot", 0.001534,
"USD", -156337.99, 0.00, 1.15 },
102 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 3),
"6M", 0.0001,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 4),
"1Y", 0.0001,
"USD", -213862.68, 0.00, -0.01 },
103 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 3),
"6M", 0.0001,
RiskFactorKey(RFType::FXSpot,
"CNYUSD", 0),
"spot", 0.001534,
"USD", -213862.68, 0.00, 1.01 },
104 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"CNY", 4),
"1Y", 0.0001,
RiskFactorKey(RFType::FXSpot,
"CNYUSD", 0),
"spot", 0.001534,
"USD", -213862.68, 0.00, 12.96 },
105 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 1),
"1M", 0.0001,
RiskFactorKey(RFType::DiscountCurve,
"USD", 2),
"3M", 0.0001,
"USD", -156337.99, 0.00, 0.00 },
106 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 3),
"6M", 0.0001,
RiskFactorKey(RFType::DiscountCurve,
"USD", 4),
"1Y", 0.0001,
"USD", -213862.68, 0.00, 0.01 },
107 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"TWD", 1),
"1M", 0.0001,
RiskFactorKey(),
"", 0.0,
"EUR", 0, 0, 0.00 },
108 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"TWD", 2),
"3M", 0.0001,
RiskFactorKey(),
"", 0.0,
"EUR", 0, 0, 0.00 },
109 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 1),
"1M", 0.0001,
RiskFactorKey(),
"", 0.0,
"EUR", 0, 0, 0.00 },
110 {
"",
false,
RiskFactorKey(RFType::DiscountCurve,
"USD", 2),
"3M", 0.0001,
RiskFactorKey(),
"", 0.0,
"EUR", 0, 0, 0.00 },
111 {
"",
false,
RiskFactorKey(RFType::FXSpot,
"TWDUSD", 0),
"spot", 0.0002,
RiskFactorKey(),
"", 0.0,
"EUR", 0, 0, 0.00 }
117set<SensitivityRecord>
filter(set<SensitivityRecord> records,
const string& tradeId) {
118 set<SensitivityRecord> res;
119 for (
auto sr : records) {
120 if (sr.tradeId == tradeId) {
130void check(
const set<SensitivityRecord>& exp,
const set<SensitivityRecord>& res,
const string& category) {
131 BOOST_CHECK_EQUAL_COLLECTIONS(
exp.begin(),
exp.end(), res.begin(), res.end());
132 for (set<SensitivityRecord>::iterator itExp =
exp.begin(), itRes = res.begin(); itExp !=
exp.end();
134 BOOST_CHECK_MESSAGE(QuantLib::close(itExp->baseNpv, itRes->baseNpv),
135 "Category = " << category <<
": Base NPVs (exp = " << itExp->baseNpv
136 <<
" vs. actual = " << itRes->baseNpv
137 <<
") are not equal for aggregated expected record " << *itExp);
138 BOOST_CHECK_MESSAGE(QuantLib::close(itExp->delta, itRes->delta),
139 "Category = " << category <<
": Deltas (exp = " << itExp->delta
140 <<
" vs. actual = " << itRes->delta
141 <<
") are not equal for aggregated expected record " << *itExp);
142 BOOST_CHECK_MESSAGE(QuantLib::close(itExp->gamma, itRes->gamma),
143 "Category = " << category <<
": Gammas (exp = " << itExp->gamma
144 <<
" vs. actual = " << itRes->gamma
145 <<
") are not equal for aggregated expected record " << *itExp);
151BOOST_AUTO_TEST_SUITE(SensitivityAggregatorTest)
155 BOOST_TEST_MESSAGE(
"Testing general aggregation using sets of trades for categories");
161 map<string, set<std::pair<std::string, QuantLib::Size>>> categories;
163 set<pair<string, QuantLib::Size>> trades = {make_pair(
"trade_001", 0), make_pair(
"trade_003", 1),
164 make_pair(
"trade_004", 2), make_pair(
"trade_005", 3),
165 make_pair(
"trade_006", 4)};
167 for (
const auto& trade : trades) {
168 categories[trade.first] = {trade};
171 categories[
"all_except_002"] = trades;
178 set<SensitivityRecord>
exp;
179 set<SensitivityRecord> res;
182 for (
const auto& trade : trades) {
185 BOOST_TEST_MESSAGE(
"Testing for category with single trade " << trade.first);
190 BOOST_TEST_MESSAGE(
"Testing for category 'all_except_002'");
197 BOOST_TEST_MESSAGE(
"Testing general aggregation using functions for categories");
203 map<string, function<
bool(
string)>> categories;
205 set<pair<string, QuantLib::Size>> trades = {make_pair(
"trade_001", 0), make_pair(
"trade_003", 1),
206 make_pair(
"trade_004", 2), make_pair(
"trade_005", 3),
207 make_pair(
"trade_006", 4)};
209 for (
const auto& trade : trades) {
210 categories[trade.first] = [&trade](
string tradeId) {
return tradeId == trade.first; };
213 categories[
"all_except_002"] = [&trades](
string tradeId) {
214 for (
auto it = trades.begin(); it != trades.end(); ++it) {
215 if (it->first == tradeId)
226 set<SensitivityRecord>
exp;
227 set<SensitivityRecord> res;
230 for (
const auto& trade : trades) {
233 BOOST_TEST_MESSAGE(
"Testing for category with single trade " << trade.first);
238 BOOST_TEST_MESSAGE(
"Testing for category 'all_except_002'");
243BOOST_AUTO_TEST_SUITE_END()
245BOOST_AUTO_TEST_SUITE_END()
Data types stored in the scenario class.
KeyType
Risk Factor types.
const std::set< SensitivityRecord > & sensitivities(const std::string &category) const
void aggregate(SensitivityStream &ss, const QuantLib::ext::shared_ptr< ScenarioFilter > &filter=QuantLib::ext::make_shared< ScenarioFilter >())
Class for streaming SensitivityRecords from csv file.
OREAnalytics Top level fixture.
SafeStack< Filter > filter
RandomVariable exp(RandomVariable x)
Fixture that can be used at top level of OREAnalytics test suites.
Class for aggregating SensitivityRecords.
Class for streaming SensitivityRecords from in-memory container.
BOOST_AUTO_TEST_CASE(testGeneralAggregationSetCategories)
set< SensitivityRecord > expAggregationAll