IRR холодного синтеза - PullRequest
       1

IRR холодного синтеза

1 голос
/ 18 августа 2011

Я пытаюсь повторить функцию IRR (внутренней нормы прибыли) в Excel.Я нашел один cfc в riaforge.com, но он не возвращает то же значение, что и irr в excel.

В методе Ньютона-Рафсона используются производные, и я не уверен, как рассчитать производные при холодном синтезе.

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

должен возвращать 14,3% (из примера Википедии)

Имееткто-нибудь делал это раньше?спасибо

Ответы [ 4 ]

4 голосов
/ 19 августа 2011

В дополнение к тому, что сказал Джейсон, вам нужно будет реализовать код, который работает эффективно и не полагается на алгоритм перебора, предложенный Фалькони. ничего личного здесь в первый раз, когда я запрограммировал IRR как сценарий на стороне сервера, он использовал грубую силу, и через день мой веб-хост позвонил мне, сказав, что они переводят мой сайт в автономный режим, поскольку код потребляет 100% системных ресурсов

Ниже приведен пошаговый расчет IRR с использованием метода Ньютона Рафсона , и вы можете следовать ему и реализовывать идеи в 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 голос
/ 18 декабря 2018

Я перепробовал все представленные решения, и ни одно из них не работало так, как должно (как в 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>
1 голос
/ 19 августа 2011
<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#">
1 голос
/ 18 августа 2011

Я не знаю, что такое 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, но это должен быть язык программирования, и поэтому он должен позволять вычислять эту базовую математику..

...