求解PV与“求和”FV之间的复利?

时间:2014-02-03 05:44:51

标签: python math quantitative-finance

给出的输入:

present value = 11, SUMMATIONS of future values that = 126, and n = 7 (periods of change)

如何解决链条的速度,从而创建一个总和为FV的链条?这与仅仅求解11到126之间的回报率不同。这就是求解总和为126的回报率。我一直在尝试不同的想法并查找IRR和NPV函数,但求和方面让我感到难过。

如果求和方面不明确,如果我假设速率为1.1,那么将PV = 11变成这样的列表(加起来几乎是FV 126),我该怎样才能解决r知道n,求和fv和pv?:

11
12.1
13.31
14.641
16.1051
17.71561
19.487171
21.4358881
总计= 125.7947691

谢谢。

编辑: 我试图创建一种迭代器,但它在第一次循环后挂起......

for r in (1.01,1.02,1.03,1.04,1.05,1.06,1.07,1.08,1.09,1.10,1.11,1.12):
    print r
    test = round(11* (1-r**8) / (1 - r),0)
    print test
    while True:
        if round(126,0) == round(11* (1-r**8) / (1 - r),0):
            answer = r
            break
        else:
            pass

编辑2:

IV = float(11)
SV = float(126)
N = 8
# sum of a geometric series: (SV = IV * (1 - r^n) / (1 - r )
# r^n - (SV/PV)*r + ((SV - IV)/IV) = 0
# long form polynomial to be solved, with an n of 3 for example:
# 1r^n + 0r^n + 0r^n + -(SV/PV)r + ((SV - IV)/IV)
# each polynomial coefficient can go into numpy.roots to solve
# for the r that solves for the abcd * R = 0 above.

import numpy
array = numpy.roots([1.,0.,0.,0.,0.,0.,0.,(-SV)/IV,(SV-IV)/IV])
for i in array:
    if i > 1:
        a = str(i)
        b = a.split("+")
        answer = float(b[0])
print answer

我收到一个ValueError,我的字符串“1.10044876702”无法转换为float。任何想法?

解决:i.real获得它的真实部分。不需要拆分或字符串转换,即:

for i in array:
        if i > 1:
            a = i.real
            answer = float(a)
    print answer

2 个答案:

答案 0 :(得分:2)

Sum of a geometric series

Subbing in,

126 = 11 * (1 - r**8) / (1 - r)

我们需要解决r。重新排列后,

r**8 - (126/11)*r + (115/11) = 0

然后使用NumPy

import numpy as np
np.roots([1., 0., 0., 0., 0., 0., 0., -126./11, 115./11])

给出

array([-1.37597528+0.62438671j, -1.37597528-0.62438671j,
   -0.42293755+1.41183514j, -0.42293755-1.41183514j,
    0.74868844+1.1640769j ,  0.74868844-1.1640769j ,
    1.10044877+0.j        ,  1.00000000+0.j        ])

其中前六个根是虚数而最后一个是无效的(在原始方程中给出了div-by-0),所以唯一可用的答案是r = 1.10044877

修改

Per the Numpy docsnp.root期望包含多项式系数的类数组对象(也称为列表)。所以上面的参数可以读作1.0*r^8 + 0.*r^7 + 0.*r^6 + 0.*r^5 + 0.*r^4 + 0.*r^3 + 0.*r^2 + -126./11*r + 115./11,这是要求解的多项式。

你的迭代求解器很粗糙;它会给你一个大概的答案,但计算时间是指数级的,具有所需的准确度。我们可以做得更好!

对于八阶方程没有已知的一般解析解,因此需要一些数值方法。

如果你真的想从头编写你自己的求解器,最简单的是Newton-Raphson方法 - 从猜测开始,然后迭代地评估函数,并通过误差除以一阶导数来抵消你的猜测,希望收敛于root - 并希望你的初步猜测是好的,你的等式有真正的根源。

如果您更关心快速获得好的答案,np.root很难被击败 - 它会计算伴随矩阵的特征向量,以同时找到真实和复杂的所有根。

编辑2:

由于您的while True子句 - r永远不会在循环中发生变化,您的迭代求解器会挂起,因此您永远不会break。此外,else: pass是多余的,可以删除。

经过一段时间的重新安排后,您的代码变为:

import numpy as np

def iterative_test(rng, fn, goal):
    return min(rng, key=lambda x: abs(goal - fn(x)))

rng  = np.arange(1.01, 1.20, 0.01)
fn   = lambda x: 11. * (1. - x**8) / (1. - x)
goal = 126.
sol  = iterative_test(rng, fn, goal)

print('Solution: {} -> {}'.format(sol, fn(sol)))

导致

Solution: 1.1 -> 125.7947691

编辑3:

你的最后一个解决方案看起来好多了,但你必须记住,多项式的程度(以及因此传递给np.roots的数组的长度)会改变作为句点的数量变化。

import numpy as np

def find_rate(present_value, final_sum, periods):
    """
    Given the initial value, sum, and number of periods in
    a geometric series, solve for the rate of growth.
    """
    # The formula for the sum of a geometric series is
    #     final_sum = sum_i[0..periods](present_value * rate**i)
    # which can be reduced to
    #     final_sum = present_value * (1 - rate**(periods+1) / (1 - rate)
    # and then rearranged as
    #     rate**(periods+1) - (final_sum / present_value)*rate + (final_sum / present_value - 1) = 0

    # Build the polynomial
    poly     = [0.] * (periods + 2)
    poly[ 0] =  1.
    poly[-2] = -1. * final_sum / present_value
    poly[-1] =  1. * final_sum / present_value - 1.

    # Find the roots
    roots = np.roots(poly)

    # Discard unusable roots
    roots = [rt for rt in roots if rt.imag == 0. and rt.real != 1.]

    # Should be zero or one roots left
    if len(roots):
        return roots[0].real
    else:
        raise ValueError('no solution found')

def main():
    pv, fs, p = 11., 126., 7
    print('Solution for present_value = {}, final_sum = {}, periods = {}:'.format(pv, fs, p))
    print('rate = {}'.format(find_rate(pv, fs, p)))

if __name__=="__main__":
    main()

这会产生:

Solution for present_value = 11.0, final_sum = 126.0, periods = 7:
rate = 1.10044876702

答案 1 :(得分:0)

解决多项式根是过度的。该计算通常使用求解器(例如直接应用于指数公式的牛顿法)来进行。也适用于小数持续时间。

例如,https://math.stackexchange.com/questions/502976/newtons-method-annuity-due-equation