Skip to content

Commit ea6e5c5

Browse files
author
O'Brien
committed
QPR-13697: Add wildcard support for Direct Zero and Discount yield curve segments
1 parent 735df28 commit ea6e5c5

2 files changed

Lines changed: 49 additions & 11 deletions

File tree

Docs/UserGuide/curve_configurations/yieldcurves.tex

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,10 @@ \subsubsection*{Direct Segment}
160160
or discount factor. The \lstinline!Conventions! node contains the ID of a node in the {\tt conventions.xml} file
161161
described in section \ref{sec:conventions}. The \lstinline!Conventions! node associates conventions with the quotes.
162162
163-
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:
163+
For both \emph{Zero} and \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. Example wildcards are:
164164
\begin{itemize}
165-
\item {DISCOUNT/RATE/EUR/EUR3M/*}
165+
\item {ZERO/RATE/EUR/*} - matches all EUR zero rate quotes
166+
\item {DISCOUNT/RATE/EUR/EUR3M/*} - matches all EUR discount factor quotes for the EUR3M curve
166167
\end{itemize}
167168
168169
\begin{listing}[H]

OREData/ored/marketdata/yieldcurve.cpp

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
#include <ored/utilities/marketdata.hpp>
7878
#include <ored/utilities/parsers.hpp>
7979
#include <ored/utilities/to_string.hpp>
80+
#include <ored/utilities/wildcard.hpp>
8081

8182
using namespace QuantLib;
8283
using namespace QuantExt;
@@ -1007,15 +1008,43 @@ void YieldCurve::buildZeroCurve(const std::size_t index) {
10071008
QuantLib::ext::dynamic_pointer_cast<DirectYieldCurveSegment>(curveSegments_[index][0]);
10081009
auto zeroQuoteIDs = zeroCurveSegment->quotes();
10091010

1010-
for (Size i = 0; i < zeroQuoteIDs.size(); ++i) {
1011-
QuantLib::ext::shared_ptr<MarketDatum> marketQuote = loader_.get(zeroQuoteIDs[i], asofDate_);
1012-
if (marketQuote) {
1013-
QL_REQUIRE(marketQuote->instrumentType() == MarketDatum::InstrumentType::ZERO,
1014-
"Market quote not of type zero.");
1015-
QuantLib::ext::shared_ptr<ZeroQuote> zeroQuote =
1016-
QuantLib::ext::dynamic_pointer_cast<ZeroQuote>(marketQuote);
1017-
zeroQuotes.push_back(zeroQuote);
1011+
// Extract quote strings for wildcard check
1012+
vector<string> quotes;
1013+
quotes.reserve(zeroQuoteIDs.size());
1014+
std::transform(zeroQuoteIDs.begin(), zeroQuoteIDs.end(),
1015+
std::back_inserter(quotes),
1016+
[](const std::pair<string, bool>& pair) {
1017+
return pair.first;
1018+
});
1019+
// Check for wildcard pattern
1020+
auto wildcard = getUniqueWildcard(quotes);
1021+
// Get market data using wildcard or traditional path
1022+
std::set<QuantLib::ext::shared_ptr<MarketDatum>> marketData;
1023+
if (wildcard) {
1024+
marketData = loader_.get(*wildcard, asofDate_);
1025+
} else {
1026+
for (Size i = 0; i < zeroQuoteIDs.size(); ++i) {
1027+
ext::shared_ptr<MarketDatum> marketQuote = loader_.get(zeroQuoteIDs[i], asofDate_);
1028+
if (marketQuote)
1029+
marketData.insert(marketQuote);
1030+
}
1031+
}
1032+
// Process market data into zero quotes
1033+
for (const auto& marketQuote : marketData) {
1034+
QL_REQUIRE(marketQuote->instrumentType() == MarketDatum::InstrumentType::ZERO,
1035+
"Market quote not of type zero.");
1036+
QuantLib::ext::shared_ptr<ZeroQuote> zeroQuote =
1037+
QuantLib::ext::dynamic_pointer_cast<ZeroQuote>(marketQuote);
1038+
// If not using wildcard, verify quote is in config list
1039+
if (!wildcard) {
1040+
auto it = std::find_if(zeroQuoteIDs.begin(), zeroQuoteIDs.end(),
1041+
[&](const std::pair<string, bool>& p) {
1042+
return p.first == marketQuote->name();
1043+
});
1044+
if (it == zeroQuoteIDs.end())
1045+
continue;
10181046
}
1047+
zeroQuotes.push_back(zeroQuote);
10191048
}
10201049

10211050
// Create the (date, zero) pairs.
@@ -1289,7 +1318,15 @@ void YieldCurve::buildDiscountCurve(const std::size_t index) {
12891318
"Market quote not of type Discount.");
12901319
QuantLib::ext::shared_ptr<DiscountQuote> discountQuote =
12911320
QuantLib::ext::dynamic_pointer_cast<DiscountQuote>(marketQuote);
1292-
1321+
// If not using wildcard, verify quote is in config list
1322+
if (!wildcard) {
1323+
auto it = std::find_if(discountQuoteIDs.begin(), discountQuoteIDs.end(),
1324+
[&](const std::pair<string, bool>& p) {
1325+
return p.first == marketQuote->name();
1326+
});
1327+
if (it == discountQuoteIDs.end())
1328+
continue;
1329+
}
12931330
if (discountQuote->date() != Date()) {
12941331

12951332
data[discountQuote->date()] = discountQuote->quote()->value();

0 commit comments

Comments
 (0)