00001
00002
00003 #include <iostream>
00004 #include <fstream>
00005 #include <iomanip>
00006 #include <cmath>
00007
00008 using std::cout;
00009 using std::cerr;
00010 using std::endl;
00011 using std::setw;
00012
00013
00014 #include <ql/date.hpp>
00015 #include <ql/array.hpp>
00016 #include <ql/Math/matrix.hpp>
00017 #include <ql/errors.hpp>
00018
00019 #include <portability.h>
00020 #include <leastsquare.h>
00021 #include <timer.h>
00022
00023 using QuantLib::Date;
00024 using QuantLib::Array;
00025 using QuantLib::Math::Matrix;
00026 using QuantLib::Math::transpose;
00027 using QuantLib::Error;
00028
00029
00030
00031 inline
00032 std::ostream& operator<< (std::ostream& os, const QuantLib::Array& v)
00033 {
00034 size_t i, sz = v.size();
00035
00036 os << "[";
00037 for (i=0; i<sz-1; ++i)
00038 os << v[i] << " ";
00039 os << v[sz-1]
00040 << "]"
00041 << std::endl;
00042
00043 return os;
00044 }
00045
00052 class BraceVolatilityFunction {
00054 double a_, b_, c_, d_;
00055 public :
00057 inline BraceVolatilityFunction(double a, double b, double c, double d)
00058 : a_(a), b_(b), c_(c), d_(d) {}
00060 inline ~BraceVolatilityFunction() {}
00061
00063 inline double operator() (double t)
00064 { return (a_+b_*t)*exp(-c_*t) + d_; }
00065
00067 inline double da(double t)
00068 { return exp(-c_*t); }
00069
00071 inline double db(double t)
00072 { return t*exp(-c_*t); }
00073
00075 inline double dc(double t)
00076 { return -t*(a_+b_*t)*exp(-c_*t); }
00077
00079 inline double dd(double t)
00080 { return 1.; }
00081 };
00082
00083
00089 class CurveFittingProblem
00090 : public LeastSquareProblem<Array,Matrix > {
00091 const Array &ttm_;
00092 const Array &target_;
00093 public :
00098 CurveFittingProblem(const Array& ttm, const Array& target)
00099 : ttm_(ttm), target_(target) {}
00101 virtual ~CurveFittingProblem() {}
00102
00104 virtual int size() { return ttm_.size(); }
00105
00107 virtual void targetAndValue(const Array& abcd,
00108 Array& target,
00109 Array& fct2fit)
00110 {
00111 BraceVolatilityFunction bvf(abcd[0],abcd[1],abcd[2],abcd[3]);
00112 target = target_;
00113 for (int i=0; i<ttm_.size(); ++i)
00114 fct2fit[i] = bvf(ttm_[i]);
00115 }
00116
00118 virtual void targetValueAndfirstDerivative(const Array& abcd,
00119 Matrix& grad_fct2fit,
00120 Array& target,
00121 Array& fct2fit)
00122 {
00123 BraceVolatilityFunction bvf(abcd[0],abcd[1],abcd[2],abcd[3]);
00124 target = target_;
00125 for (int i=0; i<ttm_.size(); ++i) {
00126
00127 fct2fit[i] = bvf(ttm_[i]);
00128
00129
00130
00131
00132
00133 grad_fct2fit[i][0] = bvf.da(ttm_[i]);
00134 grad_fct2fit[i][1] = bvf.db(ttm_[i]);
00135 grad_fct2fit[i][2] = bvf.dc(ttm_[i]);
00136 grad_fct2fit[i][3] = bvf.dd(ttm_[i]);
00137 }
00138
00139 }
00140 };
00141
00142
00143
00144
00145
00146 int main()
00147 {
00148
00149
00150
00151
00152
00153 double abcd_[4] = {0.147014, 0.057302, 0.249964, 0.148556 };
00154 Array abcd(4);
00155 abcd[0] = abcd_[0];
00156 abcd[1] = abcd_[1];
00157 abcd[2] = abcd_[2];
00158 abcd[3] = abcd_[3];
00159
00160 cout << "Optimal values : " << abcd << endl;
00161
00162
00163 BraceVolatilityFunction bvf(abcd[0],abcd[1],abcd[2],abcd[3]);
00164
00165 Timer t;
00166 t.start();
00167 try {
00168
00169 double t,
00170 startDate = 0.0,
00171 endDate = 20.,
00172 period = 0.25;
00173
00174 int i, periodNumber = (int)(endDate / period);
00175
00176 Array targetValue(periodNumber), timeToMaturity(periodNumber);
00177
00178 for (i=0; i<periodNumber; ++i) {
00179 t = startDate + i*period;
00180 timeToMaturity[i] = t;
00181 targetValue[i] = bvf(t);
00182 }
00183
00184
00185 double accuracy = 1e-10;
00186
00187 int maxiter = 10000;
00188
00189 Array initialValue(4, 0.1);
00190
00191
00192 NonLinearLeastSquare<Array > lsqnonlin(accuracy,maxiter);
00193
00194
00195 CurveFittingProblem cfp(timeToMaturity, targetValue);
00196
00197
00198 lsqnonlin.setInitialValue(initialValue);
00199
00200 Array solution = lsqnonlin.Perform(cfp);
00201
00202 cout << endl
00203 << "Optimal values : " << abcd
00204 << "Solution values : " << solution
00205 << "Solution Error : " << (solution - abcd ) << endl;
00206
00207
00208 BraceVolatilityFunction bvf2(solution[0],solution[1],solution[2],solution[3]);
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 std::ofstream file("curve.csv");
00220 const char separator[] = ", ";
00221
00222 for (i=0; i<periodNumber; ++i) {
00223 t = startDate + i*period;
00224 file << t << separator << bvf(t) << separator << bvf2(t) << endl;
00225 }
00226 file.close();
00227
00228 }
00229 catch(Error & e)
00230 {
00231 cerr << e.what() << endl;;
00232 }
00233 t.stop();
00234
00235 cout << "Ellapsed time : " << (double) t << " seconds." << endl;
00236
00237
00238 return 1;
00239 }