Skip to content

Commit 2acc67b

Browse files
author
jenkins
committed
git subrepo pull (merge) ore
subrepo: subdir: "ore" merged: "628188fc7a" upstream: origin: "git@gitlab.acadiasoft.net:qs/ore.git" branch: "master" commit: "3545afeea3" git-subrepo: version: "0.4.6" origin: "https://github.com/ingydotnet/git-subrepo" commit: "73a0129"
2 parents b6e7b29 + 3545afe commit 2acc67b

9 files changed

Lines changed: 115 additions & 7 deletions

File tree

OREAnalytics/orea/app/inputparameters.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@ void InputParameters::setScenarioSimMarketParamsFromFile(const std::string& file
192192
scenarioSimMarketParams_->fromFile(fileName);
193193
}
194194

195+
void InputParameters::setHistVarSimMarketParams(const std::string& xml) {
196+
histVarSimMarketParams_ = QuantLib::ext::make_shared<ScenarioSimMarketParameters>();
197+
histVarSimMarketParams_->fromXMLString(xml);
198+
}
199+
195200
void InputParameters::setHistVarSimMarketParamsFromFile(const std::string& fileName) {
196201
histVarSimMarketParams_ = QuantLib::ext::make_shared<ScenarioSimMarketParameters>();
197202
histVarSimMarketParams_->fromFile(fileName);

OREAnalytics/orea/app/inputparameters.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ class InputParameters {
185185
void setBenchmarkVarPeriod(const std::string& period);
186186
void setHistoricalScenarioReader(const std::string& fileName);
187187
void setSensitivityStreamFromBuffer(const std::string& buffer);
188+
void setHistVarSimMarketParams(const std::string& xml);
188189
void setHistVarSimMarketParamsFromFile(const std::string& fileName);
189190
void setOutputHistoricalScenarios(const bool b) { outputHistoricalScenarios_ = b; }
190191

OREAnalytics/orea/cube/sensitivitycube.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,16 @@ RiskFactorKey SensitivityCube::upDownFactor(const Size index) const {
156156
}
157157
}
158158

159+
SensitivityCube::FactorData SensitivityCube::upThenDownFactorData(const RiskFactorKey& rfkey) {
160+
if (auto f = upFactors_.find(rfkey); f != upFactors_.end())
161+
return f->second;
162+
else if (auto f = downFactors_.find(rfkey); f != downFactors_.end())
163+
return f->second;
164+
else {
165+
QL_FAIL("SensitivityCube::upThenDownFactorData(): no up or down factor data found for " << rfkey);
166+
}
167+
}
168+
159169
SensitivityCube::crossPair SensitivityCube::crossFactor(const Size crossIndex) const {
160170
if (auto k = crossIndexToKey_.find(crossIndex); k != crossIndexToKey_.end()) {
161171
return k->second;

OREAnalytics/orea/cube/sensitivitycube.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ class SensitivityCube {
101101
//! Return the map of down risk factors to its factor data
102102
const std::map<RiskFactorKey, SensitivityCube::FactorData>& downFactors() const { return downFactors_; };
103103

104+
//! Return the factor data for an up shift of a rf key, if that does not exist for a down shift of the same rf key
105+
SensitivityCube::FactorData upThenDownFactorData(const RiskFactorKey& rfkey);
106+
104107
//! Returns the set of pairs of risk factor keys for which a cross gamma is available
105108
const std::map<crossPair, std::tuple<SensitivityCube::FactorData, SensitivityCube::FactorData, QuantLib::Size>>&
106109
crossFactors() const;

OREAnalytics/orea/engine/sensitivitycubestream.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ SensitivityRecord SensitivityCubeStream::next() {
8484
sr.baseNpv = cubes_[currentCubeIdx_]->npv(tradeIdx);
8585

8686
if (currentDeltaKey_ != currentDeltaKeys_.end()) {
87-
auto fd = cubes_[currentCubeIdx_]->upFactors().at(*currentDeltaKey_);
87+
auto const& fd = cubes_[currentCubeIdx_]->upThenDownFactorData(*currentDeltaKey_);
8888
sr.key_1 = *currentDeltaKey_;
8989
sr.desc_1 = fd.factorDesc;
9090
sr.shift_1 = fd.targetShiftSize;
@@ -95,7 +95,7 @@ SensitivityRecord SensitivityCubeStream::next() {
9595
sr.gamma = Null<Real>();
9696
++currentDeltaKey_;
9797
} else if (currentCrossGammaKey_ != currentCrossGammaKeys_.end()) {
98-
auto fd = cubes_[currentCubeIdx_]->crossFactors().at(*currentCrossGammaKey_);
98+
auto const& fd = cubes_[currentCubeIdx_]->crossFactors().at(*currentCrossGammaKey_);
9999
sr.key_1 = currentCrossGammaKey_->first;
100100
sr.desc_1 = std::get<0>(fd).factorDesc;
101101
sr.shift_1 = std::get<0>(fd).targetShiftSize;

OREAnalytics/test/cube.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@
5353
#include <ql/time/daycounters/actualactual.hpp>
5454
#include <oret/toplevelfixture.hpp>
5555
#include <test/oreatoplevelfixture.hpp>
56+
#include <ored/report/inmemoryreport.hpp>
57+
#include <orea/app/reportwriter.hpp>
5658

5759
#include "testmarket.hpp"
5860

@@ -537,6 +539,49 @@ BOOST_AUTO_TEST_CASE(testDoublePrecisionJaggedCube) {
537539
IndexManager::instance().clearHistories();
538540
}
539541

542+
string writeCube(const QuantLib::ext::shared_ptr<NPVCube>& cube, Size bufferSize) {
543+
auto report = QuantLib::ext::make_shared<InMemoryReport>(bufferSize);
544+
ReportWriter().writeCube(*report, cube);
545+
string fileName = boost::filesystem::unique_path().string();
546+
report->toFile(fileName);
547+
return fileName;
548+
}
549+
550+
void diffFiles(string filename1, string filename2) {
551+
std::ifstream ifs1(filename1);
552+
std::ifstream ifs2(filename2);
553+
554+
std::istream_iterator<char> b1(ifs1), e1;
555+
std::istream_iterator<char> b2(ifs2), e2;
556+
557+
BOOST_CHECK_EQUAL_COLLECTIONS(b1, e1, b2, e2);
558+
}
559+
560+
// Test the functionality of class InMemoryReport to cache data on disk
561+
BOOST_AUTO_TEST_CASE(testInMemoryReportBuffer) {
562+
563+
// Generate a cube
564+
std::set<string> ids{string("id")}; // the overlap doesn't matter
565+
vector<Date> dates(50, Date());
566+
Size samples = 200;
567+
Size depth = 6;
568+
auto c = QuantLib::ext::make_shared<SinglePrecisionInMemoryCubeN>(Date(), ids, dates, samples, depth);
569+
570+
// From the cube, generate multiple copies of the report, each of which which will have ~60K rows.
571+
// Specify different values for the buffer size in InMemoryReport:
572+
string filename_0 = writeCube(c, 0); // no buffering
573+
string filename_100 = writeCube(c, 100);
574+
string filename_1000 = writeCube(c, 1000);
575+
string filename_10000 = writeCube(c, 10000);
576+
string filename_100000 = writeCube(c, 100000); // buffer size > report size, resulting in no buffering
577+
578+
// Verify that buffering generates the same output as no buffering
579+
diffFiles(filename_0, filename_100);
580+
diffFiles(filename_0, filename_1000);
581+
diffFiles(filename_0, filename_10000);
582+
diffFiles(filename_0, filename_100000);
583+
}
584+
540585
BOOST_AUTO_TEST_SUITE_END()
541586

542587
BOOST_AUTO_TEST_SUITE_END()

OREData/ored/portfolio/legdata.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -942,7 +942,9 @@ Leg makeSimpleLeg(const LegData& data) {
942942
Leg leg;
943943
for (Size i = 0; i < dates.size(); i++) {
944944
Date d = parseDate(dates[i]);
945-
leg.push_back(QuantLib::ext::shared_ptr<CashFlow>(new SimpleCashFlow(amounts[i], d)));
945+
if (!data.paymentCalendar().empty() && !data.paymentConvention().empty())
946+
d = parseCalendar(data.paymentCalendar()).adjust(d, parseBusinessDayConvention(data.paymentConvention()));
947+
leg.push_back(QuantLib::ext::make_shared<SimpleCashFlow>(amounts[i], d));
946948
}
947949
return leg;
948950
}

OREData/ored/report/inmemoryreport.cpp

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,17 @@
1717
*/
1818

1919
#include <ored/report/inmemoryreport.hpp>
20+
#include <ored/utilities/serializationdate.hpp>
21+
#include <ored/utilities/serializationperiod.hpp>
2022

2123
#include <boost/algorithm/string/join.hpp>
24+
#include <boost/serialization/serialization.hpp>
25+
#include <boost/serialization/vector.hpp>
26+
#include <boost/serialization/variant.hpp>
27+
#include <boost/archive/binary_oarchive.hpp>
28+
#include <boost/archive/binary_iarchive.hpp>
29+
30+
#include <fstream>
2231

2332
namespace ore {
2433
namespace data {
@@ -27,15 +36,26 @@ Report& InMemoryReport::addColumn(const string& name, const ReportType& rt, Size
2736
headers_.push_back(name);
2837
columnTypes_.push_back(rt);
2938
columnPrecision_.push_back(precision);
30-
data_.push_back(vector<ReportType>()); // Initialise vector for
39+
data_.push_back(vector<ReportType>()); // Initialise vector for column
3140
i_++;
3241
return *this;
3342
}
3443

3544
Report& InMemoryReport::next() {
36-
QL_REQUIRE(i_ == headers_.size(), "Cannot go to next line, only " << i_ << " entires filled, report headers are: "
45+
QL_REQUIRE(i_ == headers_.size(), "Cannot go to next line, only " << i_ << " entries filled, report headers are: "
3746
<< boost::join(headers_, ","));
3847
i_ = 0;
48+
if (bufferSize_ && data_[0].size() == bufferSize_ && !headers_.empty()) {
49+
std::string s = std::tmpnam(nullptr);
50+
std::ofstream os(s.c_str(), std::ios::binary);
51+
boost::archive::binary_oarchive oa(os, boost::archive::no_header);
52+
for (Size i = 0; i < headers_.size(); i++) {
53+
oa << data_[i];
54+
data_[i].clear();
55+
}
56+
os.close();
57+
files_.push_back(s);
58+
}
3959
return *this;
4060
}
4161

@@ -85,6 +105,8 @@ void InMemoryReport::end() {
85105
}
86106

87107
const vector<Report::ReportType>& InMemoryReport::data(Size i) const {
108+
QL_REQUIRE(files_.empty(), "Member function InMemoryReport::data() is not supported "
109+
"when buffering is active");
88110
QL_REQUIRE(data_[i].size() == rows(), "internal error: report column "
89111
<< i << " (" << header(i) << ") contains " << data_[i].size()
90112
<< " rows, expected are " << rows()
@@ -103,6 +125,24 @@ void InMemoryReport::toFile(const string& filename, const char sep, const bool c
103125

104126
auto numColumns = columns();
105127
if (numColumns > 0) {
128+
129+
for (auto &f : files_) {
130+
vector<vector<ReportType>> data(numColumns);
131+
std::ifstream is(f.c_str(), std::ios::binary);
132+
boost::archive::binary_iarchive ia(is, boost::archive::no_header);
133+
for (Size i = 0; i < numColumns; i++) {
134+
ia >> data[i];
135+
}
136+
is.close();
137+
138+
for (Size i = 0; i < data[0].size(); i++) {
139+
cReport.next();
140+
for (Size j = 0; j < numColumns; j++) {
141+
cReport.add(data[j][i]);
142+
}
143+
}
144+
}
145+
106146
auto numRows = data_[0].size();
107147

108148
for (Size i = 0; i < numRows; i++) {

OREData/ored/report/inmemoryreport.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ using std::vector;
4040
*/
4141
class InMemoryReport : public Report {
4242
public:
43-
InMemoryReport() : i_(0) {}
43+
explicit InMemoryReport(Size bufferSize=100000) : i_(0), bufferSize_(bufferSize) {}
4444

4545
Report& addColumn(const string& name, const ReportType& rt, Size precision = 0) override;
4646
Report& next() override;
@@ -50,7 +50,7 @@ class InMemoryReport : public Report {
5050

5151
// InMemoryInterface
5252
Size columns() const { return headers_.size(); }
53-
Size rows() const { return columns() == 0 ? 0 : data_[0].size(); }
53+
Size rows() const { return columns() == 0 ? 0 : files_.size() * bufferSize_ + data_[0].size(); }
5454
const string& header(Size i) const { return headers_[i]; }
5555
bool hasHeader(string h) const { return std::find(headers_.begin(), headers_.end(), h) != headers_.end(); }
5656
ReportType columnType(Size i) const { return columnTypes_[i]; }
@@ -63,10 +63,12 @@ class InMemoryReport : public Report {
6363

6464
private:
6565
Size i_;
66+
Size bufferSize_;
6667
vector<string> headers_;
6768
vector<ReportType> columnTypes_;
6869
vector<Size> columnPrecision_;
6970
vector<vector<ReportType>> data_;
71+
vector<string> files_;
7072
};
7173

7274
//! InMemoryReport with access to plain types instead of boost::variant<>, to facilitate language bindings

0 commit comments

Comments
 (0)