Skip to content

Commit 9f1bf1a

Browse files
pcaspersjenkins
authored andcommitted
Resolve QPR-12419 add optional pca-instructed coordinate transform to regression analysis (AMC and scripted trades, comes up in BNY xva-project)
1 parent 836f0fb commit 9f1bf1a

36 files changed

Lines changed: 414 additions & 178 deletions

Docs/AMC/amc.tex

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ \section*{Document Change History}
113113
\hline
114114
na & 25 February 2019 & Peter Caspers & initial version\\
115115
na & 23 October 2023 & Peter Caspers & add parameter RegressorModel\\
116+
na & 4 April 2024 & Peter Caspers & add parameter RegressionVarianceCutoff\\
116117
\hline
117118
\end{supertabular}
118119
\end{center}
@@ -247,6 +248,7 @@ \subsection{Pricing Engine Configuration}\label{sec:pricing_engine_config}
247248
<Parameter name="SobolDirectionIntegers">JoeKuoD7</Parameter>
248249
<Parameter name="MinObsDate">true</Parameter>
249250
<Parameter name="RegressorModel">Simple</Parameter>
251+
<Parameter name="RegressionVarianceCutoff">1E-5</Parameter>
250252
</EngineParameters>
251253
</Product>
252254
\end{minted}
@@ -286,6 +288,9 @@ \subsection{Pricing Engine Configuration}\label{sec:pricing_engine_config}
286288
addition, past FX states that are relevant for future cashflows are included. For example, for a FX resettable
287289
cashflow the FX state observed on the FX reset date is included.
288290
\end{itemize}
291+
\item \verb+RegressionVarianceCutoff+: Optional. If given, a coordinate transform and (possibly) a factor reduction is
292+
applied to the regressors, such that $1-\epsilon$ of the total variance of regressors is kept, where $\epsilon$ the
293+
given parameter. This helps dealing with collinearity and also reducing the dimnensionality of the regression model.
289294
\end{enumerate}
290295
291296
\begin{table}[hbt]

Docs/ScriptedTrade/docs/models.tex

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ \subsection{Pricing Engine Configuration}\label{pricingengine_config}
5050
<Parameter name="Interactive">false</Parameter>
5151
<Parameter name="BootstrapTolerance">0.1</Parameter>
5252
<Parameter name="IncludePastCashflows">true</Parameter>
53+
<Parameter name="RegressionVarianceCutoff">1E-5</Parameter>
5354
<!-- product specific parameters -->
5455
<Parameter name="RegressionOrder_SingleAssetOption(EQ)">6</Parameter>
5556
<Parameter name="RegressionOrder_SingleAssetOption(FX)">6</Parameter>
@@ -139,6 +140,10 @@ \subsection{Pricing Engine Configuration}\label{pricingengine_config}
139140
\item BootstrapTolerance: tolerance for calibration bootstrap, only applies to model = GaussianCam
140141
\item IncludePastCashflows: if true, LOGPAY() will generate cashflow information for pay dates on or before the
141142
reference date. Optional, defaults to false.
143+
\item RegressionVarianceCutoff: Optional. Only relevant for MC models. If given, a coordinate transform and (possibly) a
144+
factor reduction is applied to the regressors used for conditional expectation calculation, such that $1-\epsilon$ of
145+
the total variance of regressors is kept, where $\epsilon$ the given parameter. This helps dealing with collinearity
146+
and also reducing the dimnensionality of the regression model.
142147
\item Interactive: If true an interactive session is started on script execution for debugging purposes; should be false
143148
except for debugging purposes
144149
\item UseAD: If true and RunType in the global pricing engine parameters is SensitivityDelta, a first order pnl

OREAnalytics/orea/engine/xvaenginecg.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,8 @@ XvaEngineCG::XvaEngineCG(const Size nThreads, const Date& asof, const boost::sha
281281
LOG("XvaEngineCG: do forward evaluation");
282282

283283
Real eps = 0.0; // smoothing parameter for indicator functions
284-
ops_ = getRandomVariableOps(model_->size(), 4, QuantLib::LsmBasisSystem::Monomial, bumpCvaSensis ? eps : 0.0);
284+
ops_ = getRandomVariableOps(model_->size(), 4, QuantLib::LsmBasisSystem::Monomial, bumpCvaSensis ? eps : 0.0,
285+
Null<Real>()); // todo set regression variance cutoff
285286
grads_ = getRandomVariableGradients(model_->size(), 4, QuantLib::LsmBasisSystem::Monomial, eps);
286287
opNodeRequirements_ = getRandomVariableOpNodeRequirements();
287288

OREData/ored/portfolio/builders/currencyswap.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ boost::shared_ptr<PricingEngine> CamAmcCurrencySwapEngineBuilder::engineImpl(con
107107
parseSobolBrownianGeneratorOrdering(engineParameter("BrownianBridgeOrdering")),
108108
parseSobolRsgDirectionIntegers(engineParameter("SobolDirectionIntegers")), discountCurves, simulationDates_,
109109
externalModelIndices, parseBool(engineParameter("MinObsDate")),
110-
parseRegressorModel(engineParameter("RegressorModel", {}, false, "Simple")));
110+
parseRegressorModel(engineParameter("RegressorModel", {}, false, "Simple")),
111+
parseRealOrNull(engineParameter("RegressionVarianceCutoff", {}, false, std::string())));
111112

112113
return engine;
113114
}

OREData/ored/portfolio/builders/fxforward.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ boost::shared_ptr<PricingEngine> CamAmcFxForwardEngineBuilder::engineImpl(const
8080
parseSobolBrownianGeneratorOrdering(engineParameter("BrownianBridgeOrdering")),
8181
parseSobolRsgDirectionIntegers(engineParameter("SobolDirectionIntegers")), discountCurves, simulationDates_,
8282
externalModelIndices, parseBool(engineParameter("MinObsDate")),
83-
parseRegressorModel(engineParameter("RegressorModel", {}, false, "Simple")));
83+
parseRegressorModel(engineParameter("RegressorModel", {}, false, "Simple")),
84+
parseRealOrNull(engineParameter("RegressionVarianceCutoff", {}, false, std::string())));
8485

8586
return engine;
8687
}

OREData/ored/portfolio/builders/fxoption.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ boost::shared_ptr<PricingEngine> CamAmcFxOptionEngineBuilder::engineImpl(const s
9595
parseSobolBrownianGeneratorOrdering(engineParameter("BrownianBridgeOrdering")),
9696
parseSobolRsgDirectionIntegers(engineParameter("SobolDirectionIntegers")), discountCurves, simulationDates_,
9797
externalModelIndices, parseBool(engineParameter("MinObsDate")),
98-
parseRegressorModel(engineParameter("RegressorModel", {}, false, "Simple")));
98+
parseRegressorModel(engineParameter("RegressorModel", {}, false, "Simple")),
99+
parseRealOrNull(engineParameter("RegressionVarianceCutoff", {}, false, std::string())));
99100

100101
return engine;
101102
}

OREData/ored/portfolio/builders/multilegoption.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,8 @@ boost::shared_ptr<PricingEngine> CamAmcMultiLegOptionEngineBuilder::engineImpl(
333333
parseSobolBrownianGeneratorOrdering(engineParameter("BrownianBridgeOrdering")),
334334
parseSobolRsgDirectionIntegers(engineParameter("SobolDirectionIntegers")), discountCurves, simulationDates_,
335335
externalModelIndices, parseBool(engineParameter("MinObsDate")),
336-
parseRegressorModel(engineParameter("RegressorModel", {}, false, "Simple")));
336+
parseRegressorModel(engineParameter("RegressorModel", {}, false, "Simple")),
337+
parseRealOrNull(engineParameter("RegressionVarianceCutoff", {}, false, std::string())));
337338

338339
return engine;
339340
}

OREData/ored/portfolio/builders/scriptedtrade.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,8 @@ void ScriptedTradeEngineBuilder::populateModelParameters() {
537537
} else {
538538
mcParams_.trainingSamples = Null<Size>();
539539
}
540+
mcParams_.regressionVarianceCutoff =
541+
parseRealOrNull(engineParameter("RegressionVarianceCutoff", {resolvedProductTag_}, false, std::string()));
540542
} else if (engineParam_ == "FD") {
541543
modelSize_ = parseInteger(engineParameter("StateGridPoints", {resolvedProductTag_}));
542544
mesherEpsilon_ = parseReal(engineParameter("MesherEpsilon", {resolvedProductTag_}, false, "1.0E-4"));

OREData/ored/portfolio/builders/swap.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ boost::shared_ptr<PricingEngine> CamAmcSwapEngineBuilder::buildMcEngine(const bo
4545
parseSobolBrownianGeneratorOrdering(engineParameter("BrownianBridgeOrdering")),
4646
parseSobolRsgDirectionIntegers(engineParameter("SobolDirectionIntegers")), discountCurve, simulationDates,
4747
externalModelIndices, parseBool(engineParameter("MinObsDate")),
48-
parseRegressorModel(engineParameter("RegressorModel", {}, false, "Simple")));
48+
parseRegressorModel(engineParameter("RegressorModel", {}, false, "Simple")),
49+
parseRealOrNull(engineParameter("RegressionVarianceCutoff", {}, false, std::string())));
4950
}
5051

5152
boost::shared_ptr<PricingEngine> CamAmcSwapEngineBuilder::engineImpl(const Currency& ccy,

OREData/ored/portfolio/builders/swaption.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ boost::shared_ptr<PricingEngine> buildMcEngine(
5656
parseSobolBrownianGeneratorOrdering(engineParameter("BrownianBridgeOrdering", {}, false, "Steps")),
5757
parseSobolRsgDirectionIntegers(engineParameter("SobolDirectionIntegers", {}, false, "JoeKuoD7")), discountCurve,
5858
simulationDates, externalModelIndices, parseBool(engineParameter("MinObsDate", {}, false, "true")),
59-
parseRegressorModel(engineParameter("RegressorModel", {}, false, "Simple")));
59+
parseRegressorModel(engineParameter("RegressorModel", {}, false, "Simple")),
60+
parseRealOrNull(engineParameter("RegressionVarianceCutoff", {}, false, std::string())));
6061
}
6162
} // namespace
6263

0 commit comments

Comments
 (0)