90 lines
1.6 KiB
C++
90 lines
1.6 KiB
C++
#include <cashflow/irr.hpp>
|
|
|
|
double IRR::IRR_ERROR=-1E30;
|
|
int IRR::IRR_MAX_ITERATIONS=50;
|
|
double IRR::IRR_ACCURACY=1.0E-5;
|
|
|
|
double IRR::irr(Array<double> &cashflows)
|
|
{
|
|
double x1=0.00;
|
|
double x2=.20;
|
|
double dx=0.00;
|
|
double f1;
|
|
double f2;
|
|
double f;
|
|
double rtb;
|
|
double xmid;
|
|
double fmid;
|
|
int index;
|
|
|
|
// create initial bracket with root somewhere between bot,top
|
|
f1=pv(cashflows,x1);
|
|
f2=pv(cashflows,x2);
|
|
for(index=0;index<IRR_MAX_ITERATIONS;index++)
|
|
{
|
|
if((f1*f2)<0.00)break;
|
|
if(fabs(f1)<fabs(f2))
|
|
{
|
|
f1=pv(cashflows,x1+=1.6*(x1-x2));
|
|
}
|
|
else
|
|
{
|
|
f2=pv(cashflows,x2+=1.6*(x2-x1));
|
|
}
|
|
}
|
|
if(f2*f1>0.00)return IRR_ERROR;
|
|
f=pv(cashflows,x1);
|
|
if(f<0.00)
|
|
{
|
|
rtb=x1;
|
|
dx=x2-x1;
|
|
}
|
|
else
|
|
{
|
|
rtb=x2;
|
|
dx=x1-x2;
|
|
}
|
|
for(index=0;index<IRR_MAX_ITERATIONS;index++)
|
|
{
|
|
dx*=.50;
|
|
xmid=rtb+dx;
|
|
fmid=pv(cashflows,xmid);
|
|
if(fmid<=0.00)rtb=xmid;
|
|
if((fabs(fmid)<IRR_ACCURACY)||(fabs(dx)<IRR_ACCURACY))
|
|
{
|
|
return xmid;
|
|
}
|
|
}
|
|
return IRR_ERROR;
|
|
}
|
|
|
|
double IRR::npv(Array<double> &cashflows,double rate)
|
|
{
|
|
double npv=0.00;
|
|
for(int index=0;index<cashflows.size();index++)
|
|
{
|
|
npv+=cashflows[index]*pow(1+rate,index); // exp(-rate*(index+1)));
|
|
}
|
|
return npv;
|
|
}
|
|
|
|
double IRR::pv(Array<double> &cashflows,double rate)
|
|
{
|
|
double pv=0.00;
|
|
for(int index=0;index<cashflows.size();index++)
|
|
{
|
|
pv+=(cashflows[index]*exp(-rate*(index+1)));
|
|
}
|
|
return pv;
|
|
}
|
|
|
|
double IRR::pvD(Array<double> &cashflows,double rate)
|
|
{
|
|
double pv=0.00;
|
|
for(int index=0;index<cashflows.size();index++)
|
|
{
|
|
pv+=cashflows[index]/pow(1+rate,index+1);
|
|
}
|
|
return pv;
|
|
}
|