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

Reply via email to