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