internal static Matrix CovarianceMatrixSerialCorrelationCorrected(double[] array1, double[] array2, double decayFactor, int length)
        {
            double[] array1Len = Tools.MostRecentValues(array1, length);
            double[] array2Len = Tools.MostRecentValues(array2, length);
            double[] array1Lag = Tools.LagArray(array1, length, 1);
            double[] array2Lag = Tools.LagArray(array2, length, 1);

            double[,] lagArray = new double[length, 2];
            for (int i = 0; i < length; i++)
            {
                lagArray[i, 0] = array1Lag[i];
                lagArray[i, 1] = array2Lag[i];
            }
            WeightedLeastSquares wls1 = new WeightedLeastSquares(array1Len, lagArray, true, decayFactor);
            WeightedLeastSquares wls2 = new WeightedLeastSquares(array2Len, lagArray, true, decayFactor);
            Matrix D = new Matrix(2, 2);

            D[0, 0] = wls1.Betas[1].Value;
            D[0, 1] = wls1.Betas[2].Value;
            D[1, 0] = wls2.Betas[1].Value;
            D[1, 1] = wls2.Betas[2].Value;

            Matrix C = new Matrix(2, 2);

            C[0, 0] = Variance(array1Len, decayFactor);
            C[0, 1] = Covariance(array1Len, array2Len, decayFactor);
            C[1, 0] = C[0, 1];
            C[1, 1] = Variance(array2Len, decayFactor);

            Matrix M     = SerialCorrelationCorrection.SerialCorrelationVarianceCorrection(D, C);
            Matrix CStar = M.Multiply(C);

            return(CStar);
        }
        /// <summary>
        /// Hybrid VaR is based on historical data, but weights more recent data more heavily.
        /// </summary>
        /// <param name="returnArray">Historical returns from which VaR is to be calculated. The last value, with the highest index is assumed to be the most recent data point.</param>
        /// <param name="windowLength">Length of the VaR window. The number of historical returns that will be used to calculate the VaR.</param>
        /// <param name="confidenceLevel">VaR confidence level. 95% and 99% are typical values. If confidenceLevel is 95% then we expect 95% of days to be better (have a more positive return) than the VaR.</param>
        /// <param name="decayFactor">For a decay factor d, the most recent data point has weight 1, the second d, the third d^2, ...</param>
        /// <param name="correctSerialCorrelation">If true, correction is for infinite return length.</param>
        public static double HybridValueAtRisk(double[] returnArray, int windowLength, double confidenceLevel, double decayFactor, bool correctSerialCorrelation)
        {
            double uncorrected = HybridValueAtRisk(returnArray, windowLength, confidenceLevel, decayFactor);

            if (!correctSerialCorrelation)
            {
                return(uncorrected);
            }

            double[] subArray                 = Tools.MostRecentValues(returnArray, windowLength);
            double   serialCorrelation        = Moments.SerialCorrelation(subArray, decayFactor);
            double   varianceCorrectionFactor = SerialCorrelationCorrection.SerialCorrelationVarianceCorrection(serialCorrelation); //don't use version w/ windowLength. windowLenght != length. Length is how far back we go to get data for the calculation. windowLenght is the return lenght that we are correcting to (infinite, by default).

            return(uncorrected * Math.Sqrt(varianceCorrectionFactor));
        }
        /// <summary>
        /// Returns the sample standard deviation of an array, corrected for serial correlation.
        /// </summary>
        /// <param name="array">Array of data for which we are calculating the variance.  For time series, the last element (index = n-1), is the most recent.</param>
        /// <param name="decayFactor">In most applications, the decay factor is between 0 and 1.  Weigth on the last element in array is 1.0, the 2nd to last element d, 3rd to last d^2, ...</param>
        /// <param name="length">Window length. Method uses the most recent n points, n = length.</param>
        /// <param name="correctSerialCorrelation">If true, correction is for infinite return length.</param>
        public static double StandardDeviation(double[] array, double decayFactor, int length, bool correctSerialCorrelation)
        {
            double uncorrected = StandardDeviation(array, decayFactor, length);

            if (!correctSerialCorrelation)
            {
                return(uncorrected);
            }

            double[] subArray                 = Tools.MostRecentValues(array, length);
            double   serialCorrelation        = SerialCorrelation(subArray, decayFactor);
            double   varianceCorrectionFactor = SerialCorrelationCorrection.SerialCorrelationVarianceCorrection(serialCorrelation); //don't use version w/ windowLength. windowLenght != length. Length is how far back we go to get data for the calculation. windowLenght is the return lenght that we are correcting to (infinite, by default).

            return(uncorrected * Math.Sqrt(varianceCorrectionFactor));
        }