冷灌IRR计算

时间:2011-08-18 19:21:24

标签: coldfusion

我试图在excel中复制IRR(内部收益率)功能。我在riaforge.com上找到了一个cfc,但它没有返回与excel的irr相同的值。

newton-raphson方法使用衍生物,我不知道如何计算coldfusion中的衍生物。

year    cash flow
----    --------
0       -4000
1       1200
2       1410
3       1875
4       1050 

应该返回14.3%(来自维基百科的例子)

以前有人这样做过吗? 感谢

4 个答案:

答案 0 :(得分:4)

扩展到Jason所说的,你需要实现一个有效工作的代码,而不是依赖于Falconeyes建议的强力算法。没有个人在这里我第一次将IRR编程为服务器端脚本它使用暴力,一天后我的网络主机打电话给我说他们让我的网站脱机,因为代码消耗了100%的系统资源

以下是使用IRR calculation方法逐步Newton Raphson的方法,您可以关注它并在Cold Fusion中实施这些想法

f(x) = -4000(1+i)^0 +1200(1+i)^-1 +1410(1+i)^-2 +1875(1+i)^-3 +1050(1+i)^-4
f'(x) = -1200(1+i)^-2 -2820(1+i)^-3 -5625(1+i)^-4 -4200(1+i)^-5

x0 = 0.1
f(x0) = 382.0777
f'(x0) = -9560.2616
x1 = 0.1 - 382.0777/-9560.2616 = 0.139965195884
Error Bound = 0.139965195884 - 0.1 = 0.039965 > 0.000001

x1 = 0.139965195884
f(x1) = 25.1269
f'(x1) = -8339.5497
x2 = 0.139965195884 - 25.1269/-8339.5497 = 0.142978177747
Error Bound = 0.142978177747 - 0.139965195884 = 0.003013 > 0.000001

x2 = 0.142978177747
f(x2) = 0.126
f'(x2) = -8256.0861
x3 = 0.142978177747 - 0.126/-8256.0861 = 0.142993440675
Error Bound = 0.142993440675 - 0.142978177747 = 1.5E-5 > 0.000001

x3 = 0.142993440675
f(x3) = 0
f'(x3) = -8255.6661
x4 = 0.142993440675 - 0/-8255.6661 = 0.142993441061
Error Bound = 0.142993441061 - 0.142993440675 = 0 < 0.000001
IRR = x4 = 0.142993441061 or 14.3%

答案 1 :(得分:1)

我不知道ColdFusion是什么,但找到IRR的想法非常简单。

IRR是r的数字

sum i = 0 to N C_i * (1 + r)^(-t_i) = 0

有时N + 1现金流C_0, C_1, ..., C_N t_0, t_1, ..., t_N。定义

f(r) = sum i = 0 to N C_i * (1 + r)^(-t_i).

然后

f'(r) = sum i = 0 to N -C_i * (1 + r)^(-t_i - 1).

选择初始猜测r_0并通过

进行迭代
r_{n + 1} = r_n - f(r_n) / f'(r_n)

在您的具体示例中,您有

t_0 = 0     C_0 = -4000
t_1 = 1     C_1 = 1200
t_2 = 2     C_2 = 1410
t_3 = 3     C_3 = 1875
t_4 = 4     C_4 = 1050

尝试猜测r_0 = 0.1

同样,我不知道ColdFusion是什么,但它必须是一种编程语言,所以它应该允许计算这个基本的数学。

答案 2 :(得分:1)

<cffunction name="calcIRR">
    <cfargument name="arrCashFlow" type="Array" required="true" hint="array of cashflow">
    <cfscript>
        var guess = 0.1;
        var inc   = 0.00001;
        do {
            guess += inc;
            npv = 0; //net present value
            for (var i=1; i<=arrayLen(arguments.arrCashFlow); i++)  {
                npv += arguments.arrCashFlow[i] / ((1 + guess) ^ i);    
            }

        } while ( npv > 0 );

        guess =  guess * 100;
    </cfscript>
    <cfreturn guess>
</cffunction>



<cfscript>
    cFlow = arrayNew(1);
    cFlow[1] = -4000;
    cFlow[2] = 1200;
    cFlow[3] = 1410;
    cFlow[4] = 1875;
    cFlow[5] = 1050;

    c = calcIRR(cFlow);
</cfscript>
<cfdump var="#cFlow#">
<cfdump var="#c#">

答案 3 :(得分:1)

我尝试了所有提交的解决方案,但都没有达到应有的效果(例如在excel中)。 这是用于计算XIRR的代码,该代码应能正常工作。对于IRR,您只需要更改以下行:

<cfset npv = npv + (arguments.values[i] / ((1 + arguments.rate) ^ time_span))>

这是整个脚本

<cfoutput>

#XIRR(values=[-5000,500,110500], dates=["2015-07-06","2016-07-06","2017-07-06"])#

</cfoutput>

<cffunction name="XIRR">
    <cfargument name="values" required="true">
    <cfargument name="dates" required="true">

    <cfset var do_calculation = check_data(values=arguments.values, dates=arguments.dates)>

    <cfif do_calculation.is_ok>
        <cfset var rate = 1>
        <cfset var npv = calculate_NPV(rate=rate, values=arguments.values, dates=arguments.dates)>

        <cfloop condition="#npv# gt 10e-6">
            <cfset rate = rate + 1>
            <cfset npv = calculate_NPV(rate=rate, values=arguments.values, dates=arguments.dates)>
        </cfloop>

        <cfloop from="1" to="6" index="pow">

            <cfset fac = 1 / (10 ^ pow)>

            <cfset npv = 0>
            <cfloop condition="#npv# lt 10e-6">
                <cfset rate = rate - fac>
                <cfset npv = calculate_NPV(rate=rate, values=arguments.values, dates=arguments.dates)>
            </cfloop>

            <cfset rate = rate + fac>

        </cfloop>

        <cfreturn rate>

    <cfelse>
        <cfreturn "error: #do_calculation.error#">
    </cfif>
</cffunction>


<cffunction name="check_data">
    <cfargument name="values" required="true">
    <cfargument name="dates" required="true">

    <cfset var is_ok = true>
    <cfset var has_negative = false>
    <cfset var has_positive = false>
    <cfset var error = 0>
    <cfset var return = structNew()>
    <cfset var date_prev = "">
    <cfset var date_curr = "">

    <cfif arguments.values[1] gte 0>
        <cfset is_ok = false>
        <cfset error = -1>
    </cfif>

    <cfloop array="#arguments.values#" item="value">
        <cfif value gt 0>
            <cfset has_positive = true>
        </cfif>
        <cfif value lt 0>
            <cfset has_negative = true>
        </cfif>
    </cfloop>

    <cfif !has_negative or !has_positive>
        <cfset is_ok = false>
        <cfset error = -2>
    </cfif>

    <cfif arrayLen(arguments.values) neq arrayLen(arguments.dates)>
        <cfset is_ok = false>
        <cfset error = -3>
    </cfif>

    <cfloop from="2" to="#arrayLen(arguments.dates)#" index="d">
        <cfset date_prev = arguments.dates[d-1]>
        <cfset date_curr = arguments.dates[d]>

        <cfif dateDiff("d", date_prev, date_curr) lte 0>
            <cfset is_ok = false>
            <cfset error = -4>
        </cfif>
    </cfloop>

    <cfset return.is_ok = is_ok>
    <cfset return.error = error>

    <cfreturn return>
</cffunction>


<cffunction name="calculate_NPV">
    <cfargument name="rate" required="false" default="1">
    <cfargument name="values" required="true">
    <cfargument name="dates" required="true">

    <cfset var npv = arguments.values[1]>

    <cfset var time_span = "">

    <cfloop from="2" to="#arrayLen(arguments.values)#" index="i">
        <cfset time_span = dateDiff('d', arguments.dates[1], arguments.dates[i]) / 365>

        <cfset npv = npv + (arguments.values[i] / ((1 + arguments.rate) ^ time_span))>
    </cfloop>

    <cfreturn npv>
</cffunction>