QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
cmsmarket.cpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2007 Ferdinando Ametrano
5 Copyright (C) 2007 Marco Bianchetti
6 Copyright (C) 2006, 2007 Giorgio Facchinetti
7
8 This file is part of QuantLib, a free-software/open-source library
9 for financial quantitative analysts and developers - http://quantlib.org/
10
11 QuantLib is free software: you can redistribute it and/or modify it
12 under the terms of the QuantLib license. You should have received a
13 copy of the license along with this program; if not, please email
14 <quantlib-dev@lists.sf.net>. The license is also available online at
15 <http://quantlib.org/license.shtml>.
16
17 This program is distributed in the hope that it will be useful, but WITHOUT
18 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 FOR A PARTICULAR PURPOSE. See the license for more details.
20*/
21
22#include <ql/cashflows/cashflows.hpp>
23#include <ql/indexes/swapindex.hpp>
24#include <ql/instruments/makecms.hpp>
25#include <ql/instruments/swap.hpp>
26#include <ql/quotes/simplequote.hpp>
27#include <ql/termstructures/volatility/swaption/cmsmarket.hpp>
28#include <ql/termstructures/yieldtermstructure.hpp>
29#include <utility>
30
31using std::vector;
32
33namespace QuantLib {
34
35 CmsMarket::CmsMarket(vector<Period> swapLengths,
36 vector<ext::shared_ptr<SwapIndex> > swapIndexes,
37 ext::shared_ptr<IborIndex> iborIndex,
38 const vector<vector<Handle<Quote> > >& bidAskSpreads,
39 const vector<ext::shared_ptr<CmsCouponPricer> >& pricers,
40 Handle<YieldTermStructure> discountingTS)
41 : swapLengths_(std::move(swapLengths)), swapIndexes_(std::move(swapIndexes)),
42 iborIndex_(std::move(iborIndex)), bidAskSpreads_(bidAskSpreads), pricers_(pricers),
43 discTS_(std::move(discountingTS)),
44
45 nExercise_(swapLengths_.size()), nSwapIndexes_(swapIndexes_.size()),
46 swapTenors_(nSwapIndexes_),
47
48 spotFloatLegNPV_(nExercise_, nSwapIndexes_), spotFloatLegBPS_(nExercise_, nSwapIndexes_),
49
50 mktBidSpreads_(nExercise_, nSwapIndexes_), mktAskSpreads_(nExercise_, nSwapIndexes_),
51
52 mktSpreads_(nExercise_, nSwapIndexes_), mdlSpreads_(nExercise_, nSwapIndexes_),
53 errSpreads_(nExercise_, nSwapIndexes_),
54
55 mktSpotCmsLegNPV_(nExercise_, nSwapIndexes_), mdlSpotCmsLegNPV_(nExercise_, nSwapIndexes_),
56 errSpotCmsLegNPV_(nExercise_, nSwapIndexes_),
57
58 mktFwdCmsLegNPV_(nExercise_, nSwapIndexes_), mdlFwdCmsLegNPV_(nExercise_, nSwapIndexes_),
59 errFwdCmsLegNPV_(nExercise_, nSwapIndexes_),
60
61 spotSwaps_(nExercise_, vector<ext::shared_ptr<Swap> >(nSwapIndexes_)),
62 fwdSwaps_(nExercise_, vector<ext::shared_ptr<Swap> >(nSwapIndexes_)) {
63 QL_REQUIRE(2 * nSwapIndexes_ == bidAskSpreads[0].size(),
64 "2*nSwapIndexes_ (" << 2 * nSwapIndexes_
65 << ") != bidAskSpreads columns() ("
66 << bidAskSpreads[0].size() << ")");
67 QL_REQUIRE(nExercise_ == bidAskSpreads.size(),
68 "nExercise_ (" << nExercise_ << ") != bidAskSpreads rows() ("
69 << bidAskSpreads.size() << ")");
70 QL_REQUIRE(nSwapIndexes_ == pricers.size(),
71 "nSwapIndexes_ (" << nSwapIndexes_ << ") != pricers ("
72 << pricers_.size() << ")");
73
74 for (Size j=0; j<nSwapIndexes_; ++j) {
75 swapTenors_[j] = swapIndexes_[j]->tenor();
76 // pricers
78 for (Size i=0; i<nExercise_; ++i) {
79 // market Spread
82 }
83 }
84
85 Period start(0, Years);
86 for (Size i=0; i<nExercise_; ++i) {
87 if (i>0) start = swapLengths_[i-1];
88 for (Size j=0; j<nSwapIndexes_; ++j) {
89 // never evaluate the spot swap, only its ibor floating leg
91 swapIndexes_[j],
92 iborIndex_, 0.0,
93 Period())
94 .operator ext::shared_ptr<Swap>();
95 fwdSwaps_[i][j] = MakeCms(swapLengths_[i]-start,
96 swapIndexes_[j],
97 iborIndex_, 0.0,
98 start)
101 .operator ext::shared_ptr<Swap>();
102 }
103 }
104 // probably useless
106 }
107
109 for (Size j=0; j<nSwapIndexes_; ++j) {
110 Real mktPrevPart = 0.0, mdlPrevPart = 0.0;
111 for (Size i=0; i<nExercise_; ++i) {
112
113 // **** market
114
115 mktBidSpreads_[i][j] = bidAskSpreads_[i][j*2]->value();
116 mktAskSpreads_[i][j] = bidAskSpreads_[i][j*2+1]->value();
117 mktSpreads_[i][j] = (mktBidSpreads_[i][j]+mktAskSpreads_[i][j])/2;
118
119 const Leg& spotFloatLeg = spotSwaps_[i][j]->leg(1);
120 spotFloatLegNPV_[i][j] = CashFlows::npv(spotFloatLeg,
121 **discTS_,
122 false, discTS_->referenceDate());
123 spotFloatLegBPS_[i][j] = CashFlows::bps(spotFloatLeg,
124 **discTS_,
125 false, discTS_->referenceDate());
126
127 // imply the spot CMS leg NPV from the spot ibor floating leg NPV
128 mktSpotCmsLegNPV_[i][j] = -(spotFloatLegNPV_[i][j] +
129 spotFloatLegBPS_[i][j]*mktSpreads_[i][j]/1e-4);
130 // fwd CMS legs can be computed as differences between spot legs
131 mktFwdCmsLegNPV_[i][j] = mktSpotCmsLegNPV_[i][j] - mktPrevPart;
132 mktPrevPart = mktSpotCmsLegNPV_[i][j];
133
134 // **** model
135
136 // calculate the forward swap (the time consuming part)
137 mdlFwdCmsLegNPV_[i][j] = fwdSwaps_[i][j]->legNPV(0);
138 errFwdCmsLegNPV_[i][j] = mdlFwdCmsLegNPV_[i][j] -
139 mktFwdCmsLegNPV_[i][j];
140
141 // spot CMS legs can be computed as incremental sum of forward legs
142 mdlSpotCmsLegNPV_[i][j] = mdlPrevPart + mdlFwdCmsLegNPV_[i][j];
143 mdlPrevPart = mdlSpotCmsLegNPV_[i][j];
145 mktSpotCmsLegNPV_[i][j];
146
147 // equilibriums spread over ibor leg
148 Real npv = spotFloatLegNPV_[i][j] + mdlSpotCmsLegNPV_[i][j];
149 mdlSpreads_[i][j] = - npv/spotFloatLegBPS_[i][j]*1e-4;
150 errSpreads_[i][j] = mdlSpreads_[i][j] - mktSpreads_[i][j];
151 }
152 }
153 }
154
156 Real meanReversion) {
157 Handle<Quote> meanReversionQuote(
158 ext::make_shared<SimpleQuote>(meanReversion));
159 for (Size j = 0; j < nSwapIndexes_; ++j) {
160 // ??
161 // set new volatility structure and new mean reversion
162 pricers_[j]->setSwaptionVolatility(v);
163 if (meanReversion != Null<Real>()) {
164 ext::shared_ptr<MeanRevertingPricer> p =
165 ext::dynamic_pointer_cast<MeanRevertingPricer>(
166 pricers_[j]);
167 QL_REQUIRE(p != nullptr, "mean reverting pricer required at index " << j);
168 p->setMeanReversion(meanReversionQuote);
169 }
170 }
172 }
173
177 }
178
182 }
183
186 return weightedMean(errSpreads_, w);
187 }
188
189 // array of errors to be used by Levenberg-Marquardt optimization
190
194 }
195
199 }
200
203 return weightedMeans(errSpreads_, w);
204 }
205
206 Real CmsMarket::weightedMean(const Matrix& var, const Matrix& w) const {
207 Real mean = 0.0;
208 for (Size i=0; i<nExercise_; ++i) {
209 for (Size j=0; j<nSwapIndexes_; ++j) {
210 mean += w[i][j]*var[i][j]*var[i][j];
211 }
212 }
213 mean = std::sqrt(mean/(nExercise_*nSwapIndexes_));
214 return mean;
215 }
216
217 Array CmsMarket::weightedMeans(const Matrix& var, const Matrix& w) const {
218 Array weightedVars(nExercise_*nSwapIndexes_);
219 for (Size i=0; i<nExercise_; ++i) {
220 for (Size j=0; j<nSwapIndexes_; ++j) {
221 weightedVars[i*nSwapIndexes_+j] = std::sqrt(w[i][j])*var[i][j];
222 }
223 }
224 return weightedVars;
225 }
226
228 calculate();
229 //Matrix result(nExercise_*nSwapIndexes_, 15);
230 Matrix result(nExercise_*nSwapIndexes_, 14);
231 for (Size j=0; j<nSwapIndexes_; ++j) {
232 for (Size i=0; i<nExercise_; ++i) {
233 result[j*nExercise_+i][0] = swapTenors_[j].length();
234 result[j*nExercise_+i][1] = swapLengths_[i].length();
235
236 // Spreads
237 result[j*nExercise_+i][2] = mktBidSpreads_[i][j]*10000;
238 result[j*nExercise_+i][3] = mktAskSpreads_[i][j]*10000;
239 result[j*nExercise_+i][4] = mktSpreads_[i][j]*10000;
240 result[j*nExercise_+i][5] = mdlSpreads_[i][j]*10000;
241 result[j*nExercise_+i][6] = errSpreads_[i][j]*10000;
242 if (mdlSpreads_[i][j]>mktAskSpreads_[i][j])
243 result[j*nExercise_+i][7] = (mdlSpreads_[i][j] -
244 mktAskSpreads_[i][j])*10000;
245 else if (mdlSpreads_[i][j]<mktBidSpreads_[i][j])
246 result[j*nExercise_+i][7] = (mktBidSpreads_[i][j] -
247 mdlSpreads_[i][j])*10000;
248 else
249 result[j*nExercise_+i][7] = 0.0;
250
251 // spot CMS Leg NPVs
252 result[j*nExercise_+i][ 8] = mktSpotCmsLegNPV_[i][j];
253 result[j*nExercise_+i][ 9] = mdlSpotCmsLegNPV_[i][j];
254 result[j*nExercise_+i][10] = errSpotCmsLegNPV_[i][j];
255
256 // forward CMS Leg NPVs
257 result[j*nExercise_+i][11] = mktFwdCmsLegNPV_[i][j];
258 result[j*nExercise_+i][12] = mdlFwdCmsLegNPV_[i][j];
259 result[j*nExercise_+i][13] = errFwdCmsLegNPV_[i][j];
260 }
261 }
262 return result;
263 }
264}
1-D array used in linear algebra.
Definition: array.hpp:52
static Real npv(const Leg &leg, const YieldTermStructure &discountCurve, bool includeSettlementDateFlows, Date settlementDate=Date(), Date npvDate=Date())
NPV of the cash flows.
Definition: cashflows.cpp:425
static Real bps(const Leg &leg, const YieldTermStructure &discountCurve, bool includeSettlementDateFlows, Date settlementDate=Date(), Date npvDate=Date())
Basis-point sensitivity of the cash flows.
Definition: cashflows.cpp:450
Array weightedFwdNpvErrors(const Matrix &weights)
Definition: cmsmarket.cpp:191
void performCalculations() const override
Definition: cmsmarket.cpp:108
Handle< YieldTermStructure > discTS_
Definition: cmsmarket.hpp:82
std::vector< std::vector< Handle< Quote > > > bidAskSpreads_
Definition: cmsmarket.hpp:80
Matrix browse() const
Definition: cmsmarket.cpp:227
std::vector< Period > swapTenors_
Definition: cmsmarket.hpp:86
Real weightedSpotNpvError(const Matrix &weights)
Definition: cmsmarket.cpp:179
Real weightedSpreadError(const Matrix &weights)
Definition: cmsmarket.cpp:184
std::vector< ext::shared_ptr< CmsCouponPricer > > pricers_
Definition: cmsmarket.hpp:81
Array weightedSpotNpvErrors(const Matrix &weights)
Definition: cmsmarket.cpp:196
ext::shared_ptr< IborIndex > iborIndex_
Definition: cmsmarket.hpp:79
Matrix mdlSpotCmsLegNPV_
Definition: cmsmarket.hpp:99
Real weightedMean(const Matrix &var, const Matrix &weights) const
Definition: cmsmarket.cpp:206
std::vector< std::vector< ext::shared_ptr< Swap > > > fwdSwaps_
Definition: cmsmarket.hpp:111
std::vector< ext::shared_ptr< SwapIndex > > swapIndexes_
Definition: cmsmarket.hpp:78
Matrix mktSpotCmsLegNPV_
Definition: cmsmarket.hpp:97
Array weightedMeans(const Matrix &var, const Matrix &weights) const
Definition: cmsmarket.cpp:217
void reprice(const Handle< SwaptionVolatilityStructure > &volStructure, Real meanReversion)
Definition: cmsmarket.cpp:155
CmsMarket(std::vector< Period > swapLengths, std::vector< ext::shared_ptr< SwapIndex > > swapIndexes, ext::shared_ptr< IborIndex > iborIndex, const std::vector< std::vector< Handle< Quote > > > &bidAskSpreads, const std::vector< ext::shared_ptr< CmsCouponPricer > > &pricers, Handle< YieldTermStructure > discountingTS)
Definition: cmsmarket.cpp:35
Array weightedSpreadErrors(const Matrix &weights)
Definition: cmsmarket.cpp:201
Real weightedFwdNpvError(const Matrix &weights)
Definition: cmsmarket.cpp:174
std::vector< std::vector< ext::shared_ptr< Swap > > > spotSwaps_
Definition: cmsmarket.hpp:110
std::vector< Period > swapLengths_
Definition: cmsmarket.hpp:77
Shared handle to an observable.
Definition: handle.hpp:41
virtual void calculate() const
Definition: lazyobject.hpp:253
helper class for instantiating CMS
Definition: makecms.hpp:40
MakeCms & withDiscountingTermStructure(const Handle< YieldTermStructure > &discountingTermStructure)
Definition: makecms.cpp:188
MakeCms & withCmsCouponPricer(const ext::shared_ptr< CmsCouponPricer > &couponPricer)
Definition: makecms.cpp:194
Matrix used in linear algebra.
Definition: matrix.hpp:41
template class providing a null value for a given type.
Definition: null.hpp:76
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
Definition: observable.hpp:228
Interest rate swap.
Definition: swap.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
std::vector< ext::shared_ptr< CashFlow > > Leg
Sequence of cash-flows.
Definition: cashflow.hpp:78
STL namespace.