QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
basketgeneratingengine.hpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2013 Peter Caspers
5
6 This file is part of QuantLib, a free-software/open-source library
7 for financial quantitative analysts and developers - http://quantlib.org/
8
9 QuantLib is free software: you can redistribute it and/or modify it
10 under the terms of the QuantLib license. You should have received a
11 copy of the license along with this program; if not, please email
12 <quantlib-dev@lists.sf.net>. The license is also available online at
13 <http://quantlib.org/license.shtml>.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
25#ifndef quantlib_basketgeneratingengine_hpp
26#define quantlib_basketgeneratingengine_hpp
27
28#include <ql/cashflows/fixedratecoupon.hpp>
29#include <ql/cashflows/iborcoupon.hpp>
30#include <ql/indexes/swapindex.hpp>
31#include <ql/instruments/vanillaswap.hpp>
32#include <ql/math/optimization/costfunction.hpp>
33#include <ql/models/shortrate/onefactormodels/gaussian1dmodel.hpp>
34#include <ql/qldefines.hpp>
35#include <ql/termstructures/volatility/swaption/swaptionvolstructure.hpp>
36#include <ql/termstructures/yieldtermstructure.hpp>
37#include <utility>
38
39namespace QuantLib {
40
41 /* \warning the generated calibrating swaptions have a strike floored at
42 0.1bp (minus lognormal shift, if applicable), this is not true for atm
43 swaptions where the strike is generated in the swaption helper.
44
45 \warning the standardSwapBase index should have associated forward and
46 discount curves. These curves are used for setup of the swaption helper.
47 This means that the market price of the calibration instrument is calculated
48 using these curves. Therefore the model price must be calculated using the
49 same curves, otherwise the calibration gets incosistent, i.e. the pricing
50 engine used for model calibration has to be capable of using the same curves
51 as associated to the index. Also the volatility structure passed to construct
52 the calibration helper should use curves that are consistent with the model
53 calibration curve setup. Finally the discountCurve given in the constructor
54 should be the same curve as the discounting curve of the swapIndex used to
55 determine the calibration basket. */
56
58
59 public:
60
61 typedef enum CalibrationBasketType {
65
66 virtual ~BasketGeneratingEngine() = default;
67
68 std::vector<ext::shared_ptr<BlackCalibrationHelper>>
69 calibrationBasket(const ext::shared_ptr<Exercise>& exercise,
70 const ext::shared_ptr<SwapIndex>& standardSwapBase,
71 const ext::shared_ptr<SwaptionVolatilityStructure>& swaptionVolatility,
73
74 protected:
75 BasketGeneratingEngine(const ext::shared_ptr<Gaussian1dModel>& model,
76 Handle<Quote> oas,
77 Handle<YieldTermStructure> discountCurve)
78 : onefactormodel_(model), oas_(std::move(oas)), discountCurve_(std::move(discountCurve)) {}
79
81 Handle<Quote> oas,
82 Handle<YieldTermStructure> discountCurve)
83 : onefactormodel_(std::move(model)), oas_(std::move(oas)),
84 discountCurve_(std::move(discountCurve)) {}
85
86 virtual Real underlyingNpv(const Date& expiry, Real y) const = 0;
87
88 virtual Swap::Type underlyingType() const = 0;
89
90 virtual const Date underlyingLastDate() const = 0;
91
92 virtual const Array initialGuess(const Date &expiry) const = 0; // return (nominal,
93 // maturity, rate)
94
95 private:
96
100
101 class MatchHelper : public CostFunction {
102 public:
104 const Real npv,
105 const Real delta,
106 const Real gamma,
107 ext::shared_ptr<Gaussian1dModel> model,
108 ext::shared_ptr<SwapIndex> indexBase,
109 const Date& expiry,
110 const Real maxMaturity,
111 const Real h)
112 : type_(type), mdl_(std::move(model)), indexBase_(std::move(indexBase)),
113 expiry_(expiry), maxMaturity_(maxMaturity), npv_(npv), delta_(delta), gamma_(gamma),
114 h_(h) {}
115
116 Real NPV(const ext::shared_ptr<VanillaSwap>& swap,
117 Real fixedRate,
118 Real nominal,
119 Real y,
120 int type) const {
121 Real npv = 0.0;
122 for (const auto& i : swap->fixedLeg()) {
123 ext::shared_ptr<FixedRateCoupon> c =
124 ext::dynamic_pointer_cast<FixedRateCoupon>(i);
125 npv -=
126 fixedRate * c->accrualPeriod() * nominal *
127 mdl_->zerobond(c->date(), expiry_, y,
128 indexBase_->discountingTermStructure());
129 }
130 for (const auto& i : swap->floatingLeg()) {
131 ext::shared_ptr<IborCoupon> c = ext::dynamic_pointer_cast<IborCoupon>(i);
132 npv +=
133 mdl_->forwardRate(c->fixingDate(), expiry_, y,
134 c->iborIndex()) *
135 c->accrualPeriod() * nominal *
136 mdl_->zerobond(c->date(), expiry_, y,
137 indexBase_->discountingTermStructure());
138 }
139 return (Real)type * npv;
140 }
141
142 Real value(const Array& v) const override {
143 Array vals = values(v);
144 Real res = 0.0;
145 for (Real val : vals) {
146 res += val * val;
147 }
148 return std::sqrt(res / vals.size());
149 }
150
151 Array values(const Array& v) const override {
152 // transformations
153 int type = type_; // start with same type as non standard
154 // underlying (1 means payer, -1 receiver)
155 Real nominal = std::fabs(v[0]);
156 if (v[0] < 0.0)
157 type *= -1;
158 Real maturity = std::min(std::fabs(v[1]), maxMaturity_);
159
160 Real fixedRate = v[2]; // allow for negative rates explicitly
161 // (though it might not be reasonable for calibration depending
162 // on the model to calibrate and the market instrument quotation)
163 Size years = (Size)std::floor(maturity);
164 maturity -= (Real)years;
165 maturity *= 12.0;
166 Size months = (Size)std::floor(maturity);
167 Real alpha = 1.0 - (maturity - (Real)months);
168 if (years == 0 && months == 0) {
169 months = 1; // ensure a maturity of at least one month ...
170 alpha = 1.0; // ... but in this case only look at the lower
171 // maturity swap
172 }
173 // maturity -= (Real)months; maturity *= 365.25;
174 // Size days = (Size)std::floor(maturity);
175 // Real alpha = 1.0-(maturity-(Real)days);
176 // generate swap
177 Period lowerPeriod =
178 years * Years + months * Months; //+days*Days;
179 Period upperPeriod = lowerPeriod + 1 * Months; // 1*Days;
180 ext::shared_ptr<SwapIndex> tmpIndexLower, tmpIndexUpper;
181 tmpIndexLower = indexBase_->clone(lowerPeriod);
182 tmpIndexUpper = indexBase_->clone(upperPeriod);
183 ext::shared_ptr<VanillaSwap> swapLower =
184 tmpIndexLower->underlyingSwap(expiry_);
185 ext::shared_ptr<VanillaSwap> swapUpper =
186 tmpIndexUpper->underlyingSwap(expiry_);
187 // compute npv, delta, gamma
188 Real npvm =
189 alpha * NPV(swapLower, fixedRate, nominal, -h_, type) +
190 (1.0 - alpha) *
191 NPV(swapUpper, fixedRate, nominal, -h_, type);
192 Real npv =
193 alpha * NPV(swapLower, fixedRate, nominal, 0.0, type) +
194 (1.0 - alpha) *
195 NPV(swapUpper, fixedRate, nominal, 0.0, type);
196 Real npvu =
197 alpha * NPV(swapLower, fixedRate, nominal, h_, type) +
198 (1.0 - alpha) *
199 NPV(swapUpper, fixedRate, nominal, h_, type);
200 Real delta = (npvu - npvm) / (2.0 * h_);
201 Real gamma = (npvu - 2.0 * npv + npvm) / (h_ * h_);
202
203 // debug output global standard underlying npv
204 // Real xtmp = -5.0;
205 // std::cout << "globalStandardNpv;";
206 // while (xtmp <= 5.0 + QL_EPSILON) {
207 // std::cout << alpha *NPV(swapLower, fixedRate, nominal, xtmp,
208 // type) +
209 // (1.0 - alpha) * NPV(swapUpper, fixedRate,
210 // nominal, xtmp, type)
211 // << ";";
212 // xtmp += 0.1;
213 // }
214 // std::cout << std::endl;
215 // end debug output
216
217 // return target function values
218 Array res(3);
219 res[0] = (npv - npv_) / delta_;
220 res[1] = (delta - delta_) / delta_;
221 res[2] = (gamma - gamma_) / gamma_;
222 return res;
223 }
224
226 const ext::shared_ptr<Gaussian1dModel> mdl_;
227 const ext::shared_ptr<SwapIndex> indexBase_;
231 };
232 };
233}
234
235#endif
1-D array used in linear algebra.
Definition: array.hpp:52
Size size() const
dimension of the array
Definition: array.hpp:495
MatchHelper(const Swap::Type type, const Real npv, const Real delta, const Real gamma, ext::shared_ptr< Gaussian1dModel > model, ext::shared_ptr< SwapIndex > indexBase, const Date &expiry, const Real maxMaturity, const Real h)
Real NPV(const ext::shared_ptr< VanillaSwap > &swap, Real fixedRate, Real nominal, Real y, int type) const
Real value(const Array &v) const override
method to overload to compute the cost function value in x
const ext::shared_ptr< Gaussian1dModel > mdl_
Array values(const Array &v) const override
method to overload to compute the cost function values in x
BasketGeneratingEngine(const ext::shared_ptr< Gaussian1dModel > &model, Handle< Quote > oas, Handle< YieldTermStructure > discountCurve)
const Handle< YieldTermStructure > discountCurve_
virtual Real underlyingNpv(const Date &expiry, Real y) const =0
std::vector< ext::shared_ptr< BlackCalibrationHelper > > calibrationBasket(const ext::shared_ptr< Exercise > &exercise, const ext::shared_ptr< SwapIndex > &standardSwapBase, const ext::shared_ptr< SwaptionVolatilityStructure > &swaptionVolatility, CalibrationBasketType basketType=MaturityStrikeByDeltaGamma) const
virtual const Date underlyingLastDate() const =0
virtual const Array initialGuess(const Date &expiry) const =0
const Handle< Gaussian1dModel > onefactormodel_
virtual Swap::Type underlyingType() const =0
virtual ~BasketGeneratingEngine()=default
BasketGeneratingEngine(Handle< Gaussian1dModel > model, Handle< Quote > oas, Handle< YieldTermStructure > discountCurve)
Cost function abstract class for optimization problem.
Concrete date class.
Definition: date.hpp:125
Shared handle to an observable.
Definition: handle.hpp:41
QL_REAL Real
real number
Definition: types.hpp:50
std::size_t Size
size of a container
Definition: types.hpp:58
Definition: any.hpp:35
Real months(const Period &p)
Definition: period.cpp:296
Real years(const Period &p)
Definition: period.cpp:279
void swap(Array &v, Array &w) noexcept
Definition: array.hpp:903
STL namespace.