Skip to content

Commit 4e16c08

Browse files
committed
Merge branch 'feature/QPR-13648' into 'master'
QPR-13648 t0 curve extrapolation (contains the changes from QPR-13703 to avoid conflicts) Closes QPR-13648 See merge request qs/oreplus!3138
2 parents 5dd7494 + 5fcdcbd commit 4e16c08

11 files changed

Lines changed: 289 additions & 169 deletions

File tree

Docs/UserGuide/curve_configurations/yieldcurves.tex

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,19 @@ \subsubsection{Yield Curves}
5656
\item Extrapolation [Optional]: Set to \emph{True} or \emph{False} to enable or disable extrapolation respectively. If
5757
the element is omitted or left blank, then it defaults to \emph{True}.
5858

59-
\item ExcludeT0FromInterpolation [Optional]: Set to \emph{True} to exclude the synthetic time-zero (t0) point from
60-
yield curve interpolation. When enabled, the curve interpolates only on actual market pillar dates, while still
61-
ensuring proper behavior at the reference date (e.g., $DF(t_0) = 1.0$ for discount curves). This is useful when the
62-
first market pillar date does not coincide with the as-of date and you want to avoid including a synthetic point in
63-
the interpolation.
59+
\item ExtrapolationMethod [Optional]: Only applies to bootstrapped curves and interpolated zero / discount curves.
60+
Controls how the curve is extrapolated:
61+
\begin{itemize}
62+
\item \emph{ContinuousForward}: The instantaneous forward rate at the last curve pillar date $T$ is kept constant
63+
\item \emph{DiscreteForward}: The discrete forward rate between $T-1$ and $T$ is kept constant, where $T$ is the last
64+
curve pillar date and $T-1$ lies one calendar day before $T$.
65+
\end{itemize}
66+
67+
\item ExcludeT0FromInterpolation [Optional]: Only applies to bootstrapped curves and interpolated zero / discount curves.
68+
Set to \emph{True} to exclude the synthetic time-zero (t0) point from yield curve interpolation. When enabled, the curve
69+
interpolates only on actual market pillar dates, while still ensuring proper behavior at the reference date
70+
(e.g., $DF(t_0) = 1.0$ for discount curves). This is useful when the first market pillar date does not coincide with the
71+
as-of date and you want to avoid including a synthetic point in the interpolation.
6472

6573
This feature is supported for all three interpolation variables:
6674
\begin{itemize}

ORE-SWIG/OREData-SWIG/SWIG/ored_yieldcurveconfig.i

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ public:
259259
const std::string& discountCurveID, const std::vector<ext::shared_ptr<YieldCurveSegment>>& curveSegments,
260260
const std::string& interpolationVariable = "Discount", const std::string& interpolationMethod = "LogLinear",
261261
const std::string& zeroDayCounter = "A365", bool extrapolation = true,
262+
const std::string& extrapolationMethod = "ContinuousForward",
262263
const BootstrapConfig& bootstrapConfig = BootstrapConfig(),
263264
const QuantLib::Size mixedInterpolationCutoff = 1);
264265

OREData/ored/configuration/yieldcurveconfig.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,14 +179,14 @@ YieldCurveConfig::YieldCurveConfig(const string& curveID, const string& curveDes
179179
const string& discountCurveID,
180180
const vector<QuantLib::ext::shared_ptr<YieldCurveSegment>>& curveSegments,
181181
const string& interpolationVariable, const string& interpolationMethod,
182-
const string& zeroDayCounter, bool extrapolation,
182+
const string& zeroDayCounter, bool extrapolation, const string& extrapolationMethod,
183183
const BootstrapConfig& bootstrapConfig, const Size mixedInterpolationCutoff,
184184
QuantLib::ext::shared_ptr<IborFallbackConfig> iborFallbackConfig)
185185
: CurveConfig(curveID, curveDescription), currency_(currency), discountCurveID_(discountCurveID),
186186
curveSegments_(curveSegments), interpolationVariable_(interpolationVariable),
187187
interpolationMethod_(interpolationMethod), zeroDayCounter_(zeroDayCounter), extrapolation_(extrapolation),
188-
bootstrapConfig_(bootstrapConfig), mixedInterpolationCutoff_(mixedInterpolationCutoff),
189-
iborFallbackConfig_(iborFallbackConfig) {}
188+
extrapolationMethod_(extrapolationMethod), bootstrapConfig_(bootstrapConfig),
189+
mixedInterpolationCutoff_(mixedInterpolationCutoff), iborFallbackConfig_(iborFallbackConfig) {}
190190

191191
const vector<string>& YieldCurveConfig::quotes() {
192192
if (quotes_.size() == 0) {
@@ -284,6 +284,7 @@ void YieldCurveConfig::fromXML(XMLNode* node) {
284284
mixedInterpolationCutoff_ = XMLUtils::getChildValueAsInt(node, "MixedInterpolationCutoff", false, 1);
285285
zeroDayCounter_ = XMLUtils::getChildValue(node, "YieldCurveDayCounter", false, "A365");
286286
extrapolation_ = XMLUtils::getChildValueAsBool(node, "Extrapolation", false, true);
287+
extrapolationMethod_ = XMLUtils::getChildValue(node, "ExtrapolationMethod", false, "ContinuousForward");
287288
excludeT0FromInterpolation_ = XMLUtils::getChildValueAsBool(node, "ExcludeT0FromInterpolation", false, false);
288289

289290
// Optional bootstrap configuration
@@ -330,6 +331,7 @@ XMLNode* YieldCurveConfig::toXML(XMLDocument& doc) const {
330331
XMLUtils::addChild(doc, node, "YieldCurveDayCounter", zeroDayCounter_);
331332
XMLUtils::addChild(doc, node, "Tolerance", bootstrapConfig_.accuracy());
332333
XMLUtils::addChild(doc, node, "Extrapolation", extrapolation_);
334+
XMLUtils::addChild(doc, node, "ExtrapolationMethod", extrapolationMethod_);
333335
XMLUtils::addChild(doc, node, "ExcludeT0FromInterpolation", excludeT0FromInterpolation_);
334336
XMLUtils::appendNode(node, bootstrapConfig_.toXML(doc));
335337
XMLUtils::appendNode(node, reportConfig_.toXML(doc));

OREData/ored/configuration/yieldcurveconfig.hpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -667,12 +667,15 @@ class YieldCurveConfig : public CurveConfig {
667667
//! \name Constructors/Destructors
668668
//@{
669669
//! Default constructor
670-
YieldCurveConfig(QuantLib::ext::shared_ptr<IborFallbackConfig> iborFallbackConfig = nullptr) : iborFallbackConfig_(iborFallbackConfig) {}
670+
YieldCurveConfig(QuantLib::ext::shared_ptr<IborFallbackConfig> iborFallbackConfig = nullptr) : iborFallbackConfig_(
671+
iborFallbackConfig) {}
671672
//! Detailed constructor
672673
YieldCurveConfig(const string& curveID, const string& curveDescription, const string& currency,
673-
const string& discountCurveID, const vector<QuantLib::ext::shared_ptr<YieldCurveSegment>>& curveSegments,
674+
const string& discountCurveID,
675+
const vector<QuantLib::ext::shared_ptr<YieldCurveSegment>>& curveSegments,
674676
const string& interpolationVariable = "Discount", const string& interpolationMethod = "LogLinear",
675677
const string& zeroDayCounter = "A365", bool extrapolation = true,
678+
const string& extrapolationMethod = "ContinuousForward",
676679
const BootstrapConfig& bootstrapConfig = BootstrapConfig(),
677680
const Size mixedInterpolationCutoff = 1,
678681
QuantLib::ext::shared_ptr<IborFallbackConfig> iborFallbackConfig = nullptr);
@@ -696,6 +699,7 @@ class YieldCurveConfig : public CurveConfig {
696699
Size mixedInterpolationCutoff() const { return mixedInterpolationCutoff_; }
697700
const string& zeroDayCounter() const { return zeroDayCounter_; }
698701
bool extrapolation() const { return extrapolation_; }
702+
const string& extrapolationMethod() const { return extrapolationMethod_; }
699703
const BootstrapConfig& bootstrapConfig() const { return bootstrapConfig_; }
700704
bool excludeT0FromInterpolation() const { return excludeT0FromInterpolation_; }
701705
//@}
@@ -707,6 +711,7 @@ class YieldCurveConfig : public CurveConfig {
707711
Size& mixedInterpolationCutoff() { return mixedInterpolationCutoff_; }
708712
string& zeroDayCounter() { return zeroDayCounter_; }
709713
bool& extrapolation() { return extrapolation_; }
714+
string& extrapolationMethod() { return extrapolationMethod_; }
710715
void setBootstrapConfig(const BootstrapConfig& bootstrapConfig) { bootstrapConfig_ = bootstrapConfig; }
711716
//@}
712717
const ReportConfig& reportConfig() const { return reportConfig_; }
@@ -725,9 +730,10 @@ class YieldCurveConfig : public CurveConfig {
725730
string interpolationVariable_;
726731
string interpolationMethod_;
727732
string zeroDayCounter_;
728-
bool extrapolation_;
733+
bool extrapolation_ = true;
734+
string extrapolationMethod_;
729735
BootstrapConfig bootstrapConfig_;
730-
Size mixedInterpolationCutoff_;
736+
Size mixedInterpolationCutoff_ = 1;
731737
ReportConfig reportConfig_;
732738
QuantLib::ext::shared_ptr<IborFallbackConfig> iborFallbackConfig_;
733739
bool excludeT0FromInterpolation_ = false;

0 commit comments

Comments
 (0)