`

借呗提前还款算法模拟

 
阅读更多
/**
 * 阿里借呗计息还款规则说明实现
 * 
 * 测试阿里案例和韩哥案例通过
 * @return
 */
package jdongtech.jiebaiUtils;

import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

import jdongtech.interestUtils.AverageCapitalPlusInterestUtils;

public class advanceRepayMore {
	public static void main(String[] args) {

		Calendar lendDay = Calendar.getInstance(); // 借款日期
		Calendar rebackDay = Calendar.getInstance();// 还款日期
		double rebackInvest = 0; // 还款金额
		double invest = 0; // 借款本金
		int month = 0; // 期数
		double yearRate = 0; // 年利率
		int acctOffsetDay = 15; // 平移日期
		int accountDay = 25; // 账单日,蚂蚁会把账单日设置成借款当日

		// 文件示例
		lendDay.set(Calendar.MONTH, 9);
		lendDay.set(Calendar.DAY_OF_MONTH, 13);
		rebackInvest = 100.24;
		// rebackInvest = 60.04;
		rebackDay.set(Calendar.MONTH, 9);
		rebackDay.set(Calendar.DAY_OF_MONTH, 14);
		invest = 1200; // 本金
		month = 12; // 期数
		yearRate = 7.2 / 100; // 年利率
		acctOffsetDay = 15;
		accountDay = 25;

		// 韩哥示例
		lendDay.set(Calendar.MONTH, 4);
		lendDay.set(Calendar.DAY_OF_MONTH, 13);
		rebackInvest = 60.04;
		rebackDay.set(Calendar.MONTH, 4);
		rebackDay.set(Calendar.DAY_OF_MONTH, 13);
		invest = 120; // 本金
		month = 6; // 期数
		yearRate = 14.4 / 100; // 年利率
		acctOffsetDay = 15;
		accountDay = 13; // 账单日,蚂蚁会把账单日设置成借款当日

		double dateRate = yearRate / 360;
		int[] daysCount = new int[month];
		int IncreaseFlag = 0;
		Calendar lendCalOffset = (Calendar) lendDay.clone();
		lendCalOffset.add(Calendar.DATE, acctOffsetDay);
		Calendar accCal = (Calendar) lendDay.clone();
		accCal.set(Calendar.DAY_OF_MONTH, accountDay);
		Calendar accCalBegin = (Calendar) accCal.clone();
		if (lendCalOffset.before(accCal)) {
		} else {
			accCalBegin.add(Calendar.MONTH, 1);
			IncreaseFlag = 1;
		}
		Calendar accCalEnd = (Calendar) accCal.clone();
		accCalEnd.add(Calendar.MONTH, month - 1);

		System.out.println(lendDay.getTime() + "借款日期");
		System.out.println(accCalBegin.getTime() + "开始");
		System.out.println(accCalEnd.getTime() + "结束");
		int daysLending = RepayUtils.daysOffset(lendDay, accCalEnd);
		System.out.println("借款经历" + daysLending + "天");

		Calendar accCalPerEnd = (Calendar) accCalBegin.clone();
		for (int i = 0; i < month; i++) {
			Calendar accCalPerBeg;
			if (i == 0) {
				accCalPerBeg = (Calendar) lendDay.clone();
			} else {
				accCalPerBeg = (Calendar) accCalPerEnd.clone();
				accCalPerBeg.add(Calendar.MONTH, -1);
			}

			int daysPer = RepayUtils.daysOffset(accCalPerBeg, accCalPerEnd);
			daysCount[i] = daysPer;
			accCalPerEnd.add(Calendar.MONTH, 1);
		}

		System.out.println("部分还款前计划:");
		normalRepay.getPerMonthPrincipalInterestBig(invest, dateRate, month, daysCount, IncreaseFlag);

		System.out.println("提前还款日期:" + rebackDay.getTime());
		int curPeriod = 0;
		int daysCurPeriod = RepayUtils.daysOffset(lendDay, rebackDay);
		for (int i = 0; i < daysCount.length; i++) {
			daysCurPeriod = daysCurPeriod - daysCount[i];
			if (daysCurPeriod <= 0) { // 账单日算当前期
				curPeriod = i;
				daysCurPeriod = daysCurPeriod + daysCount[i];
				i = daysCount.length;
			}
		}
		System.out.println("提前还款当期期数:" + curPeriod);
		System.out.println("提前还款当期天数:" + daysCurPeriod);
		System.out.println("部分还款后计划:");
		getPerMonthPrincipalInterestBigRebackSome(invest, dateRate, month, daysCount, IncreaseFlag, rebackInvest,
				curPeriod, daysCurPeriod);
	}

	/**
	 * 计算实际等额本息每月额度
	 * 
	 * @return
	 */
	public static double getPerMonthPrincipalInterestBigRebackSome(double invest, double dateRate, int totalmonth,
			int[] daysCount, int IncreaseFlag, double rebackInvest, int curPeriod, int daysCurPeriod) {
		IncreaseFlag = 1;
		if (daysCurPeriod == 0) {
			daysCurPeriod = 1;
		}
		double perMonthStandard = AverageCapitalPlusInterestUtils.getPerMonthPrincipalInterest(invest, dateRate * 360,
				totalmonth);

		double perMonthMax = perMonthStandard * 1.01;
		double[] PRperMonth = new double[totalmonth];
		double[] PperMonth = new double[totalmonth];
		double[] RperMonth = new double[totalmonth];
		double[] PLeftperMonth = new double[totalmonth];
		Map<Double, Double> lastCheckMap = new HashMap<Double, Double>();
		Map<Double, double[]> PLeftperMonthMap = new HashMap<Double, double[]>();
		Map<Double, double[]> PRperMonthMap = new HashMap<Double, double[]>();
		Map<Double, double[]> PperMonthMap = new HashMap<Double, double[]>();
		Map<Double, double[]> RperMonthMap = new HashMap<Double, double[]>();
		Map<Double, Double> sumPRMap = new HashMap<Double, Double>();
		Map<Double, Double> sumPMap = new HashMap<Double, Double>();
		Map<Double, Double> sumRMap = new HashMap<Double, Double>();

		if (IncreaseFlag == 1) {
			while (perMonthStandard < perMonthMax) {
				PRperMonth = new double[totalmonth];
				PperMonth = new double[totalmonth];
				RperMonth = new double[totalmonth];
				PLeftperMonth = new double[totalmonth];

				PRperMonth[0] = RepayUtils.num2second(perMonthStandard);
				PLeftperMonth[0] = RepayUtils.num2second(invest);
				RperMonth[0] = RepayUtils.num2secondDown(PLeftperMonth[0] * daysCount[0] * dateRate);
				PperMonth[0] = RepayUtils.num2second(PRperMonth[0] - RperMonth[0]);
				for (int j = 1; j < totalmonth; j++) {
					PRperMonth[j] = RepayUtils.num2second(perMonthStandard);
					PLeftperMonth[j] = RepayUtils.num2second(PLeftperMonth[j - 1] - PperMonth[j - 1]);
					RperMonth[j] = RepayUtils.num2secondDown(PLeftperMonth[j] * dateRate * daysCount[j]);
					PperMonth[j] = RepayUtils.num2second(PRperMonth[j] - RperMonth[j]);
					if (j == totalmonth - 1) {
						PperMonth[j] = RepayUtils.num2second(PLeftperMonth[j]);
						PRperMonth[j] = RepayUtils.num2second(PperMonth[j] + RperMonth[j]);
					}
				}
				double sumP = 0;
				double sumR = 0;
				double sumPR = 0;
				for (int i = 0; i < PLeftperMonth.length; i++) {
					sumP = sumP + PperMonth[i];
					sumR = sumR + RperMonth[i];
					sumPR = sumPR + PRperMonth[i];
				}
				lastCheckMap.put(RepayUtils.num2second(perMonthStandard),
						Math.abs(PRperMonth[totalmonth - 1] - PRperMonth[totalmonth - 2]));
				PLeftperMonthMap.put(RepayUtils.num2second(perMonthStandard), PLeftperMonth);
				PRperMonthMap.put(RepayUtils.num2second(perMonthStandard), PRperMonth);
				PperMonthMap.put(RepayUtils.num2second(perMonthStandard), PperMonth);
				RperMonthMap.put(RepayUtils.num2second(perMonthStandard), RperMonth);
				sumPRMap.put(RepayUtils.num2second(perMonthStandard), RepayUtils.num2second(sumPR));
				sumPMap.put(RepayUtils.num2second(perMonthStandard), RepayUtils.num2second(sumP));
				sumRMap.put(RepayUtils.num2second(perMonthStandard), RepayUtils.num2second(sumR));

				perMonthStandard = perMonthStandard + 0.01;
			}
		}

		Double resultKey = RepayUtils.getKeyByMinValue(lastCheckMap);
		// 当期剩余天数
		int remainDaysCurPeriod = daysCount[curPeriod] - daysCurPeriod;
		double rebackPCurPeriod = RepayUtils.num2second(
				rebackInvest - RepayUtils.num2secondDown(PLeftperMonth[curPeriod] * dateRate * daysCurPeriod));

		if (rebackPCurPeriod < PperMonthMap.get(resultKey)[curPeriod]) { // 还款小于当前期本金
			PLeftperMonthMap.get(resultKey)[curPeriod] = RepayUtils
					.num2second(PLeftperMonthMap.get(resultKey)[curPeriod] - rebackPCurPeriod);
			PperMonthMap.get(resultKey)[curPeriod] = RepayUtils
					.num2second(PperMonthMap.get(resultKey)[curPeriod] - rebackPCurPeriod);
			RperMonthMap.get(resultKey)[curPeriod] = RepayUtils
					.num2secondDown(PLeftperMonthMap.get(resultKey)[curPeriod] * dateRate * remainDaysCurPeriod);
			PRperMonthMap.get(resultKey)[curPeriod] = RepayUtils
					.num2second(RperMonthMap.get(resultKey)[curPeriod] + PperMonthMap.get(resultKey)[curPeriod]);

			System.out.println("等额本息每月还款额:" + resultKey);
			System.out.println("每期经历" + Arrays.toString(daysCount));
			System.out.println("每月余本金:" + Arrays.toString(PLeftperMonthMap.get(resultKey)));
			System.out.println("每月还款额:" + Arrays.toString(PRperMonthMap.get(resultKey)));
			System.out.println("每月还本金:" + Arrays.toString(PperMonthMap.get(resultKey)));
			System.out.println("每月还利息:" + Arrays.toString(RperMonthMap.get(resultKey)));
			double sumP = 0;
			double sumR = 0;
			double sumPR = 0;
			for (int i = 0; i < PLeftperMonth.length; i++) {
				sumP = sumP + PperMonthMap.get(resultKey)[i];
				sumR = sumR + RperMonthMap.get(resultKey)[i];
				sumPR = sumPR + PRperMonthMap.get(resultKey)[i];
			}
			sumPRMap.put(RepayUtils.num2second(resultKey), RepayUtils.num2second(sumPR));
			sumPMap.put(RepayUtils.num2second(resultKey), RepayUtils.num2second(sumP));
			sumRMap.put(RepayUtils.num2second(resultKey), RepayUtils.num2second(sumR));

			System.out.println("总还款额:" + sumPRMap.get(resultKey));
			System.out.println("总还本金:" + sumPMap.get(resultKey));
			System.out.println("总还利息:" + sumRMap.get(resultKey));

		} else { // 还款本金大于当期本金
			int[] dayCountsAfter = new int[totalmonth - curPeriod];
			double[] PRperMonthAfter = new double[totalmonth - curPeriod];
			double[] PperMonthAfter = new double[totalmonth - curPeriod];
			double[] RperMonthAfter = new double[totalmonth - curPeriod];
			double[] PLeftperMonthAfter = new double[totalmonth - curPeriod];

			// P本金0的阶段 第一个月
			double remainInvest = RepayUtils.num2second(PLeftperMonthMap.get(resultKey)[curPeriod] - rebackPCurPeriod);
			PperMonthAfter[0] = RepayUtils.num2second(0);
			PLeftperMonthAfter[0] = remainInvest;
			RperMonthAfter[0] = RepayUtils.num2secondDown(PLeftperMonthAfter[0] * dateRate * remainDaysCurPeriod);
			PRperMonthAfter[0] = RperMonthAfter[0];

			// P本金非0的再平衡阶段
			int remainMonth = totalmonth - curPeriod - 1;
			double perMonthStandardRec = AverageCapitalPlusInterestUtils.getPerMonthPrincipalInterest(remainInvest,
					dateRate * 360, remainMonth);
			int[] daysCountRec = Arrays.copyOfRange(daysCount, curPeriod + 1, totalmonth); // 剩余天数数组
			for (int i = 0; i < remainMonth; i++) {
				dayCountsAfter[i + 1] = daysCountRec[i];
				dayCountsAfter[0] = remainDaysCurPeriod;
			}

			double perMonthMaxRec = perMonthStandardRec * 1.1;
			double[] PRperMonthRec = new double[remainMonth];
			double[] PperMonthRec = new double[remainMonth];
			double[] RperMonthRec = new double[remainMonth];
			double[] PLeftperMonthRec = new double[remainMonth];
			Map<Double, Double> lastCheckMapRec = new HashMap<Double, Double>();
			Map<Double, double[]> PLeftperMonthMapRec = new HashMap<Double, double[]>();
			Map<Double, double[]> PRperMonthMapRec = new HashMap<Double, double[]>();
			Map<Double, double[]> PperMonthMapRec = new HashMap<Double, double[]>();
			Map<Double, double[]> RperMonthMapRec = new HashMap<Double, double[]>();
			while (perMonthStandardRec < perMonthMaxRec) {
				PRperMonthRec = new double[remainMonth];
				PperMonthRec = new double[remainMonth];
				RperMonthRec = new double[remainMonth];
				PLeftperMonthRec = new double[remainMonth];

				PRperMonthRec[0] = RepayUtils.num2second(perMonthStandardRec);
				PLeftperMonthRec[0] = RepayUtils.num2second(remainInvest);
				RperMonthRec[0] = RepayUtils.num2secondDown(PLeftperMonthRec[0] * daysCountRec[0] * dateRate);
				PperMonthRec[0] = RepayUtils.num2second(PRperMonthRec[0] - RperMonthRec[0]);
				for (int j = 1; j < remainMonth; j++) {
					PRperMonthRec[j] = RepayUtils.num2second(perMonthStandardRec);
					PLeftperMonthRec[j] = RepayUtils.num2second(PLeftperMonthRec[j - 1] - PperMonthRec[j - 1]);
					RperMonthRec[j] = RepayUtils.num2secondDown(PLeftperMonthRec[j] * dateRate * daysCountRec[j]);
					PperMonthRec[j] = RepayUtils.num2second(PRperMonthRec[j] - RperMonthRec[j]);
					if (j == remainMonth - 1) {
						PperMonthRec[j] = RepayUtils.num2second(PLeftperMonthRec[j]);
						PRperMonthRec[j] = RepayUtils.num2second(PperMonthRec[j] + RperMonthRec[j]);
					}
				}

				lastCheckMapRec.put(RepayUtils.num2second(perMonthStandardRec),
						Math.abs(PRperMonthRec[remainMonth - 1] - PRperMonthRec[remainMonth - 2]));

				PLeftperMonthMapRec.put(RepayUtils.num2second(perMonthStandardRec), PLeftperMonthRec);
				PRperMonthMapRec.put(RepayUtils.num2second(perMonthStandardRec), PRperMonthRec);
				PperMonthMapRec.put(RepayUtils.num2second(perMonthStandardRec), PperMonthRec);
				RperMonthMapRec.put(RepayUtils.num2secondDown(perMonthStandardRec), RperMonthRec);
				perMonthStandardRec = perMonthStandardRec + 0.01;
			}

			Double resultKeyRec = RepayUtils.getKeyByMinValue(lastCheckMapRec);

			for (int i = 1; i < totalmonth; i++) {
				PperMonthAfter[i] = RepayUtils.num2second(PperMonthMapRec.get(resultKeyRec)[i - 1]);
				PLeftperMonthAfter[i] = RepayUtils.num2second(PLeftperMonthMapRec.get(resultKeyRec)[i - 1]);
				RperMonthAfter[i] = RepayUtils.num2second(RperMonthMapRec.get(resultKeyRec)[i - 1]);
				PRperMonthAfter[i] = RepayUtils.num2second(PRperMonthMapRec.get(resultKeyRec)[i - 1]);
			}

			System.out.println("重新等额本息每月还款额:" + resultKeyRec);
			System.out.println("重新每期经历" + Arrays.toString(dayCountsAfter));
			System.out.println("重新每月余本金:" + Arrays.toString(PLeftperMonthAfter));
			System.out.println("重新每月还款额:" + Arrays.toString(PRperMonthAfter));
			System.out.println("重新每月还本金:" + Arrays.toString(PperMonthAfter));
			System.out.println("重新每月还利息:" + Arrays.toString(RperMonthAfter));

			double sumP = 0;
			double sumR = 0;
			double sumPR = 0;
			for (int i = 0; i < PLeftperMonth.length; i++) {
				sumP = sumP + PperMonthAfter[i];
				sumR = sumR + RperMonthAfter[i];
				sumPR = sumPR + PRperMonthAfter[i];
			}
			sumPRMap.put(RepayUtils.num2second(resultKey), RepayUtils.num2second(sumPR));
			sumPMap.put(RepayUtils.num2second(resultKey), RepayUtils.num2second(sumP));
			sumRMap.put(RepayUtils.num2second(resultKey), RepayUtils.num2second(sumR));

			System.out.println("总还款额:" + sumPRMap.get(resultKey));
			System.out.println("总还本金:" + sumPMap.get(resultKey));
			System.out.println("总还利息:" + sumRMap.get(resultKey));
		}
		return resultKey;
	}

}
分享到:
评论

相关推荐

    最全房贷计算器 java 代码 含算法

    提前还款涉及到的算法则更为复杂,因为需要重新计算剩余贷款的利息和还款计划。通常,提前还款可以减少总的利息支出,但可能需要支付一定的手续费。具体计算涉及剩余本金、剩余期限、提前还款金额以及银行对于提前...

    住房与房屋贷款的问题

    通过对各种可能的提前还款时间和金额进行计算,可以找到最经济的提前还款策略。 此外,文章还探讨了投资股票和基金的收益模型,以模拟投资风险和收益的不确定性。通过计算机模拟,可以预测不同投资组合可能带来的...

    matlab开发-计算已标记预付款指标

    然后,可以使用MATLAB的内置函数或者自定义算法来模拟提前还款行为,计算每个时间段内的CPR值。对于SMM,我们可以设置循环结构,逐月计算每笔贷款的还款额,并累加到总还款现金流中。 MATLAB的Financial Toolbox...

    房贷计算器(VB6源码).zip

    3. 提前还款分析:模拟不同提前还款策略,分析节省的利息和缩短的还款期限。 三、房贷计算器核心算法 房贷计算器的核心算法通常采用等额本息还款法,该方法下,每月还款额固定,包括部分本金和剩余贷款的利息。...

    商业银行模拟经营沙盘实验报告.doc

    实验报告详细记录了三年内的各项战略决策,包括贷款、土地分配、建筑、价格设定、广告投放、景观费用、个人消费贷款、存款、提前还款、股票发行和国债购买等,通过对这些决策的分析和评价,评估企业经营效果。...

    房贷利率计算源代码.rar

    5. **提前还款功能**:在代码中,可能会有允许用户预付部分或全部贷款的函数,这会影响到总的利息支出和还款期限。 6. **还款计划生成**:这部分代码将生成详细的还款计划,显示每月的还款额、利息和剩余本金,帮助...

    matlab.rar_matlab贷款

    4. **提前还款**:用户可能希望在贷款期限内提前还清部分或全部贷款,MATLAB 可以帮助计算提前还款后的节省利息和新的还款计划。 5. **利率变动影响**:对于浮动利率贷款,MATLAB 可以用于模拟未来利率变化对贷款...

    Housing-loan-simulator:这是在一定条件下模拟房屋贷款

    - **提前还款**:用户可以模拟提前还款的情景,查看提前还款后节省的总利息和剩余月数。 - **利率变动**:模拟未来利率变化对贷款成本的影响。 - **货币时间价值**:考虑资金的时间价值,显示现值和未来值的对比。 -...

    房贷计算器

    - **提前还款模拟**:用户可以设定提前还款的金额和时间,看看这将如何影响总的利息支出和还款周期。 - **公积金贷款计算**:除了商业贷款,部分计算器还能处理公积金贷款的计算,考虑到不同的利率和政策。 - **税费...

    復利計算器

    4. **提前还款分析**:对于贷款,用户可以查看提前还款对总利息支出的影响。 在实际应用中,"復利計算器"可能还会包含以下特性: - **多种货币选择**:支持不同国家的货币计算,适应全球化投资需求。 - **税率计算*...

    matlab开发-Simplemortgagecalculator

    在MATLAB环境中,"Simplemortgagecalculator"是一个用于计算房贷的简单工具...此外,根据`license.txt`的条款,如果允许,可以将这个工具作为基础,扩展为更复杂的房贷计算器,比如加入提前还款、利率变动等复杂功能。

    数学建模模型案例解析-住房贷款的数学模型.zip

    最后,通过数据分析和优化算法(如线性规划、动态规划等),模型可以找到最优的贷款策略,这可能包括最佳贷款期限、最优初始利率、最合理的提前还款时间点等。 总结来说,数学建模在住房贷款问题中扮演了关键角色,...

    不良贷款问题

    数学建模是应用数学的一种方法,它利用数学工具和理论来模拟真实世界的问题,以便进行预测、决策和理解复杂系统。 首先,我们来了解什么是不良贷款。在银行术语中,不良贷款指的是那些借款人无法按时偿还本金或利息...

    mortgage-plan

    3. 提前还款:抵押贷款可能允许提前还款,C#可以设计一个模块来模拟提前还款的影响,包括节省的利息和可能的罚款计算。 四、C#的金融库与框架 在C#生态系统中,有多个金融计算相关的库和框架,如NodaTime用于处理...

    商业银行大数据审计的应用模式体系.docx

    审计人员依据专家的经验和对业务的理解,构建模型来检测潜在的风险点,例如,可能通过分析贷款客户的信用评分、还款记录等数据,预测违约风险,从而提前采取防范措施。 在实际操作中,审计人员会结合各种模型,根据...

    我应该偿还学生贷款吗?:计算偿还债务的效用。-matlab开发

    通过迭代方法,我们可以逐步更新贷款余额,考虑利息的积累,以及可能的额外还款或提前还款,以预测未来的贷款状况。迭代计算允许我们模拟不同场景,比如调整利率、还款期和每月还款额,以找出最佳的偿还策略。 ...

    HomeRoom-RetirePlanning:基本的前端贷款计算器

    3. **提前还款分析**:允许用户模拟提前还款的情况,计算出提前还款节省的总利息和剩余的贷款余额。 4. **退休储蓄规划**:根据用户的收入、支出和预期的退休年龄,为用户提供一个退休储蓄的目标和进度。 5. **...

    CS-Numerical-2011-5-21

    为了有效管理流动性风险,银行可以利用数值模拟技术构建现金流量预测模型,通过对各类资产负债项目现金流变动情况进行仿真模拟,提前识别可能出现的资金缺口,并采取相应措施予以应对。 ### 结语 综上所述,“CS-...

    23-IDEA-p2p.zip 分布式项目p2p金融项目完整版代码

    6. 还款管理:自动扣款、提前还款、逾期处理等功能。 7. 风险控制:实时监控交易数据,预警潜在风险。 五、开发工具 1. IDEA:IntelliJ IDEA,Java开发的集成开发环境,提供强大的代码编辑、调试和版本控制功能。 2...

    数据挖掘技术在信用卡业务中的应用案例分享.docx

    4. 遗传算法:受生物进化启发,通过模拟自然选择过程寻找最优解。在信用卡业务中,可能用于优化信用卡产品设计或定价策略。 综上所述,数据挖掘技术在信用卡业务中扮演着至关重要的角色,它能够帮助金融机构更准确...

Global site tag (gtag.js) - Google Analytics