#coding:utf-8
import sys
from prettytable import PrettyTable
import math

'''
月利率 = 年利率/12

1.等额本息计算公式:每月还款金额 =〔贷款本金×月利率×(1+月利率)^还款月数〕÷〔(1+月利率)^还款月数 - 1〕
  每月利息 = 每月还款金额 - (1 + 月利率 )^(还款期数-1) * (每月还款金额 - 月利率*贷款本金)
  每月偿还本金 = ( 1 + 月利率)^(还款期数-1) * (每月还款金额 - 月利率*贷款本金)

 
2.等额本金计算公式:每月还款金额 =(贷款本金 / 还款月数)+(本金 — 已归还本金累计额)* 每月利率
    每月偿还本金=贷款本金/还款月数
    每月利息=(本金-累计已还本金)×月利率

'''
YEAR_LPR=0.0385 #年利率
MONTH_LPR=round(YEAR_LPR/12,12) #月利率
UNIT= 10000 #单位万元


'''
月供计算
periods:第n期还款
pay_month:总还款月数
total:单位(万元)
等额本息:pay_way=1
等额本金:pay_way=2
'''

#月供
def get_month_pay(total,periods=1,pay_month=360,pay_way=1):
    result=0
    if pay_way==1:
        result = (total*UNIT*MONTH_LPR*((MONTH_LPR+1)**pay_month))/((MONTH_LPR+1)**pay_month-1)
    elif pay_way==2:
        result=(total*UNIT/pay_month)+(total*UNIT - (total*UNIT/pay_month)*(periods-1) )*MONTH_LPR
    return round(result,6)

#  每月还款利息
def get_month_interest(total,periods=1,pay_month=360,pay_way=1):
    result=0
    if pay_way==1:
        month_pay  = round((total*UNIT*MONTH_LPR*((MONTH_LPR+1)**pay_month))/((MONTH_LPR+1)**pay_month-1),6) #每月还款金额
        result = month_pay-((1 + MONTH_LPR)**(periods-1)) * (month_pay - MONTH_LPR * total * UNIT)
    elif pay_way==2:
        result = (total*UNIT - (total*UNIT/pay_month)*(periods-1) )*MONTH_LPR
    return round(result,6)

#每月还款本金
def get_month_principal(total,periods=1,pay_month=360,pay_way=1):
    result=0
    if pay_way==1:
        month_pay  = round((total*UNIT*MONTH_LPR*((MONTH_LPR+1)**pay_month))/((MONTH_LPR+1)**pay_month-1),6) #每月还款金额
        result = ((1 + MONTH_LPR)**(periods-1)) * (month_pay - MONTH_LPR * total* UNIT)

    elif pay_way==2:
        result = total*UNIT/pay_month
    return round(result,6)

#获取剩余还款期数(还款周期,还款金额不变,缩短剩余期数)
#pay_month:月供
#total:上期本金
#total_new:新的还款本金
#periods:上期还款周期
def get_month_periods1(total_new,pay_month):
    period = math.log10(pay_month/(pay_month-total_new*MONTH_LPR))/math.log10(1+MONTH_LPR)
    # return math.ceil(period)
    return int(period) #尽力缩短还款期数

def get_month_periods2(total,total_new,periods):
    period = total_new/(total*UNIT) * periods
    # return math.ceil(period)
    return int(period)

'''
sum_total:还款本金
pay_month:总还款期数
pay_way:还款方式
    等额本息:pay_way=1
    等额本金:pay_way=2
before_pay_dict:提前还款参数,值:{key(第几期):value(提前还款金额)}
'''
def main(sum_total,pay_month,pay_way,before_pay_dict=dict()):
    titiles = ["期数", "月还款", "还款本金","还款利息","总还款","总还款本金","剩余还款本金","总还款利息"]
    tb = PrettyTable(titiles)
    for i in titiles:tb._align[i] = 'l'

    sum_month_pay1 = 0 #总还款金额
    sum_month_pay2 = 0
    sum_month_principal1= 0 #总还款本金
    sum_month_principal2 = 0
    sum_month_interest1 = 0 #总还款利息
    sum_month_interest2 = 0
    mod_principal1 = sum_total * UNIT #剩余本金
    mod_principal2 = sum_total * UNIT
    remaining_pay_month = pay_month ##提前还款后,剩余还款期数


    total = sum_total
    periods =0 #第n期
    for i,_ in enumerate(range(1,pay_month+1),1):
        periods += 1
        month_pay1=get_month_pay(total,periods,remaining_pay_month,pay_way=1) #月供
        month_pay2=get_month_pay(total,periods,remaining_pay_month,pay_way=2)

        month_interest1 = get_month_interest(total,periods,remaining_pay_month,pay_way=1) #利息
        month_interest2 = get_month_interest(total,periods,remaining_pay_month,pay_way=2)

        month_principal1 = get_month_principal(total,periods,remaining_pay_month,pay_way=1)  #本金
        month_principal2 = get_month_principal(total,periods,remaining_pay_month,pay_way=2)

        sum_month_pay1 += month_pay1 #总还款数
        sum_month_pay2 += month_pay2

        sum_month_principal1 += month_principal1 #总还款本金
        sum_month_principal2 += month_principal2

        sum_month_interest1 += month_interest1 #总还款利息
        sum_month_interest2 += month_interest2

        mod_principal1 = (sum_total*UNIT) -sum_month_principal1 #剩余本金
        mod_principal2 = (sum_total*UNIT) -sum_month_principal2
   

        #提前还款
        if before_pay_dict.keys().__contains__(i): 
            pay_money = before_pay_dict[i] #提前还款金额
            month_principal1 += pay_money
            month_principal2 += pay_money

            sum_month_pay1 += pay_money
            sum_month_pay2 += pay_money

            sum_month_principal1 += pay_money
            sum_month_principal2 += pay_money

            mod_principal1 -= pay_money
            mod_principal2 -= pay_money
            periods = 0
            remaining_pay_month = pay_month - i

            if pay_way==1 and mod_principal1>0: total = mod_principal1/10000
            if pay_way==2 and mod_principal2>0: total = mod_principal2/10000
            
        row1=['息-{}'.format(i),round(month_pay1,2),round(month_principal1,2),round(month_interest1,2),round(sum_month_pay1,2), round(sum_month_principal1,2),abs(round(mod_principal1,2)),round(sum_month_interest1,2)] 
        row2=['金-{}'.format(i),round(month_pay2,2),round(month_principal2,2),round(month_interest2,2),round(sum_month_pay2,2),  round(sum_month_principal2,2),abs(round(mod_principal2,2)),round(sum_month_interest2,2)]
        if pay_way==1 :tb.add_row(row1)
        if pay_way==2 :tb.add_row(row2)
        if before_pay_dict.keys().__contains__(i): tb.add_row(["---", "---", "---","---","---","---","---","---"])
    print(tb)



#提前还贷,保持月供,缩短剩余期数方式
def mainv2(sum_total,pay_month,pay_way,before_pay_dict=dict()):
    titiles = ["期数", "月还款", "还款本金","还款利息","总还款","总还款本金","剩余还款本金","总还款利息"]
    tb = PrettyTable(titiles)
    for i in titiles:tb._align[i] = 'l'

    sum_month_pay1 = 0 #总还款金额
    sum_month_pay2 = 0
    sum_month_principal1= 0 #总还款本金
    sum_month_principal2 = 0
    sum_month_interest1 = 0 #总还款利息
    sum_month_interest2 = 0
    mod_principal1 = sum_total * UNIT #剩余本金
    mod_principal2 = sum_total * UNIT
    remaining_pay_month = pay_month #提前还款后,从新计算的还款周期
    remaining_periods = pay_month  #剩余还款期数

    total = sum_total
    periods =0 #第n期
    for i,_ in enumerate(range(1,pay_month+1),1):
        periods += 1
        remaining_periods -= 1
        month_pay1 = get_month_pay(total,periods,remaining_pay_month,pay_way=1) #月供
        month_pay2 = get_month_pay(total,periods,remaining_pay_month,pay_way=2)

        month_interest1 = get_month_interest(total,periods,remaining_pay_month,pay_way=1) #利息
        month_interest2 = get_month_interest(total,periods,remaining_pay_month,pay_way=2)

        month_principal1 = get_month_principal(total,periods,remaining_pay_month,pay_way=1)  #本金
        month_principal2 = get_month_principal(total,periods,remaining_pay_month,pay_way=2)

        sum_month_pay1 += month_pay1 #总还款数
        sum_month_pay2 += month_pay2

        sum_month_principal1 += month_principal1 #总还款本金
        sum_month_principal2 += month_principal2

        sum_month_interest1 += month_interest1 #总还款利息
        sum_month_interest2 += month_interest2

        mod_principal1 = (sum_total*UNIT) - sum_month_principal1 #剩余本金
        mod_principal2 = (sum_total*UNIT) - sum_month_principal2

        #提前还款
        if before_pay_dict.keys().__contains__(i): 
            pay_money = before_pay_dict[i] #提前还款金额
            month_principal1 += pay_money
            month_principal2 += pay_money

            sum_month_pay1 += pay_money
            sum_month_pay2 += pay_money

            sum_month_principal1 += pay_money
            sum_month_principal2 += pay_money

            mod_principal1 -= pay_money
            mod_principal2 -= pay_money
            periods = 0

            # remaining_pay_month = pay_month - i

            if pay_way==1 and mod_principal1>0: total = mod_principal1/10000
            if pay_way==2 and mod_principal2>0: total = mod_principal2/10000

            if pay_way==1:remaining_pay_month = get_month_periods1(mod_principal1,month_pay1)
            if pay_way==2:remaining_pay_month = get_month_periods2(sum_total,mod_principal2,pay_month)
            # print('remaining_pay_month=',remaining_pay_month,mod_principal1,mod_principal2)
            remaining_periods = remaining_pay_month
            
        row1=['息-{}'.format(i),round(month_pay1,2),round(month_principal1,2),round(month_interest1,2),round(sum_month_pay1,2), round(sum_month_principal1,2),abs(round(mod_principal1,2)),round(sum_month_interest1,2)] 
        row2=['金-{}'.format(i),round(month_pay2,2),round(month_principal2,2),round(month_interest2,2),round(sum_month_pay2,2), round(sum_month_principal2,2),abs(round(mod_principal2,2)),round(sum_month_interest2,2)]
        if pay_way==1 :tb.add_row(row1)
        if pay_way==2 :tb.add_row(row2)
        if before_pay_dict.keys().__contains__(i): tb.add_row(["---", "---", "---","---","---","---","---","---"])      
        if remaining_periods==0:break #已全部还完
if pay_way==1 and mod_principal1<=0:break
if pay_way==2 and mod_principal2<=0:break
    print(tb)  

if __name__ == "__main__":
    
    pay_way = 1 #还款方式:1为等额本息,2为等额本金
    before_pay_dict={
        4:10000, #提前还款期数:提前还款金额
        5:30000,
        8:80000,
    }

    mainv2(50,15,pay_way,before_pay_dict) #提前还款,月供不变,还款期数减少
    main(50,15,pay_way,before_pay_dict)   #提前还款,月供减少,还款期数不变
+-------+----------+----------+----------+-----------+------------+--------------+------------+
| 期数  | 月还款   | 还款本金 | 还款利息 | 总还款    | 总还款本金 | 剩余还款本金 | 总还款利息 |
+-------+----------+----------+----------+-----------+------------+--------------+------------+
| 金-1  | 34937.5  | 33333.33 | 1604.17  | 34937.5   | 33333.33   | 466666.67    | 1604.17    |
| 金-2  | 34830.56 | 33333.33 | 1497.22  | 69768.06  | 66666.67   | 433333.33    | 3101.39    |
| 金-3  | 34723.61 | 33333.33 | 1390.28  | 104491.67 | 100000.0   | 400000.0     | 4491.67    |
| 金-4  | 34616.67 | 43333.33 | 1283.33  | 149108.33 | 143333.33  | 356666.67    | 5775.0     |
| ---   | ---      | ---      | ---      | ---       | ---        | ---          | ---        |
| 金-5  | 36810.97 | 65666.67 | 1144.31  | 215919.31 | 209000.0   | 291000.0     | 6919.31    |
| ---   | ---      | ---      | ---      | ---       | ---        | ---          | ---        |
| 金-6  | 37308.62 | 36375.0  | 933.62   | 253227.93 | 245375.0   | 254625.0     | 7852.93    |
| 金-7  | 37191.92 | 36375.0  | 816.92   | 290419.85 | 281750.0   | 218250.0     | 8669.85    |
| 金-8  | 37075.22 | 116375.0 | 700.22   | 407495.07 | 398125.0   | 101875.0     | 9370.07    |
| ---   | ---      | ---      | ---      | ---       | ---        | ---          | ---        |
| 金-9  | 34285.18 | 33958.33 | 326.85   | 441780.25 | 432083.33  | 67916.67     | 9696.92    |
| 金-10 | 34176.23 | 33958.33 | 217.9    | 475956.49 | 466041.67  | 33958.33     | 9914.82    |
| 金-11 | 34067.28 | 33958.33 | 108.95   | 510023.77 | 500000.0   | 0.0          | 10023.77   |
+-------+----------+----------+----------+-----------+------------+--------------+------------+
+-------+----------+-----------+----------+-----------+------------+--------------+------------+
| 期数  | 月还款   | 还款本金  | 还款利息 | 总还款    | 总还款本金 | 剩余还款本金 | 总还款利息 |
+-------+----------+-----------+----------+-----------+------------+--------------+------------+
| 金-1  | 34937.5  | 33333.33  | 1604.17  | 34937.5   | 33333.33   | 466666.67    | 1604.17    |
| 金-2  | 34830.56 | 33333.33  | 1497.22  | 69768.06  | 66666.67   | 433333.33    | 3101.39    |
| 金-3  | 34723.61 | 33333.33  | 1390.28  | 104491.67 | 100000.0   | 400000.0     | 4491.67    |
| 金-4  | 34616.67 | 43333.33  | 1283.33  | 149108.33 | 143333.33  | 356666.67    | 5775.0     |
| ---   | ---      | ---       | ---      | ---       | ---        | ---          | ---        |
| 金-5  | 33568.55 | 62424.24  | 1144.31  | 212676.88 | 205757.58  | 294242.42    | 6919.31    |
| ---   | ---      | ---       | ---      | ---       | ---        | ---          | ---        |
| 金-6  | 30368.27 | 29424.24  | 944.03   | 243045.15 | 235181.82  | 264818.18    | 7863.33    |
| 金-7  | 30273.87 | 29424.24  | 849.62   | 273319.02 | 264606.06  | 235393.94    | 8712.96    |
| 金-8  | 30179.46 | 109424.24 | 755.22   | 383498.48 | 374030.3   | 125969.7     | 9468.18    |
| ---   | ---      | ---       | ---      | ---       | ---        | ---          | ---        |
| 金-9  | 18399.82 | 17995.67  | 404.15   | 401898.31 | 392025.97  | 107974.03    | 9872.33    |
| 金-10 | 18342.09 | 17995.67  | 346.42   | 420240.4  | 410021.65  | 89978.35     | 10218.75   |
| 金-11 | 18284.35 | 17995.67  | 288.68   | 438524.75 | 428017.32  | 71982.68     | 10507.43   |
| 金-12 | 18226.62 | 17995.67  | 230.94   | 456751.36 | 446012.99  | 53987.01     | 10738.37   |
| 金-13 | 18168.88 | 17995.67  | 173.21   | 474920.24 | 464008.66  | 35991.34     | 10911.58   |
| 金-14 | 18111.14 | 17995.67  | 115.47   | 493031.38 | 482004.33  | 17995.67     | 11027.06   |
| 金-15 | 18053.41 | 17995.67  | 57.74    | 511084.79 | 500000.0   | 0.0          | 11084.79   |
+-------+----------+-----------+----------+-----------+------------+--------------+------------+

  

 

 posted on 2024-03-27 14:25  boye169  阅读(4)  评论(0编辑  收藏  举报