apzl_leasing/calc/com/tenwa/reckon/util/IRRCalculateUtil.java
2018-06-03 22:26:41 +08:00

209 lines
6.4 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.tenwa.reckon.util;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.tenwa.reckon.bean.CalculationCondition;
import com.tenwa.reckon.constant.Scale;
/**
*
* @author SHIHONGFEI
* @version 1.0
* @copyright (C) TENWA 2011
* @date 2011-2-17
* @desc (-list 现金流处理)
*/
public class IRRCalculateUtil {
private static final BigDecimal one = new BigDecimal(1);
private static final BigDecimal second = new BigDecimal(2);
/**
* 计算财务每期的收益率,返回的是年利率。
* 中心思想二分查找irr属于(0,1)
* 然后不断尝试IRR新值直到每一期租金加利息的总和等于本金
*
* @param inflowPour
* 所有现金流入流出
* @param nhkcs
* 年还款次数,年期数
* @return irr
*/
public static BigDecimal getIRR(List<BigDecimal> inflowPour, CalculationCondition cb) {
BigDecimal irr = getIRR(inflowPour).multiply(new BigDecimal(12 / cb.getIssueNumber()));
return irr;
}
/**
* 计算财务每期的收益率,返回的是年利率。
* 中心思想二分查找irr属于(0,1)
* 然后不断尝试IRR新值直到每一期租金加利息的总和等于本金
*
* @param inflowPour
* 所有现金流入流出
* @param nhkcs
* 年还款次数,年期数
* @return irr
*/
public static BigDecimal getIRR(List<BigDecimal> inflowPour, BigDecimal issueMonth) {
return getIRR(inflowPour).multiply(new BigDecimal(12)).divide(issueMonth, Scale.RATE_SCALE, BigDecimal.ROUND_HALF_UP);
}
/**
* 期IRR计算
* @param inflowPour
* @return
*/
public static BigDecimal getIRR2(List<String> inflowPour) {
List<BigDecimal> inflowPourNew = new ArrayList<BigDecimal>();
for(String val : inflowPour){
inflowPourNew.add(new BigDecimal(val));
}
return getIRR(inflowPourNew);
}
/**
* 期IRR计算
* @param inflowPour
* @return
*/
public static BigDecimal getIRR(List<BigDecimal> inflowPour) {
BigDecimal irr = new BigDecimal("0");
BigDecimal tmp1 = new BigDecimal("0");
BigDecimal tmp2 = new BigDecimal("1");
try {
int j = 0;
BigDecimal remain = new BigDecimal("1");
while (remain.abs().doubleValue() > 0.0000000001 && j++ < 200) {
remain = inflowPour.get(0);// 这个是负值,表示本金欠值
for (int i = 1; i < inflowPour.size(); i++) {
// 本金=租金/(1+irr)i次方本金一直加
remain = remain.add(inflowPour.get(i).divide(irr.add(one).pow(i), 20, BigDecimal.ROUND_HALF_UP));
}
if (remain.doubleValue() > 0) {
// 剩余租金 >0irr小了
tmp1 = irr;
irr = irr.add(tmp2).divide(second, 20, BigDecimal.ROUND_HALF_UP);
} else if (remain.doubleValue() < 0) {
// 剩余租金<0irr大了
tmp2 = irr;
irr = irr.add(tmp1).divide(second, 20, BigDecimal.ROUND_HALF_UP);
} else {
// 剩余租金=0irr正好结束循环
break;
}
}
} catch (Exception e) {
}
return irr;
}
/**
* XIRR计算公式 参数inflowPour是对于的现金流,参数dateList是对于的现金流时间 这个需要一一对于. <br>
* 这个算法对于的是EXECL中的XIRR算法.可以用于精确到日的 日IRR计算
*
* @param inflowPour
* 现金流List
* @param dateList
* 对应的日期List
* @return
*/
public static String getXIRR(List<BigDecimal> inflowPour, List<Date> dateList) {
BigDecimal irr = new BigDecimal("0.5");
BigDecimal tmp = new BigDecimal("1");
BigDecimal tmp1 = new BigDecimal("0");
BigDecimal tmp2 = new BigDecimal("1");
BigDecimal bigdec_1 = new BigDecimal("1");
BigDecimal bigdec_2 = new BigDecimal("2");
int j = 0;
try {
while (tmp.abs().doubleValue() > 0.0000000001 && j < 200) {
tmp = inflowPour.get(0);
Date date0 = dateList.get(0);
for (int i = 1; i < inflowPour.size(); i++) {
Long quot = RentCalculateUtil.getDateDiff(dateList.get(i), date0);
BigDecimal rate2 = new BigDecimal(quot / 365.0);
tmp = tmp.add(inflowPour.get(i).divide(new BigDecimal(Math.pow(irr.add(bigdec_1).doubleValue(), rate2.doubleValue())), 20, BigDecimal.ROUND_HALF_UP));
}
if (tmp.doubleValue() > 0) {
tmp1 = irr;
irr = irr.add(tmp2).divide(bigdec_2, 20, BigDecimal.ROUND_HALF_UP);
}
if (tmp.doubleValue() < 0) {
tmp2 = irr;
irr = irr.add(tmp1).divide(bigdec_2, 20, BigDecimal.ROUND_HALF_UP);
}
j++;
}
return irr.toString().equals("") ? "0" : irr.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "0";
}
/**
* IRR计算公式 参数inflowPour是对于的现金流,参数dateList是对于的现金流时间 这个需要一一对于. <br>
* 这个算法对于的是EXECL中的IRR算法.可以用于精确到日的 日IRR计算
*
* @param inflowPour
* 现金流List
* @param dateList
* 对应的日期List
* @return
*/
public static String getIRRNew(String leaseMoney,String equipendvalue,int grace ,List<String> inflowPour, List<String> dateList,String startDate,String type) {
BigDecimal irr = new BigDecimal("1");
BigDecimal tmp = new BigDecimal("1");
BigDecimal tmp1 = new BigDecimal("0");
BigDecimal tmp2 = new BigDecimal("1");
BigDecimal bigdec_2 = new BigDecimal("2");
BigDecimal tempInx = new BigDecimal(1);
BigDecimal year = new BigDecimal(360);
dateList.add(0,startDate);
for(int i=0;i<grace;i++){
dateList.remove(0);
}
inflowPour.add(0,BigDecimal.ZERO.subtract(new BigDecimal(leaseMoney)).toString());
int j = 0;
try {
while (tmp.abs().doubleValue() > 0.0000000001 && j < 200) {
tmp =new BigDecimal(inflowPour.get(0));
tempInx = new BigDecimal(1);
Date date0 =DateUtil.getTimeByFormat(dateList.get(0),"yyyy/MM/dd");
for (int i = 1; i <inflowPour.size(); i++) {
Long dayDiff = RentCalculateUtil.getDateDiff(date0,DateUtil.getTimeByFormat(dateList.get(i),"yyyy/MM/dd"));
if(type.equals("rent_period_360")){
dayDiff=Long.parseLong(DateUtils.days360(DateUtil.getSystemTimeByFormat(date0, "yyyy/MM/dd"), dateList.get(i))+"");
}
date0=DateUtil.getTimeByFormat(dateList.get(i),"yyyy/MM/dd");
BigDecimal issue = year.divide(year.add(irr.multiply(new BigDecimal(dayDiff))),20,BigDecimal.ROUND_HALF_UP);
tempInx = tempInx.multiply(issue);
tmp = tmp.add(new BigDecimal(inflowPour.get(i)).multiply(tempInx));
}
tmp=tmp.add(new BigDecimal(equipendvalue));
if (tmp.doubleValue() > 0) {
tmp1 = irr;
irr = irr.add(tmp2).divide(bigdec_2, 20, BigDecimal.ROUND_HALF_UP);
}
if (tmp.doubleValue() < 0) {
tmp2 = irr;
irr = irr.add(tmp1).divide(bigdec_2, 20, BigDecimal.ROUND_HALF_UP);
}
j++;
}
return irr.toString().equals("") ? "0" : irr.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "0";
}
}