用python实现等额本息

Python实现等额本息

1.等额本息

等额本息下,每个月还款的本金+利息的总额是相等的,或者说,用户还款时只知道每个月还款额相等,并不关心还了多少本金和利息。这种还款方式同样适用于收入稳定的人群。

假设每期本金设为P1,P2,P3…Pn;每个分期的天数为D1,D2,D3…Dn;每期本息总额为A,本金总额为Psum,日利率为R。根据等额本息的规则,可以得到如下公式:

每一期次的本金和利息:
A = P1 + (Psum) * RD1;
A = P2 + (Psum – P1) * R
D2;
A = P3 + (Psum – P1 – P2) * R*D3;

A = Pn + (Psum – P1 – P2 - … - Pn-1) RDn;
总本金 = 每一期本金之和:
Psum = P1 + P2 + P3 + … + Pn;

综合以上等式,使用线性方程求解n+1元一次方程组。
设:变量矩阵为X[n+1],则变量矩阵如下:
在这里插入图片描述

计算每个等式中,变量的参数,得到变量的参数矩阵A[n+1][n+1]为:
在这里插入图片描述
计算每个等式中,等式的常量值,得到的常量矩阵B[n+1]为:
在这里插入图片描述
根据A[n+1][n+1] * X[n+1] = B[n+1],首先计算出A矩阵的逆矩阵 A-1 然后再左右两边同时左乘A-1 就得到X = A-1*B,这样我们就求到了所有变量A,P1,P2…Pn。那么我们每期的本金就计算出来了。

2.代码

# -*- coding: utf-8 -*-

from datetime import datetime
from dateutil.relativedelta import relativedelta
import numpy as np
from decimal import *


def benqidate(date, k):
    """
    算每一期时间
    :param date: 贷款时间,字符串类型
    :param k: 第几期
    :return: 返回本期的还款日期
    """
    date_daikuan = datetime.strptime(date,'%Y-%m-%d')
    if 1 <= k + date_daikuan.month <= 12:
        date_benqi = date_daikuan + relativedelta(month=k + date_daikuan.month)
    elif 13 <= k + date_daikuan.month <= 24:
        date_benqi = date_daikuan + relativedelta(year=date_daikuan.year + 1, month=k + date_daikuan.month - 12)
    elif 25 <= k + date_daikuan.month <= 36:
        date_benqi = date_daikuan + relativedelta(year=date_daikuan.year + 2, month=k + date_daikuan.month - 24)
    else:
        date_benqi = date_daikuan + relativedelta(year=date_daikuan.year + 4, month=k + date_daikuan.month - 48)
    return date_benqi


def calD(date, n=36):
    """
    算本期的天数,用列表表示出来,精确到天
    :param date: 贷款日期
    :param n: 期数
    :return: 每期天数的列表
    """
    result_D = []
    for i in range(1, n+1):
        date_daikuan = datetime.strptime(date, '%Y-%m-%d')
        if i == 1:
            benqitianshu = (benqidate(date, i) - date_daikuan).days
            result_D.append(benqitianshu)
        else:
            benqitianshu = (benqidate(date, i) - benqidate(date, i - 1)).days
            result_D.append(benqitianshu)
    return result_D



def calmonthpay(date, rent_sum, n=36, r=0.153/360):
    """
    计算每期的租金总额
    :param date: 贷款时间
    :param rent_sum: 贷款总额
    :param n: 期数
    :param r: 日利率
    :return: 每期的租金总额
    """
    D = calD(date)
    M = np.eye(n)
    for i in np.arange(1, n):
        for j in range(i):
            M[i, j] = -r * D[i]
    c1 = np.ones(n) * -1
    c1.shape = (n, 1)
    r1 = np.ones(n + 1).T
    r1[0] = 0
    r1.shape = (1, n + 1)
    M = np.hstack((c1, M))
    M = np.vstack((M, r1))
    B = -r * rent_sum * np.array(D)
    B = np.append(B, [rent_sum])
    X = np.mat(M).I * np.mat(B).T
    return X[0, 0]


def calzujin(date, rent_sum,  n=36, rate=0.153):
    """
    计算各个所需的参数
    :param rate: 年利率
    :param date: 贷款日期,输入为字符串形式
    :param rent_sum:本金总额
    :param n: 期数
    :return:返回每期的利息,当期本金和期末本金
    """
    month_pay = calmonthpay(date, rent_sum)
    print(month_pay)
    month_pay = Decimal(str(month_pay)).quantize(Decimal('.01'), rounding=ROUND_DOWN)
    month_pay = np.float(month_pay)
    result_lixi = []
    result_dangqi = []
    result_qimou = []
    lixi_sum_list = []
    sum = 0
    lixi_sum = 0
    for i in range(1, n+1):
        date_daikuan = datetime.strptime(date, '%Y-%m-%d')
        if i == 1:
            benqitianshu = (benqidate(date, i) - date_daikuan).days
            dangqi_lixi = (rent_sum * rate) / 360 * benqitianshu
            result_lixi.append(dangqi_lixi)
            rent_dangqi = month_pay - dangqi_lixi
            sum += round(rent_dangqi, 2)
            result_dangqi.append(rent_dangqi)
            rent_sum_qimou = rent_sum - rent_dangqi
            result_qimou.append(rent_sum_qimou)
            lixi_sum += dangqi_lixi
            lixi_sum_list.append(lixi_sum)
        elif 2 <= i <= 47:
            benqitianshu = (benqidate(date, i) - benqidate(date, i-1)).days
            rent_sum_qichu = rent_sum_qimou
            dangqi_lixi = (rent_sum_qichu * rate) / 360 * benqitianshu
            result_lixi.append(dangqi_lixi)
            rent_dangqi = month_pay - dangqi_lixi
            sum += round(rent_dangqi, 2)
            result_dangqi.append(rent_dangqi)
            rent_sum_qimou = rent_sum_qichu - rent_dangqi
            result_qimou.append(rent_sum_qimou)
            lixi_sum += dangqi_lixi
            lixi_sum_list.append(lixi_sum)
        else:
            benqitianshu = (benqidate(date, i) - benqidate(date, i - 1)).days
            rent_sum_qichu = rent_sum - sum
            dangqi_lixi = (rent_sum_qichu * rate) / 360 * benqitianshu
            result_lixi.append(dangqi_lixi)
            rent_dangqi = rent_sum - sum
            result_dangqi.append(rent_dangqi)
            rent_sum_qimou = rent_sum_qichu - rent_dangqi
            result_qimou.append(rent_sum_qimou)
            lixi_sum += dangqi_lixi
            lixi_sum_list.append(lixi_sum)
    month_pay = Decimal(str(month_pay)).quantize(Decimal('.01'), rounding=ROUND_DOWN)
    lixi_qimou = [lixi_sum-i for i in lixi_sum_list]
    return month_pay, result_lixi, result_dangqi, result_qimou, lixi_qimou


def calrent_sum(month_pay, date, n=36, r=0.153/360):
    D = calD(date=date)
    M = np.eye(n)
    for i in np.arange(1, n):
        for j in range(i):
            M[i, j] = -r * D[i]
    # 然后进行矩阵的拼接
    c1 = np.ones(n)
    for i in range(n):
        c1[i] = r * D[i]
    # 将c1拼接到矩阵中
    c1.shape = (n,1)
    M = np.hstack((c1, M))
    c2 = np.ones(n+1)
    c2[0] = -1
    c2.shape = (1, n+1)
    M = np.vstack((M, c2))
    # 构造月供矩阵
    A = np.ones(n+1).T
    for i in range(n):
        A[i] = month_pay
    A[36] = 0
    A.shape = (n+1, 1)
    X = np.mat(M).I * np.mat(A)
    return X[0,0]


if __name__ == '__main__':
    d, a, b, c, e = calzujin("2018-07-01", 100877)
    sum = 0
    for i in range(36):
        print("第 %d 期利息为:%.2f" % (i+1, round(a[i], 2)))
        sum += round(a[i], 2)
    print(sum)
    print("\n")
    for j in range(36):
        print("第 %d 期本金为:%.2f" % (j+1, round(b[j], 2)))
    print("\n")
    for k in range(36):
        print("第 %d 期末本金为:%.2f" % (k+1,round(c[k], 2)))
    print("每期月供: %s" % (d))
    for m in range(36):
        print("第 %d 期末剩余利息为:%.2f" % ( m+ 1, round(e[m], 2)))

结果如下

/Users/xudong/opt/anaconda3/python.app/Contents/MacOS/python /Users/xudong/PycharmProjects/滚动率计算/网商租金计算.py
3523.9840437764581 期利息为:1329.052 期利息为:1300.143 期利息为:1229.844 期利息为:1240.615 期利息为:1171.486 期利息为:1179.537 期利息为:1148.658 期利息为:1009.229 期利息为:1084.2210 期利息为:1018.1411 期利息为:1019.0612 期利息为:954.2513 期利息为:952.2014 期利息为:918.3215 期利息为:855.4716 期利息为:848.8317 期利息为:787.3418 期利息为:777.5319 期利息为:741.3520 期利息为:659.2221 期利息为:666.9422 期利息为:609.0023 期利息为:590.9024 期利息为:534.4425 期利息为:512.8726 期利息为:473.1927 期利息为:419.0328 期利息为:392.0929 期利息为:339.5130 期利息为:308.8831 期利息为:266.5232 期利息为:201.9633 期利息为:179.8334 期利息为:131.3935 期利息为:91.0736 期利息为:44.37
25986.439999999991 期本金为:2194.932 期本金为:2223.843 期本金为:2294.144 期本金为:2283.375 期本金为:2352.506 期本金为:2344.457 期本金为:2375.338 期本金为:2514.769 期本金为:2439.7610 期本金为:2505.8411 期本金为:2504.9212 期本金为:2569.7313 期本金为:2571.7814 期本金为:2605.6615 期本金为:2668.5116 期本金为:2675.1517 期本金为:2736.6418 期本金为:2746.4519 期本金为:2782.6320 期本金为:2864.7621 期本金为:2857.0422 期本金为:2914.9823 期本金为:2933.0824 期本金为:2989.5425 期本金为:3011.1126 期本金为:3050.7927 期本金为:3104.9528 期本金为:3131.8929 期本金为:3184.4730 期本金为:3215.1031 期本金为:3257.4632 期本金为:3322.0233 期本金为:3344.1534 期本金为:3392.5935 期本金为:3432.9136 期本金为:3479.611 期末本金为:98682.072 期末本金为:96458.233 期末本金为:94164.094 期末本金为:91880.735 期末本金为:89528.226 期末本金为:87183.787 期末本金为:84808.458 期末本金为:82293.699 期末本金为:79853.9210 期末本金为:77348.0811 期末本金为:74843.1612 期末本金为:72273.4313 期末本金为:69701.6614 期末本金为:67096.0015 期末本金为:64427.4916 期末本金为:61752.3417 期末本金为:59015.7018 期末本金为:56269.2619 期末本金为:53486.6220 期末本金为:50621.8721 期末本金为:47764.8322 期末本金为:44849.8523 期末本金为:41916.7724 期末本金为:38927.2325 期末本金为:35916.1126 期末本金为:32865.3327 期末本金为:29760.3828 期末本金为:26628.4929 期末本金为:23444.0330 期末本金为:20228.9231 期末本金为:16971.4632 期末本金为:13649.4433 期末本金为:10305.2934 期末本金为:6912.7035 期末本金为:3479.8036 期末本金为:0.18
每期月供: 3523.981 期末剩余利息为:24657.412 期末剩余利息为:23357.273 期末剩余利息为:22127.434 期末剩余利息为:20886.825 期末剩余利息为:19715.346 期末剩余利息为:18535.817 期末剩余利息为:17387.168 期末剩余利息为:16377.949 期末剩余利息为:15293.7210 期末剩余利息为:14275.5811 期末剩余利息为:13256.5212 期末剩余利息为:12302.2713 期末剩余利息为:11350.0714 期末剩余利息为:10431.7515 期末剩余利息为:9576.2716 期末剩余利息为:8727.4417 期末剩余利息为:7940.1018 期末剩余利息为:7162.5719 期末剩余利息为:6421.2220 期末剩余利息为:5762.0021 期末剩余利息为:5095.0522 期末剩余利息为:4486.0523 期末剩余利息为:3895.1624 期末剩余利息为:3360.7225 期末剩余利息为:2847.8526 期末剩余利息为:2374.6627 期末剩余利息为:1955.6228 期末剩余利息为:1563.5329 期末剩余利息为:1224.0230 期末剩余利息为:915.1431 期末剩余利息为:648.6332 期末剩余利息为:446.6733 期末剩余利息为:266.8334 期末剩余利息为:135.4435 期末剩余利息为:44.3736 期末剩余利息为:0.00

Process finished with exit code 0

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值