【Web_接口测试_Python3_房贷还款公式】正常还款/提前还款/逾期还款,本金/利息/罚息/复利,常用公式封装模板,20210201

#!/usr/bin/env/python3
# -*- coding:utf-8 -*-
'''
Author:leo
Date&Time:2021/02/01 and 11:15
Project:Python3
FileName:Repay_formula
Description:...
还款方式:等额本息
1.提前还款:
    提前还款违约金=剩余本金(包含当期)*违约金利率  --2021.02.01
2.正常还款(首期):
    首期利息=剩余本金*日利率*首期实际天数,首期本金=等额本息的本金
    中期利息=本金*年利率/12*月份=四舍五入(保留2位,第三位四舍五入)
    末期利息=本金*年利率/12*月份=四舍五入(保留2位,第三位四舍五入)
    -2021.02.01
3.逾期还款:
    逾期违约金=当期逾期本金*产品年利率/360*1.5*逾期天数  --2021.02.01
4.罚息复利:
    复利=利息*逾期天数*产品年利率/360*1.5
'''
import time, random
nowTime = time.strftime('%Y-%m-%d %H-%M-%S', time.localtime(time.time()))
nowdate, nowtime, random_number = nowTime.split(" ")[0], nowTime.split(" ")[1], str(random.randint(100, 999))
class Repay_formula():
    # 结果保留2位(截位保存)
    def cut(self, num):
        tmp = str(num)
        tmp = tmp.split('.')
        num = tmp[0]+'.'+tmp[1][:2]
        return float(num)

    # 结果四舍五入(避免python55原则)
    def tmp_round(self, num, weight):
        # if len(str(num).split('.')[1]) <= weight:
        #     num = float(num) + 0.00000001
        #     print("round长度错误", num)
        tmp = str(float(num) + 0.00000001)
        print(tmp)
        tmp = tmp.split('.')
        if int(tmp[1][weight]) < 5:
            num = tmp[0]+'.'+tmp[1][:weight]
            num = float(num)
            print(num)
        elif int(tmp[1][weight]) >= 5:
            num = tmp[0]+'.'+tmp[1][:weight]
            num = float(num) + pow(0.1, weight)
            print(num)
        return num

    #  当期实际天数(到期年月日-当前年月日)
    def date_diff(self, s_date=None, e_date=None):
        '''
        datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
        return:12
        @param s_date: 开始时间
        @param e_date: 结束时间
        @return:
        '''
        import datetime
        now = datetime.datetime.now().strftime('%Y-%m-%d')
        start_date = datetime.datetime.strptime(s_date, '%Y-%m-%d')
        end_date = datetime.datetime.strptime(e_date, '%Y-%m-%d')
        delta = end_date - start_date
        # print(delta.days)
        return delta.days

    # 下一期还款日(传入月份+1个月)
    def month_add(self, Original_date='-2021.02.01', add_num=1):
        '''
        relativedelta(years=+2, months=+8, days=+16,hours=+20, minutes=+54, seconds=+47)
        return:-2021.02.01 00:00:00
        '''
        import datetime
        from dateutil.relativedelta import relativedelta
        sdate  = datetime.datetime.strptime(Original_date, '%Y-%m-%d')
        edate  = str(sdate + relativedelta(months=add_num)).split(" ")[0]
        # print(edate)
        return edate
    
    #借款人等额本息
    def dengebenxiJ(self, principal,apr,Installments,s_date=str(nowdate),e_date='-2021.02.01'):
        """
        @param principal: 本金
        @param apr: 年利率
        @param Installments:期数
        @param s_date: 放款日期
        @param e_date: 首期还款日
        @return:
        """
        apr = apr/100.00
        yishou, count, count1, count2, m_list = 0, 0, 0, 0, []
        month_apr, day_apr = round(apr/12, 6), round(apr/360, 6)
        tmp = pow((1+month_apr), Installments)
        month_m = round((principal * month_apr * tmp)/(tmp-1), 3)  # 月供本息
        month_b = round(month_m-(principal*month_apr))  # 月供本金
        start_diff_date = Repay_formula().date_diff(s_date=s_date, e_date=e_date)
        print(f"----等额本息还款金额计算{s_date},{e_date}----\n本金:%s, 年利率:%s, 期数: %s, 月利率: %s, 日利率: %s" % (principal, apr, Installments, month_apr, day_apr))
        print(f"首月天数:{start_diff_date}, 每月月供额:{month_m}, 每日利息({round(principal-yishou)}*{day_apr})={round((principal-yishou) * day_apr, 7)}")
        for i in range(Installments):
            if i == Installments-1:
                # 日利息
                plan_interest = round((((principal-yishou) * day_apr)*int(Repay_formula().date_diff(s_date=s_date, e_date=e_date))), 2)
                month_interest = (principal-yishou)*month_apr  # 等额利息month_interest
                s_date = e_date
                e_date = Repay_formula().month_add(Original_date=s_date, add_num=1)
                end_diff_date = Repay_formula().date_diff(s_date=s_date, e_date=e_date)
                self.month_principal = round(principal - yishou, 2)
                count = count+self.month_principal+month_interest
                count1 = count1+self.month_principal
                count2 = count2+month_interest
                print("借款人第 %s 期,月供:%0.2f,应还本金:%0.2f,等额利息:%0.2f,天数利息:%0.2f" % (i+1, round(self.month_principal+month_interest, 2), self.month_principal, month_interest, plan_interest))
                print(f"末月天数:{end_diff_date}, 每月月供额:{month_m}, 每日利息({self.month_principal}*{day_apr})={round(self.month_principal * day_apr, 7)}")
                print("待还总额:%s,待还总金:%0.2f,待还总息:%0.2f" % (round(count, 3), round(count1, 3), round(count2, 3)))
            else:
                if i == 0:
                    # month_interest = round((((principal-yishou) * day_apr)*int(Repay_formula().date_diff(s_date=s_date, e_date=e_date)-30)), 3) + round(((principal-yishou) * month_apr)*1, 2)  # 首月月供利息:剩余本金*日利率*天数(大于30的天数)+剩余本金*月利率*1(舍弃)
                    month_interest = round((((principal-yishou) * day_apr)*int(Repay_formula().date_diff(s_date=s_date, e_date=e_date))), 2)
                    s_date = e_date
                    e_date = Repay_formula().month_add(Original_date=s_date, add_num=1)
                    plan_interest = (principal-yishou)*month_apr  # 等额利息
                    self.month_principal = round(month_m-((principal-yishou)*month_apr), 2)
                    print("借款人第 %2s 期,月供:%0.2f,应还本金:%0.2f,天数利息:%0.2f,等额利息:%0.2f" % (i+1, round(self.month_principal+month_interest, 2), self.month_principal, month_interest, plan_interest))
                else:
                    month_interest = round(((principal-yishou) * month_apr), 2)    # 月供利息:剩余本金*月利率
                    s_date = e_date
                    e_date = Repay_formula().month_add(Original_date=s_date, add_num=1)
                    self.month_principal = round(month_m-month_interest, 2)
                    print("借款人第 %2s 期,月供:%0.2f,应还本金:%0.2f,等额利息:%0.2f" % (i+1, round(self.month_principal+month_interest, 2), self.month_principal, month_interest))
                yishou = yishou + round(self.month_principal, 2)
                count = count+round(self.month_principal+month_interest, 2)
                count1 = count1+round(self.month_principal, 2)
                count2 = count2+round(month_interest, 2)

            m_list.append([i+1, self.month_principal, month_interest])  #  [[1, 337.65, 6.4], [2, 333.46, 10.59], [3, 328.9, 5.26]]
        print("\n还款计划列表:", m_list)
        return m_list
    
    # 提前还款违约金
    def early_repay(self, Residual_principal, curr_stage=1):
        """
        @param Residual_principal: 剩余本金
        @param month_principal: 当期本金
        @param curr_stage: 第几期
        @param early_apr: 提前还款利率
        @return:
        """
        ''' 提前还款违约金 = 剩余本金(含当期)*3% '''
        if curr_stage < 6:
            early_apr = 0.05
        elif curr_stage >= 6:
            early_apr = 0.03
        early_repay_money = Residual_principal * early_apr
        print(f"提前违约金({Residual_principal}*{early_apr}):{early_repay_money}")
        return early_repay_money
    # 逾期违约金
    def overdue_repay(self, overdue_principal=None, overdue_interest=None, overdue_days=None, overdue_apr=None, apr=None):
        """
        ''' 逾期还款:当期逾期违约金=(当期逾期本金*逾期费率)保留2位*逾期天数 --2021.02.01'''#2021.02.01,产品费用规则,逾期费用类型,一次性,当期本金*费率;按日累计,当期本金*费率*逾期天数
        ''' 逾期还款:当期复利=当期逾期罚息*逾期天数*产品年利率/360*1.5 --2021.02.01 '''
        @param overdue_principal: 当期逾期本金
        @param overdue_interest: 当期逾期利息
        @param overdue_days: 当期逾期天数
        @param overdue_apr: 逾期费率
        @param apr: 年利率,需要/100
        @return:
        """
        overdue_total_wyj = round(overdue_principal * overdue_apr, 3)  # 一次性违约金
        overdue_day_wyj = round(overdue_principal * overdue_apr * overdue_days, 3)  # 日累计违约金
        overdue_fx = round(overdue_principal * round(apr/100/360 * 1.5, 6) * overdue_days, 3)  # 罚息
        overdue_fl = round(overdue_interest * round(apr/100/360 * 1.5, 6) * overdue_days, 3)   # 复利
        print(f"一次违约金({overdue_principal} * {overdue_apr}, 3):", str(overdue_total_wyj))
        print(f"按日违约金({overdue_principal} * {overdue_apr} * {overdue_days}, 3):", str(overdue_day_wyj))
        print(f"逾期的罚息({overdue_principal} * round({apr}/100/360 * 1.5, 6)* {overdue_days}, 3):", str(overdue_fx))
        print(f"逾期的复利({overdue_interest} * round({apr}/100/360 * 1.5, 6) * {overdue_days}, 3):", str(overdue_fl))
        return overdue_total_wyj, overdue_day_wyj, overdue_fx, overdue_fl
    # 摊销费用
    def tx_feiyong(self,benjin):
        # 首次还款:放款本金*0.03
        # 还款:放款本金*0.03/24+实际分期手续费*0.05
        tx_first = benjin * 0.03
        tx_repay = (benjin * 0.03/24) + (benjin * 0.23/24*0.05)
        print("\n首次还款:", tx_first)
        print("\n还款:", tx_repay)

if __name__ == "__main__":
    early_money = Repay_formula().early_repay(Residual_principal=200000, curr_stage=1)  # 提前还款
    onece_wyj, day_wyj, faxi, fuli = Repay_formula().overdue_repay(overdue_principal=7118.82, overdue_interest=2683.40, overdue_days=9, overdue_apr=0.005, apr=16.1)  # 当期应还本金
    Repay_formula().dengebenxiJ(150000.00, 16.1, 12, s_date='2021.02.01', e_date='2021.02.01')  # 等额本息
    print("总额(本金+手续费+违约金):", day_wyj+faxi+fuli)

 

猜你喜欢

转载自blog.csdn.net/denzeleo/article/details/106982307