00001 #include ".\bond.h"
00002
00003 cashflow::cashflow(valarray<Date> dates, valarray<Real> cashflows)
00004 : _dates(dates),
00005 _cashflows(cashflows)
00006 {
00007 }
00008
00009 valarray<Date> cashflow::getDates(){
00010 return _dates;
00011 }
00012
00013 valarray<Real> cashflow::getCashflows(){
00014 return _cashflows;
00015 }
00016
00017
00018 bond::bond(Date issue, Date maturity, Date firstcoupondate, Real coupon, Frequency freq, Real faceamount,DayCountConvention daycount, yieldCurve yc)
00019 : _issue(issue),
00020 _maturity(maturity),
00021 _firstcoupondate(firstcoupondate),
00022 _coupon(coupon),
00023 _freq(freq),
00024 _faceamount(faceamount),
00025 _daycount(daycount),
00026 _yc(yc)
00027 {
00028 }
00029
00030
00031 cashflow bond::getCashflow(){
00032 Real timetomaturity = _firstcoupondate.dayCount(_maturity, _daycount);
00033 Real numberofcashflow;
00034 Real coupon;
00035
00036 Integer nbofmonth;
00037
00038 switch (_freq) {
00039 case NoFrequency:
00040 numberofcashflow = 1.0;
00041 coupon = 0;
00042 nbofmonth = 0;
00043 break;
00044 case Once:
00045 numberofcashflow = 1.0;
00046 coupon = 0;
00047 nbofmonth = 0;
00048 break;
00049 case Annual:
00050 numberofcashflow = timetomaturity + 1;
00051 coupon = _coupon;
00052 nbofmonth = 12;
00053 break;
00054 case Semiannual:
00055 numberofcashflow = 2.0*timetomaturity + 1;
00056 coupon = _coupon/2.0;
00057 nbofmonth = 6;
00058 break;
00059 case EveryFourthMonth:
00060 numberofcashflow = 3.0*timetomaturity + 1;
00061 coupon = _coupon/3.0;
00062 nbofmonth = 4;
00063 break;
00064 case Quarterly:
00065 numberofcashflow = 4.0*timetomaturity + 1;
00066 coupon = _coupon/4.0;
00067 nbofmonth = 3;
00068 break;
00069 case Bimonthly:
00070 numberofcashflow = 6.0*timetomaturity + 1;
00071 coupon = _coupon/6.0;
00072 nbofmonth = 2;
00073 break;
00074 case Monthly:
00075 numberofcashflow = 12.0*timetomaturity + 1;
00076 coupon = _coupon/12.0;
00077 nbofmonth = 1;
00078 break;
00079 default:
00080 numberofcashflow = 1.0;
00081 coupon = _coupon;
00082 nbofmonth = 0;
00083 break;
00084 }
00085
00086
00087
00088
00089 Date d(_firstcoupondate);
00090 Natural numberofCF = (int) (numberofcashflow + 0.1);
00091
00092 valarray<Date> dates(numberofCF);
00093 valarray<Real> cashflows(numberofCF);
00094
00095 dates[0]=d;
00096 Date dTest;
00097 cashflows[0] = _faceamount*coupon;
00098 Natural i;
00099 for(i=1;i<numberofCF;i++)
00100 {
00101 dTest=d.plusMonths(i*nbofmonth);
00102 dTest.applyConvention(Following);
00103 dates[i]=dTest;
00104 cashflows[i] = _faceamount*coupon;
00105 }
00106
00107 if (_freq==Once)
00108 cashflows[0] = _faceamount;
00109 else
00110 cashflows[numberofCF-1] += _faceamount;
00111
00112 cashflow CF(dates, cashflows);
00113 return CF;
00114 }
00115
00116 Real bond::fairvalue(Date today){
00117
00118 Real PV = quotedPrice(today);
00119 Real accruedinterest;
00120
00121 if(today<=_issue ||today>=_maturity)
00122 accruedinterest = 0;
00123 else
00124 {
00125 cashflow CF = getCashflow();
00126 valarray<Date> dates = CF.getDates();
00127 valarray<Real> cashflows = CF.getCashflows();
00128
00129 Natural i=0;
00130 while((dates[i]<today) && (i<dates.size()))
00131 i++;
00132
00133 Date interestaccrualdate;
00134 if (today<_firstcoupondate)
00135 interestaccrualdate = _issue;
00136 else
00137 interestaccrualdate = dates[i-1];
00138
00139 Real numberofdays, numberofdays2, numberofcoupon;
00140
00141
00142 switch(_freq){
00143 case NoFrequency:
00144 numberofcoupon = 1.0;
00145 break;
00146 case Once:
00147 numberofcoupon = 1.0;
00148 break;
00149 case Annual:
00150 numberofcoupon = 1.0;
00151 break;
00152 case Semiannual:
00153 numberofcoupon = 2.0;
00154 break;
00155 case EveryFourthMonth:
00156 numberofcoupon = 3.0;
00157 break;
00158 case Quarterly:
00159 numberofcoupon = 4.0;
00160 break;
00161 case Bimonthly:
00162 numberofcoupon = 6.0;
00163 break;
00164 case Monthly:
00165 numberofcoupon = 12.0;
00166 break;
00167 default:
00168 numberofcoupon = 1.0;
00169 break;
00170 }
00171
00172
00173 switch (_daycount) {
00174 case ACT_365:
00175 numberofdays = TN_REAL(today.serialNumber()-interestaccrualdate.serialNumber());
00176 numberofdays2 = 365.0/numberofcoupon;
00177 break;
00178 case ACT_360:
00179 numberofdays = TN_REAL(today.serialNumber()-interestaccrualdate.serialNumber());
00180 numberofdays2 = 360.0/numberofcoupon;
00181 break;
00182 case Day30_365:
00183 numberofdays = TN_REAL(today.dayOfMonth()+30-interestaccrualdate.dayOfMonth()+30*(12*(today.year()-interestaccrualdate.year())+today.month()-interestaccrualdate.month()));
00184 numberofdays2 = 365.0/numberofcoupon;
00185 break;
00186 case Day30_360:
00187 numberofdays = TN_REAL(today.dayOfMonth()+30-interestaccrualdate.dayOfMonth()+30*(12*(today.year()-interestaccrualdate.year())+today.month()-interestaccrualdate.month()));
00188 numberofdays2 = 360.0/numberofcoupon;
00189 break;
00190 default:
00191 numberofdays = TN_REAL(today.serialNumber()-dates[i].serialNumber());
00192 numberofdays2 = 365.0/numberofcoupon;
00193 }
00194 accruedinterest = numberofdays/numberofdays2*_coupon/numberofcoupon*_faceamount;
00195 }
00196
00197 return PV + accruedinterest;
00198 }
00199
00200 Real bond::quotedPrice(Date today){
00201
00202 cashflow CF = getCashflow();
00203 valarray<Date> dates = CF.getDates();
00204 valarray<Real> cashflows = CF.getCashflows();
00205
00206 Natural i=0;
00207 while((dates[i]<today) && (i<dates.size()))
00208 i++;
00209
00210 Real PV = 0;
00211 if (i==dates.size()) return 0;
00212 else if (i!=dates.size()-1){
00213 Natural j;
00214 Real timetonextCF;
00215 for(j=i;j<dates.size();j++){
00216 timetonextCF = today.dayCount(dates[j], _daycount);
00217 PV += cashflows[j]*_yc.discountFactor(timetonextCF);
00218 }
00219 }
00220
00221
00222 return PV;
00223
00224 }
00225
00226 Real bond::duration(Date today){
00227 Real yield = yieldToMaturity(today);
00228 cashflow CF = getCashflow();
00229 valarray<Date> dates = CF.getDates();
00230 valarray<Real> cashflows = CF.getCashflows();
00231
00232 Natural i=0;
00233 while((dates[i]<today) && (i<dates.size()))
00234 i++;
00235 if (i==dates.size()) return 0;
00236 Real result = 0;
00237 Real PV = 0;
00238 Real timetonextCF;
00239 Natural j;
00240 for(j=i;j<dates.size();j++){
00241 timetonextCF = today.dayCount(dates[j], _daycount);
00242 result += cashflows[j]*exp(-yield*timetonextCF)*timetonextCF;
00243 PV += cashflows[j]*exp(-yield*timetonextCF);
00244 }
00245
00246 result /= PV;
00247 return result;
00248
00249 }
00250
00251 Real bond::convexity(Date today){
00252 Real yield = yieldToMaturity(today);
00253 cashflow CF = getCashflow();
00254 valarray<Date> dates = CF.getDates();
00255 valarray<Real> cashflows = CF.getCashflows();
00256
00257 Natural i=0;
00258 while((dates[i]<today) && (i<dates.size()))
00259 i++;
00260 if (i==dates.size()) return 0;
00261 Real result = 0;
00262 Real PV = 0;
00263 Real timetonextCF;
00264 Natural j;
00265 for(j=i;j<dates.size();j++){
00266 timetonextCF = today.dayCount(dates[j], _daycount);
00267 result += cashflows[j]*exp(-yield*timetonextCF)*timetonextCF*timetonextCF;
00268 PV += cashflows[j]*exp(-yield*timetonextCF);
00269 }
00270
00271 result /= PV;
00272 return result;
00273
00274 }
00275
00276 Real bond::yieldToMaturity(Date today){
00277 Real price = fairvalue(today);
00278 Real yield = 0.05;
00279 Real deriv_price, yield_price;
00280
00281
00282 cashflow CF = getCashflow();
00283 valarray<Date> dates = CF.getDates();
00284 valarray<Real> cashflows = CF.getCashflows();
00285
00286 Natural i=0;
00287 while((dates[i]<today) && (i<dates.size()))
00288 i++;
00289 if (i==dates.size()) return 0;
00290
00291 Real timetonextCF;
00292 Natural k,j;
00293 for(k=0;k<100;k++){
00294 deriv_price = 0;
00295 yield_price = 0;
00296 for(j=i;j<dates.size();j++){
00297 timetonextCF = today.dayCount(dates[j], _daycount);
00298 yield_price += cashflows[j]*exp(-yield*timetonextCF);
00299 deriv_price += -timetonextCF*cashflows[j]*exp(-yield*timetonextCF);
00300 }
00301 yield += (price - yield_price)/deriv_price;
00302 }
00303 return yield;
00304
00305 }
00306
00307 treasurybond::treasurybond(Date issue, Date maturity, Date firstcoupondate, Real coupon, Frequency freq, Real faceamount, DayCountConvention daycount, yieldCurve yc)
00308 : bond(issue, maturity, firstcoupondate, coupon, freq, faceamount, daycount, yc)
00309 {
00310 }
00311
00312 treasurybond::treasurybond(Date issue, Date maturity, Date firstcoupondate, Real coupon, yieldCurve yc)
00313 : bond(issue, maturity, firstcoupondate, coupon, Semiannual, 100.0, ACT_360, yc)
00314 {
00315 }
00316
00317 treasurybond::treasurybond(Date issue, Date maturity, Real faceamount, DayCountConvention daycount, yieldCurve yc)
00318 : bond(issue, maturity, maturity, 0.0, Once, faceamount, daycount, yc)
00319 {
00320 }
00321
00322 treasurybond treasurybond::shiftedbond(Real shift){
00323 yieldCurve shiftedyc(_yc.shiftZCBRateCurve(shift));
00324 treasurybond shiftedtbond(_issue, _maturity, _firstcoupondate, _coupon, _freq, _faceamount, _daycount, shiftedyc);
00325 return shiftedtbond;
00326 }
00327
00328 Real treasurybond::rho(Date today){
00329 treasurybond tb = shiftedbond(0.001);
00330 Real Rho = (tb.fairvalue(today) - fairvalue(today))/0.001;
00331
00332 return Rho;
00333 }
00334
00335
00336 riskybond::riskybond(Date issue, Date maturity, Date firstcoupondate, Real coupon, Frequency freq, Real faceamount,DayCountConvention daycount, yieldCurve yc, creditCurve cc)
00337 : bond(issue, maturity, firstcoupondate, coupon, freq, faceamount, daycount, yc),
00338 _cc(cc)
00339 {
00340 }
00341
00342 riskybond::riskybond(Date issue, Date maturity, Real faceamount, DayCountConvention daycount, yieldCurve yc, creditCurve cc)
00343 : bond(issue, maturity, maturity, 0.0, Once, faceamount, daycount, yc),
00344 _cc(cc)
00345 {
00346 }
00347
00348 Real riskybond::quotedPrice(Date today){
00349
00350 cashflow CF = getCashflow();
00351 valarray<Date> dates = CF.getDates();
00352 valarray<Real> cashflows = CF.getCashflows();
00353
00354 Natural i=0;
00355 while((dates[i]<today) && (i<dates.size()))
00356 i++;
00357
00358 Real PV = 0;
00359 if (i==dates.size()) return 0;
00360 else if (i!=dates.size()-1){
00361 Natural j;
00362 Real timetonextCF;
00363 for(j=i+1;j<dates.size();j++){
00364 timetonextCF = today.dayCount(dates[j], _daycount);
00365 PV += cashflows[j]*_cc.riskyDiscountFactor(timetonextCF);
00366 }
00367 }
00368
00369
00370 return PV;
00371
00372 }
00373
00374 riskybond riskybond::shiftedbond(Real shift){
00375 yieldCurve shiftedyc(_yc.shiftZCBRateCurve(shift));
00376 riskybond shiftedtbond(_issue, _maturity, _firstcoupondate, _coupon, _freq, _faceamount, _daycount, shiftedyc, _cc);
00377 return shiftedtbond;
00378 }
00379
00380 Real riskybond::rho(Date today){
00381 riskybond tb = shiftedbond(0.001);
00382 Real Rho = (tb.fairvalue(today) - fairvalue(today))/0.001;
00383
00384 return Rho;
00385 }