Financials


package com.company;

import java.math.BigDecimal;

class Financials {
    /**
     * pmt
     *
     * @param rate 年利率 年利率除以12就是月利率
     * @param nper 贷款期数,单位月 该项贷款的付款总数。
     * @param pv   贷款金额,现值,或一系列未来付款的当前值的累积和,也称为本金。
     * @return
     */
    public static double pmt(double rate, double nper, double pv) {
        double v = (1 + (rate / 12));
        double t = (-(nper / 12) * 12);
        double result = (pv * (rate / 12)) / (1 - Math.pow(v, t));
        return result;
    }

    /**
     * irr
     * @param income 指定现金流值。此数组必须至少含有一个负值(支付)和一个正值(收入)
     * @return 指定一系列周期性现金流(支出或收入)的内部利率。
     */
    public static double irr(double[] income) {
        return irr(income, 0.1D);
    }

    /**
     * irr
     *
     * @param income 指定现金流值。此数组必须至少含有一个负值(支付)和一个正值(收入)
     * @param guess  指定 IRR 返回的估算值。如果省略,guess 为 0.1
     * @return 指定一系列周期性现金流(支出或收入)的内部利率。
     */
    public static double irr(double[] income, double guess) {
        int maxIterationCount = 20;
        double absoluteAccuracy = 1.0E-007D;
        double x0 = guess;
        int i = 0;
        while (i < maxIterationCount) {
            double fValue = 0.0D;
            double fDerivative = 0.0D;
            for (int k = 0; k < income.length; k++) {
                fValue += income[k] / Math.pow(1.0D + x0, k);
                fDerivative += -k * income[k] / Math.pow(1.0D + x0, k + 1);
            }
            double x1 = x0 - fValue / fDerivative;
            if (Math.abs(x1 - x0) <= absoluteAccuracy) {
                return x1;
            }
            x0 = x1;
            i++;
        }
        return (0.0D / 0.0D);
    }

    /**
     * npv
     *
     * @param income 指定现金流值。此数组必须至少含有一个负值(支付)和一个正值(收入)
     * @param i      折现率(基准收益率)
     * @return 净现值
     */
    public static double npv(double[] income, double i) {
        double npv = 0d;
        for (int n = 1; n < income.length + 1; n++) {
            /* (CI-CO) / ((i+i)^n) */
            npv += income[n - 1] / Math.pow(1 + i, n);
        }
        return npv;
    }


    public static double rate(double nper, double pmt, double pv) {
        double error = 0.0000001;
        double high = 1.00;
        double low = 0.00;

        double rate = (2.0 * (nper * pmt - pv)) / (pv * nper);

        while (true) {
            // check for error margin
            double calc = Math.pow(1 + rate, nper);
            calc = (rate * calc) / (calc - 1.0);
            calc -= pmt / pv;
            if (calc > error) {
                // guess too high, lower the guess
                high = rate;
                rate = (high + low) / 2;
            } else if (calc < -error) {
                // guess too low, higher the guess
                low = rate;
                rate = (high + low) / 2;
            } else {
                // acceptable guess
                break;
            }
        }
        //System.out.println("Rate : "+rate);
        return rate;
    }

    //参考 https://support.office.com/zh-CN/article/PV-%E5%87%BD%E6%95%B0-23879D31-0E02-4321-BE01-DA16E8168CBD
    /*
     * 如果您获得年利率为 10% 的汽车贷款,并且每月还款一次,则每月的利率为 10%/12(即 0.83%)。
     * 您需要在公式中输入 10%/12(即 0.83%)或 0.0083 作为利率。
     * */
    public static double pv(double monthRate, int periods, double peridsAmount) {
        /*
         * 如果年化收益率为零,monthRate作分母会出现NaN错误,需要对月利率为零进行特殊处理
         */
        if (monthRate == 0) {
            return periods * peridsAmount;
        }
        double var = Math.pow(1 + monthRate, -periods);
        double pvAmount = (peridsAmount - peridsAmount * var) / monthRate;
        return new BigDecimal(pvAmount).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    public static void main(String[] args) {
        /*
         *  验证百度百科上面的例子
         *  https://baike.baidu.com/item/%E5%87%80%E7%8E%B0%E5%80%BC/500068
         * */

        double[] income0 = {-800, -600, 500, 600, 900};
        double npv = npv(income0, 0.08);
        System.out.println(String.format("%.2f", npv));

        /*
         *  例子来源于
         *  https://wiki.mbalib.com/wiki/IRR%E5%87%BD%E6%95%B0
         * */
        double[] income1 = {-1500000, 400000, 500000, 600000, 700000, 860000};
        double irr = irr(income1, 0.1);
        System.out.println(String.format("%.2f", irr));

        /*
         * pmt计算公式
         * 例子来源于
         * https://wiki.mbalib.com/wiki/PMT%E5%87%BD%E6%95%B0
         * */

        double pmt = pmt(0.08, 12 * 15, 200000);
        System.out.println(String.format("%.2f", pmt));


        double rate1 = rate(68, 118161.59, 4146470.27);
        System.out.println(rate1);
        System.out.println("finished");


        System.out.println(pv(0.08 / 12, 5, 662.12));
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值