148 lines
2.8 KiB
C++
148 lines
2.8 KiB
C++
#include <analytic/bond.hpp>
|
|
#include <analytic/rate.hpp>
|
|
#include <analytic/coupon.hpp>
|
|
#include <common/gdata.hpp>
|
|
#include <common/math.hpp>
|
|
#include <common/stdio.hpp>
|
|
|
|
Bond::Bond(void)
|
|
: Instrument(StraightBond), mPar(0.00), mYTM(0), mYield(0.00)
|
|
{
|
|
}
|
|
|
|
Bond::Bond(const Bond &bond)
|
|
{
|
|
*this=bond;
|
|
}
|
|
|
|
Bond::Bond(double par,const Coupon &coupon,int ytm,double price)
|
|
{
|
|
Instrument::price(price);
|
|
Instrument::coupon(coupon);
|
|
Instrument::type(StraightBond);
|
|
Bond::par(par);
|
|
Bond::ytm(ytm);
|
|
Bond::yield(0.00);
|
|
}
|
|
|
|
Bond::~Bond()
|
|
{
|
|
}
|
|
|
|
Bond &Bond::operator=(const Bond &bond)
|
|
{
|
|
par(bond.par());
|
|
ytm(bond.ytm());
|
|
price(bond.price());
|
|
coupon(bond.coupon());
|
|
yield(bond.yield());
|
|
type(StraightBond);
|
|
return *this;
|
|
}
|
|
|
|
BOOL Bond::operator==(const Bond &bond)const
|
|
{
|
|
return (par()==bond.par()&&
|
|
ytm()==bond.ytm()&&
|
|
price()==bond.price()&&
|
|
coupon()==bond.coupon()&&
|
|
yield()==bond.yield()&&
|
|
type()==bond.type());
|
|
}
|
|
|
|
double Bond::par(void)const
|
|
{
|
|
return mPar;
|
|
}
|
|
|
|
void Bond::par(double par)
|
|
{
|
|
mPar=par;
|
|
}
|
|
|
|
const Rate &Bond::yield(void)const
|
|
{
|
|
return mYield;
|
|
}
|
|
|
|
void Bond::yield(const Rate &yield)
|
|
{
|
|
mYield=yield;
|
|
}
|
|
|
|
int Bond::ytm(void)const
|
|
{
|
|
return mYTM;
|
|
}
|
|
|
|
void Bond::ytm(int ytm)
|
|
{
|
|
mYTM=ytm;
|
|
}
|
|
|
|
// virtuals
|
|
|
|
BOOL Bond::cashflows(GlobalData<double> &cashflows)
|
|
{
|
|
double semiAnnualPmt;
|
|
int periods;
|
|
Coupon coupon(coupon());
|
|
|
|
coupon.makeSemiAnnual();
|
|
periods=coupon.frequency()*ytm();
|
|
semiAnnualPmt=par()*coupon.decimalRate();
|
|
cashflows.size(periods);
|
|
for(int period=0;period<cashflows.size();period++)cashflows[period]=semiAnnualPmt;
|
|
cashflows[periods-1]=cashflows[periods-1]+par();
|
|
return TRUE;
|
|
}
|
|
|
|
double Bond::discount(Rate yield)
|
|
{
|
|
double semiAnnualPmt;
|
|
double bondPrice;
|
|
int periods;
|
|
Coupon coupon(coupon());
|
|
|
|
Bond::yield(yield);
|
|
yield.makeSemiAnnual();
|
|
coupon.makeSemiAnnual();
|
|
periods=yield.frequency()*ytm();
|
|
semiAnnualPmt=par()*coupon.decimalRate();
|
|
bondPrice=semiAnnualPmt*((1.00-(1.00/::pow(1.00+yield.decimalRate(),periods)))/yield.decimalRate());
|
|
bondPrice+=par()/::pow(1.00+yield.decimalRate(),periods);
|
|
price(bondPrice);
|
|
return price();
|
|
}
|
|
|
|
Rate Bond::discount(double market)
|
|
{
|
|
Rate guess(coupon());
|
|
Rate maxGuess;
|
|
Rate minGuess;
|
|
|
|
maxGuess=guess;
|
|
minGuess=guess;
|
|
maxGuess.rate(guess.rate()+12.00);
|
|
minGuess.rate(guess.rate()-12.00);
|
|
if(minGuess.rate()<0.00)minGuess.rate(1.00);
|
|
while(TRUE)
|
|
{
|
|
discount(guess);
|
|
if(price()==market||(price()-market<0.00?market-price():price()-market)<1.00)break;
|
|
if(market>price())
|
|
{
|
|
maxGuess=guess;
|
|
guess.rate((guess.rate()+minGuess.rate())/2.00);
|
|
}
|
|
else
|
|
{
|
|
minGuess=guess;
|
|
guess.rate((guess.rate()+maxGuess.rate())/2.00);
|
|
}
|
|
printf("calculated price:%lf market price:%lf\n",price(),market);
|
|
}
|
|
yield(guess);
|
|
return yield();
|
|
}
|