Javascript IRR (Internal rate of return) Formula Accuracy

后端 未结 7 1590
名媛妹妹
名媛妹妹 2021-02-04 20:00

I\'m using a IRR function in javascript to create calculation a that is done in excel using its own IRR function. The problem is mine is little off and I have no idea why. Here\

相关标签:
7条回答
  • 2021-02-04 20:35

    Don't set your min IRR to 0. That is what bounds your answer. Try allowing it to go negative. Also don't try to calc an IRR on one number.

    0 讨论(0)
  • 2021-02-04 20:40

    Try this.

    function NPV(discountRate, cashFlow){
        var npv = 0;
        for(var t = 0; t < cashFlow.length; t++) {
            npv += cashFlow[t] / Math.pow((1+ discountRate),t);
        }
        return npv;
    }
    
    
    function IRR(cashFlow,guess){
        guess = guess ? guess : 0.1;
        var npv;
        var cnt = 0;
        do
        {
            npv = NPV(guess,cashFlow);
            guess+= 0.001;
    
            cnt++;
        }
        while(npv > 0)
    
        return guess;
    }
    
    0 讨论(0)
  • 2021-02-04 20:47

    It's a floating point issue to be sure. You're going to want to use a library like BigDecimal.js to handle your values. It's really the only way to avoid this issue.

    0 讨论(0)
  • 2021-02-04 20:48

    I would like to build on from @Zohaib Answer, but what I would like to do is show undefined where appropriate. The best I can do is get it to equal to zero. I am using this simple dataset irr_arr=[-100, 100, 100, 100, 100,100]. I would appreciate some advice.

    //IRRCALC funtion that handles irr going to infinity 
    
    function IRRCalc_test(CArray) {
    
      min = 0.0;
      max = 1.0;
      c=0;
      do {
        guest = (min + max) / 2;
        NPV = 0;
        for (var j=0; j<CArray.length; j++) {
              NPV += CArray[j]/Math.pow((1+guest),j);
        }
        if (NPV > 0) {
          min = guest;
          c++; 
        }
        else {
          max = guest;
          c++;
        }
    
        if(c>=15){ return guest*100; }
      } while(Math.abs(NPV) > 0.000001);
      return guest*100;
    }
    
    
    // some testing 
    
    irr_arr=[-100, 100, 100, 100, 100,100]
    irr_res_arr_expected=[0,0,61.8,83.93,92.76,96.6]
    for(i=1;i<=irr_arr.length;i++){
    console.log("irr_arr - ",irr_arr.slice(0,i));
    console.log("IRRCalc - ",IRRCalc(irr_arr.slice(0,i)))
    //console.log("irr_expected - ", irr_res_arr_expected[i-1])
    //if(IRRCalc(irr_arr.slice(0,i))===parseFloat(irr_res_arr_expected[i-1]).toFixed(2)){console.log(i,"- TRUE")} else {console.log(i,"- FALSE")}
    }
    

    this is the output

    irr_arr -  [-100]
    IRRCalc -  0.00      <<<<<<<<<<<<<<<<<<<------- this should be 'undefined' and not 'zero'
    irr_arr -  [-100, 100]
    IRRCalc -  0.00
    irr_arr -  [-100, 100, 100]
    IRRCalc -  61.80
    irr_arr -  [-100, 100, 100, 100]
    IRRCalc -  83.93
    irr_arr -  [-100, 100, 100, 100, 100]
    IRRCalc -  92.76
    irr_arr -  [-100, 100, 100, 100, 100, 100]
    IRRCalc -  96.60
    

    here is the excel of what I am trying to produce

    0 讨论(0)
  • 2021-02-04 20:50

    We modified the code to achieve performance and accuracy. Try this:

    function IRRCalc(CArray) {
    
      min = 0.0;
      max = 1.0;
      do {
        guest = (min + max) / 2;
        NPV = 0;
        for (var j=0; j<CArray.length; j++) {
              NPV += CArray[j]/Math.pow((1+guest),j);
        }
        if (NPV > 0) {
          min = guest;
        }
        else {
          max = guest;
        }
      } while(Math.abs(NPV) > 0.000001);
      return guest * 100;
    }
    
    0 讨论(0)
  • 2021-02-04 20:55

    After a quick skim read through your code, the error seems to be related to floating point precision error. More information can be found here: http://ajaxian.com/archives/crock-on-floating-points-in-javascript

    In older javascript engines, if you did 0.3 + 0.3 you get something like 0.600000000001

    Though most javascript engines today return 0.6, under the hood, the problem remains. Adding floats together causes unexpected results. So in your case the

    inc = 0.000001;
    guest += inc;
    

    seems to me, to be the problem.

    A way to solve this would be to use whole numbers. So instead of 0.000001 you would use 1 and instead of 0.001 you would use 1000. Then divide your return result by 100000

    0 讨论(0)
提交回复
热议问题