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: dev-unsubscr...@openoffice.apache.org For additional commands, e-mail: dev-h...@openoffice.apache.org