Skip to content

Commit a1a11f8

Browse files
author
jenkins
committed
git subrepo pull (merge) ore
subrepo: subdir: "ore" merged: "920aa547a9" upstream: origin: "git@gitlab.acadiasoft.net:qs/ore.git" branch: "master" commit: "c3289af6f4" git-subrepo: version: "0.4.6" origin: "https://github.com/ingydotnet/git-subrepo" commit: "110b9eb"
2 parents 3a80f3d + c3289af commit a1a11f8

12 files changed

Lines changed: 257 additions & 28 deletions

File tree

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: C/C++ CI Windows
2+
3+
on:
4+
push:
5+
branches: [master]
6+
pull_request:
7+
branches: [master]
8+
types: [ready_for_review, opened, synchronize, reopened]
9+
paths:
10+
- .github/workflows/linux_build.yaml
11+
- ./App/**
12+
- ./OREAnalytics/**
13+
- '!./OREAnalytics/doc/**'
14+
- ./OREData/**
15+
- '!./OREData/doc/**'
16+
- ./ORETest/**
17+
- ./QuantExt/**
18+
- '!./QuantExt/doc/**'
19+
- CMakeLists.txt
20+
workflow_dispatch:
21+
22+
jobs:
23+
build:
24+
name: building
25+
runs-on: windows-2022
26+
steps:
27+
- uses: actions/checkout@v3
28+
- name: get QuantLib
29+
run: |
30+
git submodule update --init
31+
- name: Set up Boost
32+
run: |
33+
$Url = "https://boostorg.jfrog.io/artifactory/main/release/1.72.0/binaries/boost_1_72_0-msvc-14.2-64.exe"
34+
(New-Object System.Net.WebClient).DownloadFile($Url, "$env:TEMP\boost.exe")
35+
Start-Process -Wait -FilePath "$env:TEMP\boost.exe" "/SILENT","/SP-","/SUPPRESSMSGBOXES","/DIR=C:\local\boost"
36+
choco install -y ninja
37+
- name: cmake configure and build
38+
env:
39+
BOOST_ROOT: C:\local\boost
40+
shell: cmd
41+
run: |
42+
mkdir build
43+
cd build
44+
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Vc\Auxiliary\Build\vcvarsall.bat" amd64 -vcvars_ver=14.3 || exit 1
45+
cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DQL_BUILD_EXAMPLES=false -DQL_BUILD_TEST_SUITE=false -DQL_BUILD_BENCHMARK=false -DQL_ENABLE_SESSIONS=true -DORE_BUILD_DOC=false -DBOOST_INCLUDEDIR=C:\local\boost -DBOOST_LIBRARYDIR=C:\local\boost\lib64-msvc-14.3 -L
46+
cmake --build . -j 2 --verbose

.github/workflows/linux_build.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
name: C/C++ CI
1+
name: C/C++ CI Ubuntu
22

33
on:
44
push:
5-
branches: master
5+
branches: [master]
66
pull_request:
7-
branches: master
7+
branches: [master]
88
types: [ready_for_review, opened, synchronize, reopened]
99
paths:
1010
- .github/workflows/linux_build.yaml

.gitmodules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[submodule "QuantLib"]
22
path = QuantLib
3-
url = https://github.com/OpenSourceRisk/QuantLib.git
3+
url = git@gitlab.acadiasoft.net:qs/quantlib.git
44
branch = master
55
ignore = dirty

CMakePresets.json

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,26 @@
158158
"QL_BUILD_TEST_SUITE": false,
159159
"QL_BUILD_BENCHMARK": false,
160160
"QL_ENABLE_SESSIONS": true,
161+
"ORE_BUILD_DOC": false,
162+
"BUILD_SHARED_LIBS": false
163+
},
164+
"condition": {
165+
"type": "equals",
166+
"lhs": "${hostSystemName}",
167+
"rhs": "Linux"
168+
}
169+
},
170+
{
171+
"name": "linux-clang-base",
172+
"hidden": true,
173+
"binaryDir": "${sourceDir}/build/${presetName}",
174+
"cacheVariables": {
175+
"CMAKE_CXX_COMPILER": "clang++",
176+
"BOOST_ROOT": "$env{BOOST}",
177+
"QL_BUILD_EXAMPLES": false,
178+
"QL_BUILD_TEST_SUITE": false,
179+
"QL_BUILD_BENCHMARK": false,
180+
"QL_ENABLE_SESSIONS": true,
161181
"ORE_BUILD_DOC": false
162182
},
163183
"condition": {
@@ -192,6 +212,11 @@
192212
"hidden": true,
193213
"generator": "Ninja"
194214
},
215+
{
216+
"name": "_make",
217+
"hidden": true,
218+
"generator": "Unix Makefiles"
219+
},
195220
{
196221
"name": "linux-gcc-ninja-debug",
197222
"inherits": [
@@ -215,6 +240,54 @@
215240
"_ninja",
216241
"_relwithdebinfo"
217242
]
243+
},
244+
{
245+
"name": "linux-clang-debug",
246+
"inherits": [
247+
"linux-clang-base",
248+
"_make",
249+
"_debug"
250+
]
251+
},
252+
{
253+
"name": "linux-clang-release",
254+
"inherits": [
255+
"linux-clang-base",
256+
"_make",
257+
"_release"
258+
]
259+
},
260+
{
261+
"name": "linux-clang-relwithdebinfo",
262+
"inherits": [
263+
"linux-clang-base",
264+
"_make",
265+
"_relwithdebinfo"
266+
]
267+
},
268+
{
269+
"name": "linux-clang-ninja-debug",
270+
"inherits": [
271+
"linux-clang-base",
272+
"_ninja",
273+
"_debug"
274+
]
275+
},
276+
{
277+
"name": "linux-clang-ninja-release",
278+
"inherits": [
279+
"linux-clang-base",
280+
"_ninja",
281+
"_release"
282+
]
283+
},
284+
{
285+
"name": "linux-clang-ninja-relwithdebinfo",
286+
"inherits": [
287+
"linux-clang-base",
288+
"_ninja",
289+
"_relwithdebinfo"
290+
]
218291
}
219292
],
220293
"buildPresets": [

Docs/UserGuide/curve_configurations/yieldcurves.tex

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ \subsubsection*{Direct Segment}
128128
or discount factor. The \lstinline!Conventions! node contains the ID of a node in the {\tt conventions.xml} file
129129
described in section \ref{sec:conventions}. The \lstinline!Conventions! node associates conventions with the quotes.
130130
131+
For \emph{Discount} type segments, the quotes can be given using a wildcard. Any valid and matching quotes will then be loaded from the provided market data. An example wildcard is:
132+
\begin{itemize}
133+
\item {DISCOUNT/RATE/EUR/EUR3M/*}
134+
\end{itemize}
135+
131136
\begin{listing}[H]
132137
%\hrule\medskip
133138
\begin{minted}[fontsize=\footnotesize]{xml}

Docs/UserGuide/marketdata.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ \subsection{Discount Factor}\label{ss:discount_rate}
144144
Examples with a Term and with a DiscountDate:
145145
\begin{itemize}
146146
\item {DISCOUNT/RATE/EUR/EUR3M/3Y}
147-
\item {DISCOUNT/RATE/EUR/EUR3M/A365F/12-05-2018}
147+
\item {DISCOUNT/RATE/EUR/EUR3M/12-05-2018}
148148
\end{itemize}
149149

150150
%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

OREAnalytics/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@ add_test(NAME orea-test-suite WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} COMMAN
3737
install(TARGETS orea-test-suite
3838
RUNTIME DESTINATION bin
3939
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
40+
OPTIONAL
4041
)

OREData/ored/marketdata/yieldcurve.cpp

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,39 +1062,70 @@ void YieldCurve::buildDiscountCurve() {
10621062
boost::shared_ptr<Conventions> conventions = InstrumentConventions::instance().conventions();
10631063
boost::shared_ptr<Convention> convention;
10641064

1065-
for (Size i = 0; i < discountQuoteIDs.size(); ++i) {
1066-
boost::shared_ptr<MarketDatum> marketQuote = loader_.get(discountQuoteIDs[i], asofDate_);
1067-
if (marketQuote) {
1068-
QL_REQUIRE(marketQuote->instrumentType() == MarketDatum::InstrumentType::DISCOUNT,
1069-
"Market quote not of type Discount.");
1070-
boost::shared_ptr<DiscountQuote> discountQuote = boost::dynamic_pointer_cast<DiscountQuote>(marketQuote);
1065+
vector<string> quotes;
1066+
quotes.reserve(discountQuoteIDs.size()); // Reserve space for efficiency
10711067

1072-
if(discountQuote->date() != Date()){
1068+
std::transform(discountQuoteIDs.begin(), discountQuoteIDs.end(), std::back_inserter(quotes),
1069+
[](const std::pair<string, bool>& pair) {
1070+
return pair.first; // Extract only the quote part
1071+
});
10731072

1074-
data[discountQuote->date()] = discountQuote->quote()->value();
1073+
auto wildcard = getUniqueWildcard(quotes);
10751074

1076-
} else if (discountQuote->tenor() != Period()){
1075+
std::set<boost::shared_ptr<MarketDatum>> marketData;
1076+
if (wildcard) {
1077+
marketData = loader_.get(*wildcard, asofDate_);
1078+
} else {
1079+
std::ostringstream ss;
1080+
ss << MarketDatum::InstrumentType::DISCOUNT << "/" << MarketDatum::QuoteType::RATE << "/" << currency_ << "/*";
1081+
Wildcard w(ss.str());
1082+
marketData = loader_.get(w, asofDate_);
1083+
}
1084+
1085+
for (const auto& marketQuote : marketData) {
1086+
QL_REQUIRE(marketQuote->instrumentType() == MarketDatum::InstrumentType::DISCOUNT,
1087+
"Market quote not of type Discount.");
1088+
boost::shared_ptr<DiscountQuote> discountQuote = boost::dynamic_pointer_cast<DiscountQuote>(marketQuote);
1089+
1090+
// filtering
1091+
if (!wildcard) {
1092+
vector<string>::const_iterator it = find(quotes.begin(), quotes.end(), discountQuote->name());
1093+
if (it == quotes.end())
1094+
continue;
1095+
}
10771096

1078-
if(!convention)
1079-
convention = conventions->get(discountCurveSegment->conventionsID());
1080-
boost::shared_ptr<ZeroRateConvention> zeroConvention = boost::dynamic_pointer_cast<ZeroRateConvention>(convention);
1081-
QL_REQUIRE(zeroConvention, "could not cast to ZeroRateConvention");
1097+
if (discountQuote->date() != Date()) {
10821098

1083-
Calendar cal = zeroConvention->tenorCalendar();
1084-
BusinessDayConvention rollConvention = zeroConvention->rollConvention();
1085-
Date date = cal.adjust(cal.adjust(asofDate_, rollConvention) + discountQuote->tenor(), rollConvention);
1086-
DLOG("YieldCurve::buildDiscountCurve - tenor " << discountQuote->tenor() << " to date " << io::iso_date(date));
1087-
data[date] = discountQuote->quote()->value();
1099+
data[discountQuote->date()] = discountQuote->quote()->value();
10881100

1089-
} else {
1090-
QL_FAIL("YieldCurve::buildDiscountCurve - neither date nor tenor recognised");
1091-
}
1101+
} else if (discountQuote->tenor() != Period()) {
10921102

1103+
if (!convention)
1104+
convention = conventions->get(discountCurveSegment->conventionsID());
1105+
boost::shared_ptr<ZeroRateConvention> zeroConvention =
1106+
boost::dynamic_pointer_cast<ZeroRateConvention>(convention);
1107+
QL_REQUIRE(zeroConvention, "could not cast to ZeroRateConvention");
1108+
1109+
Calendar cal = zeroConvention->tenorCalendar();
1110+
BusinessDayConvention rollConvention = zeroConvention->rollConvention();
1111+
Date date = cal.adjust(cal.adjust(asofDate_, rollConvention) + discountQuote->tenor(), rollConvention);
1112+
DLOG("YieldCurve::buildDiscountCurve - tenor " << discountQuote->tenor() << " to date "
1113+
<< io::iso_date(date));
1114+
data[date] = discountQuote->quote()->value();
1115+
1116+
} else {
1117+
QL_FAIL("YieldCurve::buildDiscountCurve - neither date nor tenor recognised");
10931118
}
10941119
}
10951120

1121+
// Some logging and checks
10961122
QL_REQUIRE(data.size() > 0, "No market data found for curve spec " << curveSpec_.name() << " with as of date "
10971123
<< io::iso_date(asofDate_));
1124+
if (!wildcard) {
1125+
QL_REQUIRE(data.size() == quotes.size(), "Found " << data.size() << " quotes, but "
1126+
<< quotes.size()
1127+
<< " quotes given in config " << curveConfig_->curveID());
1128+
}
10981129

10991130
if (data.begin()->first > asofDate_) {
11001131
DLOG("Insert discount curve point at time zero for " << curveSpec_.name());

OREData/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,5 @@ add_test(NAME ored-test-suite WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} COMMAN
8686
install(TARGETS ored-test-suite
8787
RUNTIME DESTINATION bin
8888
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
89+
OPTIONAL
8990
)

OREData/test/yieldcurve.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,75 @@ BOOST_AUTO_TEST_CASE(testBootstrapAndFixings) {
246246
BOOST_CHECK_NO_THROW(YieldCurve jpyYieldCurve(asof, spec, curveConfigs, loader));
247247
}
248248

249+
BOOST_AUTO_TEST_CASE(testBuildDiscountCurveDirectSegment) {
250+
251+
Date asof(13, October, 2023);
252+
Settings::instance().evaluationDate() = asof;
253+
254+
YieldCurveSpec spec("EUR", "EUR-CURVE");
255+
256+
CurveConfigurations curveConfigs;
257+
258+
vector<string> quotes;
259+
quotes.emplace_back("DISCOUNT/RATE/EUR/EUR-CURVE/2023-10-14");
260+
quotes.emplace_back("DISCOUNT/RATE/EUR/EUR-CURVE/2023-10-15");
261+
262+
vector<boost::shared_ptr<YieldCurveSegment>> segments{boost::make_shared<DirectYieldCurveSegment>(
263+
"Discount", "", quotes)};
264+
265+
boost::shared_ptr<YieldCurveConfig> yCConfig =
266+
boost::make_shared<YieldCurveConfig>("EUR-CURVE", "ORE YieldCurve built from EUR-CURVE", "EUR", "", segments);
267+
curveConfigs.add(CurveSpec::CurveType::Yield, "EUR-CURVE", yCConfig);
268+
269+
vector<string> data{"2023-10-12 DISCOUNT/RATE/SEK/STINA-CURVE/2023-10-13 0.77",
270+
"2023-10-12 DISCOUNT/RATE/EUR/EUR-ANOTHER-CURVE/2023-10-13 0.95",
271+
"2023-10-13 DISCOUNT/RATE/EUR/EUR-ANOTHER-CURVE/2023-10-14 0.95",
272+
"2023-10-12 DISCOUNT/RATE/EUR/EUR-CURVE/2023-10-12 0.88",
273+
"2023-10-13 DISCOUNT/RATE/EUR/EUR-CURVE/2023-10-13 1.0",
274+
"2023-10-13 DISCOUNT/RATE/EUR/EUR-CURVE/2023-10-14 0.99",
275+
"2023-10-13 DISCOUNT/RATE/EUR/EUR-CURVE/2023-10-15 0.98",
276+
"2023-10-13 COMMODITY_FWD/PRICE/GOLD/USD/2023-10-31 1158.8",
277+
"2023-10-13 COMMODITY_FWD/PRICE/GOLD/USD/2023-11-01 1160.9",
278+
"2023-10-13 COMMODITY_FWD/PRICE/GOLD/USD/2023-11-02 1163.4"};
279+
MarketDataLoader loader(data);
280+
281+
BOOST_CHECK_NO_THROW(YieldCurve yieldCurve(asof, spec, curveConfigs, loader));
282+
}
283+
284+
BOOST_AUTO_TEST_CASE(testBuildDiscountCurveDirectSegmentWildcard) {
285+
286+
Date asof(13, October, 2023);
287+
Settings::instance().evaluationDate() = asof;
288+
289+
YieldCurveSpec spec("EUR", "EUR-CURVE");
290+
291+
CurveConfigurations curveConfigs;
292+
293+
vector<string> quotes;
294+
quotes.emplace_back("DISCOUNT/RATE/EUR/EUR-CURVE/*");
295+
296+
vector<boost::shared_ptr<YieldCurveSegment>> segments{
297+
boost::make_shared<DirectYieldCurveSegment>("Discount", "", quotes)};
298+
299+
boost::shared_ptr<YieldCurveConfig> yCConfig = boost::make_shared<YieldCurveConfig>(
300+
"EUR-CURVE", "ORE YieldCurve built from EUR-CURVE", "EUR", "", segments);
301+
curveConfigs.add(CurveSpec::CurveType::Yield, "EUR-CURVE", yCConfig);
302+
303+
vector<string> data{"2023-10-12 DISCOUNT/RATE/SEK/STINA-CURVE/2023-10-13 0.77",
304+
"2023-10-12 DISCOUNT/RATE/EUR/EUR-ANOTHER-CURVE/2023-10-13 0.95",
305+
"2023-10-13 DISCOUNT/RATE/EUR/EUR-ANOTHER-CURVE/2023-10-14 0.95",
306+
"2023-10-13 DISCOUNT/RATE/EUR/EUR-CURVE/2023-10-13 1.0",
307+
"2023-10-13 DISCOUNT/RATE/EUR/EUR-CURVE/2023-10-14 0.99",
308+
"2023-10-13 DISCOUNT/RATE/EUR/EUR-CURVE/2023-10-15 0.98",
309+
"2023-10-13 EQUITY_FWD/PRICE/SP5/USD/1Y 1500.00",
310+
"2023-10-13 EQUITY_FWD/PRICE/SP5/USD/20231014 1500.00",
311+
"2023-10-13 EQUITY_DIVIDEND/RATE/SP5/USD/20231015 0.00",
312+
"2023-10-13 EQUITY_DIVIDEND/RATE/SP5/USD/2Y 0.00"};
313+
MarketDataLoader loader(data);
314+
315+
BOOST_CHECK_NO_THROW(YieldCurve yieldCurve(asof, spec, curveConfigs, loader));
316+
}
317+
249318
// Test ARS-IN-USD failures using the old QuantLib::IterativeBootstrap parameters
250319
BOOST_DATA_TEST_CASE(testBootstrapARSinUSDFailures, bdata::make(curveConfigFiles), curveConfigFile) {
251320

0 commit comments

Comments
 (0)