Main Page | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members

yieldCurve.cpp

Go to the documentation of this file.
00001 #include ".\yieldCurve.h"
00002 
00003 /*------------------------------------------------------*/
00004 /*                 Yield Point Implementation           */
00005 /*------------------------------------------------------*/
00006 
00007 yieldPoint::yieldPoint(void) {
00008    _rate     = 0.0;
00009    _maturity = 0.0;
00010    _type     = Cash;
00011    _dayCount = ACT_360;
00012 }
00013 
00014 yieldPoint::yieldPoint(Real r,Real T,TypeOfRate type,DayCountConvention dayCount)
00015 {
00016    _rate     = r;
00017    _maturity = T;
00018    _type     = type;
00019    _dayCount = dayCount;                              
00020 }
00021 
00022 
00023 char *yieldPoint::TypeAsString(TypeOfRate t)
00024 {
00025         switch (t) {
00026                 case Cash:
00027                         return "Cash";
00028                 case Swap:
00029                         return "Swap";
00030                 default:
00031                         return "No rate type has been defined";
00032         }
00033 }
00034 
00035 yieldPoint::~yieldPoint(void)
00036 {
00037 };
00038 
00039 /*------------------------------------------------------*/
00040 /*                 Yield Curve Implementation           */
00041 /*------------------------------------------------------*/
00042 yieldCurve::yieldCurve(void)
00043 :_marketRates(YC_MAX_NUMBER_POINTS),
00044  _zcbRates(YC_MAX_NUMBER_POINTS)
00045 {
00046       sprintf(_name, "unamed");
00048       assignFlatRate();
00049       computeZCBRatesBootstrap();
00050 }
00051 
00052 
00053 void yieldCurve::assignFlatRate(Real r)
00054 {
00055      Natural size = _marketRates.size();
00056      for(Natural i=0;i<size;i++){
00057          _marketRates[i].setRate(r);       
00058                  _marketRates[i].setDayCount(ACT_360);   
00059                  _marketRates[i].setType(Cash);   
00060                  _marketRates[i].setMaturity(i);   
00061      }    
00062 }
00063 
00064 yieldCurve::yieldCurve(Real flatRate)
00065 :_marketRates(YC_MAX_NUMBER_POINTS),
00066  _zcbRates(YC_MAX_NUMBER_POINTS)
00067 {
00068       sprintf(_name, "unamed");
00070       assignFlatRate(flatRate);  
00071       computeZCBRatesBootstrap();                         
00072 }
00073 
00074 yieldCurve::yieldCurve(valarray<yieldPoint> yieldPoints,char *name)
00075 :_marketRates(yieldPoints),
00076  _zcbRates(yieldPoints) //default they are equal
00077 {
00078       strcpy(_name,name);
00079           sortMarketRatesByMaturity();
00080           sortCashSwap();
00082       computeZCBRatesBootstrap();
00083 }
00084 
00085 yieldCurve::~yieldCurve(void)
00086 {
00087 }
00088 
00089 yieldPoint yieldCurve::getPointAtMaturity(Real maturity)
00090 {
00091         Natural size =_marketRates.size(),i=0,indexFound=0;
00092         yieldPoint y;
00093         bool hasFound=false;
00094 
00095         while (i<size && !hasFound){
00096                 if(_marketRates[i].getMaturity()==maturity){
00097                         hasFound=true;
00098                         indexFound =i;
00099                 }
00100                 i++;
00101         }
00102         if(hasFound){
00103                 y=_marketRates[indexFound];
00104         }
00105         else{
00106                 y=yieldPoint();
00107         }
00108         return y;
00109 }
00110 
00111 
00112 void yieldCurve::sortMarketRatesByMaturity()
00113 {
00114         Natural size = _marketRates.size();
00115         valarray<yieldPoint> tempstorage(size);
00116         Real toSort[YC_MAX_NUMBER_POINTS];
00117         for (Natural i=0;i<size;i++) 
00118         {
00119                 toSort[i]=_marketRates[i].getMaturity();
00120         }
00121         sort(toSort,toSort+size);
00122         // toSort now is sorted by ascending maturity
00123         for (i=0;i<size;i++) 
00124         {
00125                 tempstorage[i]=getPointAtMaturity(toSort[i]);
00126                 // we just have to assign the yieldPoints corresponding to the maturity sorted
00127                 // no need to handle not found maturities here as we know that the maturities in toSort
00128                 // are bijectively taken from _marketRates
00129         }
00130         _marketRates = tempstorage;
00131 }
00132 
00133 
00134 void yieldCurve::sortCashSwap()
00135 {
00136         valarray<yieldPoint> tempstorage(_marketRates.size());
00137         Natural count=0;
00138         for (Natural i=0;i<_marketRates.size();i++)
00139         {
00140                 if(_marketRates[i].getType()==Cash){
00141                         tempstorage[count]=_marketRates[i];
00142                         count++;
00143                 }
00144         }
00145         for (Natural i=0;i<_marketRates.size();i++)
00146         {
00147                 if(_marketRates[i].getType()==Swap){
00148                         tempstorage[count]=_marketRates[i];
00149                         count++;
00150                 }
00151         }
00152         _marketRates=tempstorage;
00153 }
00154 
00155 valarray<yieldPoint> yieldCurve::getSwapRates()
00156 {
00157         valarray<yieldPoint> tempstorage(YC_MAX_NUMBER_POINTS);
00158         tempstorage[0]=yieldPoint(spotRate(1),1,Swap); //1Y swap rate = 1y cash rate as (1+s1Y)*DF1=1
00159         Natural i=0,count=1;
00160         while(i<_marketRates.size() && _marketRates[i].getType()==Cash) {i++;} //get to the first swap rate of the array
00161         while(i<_marketRates.size())
00162         {
00163                 tempstorage[count]=_marketRates[i];
00164                 count++;
00165                 i++;
00166         }
00167 
00168         tempstorage.resize(count);
00169         return tempstorage;
00170 }
00171 
00172 valarray<yieldPoint> yieldCurve::getSequentSwapRates()
00173 {
00175         valarray<yieldPoint> tempstorage(getSwapRates());
00176         Natural size=tempstorage.size();
00177         valarray<yieldPoint> res((Natural)tempstorage[size-1].getMaturity());
00178         Natural i=1,diff=0,j=0,nextMat=0,prevMat=0,start=0;
00181         while(i<size && tempstorage[i-1].getMaturity()==(tempstorage[i].getMaturity()-1)) {
00182                 res[j]=tempstorage[i-1];
00183                 i++;
00184                 j++;
00185         }
00186         start=j;
00187         // set natural year maturities from 1 up to the last swap maturity 
00188 //and tests if maturities are sequent or not
00189         while (j<res.size() && i<size){ 
00190                 if(tempstorage[i].getMaturity()==(Real)(j+1)){
00191                         res[j]=tempstorage[i];
00192                         i++;
00193                 }
00194                 else{
00195                         res[j].setMaturity((Real)(j+1)); 
00196                         res[j].setType(Swap);
00197                         nextMat=(Natural)tempstorage[i].getMaturity();
00198                         prevMat=(Natural)tempstorage[i-1].getMaturity();
00199                         diff= nextMat-prevMat;
00200                         res[j].setRate( (tempstorage[i-1].getRate()*(nextMat-j-1)+  tempstorage[i].getRate()*(j+1-prevMat )) /diff);
00201                 }       
00202                 j++;
00203         }
00204         return res;     
00205 }
00206 
00207 Real yieldCurve::spotRate(Real maturity) const
00208 {
00209       Natural i =0;
00210       while(i<_zcbRates.size() &&  _zcbRates[i].getMaturity()<maturity ) {i++;}
00211       if (i==_zcbRates.size())
00212                         //longer term than we know : best approximation is the last Point
00213             return _zcbRates[i-1].getRate(); 
00214       else if(i==0)
00215                         // we are looking for a rate of a shorter term : best approximation is the 1st rate on the curve
00216             return _zcbRates[i].getRate();
00217       else{
00218                         // linear Naturalepolation
00219             Real rmin=_zcbRates[i-1].getRate();
00220             Real rmax=_zcbRates[i].getRate();
00221             Real tmin=_zcbRates[i-1].getMaturity();
00222             Real tmax=_zcbRates[i].getMaturity();
00223             
00224             //in the zcb calculation we get sure that there is no redundant rate
00225             return ( (tmax-maturity)*rmin + (maturity-tmin)*rmax )/(tmax-tmin);
00226       }
00227 }
00228 
00229 Real yieldCurve::spotRate(Date maturityDate) const {
00230         Date today=Date();
00231         today.setDateToToday();
00232         return  spotRate(today.dayCount(maturityDate,Day30_360));
00233 }
00234 
00235 Real yieldCurve::discountFactor(Real maturity,interestComposition composition) // continuously compound for now - see dayCOunt later
00236 {
00237         switch (composition) {
00238                   case Discrete:
00239                           return (Real)pow(1/(1+spotRate(maturity)),maturity);
00240                   case Continuous:
00241                           return (Real)exp(-maturity*spotRate(maturity));
00242                   default:
00243                           return (Real)exp(-maturity*spotRate(maturity));
00244         }
00245 }
00246 
00247 Real yieldCurve::discountFactor(Date maturityDate,interestComposition composition){
00248         Date today=Date();
00249         today.setDateToToday();
00250         return discountFactor(today.dayCount(maturityDate,Day30_360),composition);
00251 }
00252 
00253 Real yieldCurve::forwardDiscountFactor(Real forwardstart,Real lengthofcontractafterstart,interestComposition composition){
00254         switch (composition) {
00255                   case Discrete:
00256                           return (Real)pow(1/(1+forwardRate(forwardstart,lengthofcontractafterstart,composition)),lengthofcontractafterstart);
00257                   case Continuous:
00258                           return (Real)exp(-lengthofcontractafterstart*forwardRate(forwardstart,lengthofcontractafterstart,composition));
00259                   default:
00260                           return (Real)exp(-lengthofcontractafterstart*forwardRate(forwardstart,lengthofcontractafterstart,composition));
00261         }       
00262 }
00263 
00264 Real yieldCurve::forwardRate(Real forwardStart,Real effectiveLengthOfTheContractAfterStart,interestComposition composition)
00265 {
00266         switch (composition) {
00267         case Discrete:
00268                 return (Real)(pow(discountFactor(forwardStart,composition)/discountFactor(forwardStart+effectiveLengthOfTheContractAfterStart,composition),1/effectiveLengthOfTheContractAfterStart)-1) ;
00269         case Continuous:
00270                 return (Real) (spotRate(forwardStart+effectiveLengthOfTheContractAfterStart)*(forwardStart+effectiveLengthOfTheContractAfterStart)
00271                         -spotRate(forwardStart)*forwardStart)/effectiveLengthOfTheContractAfterStart;
00272         default:
00273                 return (Real) (spotRate(forwardStart+effectiveLengthOfTheContractAfterStart)*(forwardStart+effectiveLengthOfTheContractAfterStart)
00274                         -spotRate(forwardStart)*forwardStart)/effectiveLengthOfTheContractAfterStart;
00275         }
00276 
00277 }
00278 
00279 yieldCurve yieldCurve::forwardZCBCurve(Real forwardStart){
00280         valarray<yieldPoint> fwdPts(_zcbRates);
00281         Natural i=0,size=fwdPts.size(),start;
00282         while(i<size && forwardStart>=_zcbRates[i].getRate())
00283                 i++;
00284         if(i==size) //fwd term too high
00285                 return yieldCurve();
00286         else{
00287                 start=i;
00288                 fwdPts.resize(size-start);
00289                 for (Natural i=start;i<fwdPts.size();i++){
00290                         fwdPts[i-start].setRate(forwardRate(forwardStart,_zcbRates[i].getMaturity()-forwardStart));
00291                         fwdPts[i-start].setMaturity(_zcbRates[i].getMaturity()-forwardStart);
00292                 }
00293                 return yieldCurve(fwdPts,"forwardCurve");
00294         }
00295 
00296 }
00297 
00298 Real yieldCurve::forwardRate(Date forwardStart,Date forwardEnd,interestComposition composition){
00299         Date today=Date();
00300         today.setDateToToday(); 
00301         return forwardRate(today.dayCount(forwardStart,Day30_360),forwardStart.dayCount(forwardEnd,Day30_360),composition);
00302 }
00303 
00304 
00305 valarray<Real> yieldCurve::SequentDiscountFactorsByInvertSwapMatrix()
00306 {
00307         valarray<yieldPoint> tempstorage(getSequentSwapRates());
00308 
00309         Natural size = tempstorage.size();
00310         Matrix *M= new Matrix (0.0,size,size);
00311         for (Natural i=0; i < size; i++)  
00312         {
00313                 for (Natural j=0; j<size; j++)
00314                 {
00315                         if(i==j) 
00316                                 M->SetValue(i,j,1+tempstorage[i].getRate()); // diagonals are 1 + s(i)
00317                         else if (i>j)
00318                                 M->SetValue(i,j,tempstorage[i].getRate()); // inferior triangle are s(i)
00319                         else
00320                                 M->SetValue(i,j,0); // superior triangle are 0
00321                 }
00322         }
00323         M->Invert();//M now contains the invert of the swap formatted matrix
00324         valarray<Real> res(size);
00325         for(i=0;i<size;i++){
00326                 res[i]=M->SumRow (i);
00327         }
00328         delete M;
00329 
00330         return res;
00331 }
00332 
00333 valarray<Real> yieldCurve::getMaturitiesInTheMarketCurve() const
00334 {
00335         Natural size=_marketRates.size();
00336         valarray<Real> maturities(size);
00337         for (Natural i=0;i<size;i++){
00338                 maturities[i]=_marketRates[i].getMaturity();
00339         }
00340         return maturities;
00341 }
00342 
00343 valarray<Real> yieldCurve::getMaturitiesInTheZCBCurve() const
00344 {
00345         Natural size= _zcbRates.size();
00346         valarray<Real> maturities(size);
00347         for (Natural i=0;i<size;i++){
00348                 maturities[i]=_zcbRates[i].getMaturity();
00349         }
00350         return maturities;
00351 }
00352 
00353 
00354 void yieldCurve::computeZCBRatesBootstrap()
00355 {
00356     _zcbRates=_marketRates;
00357         
00358         if(_marketRates[_marketRates.size()-1].getType()!=Cash){
00359                 // if the last rate (as it is sorted) of the mkt is a cash rate, then it means that all the curve is already ZCB'd
00360                 valarray<Real> DFs(SequentDiscountFactorsByInvertSwapMatrix());
00361                 Natural start=0,size = DFs.size();
00362 
00363                 while (_zcbRates[start].getType()==Cash) {start ++;}
00364                 start --; // as 1Y ZC = 1 Y swap
00365                 _zcbRates.resize(size+start);
00366                 for (Natural i=0;i<size;i++){
00367                         
00368                 
00369                         //they are 1Y sequent swap rates
00370                         _zcbRates[start+i].setRate((Real)pow(1/DFs[i],1/((Real)(i+1)))-1);// Rm = (1/DFm)^(1/m)
00371                         _zcbRates[start+i].setMaturity((Real)i+1);
00372                         _zcbRates[start+i].setType(Cash);
00373                 }
00374         }
00375 }
00376 
00377 void yieldCurve::assignZCBrateAtIndex(Real rate,Natural i){
00378         if (i<_zcbRates.size())
00379                 _zcbRates[i].setRate(rate); //else do nothing
00380 }
00381 
00382 yieldCurve yieldCurve::shiftZCBRateCurve(Real shift)
00383 {
00384         char * name=new char[50];
00385         sprintf (name,"%f",shift);
00386         strcat (name," shift on the current ZCB curve");
00387         
00388         yieldCurve resultShifted=yieldCurve(_zcbRates,name);//new yc to output, already ZCB is good
00389         for (Natural i=0;i<_zcbRates.size();i++)
00390                 resultShifted.assignZCBrateAtIndex(_zcbRates[i].getRate()+shift,i);
00391         return resultShifted;
00392 }
00393 
00399 yieldCurve yieldCurve::rotateZCBRateCurve(Real moveInShortestRate,Real maturityOfRotation){
00400         char * name=new char[64];
00401         sprintf (name,"%f",moveInShortestRate);
00402         strcat (name," move on short rate and rotation around 7Y");
00403         
00404         yieldCurve resultRotated=yieldCurve(_zcbRates,name);//new yc to output, already ZCB is good
00405         Real move=0.;
00406         Real difmat=_zcbRates[0].getMaturity()-min(2*maturityOfRotation,_zcbRates[_zcbRates.size()-1].getMaturity()); // <0
00407         Real summat=_zcbRates[0].getMaturity()+min(2*maturityOfRotation,_zcbRates[_zcbRates.size()-1].getMaturity());
00408         for (Natural i=0;i<_zcbRates.size();i++){
00409                 move= (moveInShortestRate/difmat)*(2*_zcbRates[i].getMaturity()-summat);
00410                 resultRotated.assignZCBrateAtIndex(_zcbRates[i].getRate()+move,i);
00411         }
00412         return resultRotated;   
00413 }
00414 
00422 bool
00423 yieldCurve::operator==(const yieldCurve& yours) {
00424         bool result = true;
00425 
00426         valarray<Real> myMaturities =
00427                 getMaturitiesInTheZCBCurve();
00428         valarray<Real> yourMaturities =
00429                 yours.getMaturitiesInTheZCBCurve();
00430         valarray<Real> termValues = 
00431                 mergeunique(myMaturities, yourMaturities);
00432         Natural numTermValues = termValues.size();
00433 
00434         Real m = 0;
00435         Real y = 0;
00436         for (Natural i = 0; (i < numTermValues) && result; i++) {
00437                 m = spotRate(termValues[i]);
00438                 y = yours.spotRate(termValues[i]);
00439 
00440                 // if difference is > .1 basis Points we say they are not equal
00441                 // (a function of precision in the input file)
00442                 if (fabs(m - y) > 0.00001) {
00443                         cout << "mismatch m: " << m << " y: " << y << endl;
00444                         result &= false;
00445                 }
00446         }
00447 
00448         return result;
00449 }
00450 
00451 bool
00452 yieldCurve::operator!=(const yieldCurve& yours) {
00453         return !operator==(yours);
00454 }
00455 
00456 ostream& 
00457 operator << (ostream &os, const yieldCurve &c) {
00458         valarray<Real> myMaturities = 
00459                 c.getMaturitiesInTheZCBCurve();
00460         Natural numTermValues = myMaturities.size();
00461 
00462         for (Natural i = 0; i < numTermValues; i++) {
00463                 os << myMaturities[i] << "," << c.spotRate(myMaturities[i]) << endl;
00464         }
00465 
00466         return os;
00467 }
00468   
00469 

Note: Generated nightly - reload for latest version
Generated on Thu Dec 22 23:12:37 2005 for terreneuve by doxygen 1.3.6