#!/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)