我试图在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%(来自维基百科的例子)
以前有人这样做过吗? 感谢
答案 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>