首页 > 代码库 > 某呗提前还款模拟

某呗提前还款模拟

  1. /** 
  2.  * 阿里借呗计息还款规则说明实现 
  3.  *  
  4.  * 测试阿里案例和韩哥案例通过 
  5.  * @return 
  6.  */  
  7. package jdongtech.jiebaiUtils;  
  8.   
  9. import java.util.Arrays;  
  10. import java.util.Calendar;  
  11. import java.util.HashMap;  
  12. import java.util.Map;  
  13.   
  14. import jdongtech.interestUtils.AverageCapitalPlusInterestUtils;  
  15.   
  16. public class advanceRepayMore {  
  17.     public static void main(String[] args) {  
  18.   
  19.         Calendar lendDay = Calendar.getInstance(); // 借款日期  
  20.         Calendar rebackDay = Calendar.getInstance();// 还款日期  
  21.         double rebackInvest = 0; // 还款金额  
  22.         double invest = 0; // 借款本金  
  23.         int month = 0; // 期数  
  24.         double yearRate = 0; // 年利率  
  25.         int acctOffsetDay = 15; // 平移日期  
  26.         int accountDay = 25; // 账单日,蚂蚁会把账单日设置成借款当日  
  27.   
  28.         // 文件示例  
  29.         lendDay.set(Calendar.MONTH, 9);  
  30.         lendDay.set(Calendar.DAY_OF_MONTH, 13);  
  31.         rebackInvest = 100.24;  
  32.         // rebackInvest = 60.04;  
  33.         rebackDay.set(Calendar.MONTH, 9);  
  34.         rebackDay.set(Calendar.DAY_OF_MONTH, 14);  
  35.         invest = 1200; // 本金  
  36.         month = 12; // 期数  
  37.         yearRate = 7.2 / 100; // 年利率  
  38.         acctOffsetDay = 15;  
  39.         accountDay = 25;  
  40.   
  41.         // 韩哥示例  
  42.         lendDay.set(Calendar.MONTH, 4);  
  43.         lendDay.set(Calendar.DAY_OF_MONTH, 13);  
  44.         rebackInvest = 60.04;  
  45.         rebackDay.set(Calendar.MONTH, 4);  
  46.         rebackDay.set(Calendar.DAY_OF_MONTH, 13);  
  47.         invest = 120; // 本金  
  48.         month = 6; // 期数  
  49.         yearRate = 14.4 / 100; // 年利率  
  50.         acctOffsetDay = 15;  
  51.         accountDay = 13; // 账单日,蚂蚁会把账单日设置成借款当日  
  52.   
  53.         double dateRate = yearRate / 360;  
  54.         int[] daysCount = new int[month];  
  55.         int IncreaseFlag = 0;  
  56.         Calendar lendCalOffset = (Calendar) lendDay.clone();  
  57.         lendCalOffset.add(Calendar.DATE, acctOffsetDay);  
  58.         Calendar accCal = (Calendar) lendDay.clone();  
  59.         accCal.set(Calendar.DAY_OF_MONTH, accountDay);  
  60.         Calendar accCalBegin = (Calendar) accCal.clone();  
  61.         if (lendCalOffset.before(accCal)) {  
  62.         } else {  
  63.             accCalBegin.add(Calendar.MONTH, 1);  
  64.             IncreaseFlag = 1;  
  65.         }  
  66.         Calendar accCalEnd = (Calendar) accCal.clone();  
  67.         accCalEnd.add(Calendar.MONTH, month - 1);  
  68.   
  69.         System.out.println(lendDay.getTime() + "借款日期");  
  70.         System.out.println(accCalBegin.getTime() + "开始");  
  71.         System.out.println(accCalEnd.getTime() + "结束");  
  72.         int daysLending = RepayUtils.daysOffset(lendDay, accCalEnd);  
  73.         System.out.println("借款经历" + daysLending + "天");  
  74.   
  75.         Calendar accCalPerEnd = (Calendar) accCalBegin.clone();  
  76.         for (int i = 0; i < month; i++) {  
  77.             Calendar accCalPerBeg;  
  78.             if (i == 0) {  
  79.                 accCalPerBeg = (Calendar) lendDay.clone();  
  80.             } else {  
  81.                 accCalPerBeg = (Calendar) accCalPerEnd.clone();  
  82.                 accCalPerBeg.add(Calendar.MONTH, -1);  
  83.             }  
  84.   
  85.             int daysPer = RepayUtils.daysOffset(accCalPerBeg, accCalPerEnd);  
  86.             daysCount[i] = daysPer;  
  87.             accCalPerEnd.add(Calendar.MONTH, 1);  
  88.         }  
  89.   
  90.         System.out.println("部分还款前计划:");  
  91.         normalRepay.getPerMonthPrincipalInterestBig(invest, dateRate, month, daysCount, IncreaseFlag);  
  92.   
  93.         System.out.println("提前还款日期:" + rebackDay.getTime());  
  94.         int curPeriod = 0;  
  95.         int daysCurPeriod = RepayUtils.daysOffset(lendDay, rebackDay);  
  96.         for (int i = 0; i < daysCount.length; i++) {  
  97.             daysCurPeriod = daysCurPeriod - daysCount[i];  
  98.             if (daysCurPeriod <= 0) { // 账单日算当前期  
  99.                 curPeriod = i;  
  100.                 daysCurPeriod = daysCurPeriod + daysCount[i];  
  101.                 i = daysCount.length;  
  102.             }  
  103.         }  
  104.         System.out.println("提前还款当期期数:" + curPeriod);  
  105.         System.out.println("提前还款当期天数:" + daysCurPeriod);  
  106.         System.out.println("部分还款后计划:");  
  107.         getPerMonthPrincipalInterestBigRebackSome(invest, dateRate, month, daysCount, IncreaseFlag, rebackInvest,  
  108.                 curPeriod, daysCurPeriod);  
  109.     }  
  110.   
  111.     /** 
  112.      * 计算实际等额本息每月额度 
  113.      *  
  114.      * @return 
  115.      */  
  116.     public static double getPerMonthPrincipalInterestBigRebackSome(double invest, double dateRate, int totalmonth,  
  117.             int[] daysCount, int IncreaseFlag, double rebackInvest, int curPeriod, int daysCurPeriod) {  
  118.         IncreaseFlag = 1;  
  119.         if (daysCurPeriod == 0) {  
  120.             daysCurPeriod = 1;  
  121.         }  
  122.         double perMonthStandard = AverageCapitalPlusInterestUtils.getPerMonthPrincipalInterest(invest, dateRate * 360,  
  123.                 totalmonth);  
  124.   
  125.         double perMonthMax = perMonthStandard * 1.01;  
  126.         double[] PRperMonth = new double[totalmonth];  
  127.         double[] PperMonth = new double[totalmonth];  
  128.         double[] RperMonth = new double[totalmonth];  
  129.         double[] PLeftperMonth = new double[totalmonth];  
  130.         Map<Double, Double> lastCheckMap = new HashMap<Double, Double>();  
  131.         Map<Double, double[]> PLeftperMonthMap = new HashMap<Double, double[]>();  
  132.         Map<Double, double[]> PRperMonthMap = new HashMap<Double, double[]>();  
  133.         Map<Double, double[]> PperMonthMap = new HashMap<Double, double[]>();  
  134.         Map<Double, double[]> RperMonthMap = new HashMap<Double, double[]>();  
  135.         Map<Double, Double> sumPRMap = new HashMap<Double, Double>();  
  136.         Map<Double, Double> sumPMap = new HashMap<Double, Double>();  
  137.         Map<Double, Double> sumRMap = new HashMap<Double, Double>();  
  138.   
  139.         if (IncreaseFlag == 1) {  
  140.             while (perMonthStandard < perMonthMax) {  
  141.                 PRperMonth = new double[totalmonth];  
  142.                 PperMonth = new double[totalmonth];  
  143.                 RperMonth = new double[totalmonth];  
  144.                 PLeftperMonth = new double[totalmonth];  
  145.   
  146.                 PRperMonth[0] = RepayUtils.num2second(perMonthStandard);  
  147.                 PLeftperMonth[0] = RepayUtils.num2second(invest);  
  148.                 RperMonth[0] = RepayUtils.num2secondDown(PLeftperMonth[0] * daysCount[0] * dateRate);  
  149.                 PperMonth[0] = RepayUtils.num2second(PRperMonth[0] - RperMonth[0]);  
  150.                 for (int j = 1; j < totalmonth; j++) {  
  151.                     PRperMonth[j] = RepayUtils.num2second(perMonthStandard);  
  152.                     PLeftperMonth[j] = RepayUtils.num2second(PLeftperMonth[j - 1] - PperMonth[j - 1]);  
  153.                     RperMonth[j] = RepayUtils.num2secondDown(PLeftperMonth[j] * dateRate * daysCount[j]);  
  154.                     PperMonth[j] = RepayUtils.num2second(PRperMonth[j] - RperMonth[j]);  
  155.                     if (j == totalmonth - 1) {  
  156.                         PperMonth[j] = RepayUtils.num2second(PLeftperMonth[j]);  
  157.                         PRperMonth[j] = RepayUtils.num2second(PperMonth[j] + RperMonth[j]);  
  158.                     }  
  159.                 }  
  160.                 double sumP = 0;  
  161.                 double sumR = 0;  
  162.                 double sumPR = 0;  
  163.                 for (int i = 0; i < PLeftperMonth.length; i++) {  
  164.                     sumP = sumP + PperMonth[i];  
  165.                     sumR = sumR + RperMonth[i];  
  166.                     sumPR = sumPR + PRperMonth[i];  
  167.                 }  
  168.                 lastCheckMap.put(RepayUtils.num2second(perMonthStandard),  
  169.                         Math.abs(PRperMonth[totalmonth - 1] - PRperMonth[totalmonth - 2]));  
  170.                 PLeftperMonthMap.put(RepayUtils.num2second(perMonthStandard), PLeftperMonth);  
  171.                 PRperMonthMap.put(RepayUtils.num2second(perMonthStandard), PRperMonth);  
  172.                 PperMonthMap.put(RepayUtils.num2second(perMonthStandard), PperMonth);  
  173.                 RperMonthMap.put(RepayUtils.num2second(perMonthStandard), RperMonth);  
  174.                 sumPRMap.put(RepayUtils.num2second(perMonthStandard), RepayUtils.num2second(sumPR));  
  175.                 sumPMap.put(RepayUtils.num2second(perMonthStandard), RepayUtils.num2second(sumP));  
  176.                 sumRMap.put(RepayUtils.num2second(perMonthStandard), RepayUtils.num2second(sumR));  
  177.   
  178.                 perMonthStandard = perMonthStandard + 0.01;  
  179.             }  
  180.         }  
  181.   
  182.         Double resultKey = RepayUtils.getKeyByMinValue(lastCheckMap);  
  183.         // 当期剩余天数  
  184.         int remainDaysCurPeriod = daysCount[curPeriod] - daysCurPeriod;  
  185.         double rebackPCurPeriod = RepayUtils.num2second(  
  186.                 rebackInvest - RepayUtils.num2secondDown(PLeftperMonth[curPeriod] * dateRate * daysCurPeriod));  
  187.   
  188.         if (rebackPCurPeriod < PperMonthMap.get(resultKey)[curPeriod]) { // 还款小于当前期本金  
  189.             PLeftperMonthMap.get(resultKey)[curPeriod] = RepayUtils  
  190.                     .num2second(PLeftperMonthMap.get(resultKey)[curPeriod] - rebackPCurPeriod);  
  191.             PperMonthMap.get(resultKey)[curPeriod] = RepayUtils  
  192.                     .num2second(PperMonthMap.get(resultKey)[curPeriod] - rebackPCurPeriod);  
  193.             RperMonthMap.get(resultKey)[curPeriod] = RepayUtils  
  194.                     .num2secondDown(PLeftperMonthMap.get(resultKey)[curPeriod] * dateRate * remainDaysCurPeriod);  
  195.             PRperMonthMap.get(resultKey)[curPeriod] = RepayUtils  
  196.                     .num2second(RperMonthMap.get(resultKey)[curPeriod] + PperMonthMap.get(resultKey)[curPeriod]);  
  197.   
  198.             System.out.println("等额本息每月还款额:" + resultKey);  
  199.             System.out.println("每期经历" + Arrays.toString(daysCount));  
  200.             System.out.println("每月余本金:" + Arrays.toString(PLeftperMonthMap.get(resultKey)));  
  201.             System.out.println("每月还款额:" + Arrays.toString(PRperMonthMap.get(resultKey)));  
  202.             System.out.println("每月还本金:" + Arrays.toString(PperMonthMap.get(resultKey)));  
  203.             System.out.println("每月还利息:" + Arrays.toString(RperMonthMap.get(resultKey)));  
  204.             double sumP = 0;  
  205.             double sumR = 0;  
  206.             double sumPR = 0;  
  207.             for (int i = 0; i < PLeftperMonth.length; i++) {  
  208.                 sumP = sumP + PperMonthMap.get(resultKey)[i];  
  209.                 sumR = sumR + RperMonthMap.get(resultKey)[i];  
  210.                 sumPR = sumPR + PRperMonthMap.get(resultKey)[i];  
  211.             }  
  212.             sumPRMap.put(RepayUtils.num2second(resultKey), RepayUtils.num2second(sumPR));  
  213.             sumPMap.put(RepayUtils.num2second(resultKey), RepayUtils.num2second(sumP));  
  214.             sumRMap.put(RepayUtils.num2second(resultKey), RepayUtils.num2second(sumR));  
  215.   
  216.             System.out.println("总还款额:" + sumPRMap.get(resultKey));  
  217.             System.out.println("总还本金:" + sumPMap.get(resultKey));  
  218.             System.out.println("总还利息:" + sumRMap.get(resultKey));  
  219.   
  220.         } else { // 还款本金大于当期本金  
  221.             int[] dayCountsAfter = new int[totalmonth - curPeriod];  
  222.             double[] PRperMonthAfter = new double[totalmonth - curPeriod];  
  223.             double[] PperMonthAfter = new double[totalmonth - curPeriod];  
  224.             double[] RperMonthAfter = new double[totalmonth - curPeriod];  
  225.             double[] PLeftperMonthAfter = new double[totalmonth - curPeriod];  
  226.   
  227.             // P本金0的阶段 第一个月  
  228.             double remainInvest = RepayUtils.num2second(PLeftperMonthMap.get(resultKey)[curPeriod] - rebackPCurPeriod);  
  229.             PperMonthAfter[0] = RepayUtils.num2second(0);  
  230.             PLeftperMonthAfter[0] = remainInvest;  
  231.             RperMonthAfter[0] = RepayUtils.num2secondDown(PLeftperMonthAfter[0] * dateRate * remainDaysCurPeriod);  
  232.             PRperMonthAfter[0] = RperMonthAfter[0];  
  233.   
  234.             // P本金非0的再平衡阶段  
  235.             int remainMonth = totalmonth - curPeriod - 1;  
  236.             double perMonthStandardRec = AverageCapitalPlusInterestUtils.getPerMonthPrincipalInterest(remainInvest,  
  237.                     dateRate * 360, remainMonth);  
  238.             int[] daysCountRec = Arrays.copyOfRange(daysCount, curPeriod + 1, totalmonth); // 剩余天数数组  
  239.             for (int i = 0; i < remainMonth; i++) {  
  240.                 dayCountsAfter[i + 1] = daysCountRec[i];  
  241.                 dayCountsAfter[0] = remainDaysCurPeriod;  
  242.             }  
  243.   
  244.             double perMonthMaxRec = perMonthStandardRec * 1.1;  
  245.             double[] PRperMonthRec = new double[remainMonth];  
  246.             double[] PperMonthRec = new double[remainMonth];  
  247.             double[] RperMonthRec = new double[remainMonth];  
  248.             double[] PLeftperMonthRec = new double[remainMonth];  
  249.             Map<Double, Double> lastCheckMapRec = new HashMap<Double, Double>();  
  250.             Map<Double, double[]> PLeftperMonthMapRec = new HashMap<Double, double[]>();  
  251.             Map<Double, double[]> PRperMonthMapRec = new HashMap<Double, double[]>();  
  252.             Map<Double, double[]> PperMonthMapRec = new HashMap<Double, double[]>();  
  253.             Map<Double, double[]> RperMonthMapRec = new HashMap<Double, double[]>();  
  254.             while (perMonthStandardRec < perMonthMaxRec) {  
  255.                 PRperMonthRec = new double[remainMonth];  
  256.                 PperMonthRec = new double[remainMonth];  
  257.                 RperMonthRec = new double[remainMonth];  
  258.                 PLeftperMonthRec = new double[remainMonth];  
  259.   
  260.                 PRperMonthRec[0] = RepayUtils.num2second(perMonthStandardRec);  
  261.                 PLeftperMonthRec[0] = RepayUtils.num2second(remainInvest);  
  262.                 RperMonthRec[0] = RepayUtils.num2secondDown(PLeftperMonthRec[0] * daysCountRec[0] * dateRate);  
  263.                 PperMonthRec[0] = RepayUtils.num2second(PRperMonthRec[0] - RperMonthRec[0]);  
  264.                 for (int j = 1; j < remainMonth; j++) {  
  265.                     PRperMonthRec[j] = RepayUtils.num2second(perMonthStandardRec);  
  266.                     PLeftperMonthRec[j] = RepayUtils.num2second(PLeftperMonthRec[j - 1] - PperMonthRec[j - 1]);  
  267.                     RperMonthRec[j] = RepayUtils.num2secondDown(PLeftperMonthRec[j] * dateRate * daysCountRec[j]);  
  268.                     PperMonthRec[j] = RepayUtils.num2second(PRperMonthRec[j] - RperMonthRec[j]);  
  269.                     if (j == remainMonth - 1) {  
  270.                         PperMonthRec[j] = RepayUtils.num2second(PLeftperMonthRec[j]);  
  271.                         PRperMonthRec[j] = RepayUtils.num2second(PperMonthRec[j] + RperMonthRec[j]);  
  272.                     }  
  273.                 }  
  274.   
  275.                 lastCheckMapRec.put(RepayUtils.num2second(perMonthStandardRec),  
  276.                         Math.abs(PRperMonthRec[remainMonth - 1] - PRperMonthRec[remainMonth - 2]));  
  277.   
  278.                 PLeftperMonthMapRec.put(RepayUtils.num2second(perMonthStandardRec), PLeftperMonthRec);  
  279.                 PRperMonthMapRec.put(RepayUtils.num2second(perMonthStandardRec), PRperMonthRec);  
  280.                 PperMonthMapRec.put(RepayUtils.num2second(perMonthStandardRec), PperMonthRec);  
  281.                 RperMonthMapRec.put(RepayUtils.num2secondDown(perMonthStandardRec), RperMonthRec);  
  282.                 perMonthStandardRec = perMonthStandardRec + 0.01;  
  283.             }  
  284.   
  285.             Double resultKeyRec = RepayUtils.getKeyByMinValue(lastCheckMapRec);  
  286.   
  287.             for (int i = 1; i < totalmonth; i++) {  
  288.                 PperMonthAfter[i] = RepayUtils.num2second(PperMonthMapRec.get(resultKeyRec)[i - 1]);  
  289.                 PLeftperMonthAfter[i] = RepayUtils.num2second(PLeftperMonthMapRec.get(resultKeyRec)[i - 1]);  
  290.                 RperMonthAfter[i] = RepayUtils.num2second(RperMonthMapRec.get(resultKeyRec)[i - 1]);  
  291.                 PRperMonthAfter[i] = RepayUtils.num2second(PRperMonthMapRec.get(resultKeyRec)[i - 1]);  
  292.             }  
  293.   
  294.             System.out.println("重新等额本息每月还款额:" + resultKeyRec);  
  295.             System.out.println("重新每期经历" + Arrays.toString(dayCountsAfter));  
  296.             System.out.println("重新每月余本金:" + Arrays.toString(PLeftperMonthAfter));  
  297.             System.out.println("重新每月还款额:" + Arrays.toString(PRperMonthAfter));  
  298.             System.out.println("重新每月还本金:" + Arrays.toString(PperMonthAfter));  
  299.             System.out.println("重新每月还利息:" + Arrays.toString(RperMonthAfter));  
  300.   
  301.             double sumP = 0;  
  302.             double sumR = 0;  
  303.             double sumPR = 0;  
  304.             for (int i = 0; i < PLeftperMonth.length; i++) {  
  305.                 sumP = sumP + PperMonthAfter[i];  
  306.                 sumR = sumR + RperMonthAfter[i];  
  307.                 sumPR = sumPR + PRperMonthAfter[i];  
  308.             }  
  309.             sumPRMap.put(RepayUtils.num2second(resultKey), RepayUtils.num2second(sumPR));  
  310.             sumPMap.put(RepayUtils.num2second(resultKey), RepayUtils.num2second(sumP));  
  311.             sumRMap.put(RepayUtils.num2second(resultKey), RepayUtils.num2second(sumR));  
  312.   
  313.             System.out.println("总还款额:" + sumPRMap.get(resultKey));  
  314.             System.out.println("总还本金:" + sumPMap.get(resultKey));  
  315.             System.out.println("总还利息:" + sumRMap.get(resultKey));  
  316.         }  
  317.         return resultKey;  
  318.     }  
  319.   
  320. }  

某呗提前还款模拟