复利计算

复利计算_第1张图片

起因

最近一个搞投融资的好哥们儿问我分期付款利率的计算,说实在的我也不懂,答应他过几天帮他看看。

数学理论

忙了几天后,今天闲下来了,在网上搜了搜相关的知识。
主要是这七个公式:


复利计算_第2张图片
计算公式
  • 【式1】最简单,是下面所有式子推导的起点。它的含义是初始资金P在利率i下进行n期利滚利迭代后的资金额F。
  • 【式2】由式1反推
  • 【式3】是指在每期固定还款额度情况下,执行n期后的资金总额。具体就是式1从1到n的和,按等比数列求和公式可得。
  • 【式4】由式3反推。
  • 【式5】则是将式3带入式2得到。
  • 【式6】是式5反推。这是计算等额本息分期付款额度的关键公式。
  • 【式7】是计算每期还款额度中多少属于偿还上期剩余本金的利息,这样每期还款额A减去利息后剩余的额度就用来偿还本金。
    在等额本息偿还方式下,随着偿还期数递增,本金逐渐减少,每期的需偿还的利息比重也逐渐减少。到了还款后期每次基本上是在偿还本金,从这点儿看等额本息的还款方式确实不太适合提前偿还。

python 实现

最近几天由于项目发展需要又开始拾起来python了,这个小小的计算程序用python简直不要太简单了!

# 复利终值计算
def rF(P,n):
    ret = P * pow(1 + r, n)
    return ret

# 复利现值
def rP(F,n):
    ret = F * pow(1 + r, -n)
    return ret

# 等额多次支付终值计算
def mrF(A,n):
    ret = A * (pow((1 + r), n) - 1) / r
    return ret

# 等额多次支付现值计算
def mrP(A,n):
    ret = A * (pow((1 + r), n) - 1) / pow((1 + r), n) / r
    return ret

# 资金回笼计算
def mrA(P,n):
    ret = P * pow((1 + r), n) * r / (pow((1 + r), n) - 1)
    return ret
# 
def mrAr(P,n,r):
    ret = P * pow((1 + r), n) * r / (pow((1 + r), n) - 1)
    return ret

# 月还款利息成分
def mrR(P,n,i):
    A = P * pow((1 + r), n) * r / (pow((1 + r), n) - 1)
    return (P * r - A) * pow(1 + r, i - 1) + A

先把几个公式写出来,利率i用全局变量r来代替。接下来用python列表操作得出每期的还款额,利息,本金,


# 计算等额本息----开始
# 本金
P = 1000000
# 分期多少月
n = 36
# 利率 1分=0.01
r = 0.01

# A:每月还钱数;R:其中包含的利息; p:其中包含的本金。A=R+p
A = [mrA(P,n)]*n
R = [mrR(P,n,i) for i in range(1,n+1)]
p = [mrp(P,n,i) for i in range(1,n+1)]

连个循环都不用写,真是不习惯!

分阶段的等额本息

这哥们儿接着提出了个要求:还是等额本息,但在借款期间的利息计算是变动的,比如借三年,第一年24%,第二年8%,第三年4%,这样三年平均起来的利息还接近12%,但第一年就将大部分利息收回来了,从而提高了资金收益率。我听了心里不由得道了声--我嚓~,你一个月收到3万,里面有多少利息其实并不是算法或其他什么规定的,这只是一个在利率迭代过程给出的等效值啊等效值啊等效值啊!如果你想,你把这三万全定位利息也不错啊!哈哈
后来这哥们儿又给出解释:像从事他们这一行的,遇见的客户也很少能规规矩矩的按时执行还款合约的,这样即使半截终止了合同,前面收回了利息,等等,但我估计还应该是后面再追回了本金才不亏,否则或者客户到后期感觉这钱白用着很好,干脆用满整个期间,咋办
好吧,虽然觉得还是有点儿问题,咱只要给他搞出个算法就好了。
由于是分段计息,又要求整个过程是等额还款,这样不太好法直接确定各个阶段的资金比例,也就没办法套用上面的公式,如果非要先推一个解析式的话,估计只能是个分段函数。
但考虑到这个终值F和还款额A的函数关系一定是收敛的,而且A的区间比较好确定,整个算法递推上几十步对计算机来说简直小菜一碟,所以插值逼近的算法正适合这个问题。
算法描述:

1、确定A的上下区间MaxA、MinA
2、取A当前值curA=区间中点
3、递推还款期间本金偿还数量
    3.1、设置还款期数=1,本金curP=P
    3.2、计算本期利息curR=curP*r
             还款额扣除利息后偿还本金curP -= curR
             还款期数+1
    3.3、若未到最后还款期执行步骤3.2,否则向下继续
4、如果curP==0(实际上是curP绝对值小于ε(ε=0.01)),说明还款额度适中,算法结束,输出结果。
      如果curP>0,则说明还款额度不够,继续向上插值。修改插值区间低点MinA=curA,设置 = (MinA+MaxA)/2,执行步骤3
      如果curP<0,则说明还款额度超出,继续向下插值。修改插值区间高点MaxA=curA,设置 = (MinA+MaxA)/2,执行步骤3      

python代码:

 计算--阶段利息---等额本息----开始
RPerYear = [0.24,0.08,0.04]

RPerMonth = []
for RYear in RPerYear:
    slicRPerYear = [RYear / 12.0] * 12
    RPerMonth += slicRPerYear

#printFloat(RPerMonth,1)


# 本金
P = 1000000

# 迭代计算每月还款额度
MinA = RPerMonth[0] * P
MaxA = P
count = len(RPerMonth)
# 初值
curA = (MaxA + MinA) / 2.0

while 1:
    curP = P
    for i in range(count):
        curR = curP * RPerMonth[i]
        curP -= curA - curR

    #print("curP=%.2f,curA=%.2f"%(curP,curA))
    #print("MinA=%.2f,MaxA=%.2f"%(MinA,MaxA))
    # 迭代精度0。01=1分
    if abs(curP) < 0.01:
        break;
    else:
        if curP > 0:
            MinA = curA
            curA = (MinA + MaxA) / 2.0
        else:
            MaxA = curA
            curA = (MinA + MaxA) / 2.0

print(RPerYear)
print("等额本息还款额度=%.2f"%(curA))

运行结果:

[0.24, 0.08, 0.04]
等额本息还款额度=35473.49

接下来计算平均利息以及每期还款情况。从前面的公式分析可知,由利息计算F或P比较容易,但已知A、F或P反推利息则相当于解高次方程,最好也采用插值算法。具体算法就不多啰嗦了,直接上代码:


# 迭代计算等价利息
MaxR = max(RPerMonth)
MinR = min(RPerMonth)
curR = (MaxR + MinR) / 2.0
while 1:
    newA = mrAr(P,len(RPerMonth),curR)
    if abs(newA - curA) < 0.001:
        break
    else:
        if newA > curA: #高了
            MaxR = curR
            curR = (MinR + MaxR) / 2.0
        else:
            MinR = curR
            curR = (MinR + MaxR) / 2.0

print("等价利息=%.4f" % (curR))

# 推算每个月还款额度中的利息和本金
count = len(RPerMonth)
A = [curA]*count
R = []
p = []
curP = P
for i in range(count):
    step_R = curP * RPerMonth[i]
    step_p = A[i] - step_R
    curP -= step_p

    R.append(step_R)
    p.append(step_p)

# all done!!
#printVFloat((A,RPerMonth,R,p))
printVFloatWithR((A,R,p),RPerMonth)

运行结果:


等价利息=0.0139
|   序 号 |       1 |       2 |       3 |       4 |

|       1 |35473.49 |  0.0200 |20000.00 |15473.49 |

|       2 |35473.49 |  0.0200 |19690.53 |15782.96 |

|       3 |35473.49 |  0.0200 |19374.87 |16098.61 |

|       4 |35473.49 |  0.0200 |19052.90 |16420.59 |
......


|      36 |35473.49 |  0.0033 |  117.85 |35355.63 |

|   总 计 |1277045.49|  0.3600 |277045.49|1000000.01|

总结

从这个实际应用来看,利用python提供的元组、列表以及针对性的批量操作算法进行数据处理简直太好用了,无愧于它在大数据领域的名声!

你可能感兴趣的:(复利计算)