Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
lgm.hpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19/*! \file lgm.hpp
20 \brief lgm model class
21 \ingroup models
22*/
23
24#ifndef quantext_lgm_model_hpp
25#define quantext_lgm_model_hpp
26
31
32#include <ql/math/comparison.hpp>
33#include <ql/math/distributions/normaldistribution.hpp>
34#include <ql/math/integrals/integral.hpp>
35#include <ql/math/integrals/simpsonintegral.hpp>
36#include <ql/stochasticprocess.hpp>
37
38namespace QuantExt {
39using namespace QuantLib;
40
41//! Linear Gauss Morkov Model
42/*! LGM 1f interest rate model
43 Basically the same remarks as for CrossAssetModel hold
44 \ingroup models
45*/
47public:
48 enum class Discretization { Euler, Exact };
49
50 LinearGaussMarkovModel(const QuantLib::ext::shared_ptr<IrLgm1fParametrization>& parametrization,
52 const bool evaluateBankAccount = true,
53 const QuantLib::ext::shared_ptr<Integrator>& integrator = QuantLib::ext::make_shared<SimpsonIntegral>(1.0E-8,
54 100));
55
56 //! IrModel interface
57
58 Measure measure() const override { return measure_; }
59 const QuantLib::ext::shared_ptr<Parametrization> parametrizationBase() const override { return parametrization_; }
60 Handle<YieldTermStructure> termStructure() const override { return parametrization_->termStructure(); }
61 Size n() const override;
62 Size m() const override;
63 Size n_aux() const override;
64 Size m_aux() const override;
65 QuantLib::ext::shared_ptr<StochasticProcess> stateProcess() const override;
66
67 QuantLib::Real discountBond(const QuantLib::Time t, const QuantLib::Time T, const QuantLib::Array& x,
68 const QuantLib::Handle<QuantLib::YieldTermStructure>& discountCurve =
69 Handle<YieldTermStructure>()) const override;
70
71 QuantLib::Real
72 numeraire(const QuantLib::Time t, const QuantLib::Array& x,
73 const QuantLib::Handle<QuantLib::YieldTermStructure>& discountCurve = Handle<YieldTermStructure>(),
74 const QuantLib::Array& aux = Array()) const override;
75
76 QuantLib::Real shortRate(const QuantLib::Time t, const QuantLib::Array& x,
77 const QuantLib::Handle<QuantLib::YieldTermStructure>& discountCurve =
78 Handle<YieldTermStructure>()) const override;
79
80 //! LGM specific methods
81
82 const QuantLib::ext::shared_ptr<IrLgm1fParametrization> parametrization() const;
83
84 Real numeraire(const Time t, const Real x,
85 const Handle<YieldTermStructure> discountCurve = Handle<YieldTermStructure>()) const;
86
87 /*! Bank account measure numeraire B(t) as a function of LGM state variable x (with drift) and auxiliary state
88 * variable y */
89 Real bankAccountNumeraire(const Time t, const Real x, const Real y,
90 const Handle<YieldTermStructure> discountCurve = Handle<YieldTermStructure>()) const;
91
92 Real discountBond(const Time t, const Time T, const Real x,
93 Handle<YieldTermStructure> discountCurve = Handle<YieldTermStructure>()) const;
94
95 Real reducedDiscountBond(const Time t, const Time T, const Real x,
96 const Handle<YieldTermStructure> discountCurve = Handle<YieldTermStructure>()) const;
97
98 Real discountBondOption(Option::Type type, const Real K, const Time t, const Time S, const Time T,
99 Handle<YieldTermStructure> discountCurve = Handle<YieldTermStructure>()) const;
100
101 /*! calibrate volatilities to a sequence of ir options with
102 expiry times equal to step times in the parametrization */
103 void calibrateVolatilitiesIterative(const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& helpers,
104 OptimizationMethod& method, const EndCriteria& endCriteria,
106 const std::vector<Real>& weights = std::vector<Real>());
107
108 /*! calibrate reversion to a sequence of ir options with
109 maturities equal to step times in the parametrization */
110 void calibrateReversionsIterative(const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& helpers,
111 OptimizationMethod& method, const EndCriteria& endCriteria,
113 const std::vector<Real>& weights = std::vector<Real>());
114
115 /*! calibrate volatilities globally */
116 void calibrateVolatilities(const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& helpers,
117 OptimizationMethod& method, const EndCriteria& endCriteria,
119 const std::vector<Real>& weights = std::vector<Real>());
120
121 /*! calibrate volatilities globally */
122 void calibrateReversions(const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& helpers,
123 OptimizationMethod& method, const EndCriteria& endCriteria,
125 const std::vector<Real>& weights = std::vector<Real>());
126
127 /*! observer and linked calibrated model interface */
128 void update() override;
129 void generateArguments() override;
130
131 /*! calibration constraints, these can be used directly, or
132 through the customized calibrate methods above */
133 std::vector<bool> MoveVolatility(const Size i) {
134 QL_REQUIRE(i < parametrization_->parameter(0)->size(),
135 "volatility index (" << i << ") out of range 0..." << parametrization_->parameter(0)->size() - 1);
136 std::vector<bool> res(parametrization_->parameter(0)->size() + parametrization_->parameter(1)->size(), true);
137 res[i] = false;
138 return res;
139 }
140
141 std::vector<bool> MoveReversion(const Size i) {
142 QL_REQUIRE(i < parametrization_->parameter(1)->size(),
143 "reversion index (" << i << ") out of range 0..." << parametrization_->parameter(1)->size() - 1);
144 std::vector<bool> res(parametrization_->parameter(0)->size() + parametrization_->parameter(1)->size(), true);
145 res[parametrization_->parameter(0)->size() + i] = false;
146 return res;
147 }
148
149 /*! set info on how the model was calibrated */
150 void setCalibrationInfo(const LgmCalibrationInfo& calibrationInfo) { calibrationInfo_ = calibrationInfo; }
151 /*! get info on how the model was calibrated */
153
154private:
155 QuantLib::ext::shared_ptr<IrLgm1fParametrization> parametrization_;
156 QuantLib::ext::shared_ptr<Integrator> integrator_;
160 QuantLib::ext::shared_ptr<StochasticProcess1D> stateProcess_;
162};
163
165
166// inline
167
169 parametrization_->update();
170 notifyObservers();
171}
172
174
175inline QuantLib::ext::shared_ptr<StochasticProcess> LinearGaussMarkovModel::stateProcess() const {
176 QL_REQUIRE(measure_ == Measure::LGM, "LinearGaussMarkovModel::stateProcess() only supports measure = LGM");
177 return stateProcess_;
178}
179
180inline QuantLib::Real
181LinearGaussMarkovModel::discountBond(const QuantLib::Time t, const QuantLib::Time T, const QuantLib::Array& x,
182 const QuantLib::Handle<QuantLib::YieldTermStructure>& discountCurve) const {
183 QL_REQUIRE(x.size() == n(), "LinearGaussMarkovModel::discountBond() requires input state of dimension " << n());
184 return discountBond(t, T, x[0], discountCurve);
185}
186
187inline QuantLib::Real
188LinearGaussMarkovModel::numeraire(const QuantLib::Time t, const QuantLib::Array& x,
189 const QuantLib::Handle<QuantLib::YieldTermStructure>& discountCurve,
190 const QuantLib::Array& aux) const {
191 QL_REQUIRE(x.size() == n(), "LinearGaussMarkovModel::numeraire() requires input state of dimension " << n());
192 QL_REQUIRE(aux.size() == n_aux(),
193 "LinearGaussMarkovModel::numeraire() requires aux input state of dimension " << n_aux());
194 if (measure() == Measure::LGM) {
195 return numeraire(t, x[0], discountCurve);
196 } else {
197 return bankAccountNumeraire(t, x[0], aux[0], discountCurve);
198 }
199}
200
201inline const QuantLib::ext::shared_ptr<IrLgm1fParametrization> LinearGaussMarkovModel::parametrization() const {
202 return parametrization_;
203}
204
205inline Real LinearGaussMarkovModel::numeraire(const Time t, const Real x,
206 const Handle<YieldTermStructure> discountCurve) const {
207 QL_REQUIRE(t >= 0.0, "t (" << t << ") >= 0 required in LGM::numeraire");
208 Real Ht = parametrization_->H(t);
209 return std::exp(Ht * x + 0.5 * Ht * Ht * parametrization_->zeta(t)) /
210 (discountCurve.empty() ? parametrization_->termStructure()->discount(t) : discountCurve->discount(t));
211}
212
213inline Real LinearGaussMarkovModel::discountBond(const Time t, const Time T, const Real x,
214 const Handle<YieldTermStructure> discountCurve) const {
215 if (QuantLib::close_enough(t, T))
216 return 1.0;
217 QL_REQUIRE(T >= t && t >= 0.0, "T(" << T << ") >= t(" << t << ") >= 0 required in LGM::discountBond");
218 Real Ht = parametrization_->H(t);
219 Real HT = parametrization_->H(T);
220 return (discountCurve.empty()
221 ? parametrization_->termStructure()->discount(T) / parametrization_->termStructure()->discount(t)
222 : discountCurve->discount(T) / discountCurve->discount(t)) *
223 std::exp(-(HT - Ht) * x - 0.5 * (HT * HT - Ht * Ht) * parametrization_->zeta(t));
224}
225
226inline QuantLib::Real
227LinearGaussMarkovModel::shortRate(const QuantLib::Time t, const QuantLib::Array& x,
228 const QuantLib::Handle<QuantLib::YieldTermStructure>& discountCurve) const {
229 QL_FAIL("LGM does not provide short rate.");
230}
231
232inline Real LinearGaussMarkovModel::reducedDiscountBond(const Time t, const Time T, const Real x,
233 const Handle<YieldTermStructure> discountCurve) const {
234 if (QuantLib::close_enough(t, T))
235 return 1.0 / numeraire(t, x, discountCurve);
236 QL_REQUIRE(T >= t && t >= 0.0, "T(" << T << ") >= t(" << t << ") >= 0 required in LGM::reducedDiscountBond");
237 Real HT = parametrization_->H(T);
238 return (discountCurve.empty() ? parametrization_->termStructure()->discount(T) : discountCurve->discount(T)) *
239 std::exp(-HT * x - 0.5 * HT * HT * parametrization_->zeta(t));
240}
241
242inline Real LinearGaussMarkovModel::discountBondOption(Option::Type type, const Real K, const Time t, const Time S,
243 const Time T,
244 const Handle<YieldTermStructure> discountCurve) const {
245 QL_REQUIRE(T > S && S >= t && t >= 0.0,
246 "T(" << T << ") > S(" << S << ") >= t(" << t << ") >= 0 required in LGM::discountBondOption");
247 Real w = (type == Option::Call ? 1.0 : -1.0);
248 Real pS = discountCurve.empty() ? parametrization_->termStructure()->discount(S) : discountCurve->discount(S);
249 Real pT = discountCurve.empty() ? parametrization_->termStructure()->discount(T) : discountCurve->discount(T);
250 // slight generalization of Lichters, Stamm, Gallagher 11.2.1
251 // with t < S, SSRN: https://ssrn.com/abstract=2246054
252 Real sigma = std::sqrt(parametrization_->zeta(t)) * (parametrization_->H(T) - parametrization_->H(S));
253 Real dp = std::log(pT / (K * pS)) / sigma + 0.5 * sigma * sigma;
254 Real dm = dp - sigma;
255 CumulativeNormalDistribution N;
256 return w * (pT * N(w * dp) - pS * K * N(w * dm));
257}
258
260 const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& helpers, OptimizationMethod& method,
261 const EndCriteria& endCriteria, const Constraint& constraint, const std::vector<Real>& weights) {
262 for (Size i = 0; i < helpers.size(); ++i) {
263 std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>> h(1, helpers[i]);
264 calibrate(h, method, endCriteria, constraint, weights, MoveVolatility(i));
265 }
266 update();
267}
268
270 const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& helpers, OptimizationMethod& method,
271 const EndCriteria& endCriteria, const Constraint& constraint, const std::vector<Real>& weights) {
272 for (Size i = 0; i < helpers.size(); ++i) {
273 std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>> h(1, helpers[i]);
274 calibrate(h, method, endCriteria, constraint, weights, MoveReversion(i));
275 }
276 update();
277}
278
279inline void
280LinearGaussMarkovModel::calibrateVolatilities(const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& helpers,
281 OptimizationMethod& method, const EndCriteria& endCriteria,
282 const Constraint& constraint, const std::vector<Real>& weights) {
283 std::vector<bool> moveVols(parametrization_->parameter(0)->size() + parametrization_->parameter(1)->size(), true);
284 for (Size i = 0; i < parametrization_->parameter(0)->size(); ++i)
285 moveVols[i] = false;
286 calibrate(helpers, method, endCriteria, constraint, weights, moveVols);
287 update();
288}
289
290inline void
291LinearGaussMarkovModel::calibrateReversions(const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& helpers,
292 OptimizationMethod& method, const EndCriteria& endCriteria,
293 const Constraint& constraint, const std::vector<Real>& weights) {
294 std::vector<bool> moveRevs(parametrization_->parameter(0)->size() + parametrization_->parameter(1)->size(), true);
295 for (Size i = 0; i < parametrization_->parameter(1)->size(); ++i)
296 moveRevs[parametrization_->parameter(0)->size() + i] = false;
297 calibrate(helpers, method, endCriteria, constraint, weights, moveRevs);
298 update();
299}
300
301} // namespace QuantExt
302
303#endif
Linear Gauss Morkov Model.
Definition: lgm.hpp:46
void calibrateVolatilities(const std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > &helpers, OptimizationMethod &method, const EndCriteria &endCriteria, const Constraint &constraint=Constraint(), const std::vector< Real > &weights=std::vector< Real >())
Definition: lgm.hpp:280
Size m() const override
Definition: lgm.cpp:59
const QuantLib::ext::shared_ptr< Parametrization > parametrizationBase() const override
Definition: lgm.hpp:59
QuantLib::ext::shared_ptr< StochasticProcess > stateProcess() const override
Definition: lgm.hpp:175
Size n() const override
Definition: lgm.cpp:58
Size n_aux() const override
Definition: lgm.cpp:60
LgmCalibrationInfo calibrationInfo_
Definition: lgm.hpp:161
void update() override
Definition: lgm.hpp:168
const QuantLib::ext::shared_ptr< IrLgm1fParametrization > parametrization() const
LGM specific methods.
Definition: lgm.hpp:201
Measure measure() const override
IrModel interface.
Definition: lgm.hpp:58
QuantLib::Real discountBond(const QuantLib::Time t, const QuantLib::Time T, const QuantLib::Array &x, const QuantLib::Handle< QuantLib::YieldTermStructure > &discountCurve=Handle< YieldTermStructure >()) const override
Definition: lgm.hpp:181
void generateArguments() override
Definition: lgm.hpp:173
QuantLib::ext::shared_ptr< IrLgm1fParametrization > parametrization_
Definition: lgm.hpp:155
void setCalibrationInfo(const LgmCalibrationInfo &calibrationInfo)
Definition: lgm.hpp:150
Handle< YieldTermStructure > termStructure() const override
Definition: lgm.hpp:60
QuantLib::Real shortRate(const QuantLib::Time t, const QuantLib::Array &x, const QuantLib::Handle< QuantLib::YieldTermStructure > &discountCurve=Handle< YieldTermStructure >()) const override
Definition: lgm.hpp:227
QuantLib::ext::shared_ptr< StochasticProcess1D > stateProcess_
Definition: lgm.hpp:160
const LgmCalibrationInfo & getCalibrationInfo() const
Definition: lgm.hpp:152
std::vector< bool > MoveReversion(const Size i)
Definition: lgm.hpp:141
Discretization discretization_
Definition: lgm.hpp:158
Real reducedDiscountBond(const Time t, const Time T, const Real x, const Handle< YieldTermStructure > discountCurve=Handle< YieldTermStructure >()) const
Definition: lgm.hpp:232
Size m_aux() const override
Definition: lgm.cpp:61
QuantLib::ext::shared_ptr< Integrator > integrator_
Definition: lgm.hpp:156
void calibrateVolatilitiesIterative(const std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > &helpers, OptimizationMethod &method, const EndCriteria &endCriteria, const Constraint &constraint=Constraint(), const std::vector< Real > &weights=std::vector< Real >())
Definition: lgm.hpp:259
std::vector< bool > MoveVolatility(const Size i)
Definition: lgm.hpp:133
Real bankAccountNumeraire(const Time t, const Real x, const Real y, const Handle< YieldTermStructure > discountCurve=Handle< YieldTermStructure >()) const
Definition: lgm.cpp:47
void calibrateReversionsIterative(const std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > &helpers, OptimizationMethod &method, const EndCriteria &endCriteria, const Constraint &constraint=Constraint(), const std::vector< Real > &weights=std::vector< Real >())
Definition: lgm.hpp:269
QuantLib::Real numeraire(const QuantLib::Time t, const QuantLib::Array &x, const QuantLib::Handle< QuantLib::YieldTermStructure > &discountCurve=Handle< YieldTermStructure >(), const QuantLib::Array &aux=Array()) const override
Definition: lgm.hpp:188
Real discountBondOption(Option::Type type, const Real K, const Time t, const Time S, const Time T, Handle< YieldTermStructure > discountCurve=Handle< YieldTermStructure >()) const
Definition: lgm.hpp:242
void calibrateReversions(const std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > &helpers, OptimizationMethod &method, const EndCriteria &endCriteria, const Constraint &constraint=Constraint(), const std::vector< Real > &weights=std::vector< Real >())
Definition: lgm.hpp:291
const QuantLib::ext::shared_ptr< Constraint > & constraint() const
EndCriteria::Type endCriteria() const
Returns end criteria result.
virtual void calibrate(const std::vector< QuantLib::ext::shared_ptr< CalibrationHelper > > &, OptimizationMethod &method, const EndCriteria &endCriteria, const Constraint &constraint=Constraint(), const std::vector< Real > &weights=std::vector< Real >(), const std::vector< bool > &fixParameters=std::vector< bool >())
Calibrate to a set of market instruments (usually caps/swaptions)
Interest Rate Linear Gaussian Markov 1 factor parametrization.
ir model base class
info data on how a lgm model was calibrated
calibrated model class with linkable parameters
LinearGaussMarkovModel LGM
Definition: lgm.hpp:164