复利计算

起因

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

数学理论

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


计算公式
  • 【式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提供的元组、列表以及针对性的批量操作算法进行数据处理简直太好用了,无愧于它在大数据领域的名声!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容