Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
hwbuilder.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2022 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
27
30
31#include <ql/math/optimization/levenbergmarquardt.hpp>
32#include <ql/models/shortrate/calibrationhelpers/swaptionhelper.hpp>
33#include <ql/pricingengines/swaption/blackswaptionengine.hpp>
34#include <ql/quotes/simplequote.hpp>
35
36using namespace QuantLib;
37using namespace QuantExt;
38using namespace std;
39
40namespace ore {
41namespace data {
42
43HwBuilder::HwBuilder(const QuantLib::ext::shared_ptr<ore::data::Market>& market, const QuantLib::ext::shared_ptr<HwModelData>& data,
44 const IrModel::Measure measure, const HwModel::Discretization discretization,
45 const bool evaluateBankAccount, const std::string& configuration, const Real bootstrapTolerance,
46 const bool continueOnError, const std::string& referenceCalibrationGrid,
47 const bool setCalibrationInfo)
48 : market_(market), configuration_(configuration), data_(data), measure_(measure), discretization_(discretization),
49 /*bootstrapTolerance_(bootstrapTolerance), continueOnError_(continueOnError),*/
50 referenceCalibrationGrid_(referenceCalibrationGrid), /*setCalibrationInfo_(setCalibrationInfo),*/
51 optimizationMethod_(QuantLib::ext::shared_ptr<OptimizationMethod>(new LevenbergMarquardt(1E-8, 1E-8, 1E-8))),
52 endCriteria_(EndCriteria(1000, 500, 1E-8, 1E-8, 1E-8))
53 /*,calibrationErrorType_(BlackCalibrationHelper::RelativePriceError)*/ {
54
55 marketObserver_ = QuantLib::ext::make_shared<MarketObserver>();
56 string qualifier = data_->qualifier();
58 QuantLib::ext::shared_ptr<IborIndex> index;
59 if (tryParseIborIndex(qualifier, index)) {
60 currency_ = index->currency().code();
61 }
62 LOG("HwCalibration for qualifier " << qualifier << " (ccy=" << currency_ << "), configuration is "
64 Currency ccy = parseCurrency(currency_);
65
67 (data_->calibrateSigma() || data_->calibrateKappa()) && data_->calibrationType() != CalibrationType::None;
68
69 QL_REQUIRE(!requiresCalibration_, "HwBuilder: HwModel does not support calibration at the moment.");
70
71 // the discount curve underlying the model might be relinked to a different curve outside this builder
72 // the calibration curve should always stay the same though, therefore we create a different handle for this
73 modelDiscountCurve_ = RelinkableHandle<YieldTermStructure>(*market_->discountCurve(currency_, configuration_));
74 calibrationDiscountCurve_ = Handle<YieldTermStructure>(*modelDiscountCurve_);
75
77 svts_ = market_->swaptionVol(data_->qualifier(), configuration_);
78 swapIndex_ = market_->swapIndex(market_->swapIndexBase(data_->qualifier(), configuration_), configuration_);
80 market_->swapIndex(market_->shortSwapIndexBase(data_->qualifier(), configuration_), configuration_);
81 registerWith(svts_);
82 marketObserver_->addObservable(swapIndex_->forwardingTermStructure());
83 marketObserver_->addObservable(swapIndex_->discountingTermStructure());
84 marketObserver_->addObservable(shortSwapIndex_->forwardingTermStructure());
85 marketObserver_->addObservable(shortSwapIndex_->discountingTermStructure());
86 }
88 registerWith(marketObserver_);
89 // notify observers of all market data changes, not only when not calculated
90 alwaysForwardNotifications();
91
92 swaptionActive_ = std::vector<bool>(data_->optionExpiries().size(), false);
93
95 // buildSwaptionBasket();
96 }
97
98 Array sigmaTimes(data_->sigmaTimes().begin(), data_->sigmaTimes().end());
99 Array kappaTimes(data_->kappaTimes().begin(), data_->kappaTimes().end());
100 std::vector<Matrix> sigma(data_->sigmaValues().begin(), data_->sigmaValues().end());
101 std::vector<Array> kappa(data_->kappaValues().begin(), data_->kappaValues().end());
102
103 QL_REQUIRE(data_->sigmaType() == ParamType::Constant,
104 "HwBuilder: only constant sigma is supported at the moment");
105 QL_REQUIRE(data_->kappaType() == ParamType::Constant,
106 "HwBuilder: only constant sigma is supported at the moment");
107
108 if (data_->sigmaType() == ParamType::Constant) {
109 QL_REQUIRE(data_->sigmaTimes().size() == 0,
110 "HwBuilder: empty volatility time grid expected for constant parameter type");
111 QL_REQUIRE(data_->sigmaValues().size() == 1,
112 "HwBuilder: initial volatility values should have size 1 for constant parameter type");
113 } else if (data_->sigmaType() == ParamType::Piecewise) {
114 if (data_->calibrateSigma() && data_->calibrationType() == CalibrationType::Bootstrap) {
115 if (data_->sigmaTimes().size() > 0) {
116 DLOG("overriding alpha time grid with swaption expiries, set all initial values to first given value");
117 }
118 QL_REQUIRE(swaptionExpiries_.size() > 0, "empty swaptionExpiries");
119 sigmaTimes = Array(swaptionExpiries_.begin(), swaptionExpiries_.end() - 1);
120 sigma = std::vector<Matrix>(sigmaTimes.size() + 1, data_->sigmaValues()[0]);
121 } else {
122 QL_REQUIRE(sigma.size() == sigmaTimes.size() + 1,
123 "HwBBuilder: hw volatility time and initial value array sizes do not match");
124 }
125 } else {
126 QL_FAIL("HwBuilder: volatility parameter type not covered");
127 }
128
129 if (data_->kappaType() == ParamType::Constant) {
130 QL_REQUIRE(data_->kappaTimes().size() == 0,
131 "HwBuilder: empty reversion time grid expected for constant parameter type");
132 QL_REQUIRE(data_->kappaValues().size() == 1,
133 "HwBuidler: initial reversion values should have size 1 for constant parameter type");
134 } else if (data_->kappaType() == ParamType::Piecewise) {
135 if (data_->calibrateKappa() && data_->calibrationType() == CalibrationType::Bootstrap) {
136 if (data_->kappaTimes().size() > 0) {
137 DLOG("overriding h time grid with swaption underlying maturities, set all initial values to first "
138 "given value");
139 }
140 kappaTimes = swaptionMaturities_;
141 kappa = std::vector<Array>(kappaTimes.size() + 1, data_->kappaValues()[0]);
142 } else { // use input time grid and input h array otherwise
143 QL_REQUIRE(kappa.size() == kappaTimes.size() + 1, "HwBuilder:: hw kappa grids do not match");
144 }
145 } else
146 QL_FAIL("HwBuilder: reversion parameter type case not covered");
147
148 DLOGGERSTREAM("before calibration: sigma times = " << sigmaTimes);
149 DLOGGERSTREAM("before calibration: kappa times = " << kappaTimes);
150
152 QuantLib::ext::make_shared<QuantExt::IrHwConstantParametrization>(ccy, modelDiscountCurve_, sigma[0], kappa[0]);
153
154 DLOG("alpha times size: " << sigmaTimes.size());
155 DLOG("lambda times size: " << kappaTimes.size());
156
157 model_ = QuantLib::ext::make_shared<QuantExt::HwModel>(parametrization_, measure_, discretization_, evaluateBankAccount_);
158 params_ = model_->params();
159}
160
161Real HwBuilder::error() const {
162 calculate();
163 return error_;
164}
165
166QuantLib::ext::shared_ptr<QuantExt::HwModel> HwBuilder::model() const {
167 calculate();
168 return model_;
169}
170
171QuantLib::ext::shared_ptr<QuantExt::IrHwParametrization> HwBuilder::parametrization() const {
172 calculate();
173 return parametrization_;
174}
175
176std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>> HwBuilder::swaptionBasket() const {
177 calculate();
178 return swaptionBasket_;
179}
180
182 // TODO
183 // return requiresCalibration_ &&
184 // (volSurfaceChanged(false) || marketObserver_->hasUpdated(false) || forceCalibration_);
185 return false;
186}
187
189
190 DLOG("Recalibrate HW model for qualifier " << data_->qualifier() << " currency " << currency_);
191
192 // TODO...
193
194} // performCalculations()
195
197 forceCalibration_ = true;
199 forceCalibration_ = false;
200}
201
202} // namespace data
203} // namespace ore
virtual void forceRecalculate()
std::vector< bool > swaptionActive_
Definition: hwbuilder.hpp:96
Handle< SwapIndex > swapIndex_
Definition: hwbuilder.hpp:107
QuantLib::ext::shared_ptr< QuantExt::IrHwParametrization > parametrization() const
Definition: hwbuilder.cpp:171
IrModel::Measure measure_
Definition: hwbuilder.hpp:80
const std::string configuration_
Definition: hwbuilder.hpp:78
void forceRecalculate() override
Definition: hwbuilder.cpp:196
void performCalculations() const override
Definition: hwbuilder.cpp:188
QuantLib::ext::shared_ptr< QuantExt::MarketObserver > marketObserver_
Definition: hwbuilder.hpp:120
QuantLib::ext::shared_ptr< QuantExt::HwModel > model_
Definition: hwbuilder.hpp:91
std::string currency_
Definition: hwbuilder.hpp:88
QuantLib::ext::shared_ptr< QuantExt::HwModel > model() const
Definition: hwbuilder.cpp:166
HwBuilder(const QuantLib::ext::shared_ptr< ore::data::Market > &market, const QuantLib::ext::shared_ptr< HwModelData > &data, const IrModel::Measure measure=IrModel::Measure::BA, const HwModel::Discretization discretization=HwModel::Discretization::Euler, const bool evaluateBankAccount=true, const std::string &configuration=Market::defaultConfiguration, Real bootstrapTolerance=0.001, const bool continueOnError=false, const std::string &referenceCalibrationGrid="", const bool setCalibrationInfo=false)
Definition: hwbuilder.cpp:43
HwModel::Discretization discretization_
Definition: hwbuilder.hpp:81
QuantLib::ext::shared_ptr< HwModelData > data_
Definition: hwbuilder.hpp:79
bool requiresRecalibration() const override
Definition: hwbuilder.cpp:181
std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > swaptionBasket() const
Definition: hwbuilder.cpp:176
Handle< YieldTermStructure > calibrationDiscountCurve_
Definition: hwbuilder.hpp:105
QuantLib::ext::shared_ptr< ore::data::Market > market_
Definition: hwbuilder.hpp:77
std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > swaptionBasket_
Definition: hwbuilder.hpp:97
Handle< SwapIndex > shortSwapIndex_
Definition: hwbuilder.hpp:107
QuantLib::ext::shared_ptr< QuantExt::IrHwParametrization > parametrization_
Definition: hwbuilder.hpp:93
std::string ccy()
Definition: hwbuilder.hpp:61
std::string qualifier()
Definition: hwbuilder.hpp:60
Real error() const
Return calibration error.
Definition: hwbuilder.cpp:161
Handle< QuantLib::SwaptionVolatilityStructure > svts_
Definition: hwbuilder.hpp:106
RelinkableHandle< YieldTermStructure > modelDiscountCurve_
Definition: hwbuilder.hpp:104
The date grid class.
bool tryParseIborIndex(const string &s, QuantLib::ext::shared_ptr< IborIndex > &index)
Try to convert std::string to QuantLib::IborIndex.
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
Definition: parsers.cpp:290
Build a hw model.
Map text representations to QuantLib/QuantExt types.
Classes and functions for log message handling.
@ data
Definition: log.hpp:77
#define LOG(text)
Logging Macro (Level = Notice)
Definition: log.hpp:552
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
#define DLOGGERSTREAM(text)
Definition: log.hpp:632
Shared utilities for model building and calibration.
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Map text representations to QuantLib/QuantExt types.
Error for model calibration / building.
strike description