Skip to content

Commit 64f4af8

Browse files
committed
Merge branch 'master' into 'master'
v1.8.12.0.1 update Closes QPR-12520 and QPR-12398 See merge request qs/ore-github!57
2 parents b5c909a + c7388b7 commit 64f4af8

24 files changed

Lines changed: 210 additions & 32 deletions

Docs/UserGuide/tradecomponents/scheduledata.tex

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ \subsubsection{Schedule Data (Rules, Dates and Derived)}\label{ss:schedule_data}
3838
<Convention>Following</Convention>
3939
<Tenor>3M</Tenor>
4040
<EndOfMonth>false</EndOfMonth>
41+
<EndOfMOnthConvention>Following</EndOfMOnthConvention>
4142
<Dates>
4243
<Date>2012-01-06</Date>
4344
<Date>2012-04-10</Date>
@@ -129,6 +130,14 @@ \subsubsection{Schedule Data (Rules, Dates and Derived)}\label{ss:schedule_data}
129130

130131
Allowable values: Boolean node, allowing \emph{Y, N, 1, 0, true, false} etc. The full set of allowable values is given in Table \ref{tab:boolean_allowable}. Defaults to \emph{false} if left blank or omitted. Must be set to \emph{false} or omitted if the date generation Rule is set to \emph{CDS} or \emph{CDS2015}.
131132

133+
\item \lstinline!EndOfMonthConvention! [Optional]: Determines the adjustment of the end-of-month schedule dates with regards to the selected calendar.
134+
This field is only used when \lstinline!EndOfMonth! is true. If left blank or omitted, then the default \lstinline!Preceding! convention is applied
135+
(i.e.\ end-of-month dates will never be adjusted over to the beginning of the next month)
136+
137+
Allowable values: See Table \ref{tab:convention} Roll Convention.
138+
139+
Allowable values: Boolean node, allowing \emph{Y, N, 1, 0, true, false} etc. The full set of allowable values is given in Table \ref{tab:boolean_allowable}. Defaults to \emph{false} if left blank or omitted. Must be set to \emph{false} or omitted if the date generation Rule is set to \emph{CDS} or \emph{CDS2015}.
140+
132141
\item \lstinline!FirstDate! [Optional]: Date for initial stub period. For date generation rules \emph{CDS} and \emph{CDS2015}, if given, this
133142
overwrites the first date of the schedule that is otherwise built from IMM dates.
134143

@@ -178,6 +187,10 @@ \subsubsection{Schedule Data (Rules, Dates and Derived)}\label{ss:schedule_data}
178187

179188
Allowable values: Boolean node, allowing \emph{Y, N, 1, 0, true, false} etc. The full set of allowable values is given in Table \ref{tab:boolean_allowable}. Defaults to \emph{false} if left blank or omitted.
180189

190+
\item \lstinline!EndOfMonthConvention! [Optional]: Whenever the \lstinline!EndOfMonth! logic is applied, this is used as the roll convention along with the \lstinline!Calendar!for any date adjustments.
191+
192+
Allowable values: See Table \ref{tab:convention} Roll Convention. Defaults to \emph{Preceding} if omitted.
193+
181194
\item \lstinline!Dates!: This is a sub-sub-node and contains child elements of type
182195
\lstinline!Date!. In this case the schedule dates are determined
183196
directly by the \lstinline!Date! child elements. At least two
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,9 @@
1-
#TradeId,Type,CashflowNo,LegNo,PayDate,FlowType,Amount,Currency,Coupon,Accrual,AccrualStartDate,AccrualEndDate,AccruedAmount,fixingDate,fixingValue,Notional,DiscountFactor,PresentValue,FXRate(Local-Base),PresentValue(Base),BaseCurrency,FloorStrike,CapStrike,FloorVolatility,CapVolatility
1+
#TradeId,Type,CashflowNo,LegNo,PayDate,FlowType,Amount,Currency,Coupon,Accrual,AccrualStartDate,AccrualEndDate,AccruedAmount,fixingDate,fixingValue,Notional,DiscountFactor,PresentValue,FXRate(Local-Base),PresentValue(Base),BaseCurrency,FloorStrike,CapStrike,FloorVolatility,CapVolatility,EffectiveFloorVolatility,EffectiveCapVolatility
2+
CommodityForward_Gold_1Y,CommodityForward,1,0,#N/A,Notional,-1160593.3333,USD,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,0.9943418517,-1154026.5240929599,1.0000000000,-1154026.5240929599,USD,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A
3+
CommodityForward_Gold_1Y,CommodityForward,1,1,#N/A,Notional,1162000.0000,USD,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,0.9943418517,1155425.2316309642,1.0000000000,1155425.2316309642,USD,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A
4+
CommodityForward_Gold_Apr_17,CommodityForward,1,0,#N/A,Notional,580900.0000,USD,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,0.9928024234,576718.9277435583,1.0000000000,576718.9277435583,USD,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A
5+
CommodityForward_Gold_Apr_17,CommodityForward,1,1,#N/A,Notional,-580900.0000,USD,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,0.9928024234,-576718.9277435583,1.0000000000,-576718.9277435583,USD,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A
6+
CommodityForward_WTI_2Y,CommodityForward,1,0,#N/A,Notional,44308571.4286,USD,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,0.9871068084,43737292.5278331637,1.0000000000,43737292.5278331637,USD,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A
7+
CommodityForward_WTI_2Y,CommodityForward,1,1,#N/A,Notional,-46000000.0000,USD,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,0.9871068084,-45406913.1866207123,1.0000000000,-45406913.1866207123,USD,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A
8+
CommodityForward_WTI_Oct_21,CommodityForward,1,0,#N/A,Notional,-24875000.0000,USD,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,0.9432249101,-23462719.6376393437,1.0000000000,-23462719.6376393437,USD,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A
9+
CommodityForward_WTI_Oct_21,CommodityForward,1,1,#N/A,Notional,24875000.0000,USD,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,0.9432249101,23462719.6376393437,1.0000000000,23462719.6376393437,USD,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A

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/configuration/curveconfigurations.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,8 @@ std::set<string> CurveConfigurations::quotes(const QuantLib::ext::shared_ptr<Tod
235235
if (spec->baseType() == CurveSpec::CurveType::FX) {
236236
QuantLib::ext::shared_ptr<FXSpotSpec> fxss = QuantLib::ext::dynamic_pointer_cast<FXSpotSpec>(spec);
237237
QL_REQUIRE(fxss, "Expected an FXSpotSpec but did not get one");
238-
string strQuote = "FX/RATE/" + fxss->unitCcy() + "/" + fxss->ccy();
239-
quotes.insert(strQuote);
238+
quotes.insert("FX/RATE/" + fxss->unitCcy() + "/" + fxss->ccy());
239+
quotes.insert("FX/RATE/" + fxss->ccy() + "/" + fxss->unitCcy());
240240
}
241241
}
242242
}

OREData/ored/configuration/yieldcurveconfig.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,15 @@ const vector<string>& YieldCurveConfig::quotes() {
235235
// Check if the segment is a CrossCcyYieldCurveSegment and add the FX spot rate to the
236236
// set of quotes needed for the YieldCurveConfig if it has not already been added.
237237
if (auto xccySegment = QuantLib::ext::dynamic_pointer_cast<CrossCcyYieldCurveSegment>(c)) {
238-
if (!addedFxSpot)
238+
if (!addedFxSpot) {
239239
quotes_.push_back(xccySegment->spotRateID());
240+
// we add the inverted pair as well, because the original pair might get removed from the market
241+
// data loader if both are present in the input market data
242+
if (auto md = boost::dynamic_pointer_cast<FXSpotQuote>(
243+
parseMarketDatum(Date(), xccySegment->spotRateID(), 1.0))) {
244+
quotes_.push_back("FX/RATE/" + md->ccy() + "/" + md->unitCcy());
245+
}
246+
}
240247
}
241248
}
242249
}

0 commit comments

Comments
 (0)