package com.tanpu.fund.utils;

import com.tanpu.fund.utils.model.Linear;

import java.math.BigDecimal;
import java.util.List;

/**
 * 基金公式管理
 */
public class FormulaToFundUtil {

    /**
     * 标准差
     *
     * @param x
     * @return
     */
    public static BigDecimal annual(List<Double> x) {
        int m = x.size();
        double sum = 0;
        for (int i = 0; i < m; i++) {//求和
            sum += x.get(i);
        }
        double dAve = sum / m;//求平均值
        double dVar = 0;
        for (int i = 0; i < m; i++) {//求方差
            dVar += (x.get(i) - dAve) * (x.get(i) - dAve);
        }

        double sqrt = Math.sqrt(dVar / (m - 1));
        return new BigDecimal(sqrt).setScale(6, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 求下行风险标准差
     *
     * @param rp
     * @param rf
     * @return
     */
    static double downRisk(double[] rp, double rf) {
        int len = rp.length;
        if (len > 0) {
            double output = 0.0;
            int count = 0;
            for (double p : rp) {
                if (p < rf) {
                    count++;
                    output += Math.pow((p - rf), 2);
                }
            }
            if (count > 1) {
                output = Math.sqrt(output / (count - 1));
                return output;
            } else {
                System.out.println("益率小于无风险利率的天数刚好为1");
                return -9999;
            }
        } else {
            return -9999;
        }
    }

    /**
     * 求索提诺比率
     *
     * @param exp
     * @param rf
     * @param dr
     * @return
     */
    static double sortinoRatio(double exp, double rf, double dr) {
        if (dr != 0) {
            return (exp - rf) / dr;
        } else {
            System.out.println("下行风险标准差有误");
            return -9999;
        }
    }

    /**
     * 求夏普比率
     *
     * @param exp
     * @param rf
     * @param dp
     * @return
     */
    static double sharpRatio(double exp, double rf, double dp) {
        if (dp != 0) {
            return (exp - rf) / dp;
        } else {
            System.out.println("标准差为0");
            return -9999;
        }
    }

    /**
     * 求线性回归 alpha beta R2
     *
     * @param rp
     * @param rm
     * @param rf
     * @return
     */
    static Linear linearRegression(double[] rp, double[] rm, double rf) {
        Linear output = new Linear(-9999, -9999, -9999);
        int len = rp.length;
        int lenrm = rm.length;
        if (len > 0) {
            if (len == lenrm) {
                double xexp = 0.0;
                double yexp = 0.0;
                double xsqura = 0.0;
                double ysqura = 0.0;
                double xy = 0.0;
                for (int i = 0; i < len; i++) {
                    double yi = rp[i] - rf;
                    double xi = rm[i] - rf;
                    xexp += xi;
                    yexp += yi;
                    xy += xi * yi;
                    xsqura += Math.pow(xi, 2);
                    ysqura += Math.pow(yi, 2);
                }
                xexp /= len;
                yexp /= len;
                double lxy = xy - len * xexp * yexp;
                double lxx = xsqura - len * Math.pow(xexp, 2);
                double lyy = ysqura - len * Math.pow(yexp, 2);
                output.beta = lxy / lxx;
                output.alpha = yexp - output.beta * xexp;
                output.rsquare = Math.pow(lxy, 2) / (lxx * lyy);
                return output;
            } else {
                System.out.println("市场收益序列长度不匹配");
            }
        } else {
            System.out.println("收益输入为空");
        }
        return output;
    }

    /**
     * 求詹森系数
     *
     * @param eRp
     * @param eRm
     * @param rf
     * @param beta
     * @return
     */
    static double jensen(double eRp, double eRm, double rf, double beta) {
        return eRp - rf - beta * (eRm - rf);
    }

    /**
     * 求特雷诺系数
     *
     * @param exp
     * @param rf
     * @param beta
     * @return
     */
    static double treynorRatio(double exp, double rf, double beta) {
        if (beta != 0) {
            return (exp - rf) / beta;
        } else {
            System.out.println("系统风险beta为0");
            return -9999;
        }
    }

    /**
     * 收益率(非首次买进,首次认购 周收益率=认购时的基金单位净值-1)
     *
     * @param startCumulativeNav
     * @param endCumulativeNav
     * @return
     */
    public static BigDecimal profitRate(BigDecimal startCumulativeNav, BigDecimal endCumulativeNav) {
        if (startCumulativeNav == null || endCumulativeNav == null) {
            return null;
        }

        return endCumulativeNav.subtract(startCumulativeNav).divide(startCumulativeNav, 6, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 最大回撤
     *
     * @param annual
     * @return
     */
    private static double getRetracement(double[] annual)// 最大回撤L1
    {
        double diff = 0;
        double max = annual[0];
        for (int temp = 1; temp < annual.length; temp++)
        {
            if (annual[temp] - max < diff)
                diff = annual[temp] - max;
            if (annual[temp] > max)
                max = annual[temp];
        }

        return diff;
    }

    public static void main(String[] args) {
        double[] aaa = {1, 2, 3, 7, 3, 2.5, 1.1, 0.5, 1, 3, 4, 9, 5, 10, 3};
        System.out.println(getRetracement(aaa));
    }
}