예제 #1
0
        protected internal override QuantileResult expectedShortfall(double level, DoubleArray sample)
        {
            ArgChecker.isTrue(level > 0, "Quantile should be above 0.");
            ArgChecker.isTrue(level < 1, "Quantile should be below 1.");
            int sampleSize = sampleCorrection(sample.size());

            double[] order = createIndexArray(sample.size());
            double[] s     = sample.toArray();
            DoubleArrayMath.sortPairs(s, order);
            double fractionalIndex = level * sampleSize;
            int    index           = (int)checkIndex(this.index(fractionalIndex), sample.size(), true);

            int[]    indices  = new int[index];
            double[] weights  = new double[index];
            double   interval = 1d / (double)sampleSize;
            double   losses   = s[0] * interval *indexShift();

            for (int i = 0; i < index - 1; i++)
            {
                losses    += s[i] * interval;
                indices[i] = (int)order[i];
                weights[i] = interval;
            }
            losses            += s[index - 1] * (fractionalIndex - index + 1 - indexShift()) * interval;
            indices[index - 1] = (int)order[index - 1];
            weights[0]        += interval * indexShift();
            weights[index - 1] = (fractionalIndex - index + 1 - indexShift()) * interval;
            return(QuantileResult.of(losses / level, indices, DoubleArray.ofUnsafe(weights).dividedBy(level)));
        }
        /// <summary>
        /// Computes expected shortfall.
        /// </summary>
        /// <param name="index">  the index from which the ES should be computed </param>
        /// <param name="runningWeight">  the running weight up to index </param>
        /// <param name="s">  the sorted sample </param>
        /// <param name="w">  the sorted weights </param>
        /// <param name="order">  the order of the sorted sample in the unsorted sample </param>
        /// <param name="level">  the level at which the ES should be computed </param>
        /// <returns> the expected shortfall and the details of sample data used to compute it </returns>
        private QuantileResult esFromIndexRunningWeight(int index, double runningWeight, double[] s, double[] w, double[] order, double level)
        {
            int nbData = s.Length;

            if ((index == nbData - 1) || (index == nbData))
            {
                return(QuantileResult.of(s[nbData - 1], new int[] { (int)(long)Math.Round(order[nbData - 1], MidpointRounding.AwayFromZero) }, DoubleArray.of(1.0d)));
            }
            double alpha = (runningWeight - (1.0 - level)) / w[index];

            int[]    indices = new int[nbData - index];
            double[] impacts = new double[nbData - index];
            for (int i = 0; i < nbData - index; i++)
            {
                indices[i] = (int)(long)Math.Round(order[index + i], MidpointRounding.AwayFromZero);
            }
            impacts[0] = 0.5 * (1 - alpha) * (1 - alpha) * w[index] / (1.0 - level);
            impacts[1] = (alpha + 1) * 0.5 * (1 - alpha) * w[index] / (1.0 - level);
            for (int i = 1; i < nbData - index - 1; i++)
            {
                impacts[i]     += 0.5 * w[index + i] / (1.0 - level);
                impacts[i + 1] += 0.5 * w[index + i] / (1.0 - level);
            }
            impacts[nbData - index - 1] += w[nbData - 1] / (1.0 - level);
            double es = 0;

            for (int i = 0; i < nbData - index; i++)
            {
                es += s[index + i] * impacts[i];
            }
            return(QuantileResult.of(es, indices, DoubleArray.ofUnsafe(impacts)));
        }
예제 #3
0
        protected internal override QuantileResult quantile(double level, DoubleArray sample, bool isExtrapolated)
        {
            ArgChecker.isTrue(level > 0, "Quantile should be above 0.");
            ArgChecker.isTrue(level < 1, "Quantile should be below 1.");
            int sampleSize = sampleCorrection(sample.size());

            double[] order = createIndexArray(sample.size());
            double[] s     = sample.toArray();
            DoubleArrayMath.sortPairs(s, order);
            int index = (int)checkIndex(this.index(level * sampleSize), sample.size(), isExtrapolated);

            int[] ind = new int[1];
            ind[0] = (int)order[index - 1];
            return(QuantileResult.of(s[index - 1], ind, DoubleArray.of(1)));
        }
        protected internal override QuantileResult expectedShortfall(double level, DoubleArray sample)
        {
            ArgChecker.isTrue(level > 0, "Quantile should be above 0.");
            ArgChecker.isTrue(level < 1, "Quantile should be below 1.");
            int    sampleSize      = sampleCorrection(sample.size());
            double fractionalIndex = level * sampleSize + indexCorrection();
            double adjustedLevel   = checkIndex(fractionalIndex, sample.size(), true);

            double[] order = createIndexArray(sample.size());
            double[] s     = sample.toArray();
            DoubleArrayMath.sortPairs(s, order);
            int lowerIndex = (int)Math.Floor(adjustedLevel);
            int upperIndex = (int)Math.Ceiling(adjustedLevel);

            int[]    indices  = new int[upperIndex];
            double[] weights  = new double[upperIndex];
            double   interval = 1d / (double)sampleSize;

            weights[0] = interval * (Math.Min(fractionalIndex, 1d) - indexCorrection());
            double losses = s[0] * weights[0];

            for (int i = 0; i < lowerIndex - 1; i++)
            {
                losses         += 0.5 * (s[i] + s[i + 1]) * interval;
                indices[i]      = (int)order[i];
                weights[i]     += 0.5 * interval;
                weights[i + 1] += 0.5 * interval;
            }
            if (lowerIndex != upperIndex)
            {
                double lowerWeight = upperIndex - adjustedLevel;
                double upperWeight = 1d - lowerWeight;
                double quantile    = lowerWeight * s[lowerIndex - 1] + upperWeight * s[upperIndex - 1];
                losses += 0.5 * (s[lowerIndex - 1] + quantile) * interval * upperWeight;
                indices[lowerIndex - 1]  = (int)order[lowerIndex - 1];
                indices[upperIndex - 1]  = (int)order[upperIndex - 1];
                weights[lowerIndex - 1] += 0.5 * (1d + lowerWeight) * interval * upperWeight;
                weights[upperIndex - 1]  = 0.5 * upperWeight * interval * upperWeight;
            }
            if (fractionalIndex > sample.size())
            {
                losses += s[sample.size() - 1] * (fractionalIndex - sample.size()) * interval;
                indices[sample.size() - 1]  = (int)order[sample.size() - 1];
                weights[sample.size() - 1] += (fractionalIndex - sample.size()) * interval;
            }
            return(QuantileResult.of(losses / level, indices, DoubleArray.ofUnsafe(weights).dividedBy(level)));
        }
        protected internal override QuantileResult quantile(double level, DoubleArray sample, bool isExtrapolated)
        {
            ArgChecker.isTrue(level > 0, "Quantile should be above 0.");
            ArgChecker.isTrue(level < 1, "Quantile should be below 1.");
            int    sampleSize    = sampleCorrection(sample.size());
            double adjustedLevel = checkIndex(level * sampleSize + indexCorrection(), sample.size(), isExtrapolated);

            double[] order = createIndexArray(sample.size());
            double[] s     = sample.toArray();
            DoubleArrayMath.sortPairs(s, order);
            int    lowerIndex  = (int)Math.Floor(adjustedLevel);
            int    upperIndex  = (int)Math.Ceiling(adjustedLevel);
            double lowerWeight = upperIndex - adjustedLevel;
            double upperWeight = 1d - lowerWeight;

            return(QuantileResult.of(lowerWeight * s[lowerIndex - 1] + upperWeight * s[upperIndex - 1], new int[] { (int)order[lowerIndex - 1], (int)order[upperIndex - 1] }, DoubleArray.of(lowerWeight, upperWeight)));
        }
        /// <summary>
        /// Computes value-at-risk.
        /// </summary>
        /// <param name="index">  the index from which the VaR should be computed </param>
        /// <param name="runningWeight">  the running weight up to index </param>
        /// <param name="isExtrapolated">  flag indicating if value should be extrapolated (flat) beyond the last value </param>
        /// <param name="s">  the sorted sample </param>
        /// <param name="w">  the sorted weights </param>
        /// <param name="order">  the order of the sorted sample in the unsorted sample </param>
        /// <param name="level">  the level at which the VaR should be computed </param>
        /// <returns> the VaR and the details of sample data used to compute it </returns>
        private QuantileResult quantileFromIndexRunningWeight(int index, double runningWeight, bool isExtrapolated, double[] s, double[] w, double[] order, double level)
        {
            int nbData = s.Length;

            if ((index == nbData - 1) || (index == nbData))
            {
                ArgChecker.isTrue(isExtrapolated, "Quantile can not be computed above the highest probability level.");
                return(QuantileResult.of(s[nbData - 1], new int[] { (int)(long)Math.Round(order[nbData - 1], MidpointRounding.AwayFromZero) }, DoubleArray.of(1.0d)));
            }
            double alpha = (runningWeight - (1.0 - level)) / w[index];

            int[]    indices = new int[nbData - index];
            double[] impacts = new double[nbData - index];
            for (int i = 0; i < nbData - index; i++)
            {
                indices[i] = (int)(long)Math.Round(order[index + i], MidpointRounding.AwayFromZero);
            }
            impacts[0] = 1 - alpha;
            impacts[1] = alpha;
            return(QuantileResult.of((1 - alpha) * s[index] + alpha * s[index + 1], indices, DoubleArray.ofUnsafe(impacts)));
        }