1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3 /*
4 Copyright (C) 2006 Ferdinando Ametrano
5 Copyright (C) 2006 Marco Bianchetti
6 Copyright (C) 2006 Cristina Duminuco
7 Copyright (C) 2006 StatPro Italia srl
8
9 This file is part of QuantLib, a free-software/open-source library
10 for financial quantitative analysts and developers - http://quantlib.org/
11
12 QuantLib is free software: you can redistribute it and/or modify it
13 under the terms of the QuantLib license. You should have received a
14 copy of the license along with this program; if not, please email
15 <quantlib-dev@lists.sf.net>. The license is also available online at
16 <http://quantlib.org/license.shtml>.
17
18 This program is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20 FOR A PARTICULAR PURPOSE. See the license for more details.
21 */
22
23 #include "curvestates.hpp"
24 #include "utilities.hpp"
25 #include <ql/models/marketmodels/curvestates/lmmcurvestate.hpp>
26 #include <ql/models/marketmodels/curvestates/coterminalswapcurvestate.hpp>
27 #include <ql/models/marketmodels/curvestates/cmswapcurvestate.hpp>
28 #include <ql/models/marketmodels/evolutiondescription.hpp>
29 #include <ql/models/marketmodels/driftcomputation/lmmdriftcalculator.hpp>
30 #include <ql/models/marketmodels/driftcomputation/cmsmmdriftcalculator.hpp>
31 #include <ql/utilities/dataformatters.hpp>
32 #include <ql/math/matrix.hpp>
33 #include <ql/time/schedule.hpp>
34 #include <ql/time/daycounters/simpledaycounter.hpp>
35 #include <sstream>
36
37 using namespace QuantLib;
38 using namespace boost::unit_test_framework;
39
40 #define BEGIN(x) (x+0)
41 #define END(x) (x+LENGTH(x))
42
43 namespace curve_states_test {
44
45 struct CommonVars {
46 // global data
47 Date todaysDate, startDate, endDate;
48 std::vector<Time> rateTimes, paymentTimes;
49 std::vector<Real> accruals;
50 Calendar calendar;
51 DayCounter dayCounter;
52 std::vector<Rate> todaysForwards, todaysCoterminalSwapRates;
53 std::vector<Real> coterminalAnnuity;
54 Spread displacement;
55 std::vector<DiscountFactor> todaysDiscounts;
56
57 // cleanup
58 SavedSettings backup;
59
CommonVarscurve_states_test::CommonVars60 CommonVars() {
61 // Times
62 calendar = NullCalendar();
63 todaysDate = Settings::instance().evaluationDate();
64 //startDate = todaysDate + 5*Years;
65 endDate = todaysDate + 10*Years;
66 Schedule dates(todaysDate, endDate, Period(Semiannual),
67 calendar, Following, Following,
68 DateGeneration::Backward, false);
69 rateTimes = std::vector<Time>(dates.size()-1);
70 paymentTimes = std::vector<Time>(rateTimes.size()-1);
71 accruals = std::vector<Real>(rateTimes.size()-1);
72 dayCounter = SimpleDayCounter();
73 for (Size i=1; i<dates.size(); ++i)
74 rateTimes[i-1] = dayCounter.yearFraction(todaysDate, dates[i]);
75 std::copy(rateTimes.begin()+1, rateTimes.end(),
76 paymentTimes.begin());
77 for (Size i=1; i<rateTimes.size(); ++i)
78 accruals[i-1] = rateTimes[i] - rateTimes[i-1];
79
80 // Rates & displacement
81 todaysForwards = std::vector<Rate>(paymentTimes.size());
82 displacement = 0.0;
83 for (Size i=0; i<todaysForwards.size(); ++i)
84 todaysForwards[i] = 0.03 + 0.0010*i;
85
86 // Discounts
87 todaysDiscounts = std::vector<DiscountFactor>(rateTimes.size());
88 todaysDiscounts[0] = 0.95;
89 for (Size i=1; i<rateTimes.size(); ++i)
90 todaysDiscounts[i] = todaysDiscounts[i-1] /
91 (1.0+todaysForwards[i-1]*accruals[i-1]);
92
93 // Coterminal swap rates & annuities
94 Size N = todaysForwards.size();
95 todaysCoterminalSwapRates = std::vector<Rate>(N);
96 coterminalAnnuity = std::vector<Real>(N);
97 Real floatingLeg = 0.0;
98 for (Size i=1; i<=N; ++i) {
99 if (i==1) {
100 coterminalAnnuity[N-1] = accruals[N-1]*todaysDiscounts[N];
101 } else {
102 coterminalAnnuity[N-i] = coterminalAnnuity[N-i+1] +
103 accruals[N-i]*todaysDiscounts[N-i+1];
104 }
105 floatingLeg = todaysDiscounts[N-i]-todaysDiscounts[N];
106 todaysCoterminalSwapRates[N-i] =
107 floatingLeg/coterminalAnnuity[N-i];
108 }
109
110 std::vector<Time> evolutionTimes(rateTimes.size()-1);
111 std::copy(rateTimes.begin(), rateTimes.end()-1,
112 evolutionTimes.begin());
113 EvolutionDescription evolution(rateTimes,evolutionTimes);
114 evolution.rateTaus();
115 evolution.firstAliveRate();
116 }
117 };
118
119 }
120
121
testLMMCurveState()122 void CurveStatesTest::testLMMCurveState() {
123
124 BOOST_TEST_MESSAGE("Testing Libor-market-model curve state...");
125
126 using namespace curve_states_test;
127
128 CommonVars vars;
129 }
130
testCoterminalSwapCurveState()131 void CurveStatesTest::testCoterminalSwapCurveState() {
132
133 BOOST_TEST_MESSAGE("Testing coterminal-swap-market-model curve state...");
134
135 using namespace curve_states_test;
136
137 CommonVars vars;
138 }
139
140
testCMSwapCurveState()141 void CurveStatesTest::testCMSwapCurveState() {
142
143 BOOST_TEST_MESSAGE("Testing constant-maturity-swap-market-model curve state...");
144
145 using namespace curve_states_test;
146
147 CommonVars vars;
148
149 Size nbRates = vars.todaysForwards.size();
150 Size factors = nbRates;
151 Matrix pseudo(nbRates, factors, 0.1);
152 std::vector<Spread> displacements(nbRates, .0);
153 std::vector<Time> rateTimes(nbRates+1);
154 std::vector<Time> taus(nbRates, .5);
155 std::vector<Rate> forwards(nbRates, 0.0);
156
157 //std::cout << "rate value:"<< std::endl;
158
159 for (Size i = 0; i < forwards.size(); ++i)
160 forwards[i] = static_cast<Rate>(i)*.001+.04;
161
162 for (Size i = 0; i < rateTimes.size(); ++i)
163 rateTimes[i] = static_cast<Time>(i+1)*.5;
164
165 //BOOST_TEST_MESSAGE( << "Rates\nTime\tValue:"<< std::endl;)
166 //for (Size i = 0; i < rateTimes.size()-1; ++i){
167 // std::cout << rateTimes[i+1] << "\t"<<io::rate(forwards[i]) << std::endl;
168 //}
169
170 Size numeraire = nbRates;
171 Size alive = 0;
172
173 Size spanningFwds = 1;
174
175 CMSMMDriftCalculator cmsDriftcalculator(pseudo, displacements, taus,
176 numeraire, alive, spanningFwds);
177
178 CMSwapCurveState cmsCs(rateTimes, spanningFwds);
179 cmsCs.setOnCMSwapRates(forwards);
180 std::vector<Real> cmsDrifts(nbRates);
181 cmsDriftcalculator.compute(cmsCs,cmsDrifts);
182
183 LMMDriftCalculator lmmDriftcalculator(pseudo, displacements, taus,
184 numeraire, alive);
185 LMMCurveState lmmCs(rateTimes);
186 lmmCs.setOnForwardRates(forwards);
187 /*
188 std::vector<Real> lmmDrifts(nbRates);
189
190 std::cout << "drifts:"<< std::endl;
191 std::cout << "LMM\t\tCMS"<< std::endl;
192 for (Size i = 0; i<nbRates; ++i){
193 std::cout << lmmDrifts[i] << "\t\t"<< cmsDrifts[i] << std::endl;
194 }*/
195
196 // const std::vector<Rate>& dfs = cs.discountRatios();
197 //std::cout << "discounts ratios:"<< std::endl;
198 //std::cout << "LMM\tCMS"<< std::endl;
199 /*for (Size i = 0; i <nbRates; ++i){
200 std::cout << lmmCs.discountRatio(i, nbRates) << "\t"<< cmsCs.discountRatio(i, nbRates) << std::endl;
201 }*/
202 }
203
204 // --- Call the desired tests
suite()205 test_suite* CurveStatesTest::suite() {
206 test_suite* suite = BOOST_TEST_SUITE("Curve States tests");
207 //suite->add(QUANTLIB_TEST_CASE(&CurveStatesTest::testLMMCurveState));
208 //suite->add(QUANTLIB_TEST_CASE(&CurveStatesTest::testCoterminalSwapCurveState));
209 suite->add(QUANTLIB_TEST_CASE(&CurveStatesTest::testCMSwapCurveState));
210 return suite;
211 }
212