Hi,
I am trying to correct a bug in the XIRR function (it is rather improve
than correct). The idea behind the correction is the following:
1- try to find a solution (XIRR) using the guess value given by the user
or using the default value
2-if the try with those values does not lead to a solution so begin to scan
for a guess value from -0.99 to +0.99 with 0.01 step until one get a Guess
Value which leads to Solution.
first to experiments I have written a code but It seems that I have a
problem with the outer while loop. Can someone give me a hint where is the
problem?
regards
Driss
#include <iostream>
#include <math.h>
//#include "FinFunc.h"
using namespace std;
double getXirr(double *aValues, double *aDates, double fRate);
/** Calculates the resulting amount for the passed interest rate and the given XIRR parameters. */
double lcl_sca_XirrResult( double *rValues, double *rDates, double fRate );
/** Calculates the first derivation of lcl_sca_XirrResult(). */
double lcl_sca_XirrResult_Deriv1( double *rValues, double *rDates, double fRate );
int arrSize = 13;
int main()
{
double xirr;
double Dates[13] = {39356, 39387, 39417, 39448, 39479, 39508,
39539, 39569, 39600, 39630, 39661, 39692, 39722};
double Values[13] = {100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100,
-1200};
// double Dates[5] = {39448,39508,39751,39859,39904};
// double Values[5] = {-10000, 2750, 4250, 3250,2750};
//double* ptrDates = Dates;
//double* ptrValues = Values;
xirr = getXirr(Values, Dates, 0);
cout <<"XIRR =" << xirr;
return 0;
}
// XIRR calculation
double getXirr(double *aValues, double *aDates, double fRate)
{
// maximum epsilon for end of iteration
static const double fMaxEps = 1e-10;
// maximum number of iterations
static const int nMaxIter = 50;
// Newton's method - try to find a fResultRate, so that lcl_sca_XirrResult() returns 0.
double fNewRate, fRateEps, fResultValue, fResultRate;
int nIter = 0;
bool bContLoop = false;
double fResultBuffer = 0.1;
double fResultRateInit;
bool IncrementDone = false;
bool DecrementDone = false;
fResultRate = fResultBuffer;
fResultRateInit = fResultBuffer;
do{
do
{
fResultValue = lcl_sca_XirrResult( aValues, aDates, fResultRate );
fNewRate = fResultRate - fResultValue / lcl_sca_XirrResult_Deriv1( aValues, aDates, fResultRate );
fRateEps = fabs(fNewRate - fResultRate );
fResultRate = fNewRate;
bContLoop = (fRateEps > fMaxEps)&& (fabs( fResultValue ) > fMaxEps);
}
while (bContLoop && (++nIter < nMaxIter));
IncrementDone = (fResultRate > 1);
DecrementDone = (fResultRate < -1);
if (!IncrementDone)
fResultRate = fResultRate + 0.01;
else
{
fResultRate = fResultRateInit;
}
if (IncrementDone && !DecrementDone)
fResultRate = fResultRate - 0.01;
}
while (bContLoop && !IncrementDone && !DecrementDone);
cout << "bCount = "<<bContLoop<<endl;
//if( bContLoop )
// cout<< "if condition";
return fResultRate;
}
/** Calculates the resulting amount for the passed interest rate and the given XIRR parameters. */
double lcl_sca_XirrResult( double *rValues, double *rDates, double fRate )
{
/* V_0 ... V_n = input values.
D_0 ... D_n = input dates.
R = input interest rate.
r := R+1
E_i := (D_i-D_0) / 365
n V_i n V_i
f(R) = SUM ------- = V_0 + SUM ------- .
i=0 r^E_i i=1 r^E_i
*/
double D_0 = *rDates;
double r = fRate + 1.0;
double fResult = *rValues;
for( int i = 1; i < arrSize; ++i )
fResult += rValues[i] / pow( r, (rDates[i] - D_0) / 365.0 );
return fResult;
}
/** Calculates the first derivation of lcl_sca_XirrResult(). */
double lcl_sca_XirrResult_Deriv1( double *rValues, double *rDates, double fRate )
{
/* V_0 ... V_n = input values.
D_0 ... D_n = input dates.
R = input interest rate.
r := R+1
E_i := (D_i-D_0) / 365
n V_i
f'(R) = [ V_0 + SUM ------- ]'
i=1 r^E_i
n V_i n E_i V_i
= 0 + SUM -E_i ----------- r' = - SUM ----------- .
i=1 r^(E_i+1) i=1 r^(E_i+1)
*/
double D_0 = rDates[0];
double r = fRate + 1.0;
double fResult = 0.0;
for( int i = 1; i < arrSize; ++i )
{
double E_i = (rDates[i] - D_0) / 365.0;
fResult -= E_i * rValues[i] / pow( r, E_i + 1.0 );
}
return fResult;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]