/// <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)));
        }
Esempio n. 2
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)));
        }
Esempio n. 3
0
 //-----------------------------------------------------------------------
 public override bool Equals(object obj)
 {
     if (obj == this)
     {
         return(true);
     }
     if (obj != null && obj.GetType() == this.GetType())
     {
         QuantileResult other = (QuantileResult)obj;
         return(JodaBeanUtils.equal(value, other.value) && JodaBeanUtils.equal(indices, other.indices) && JodaBeanUtils.equal(weights, other.weights));
     }
     return(false);
 }
Esempio n. 4
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)));
        }
 public virtual void es_details()
 {
     double[] level = new double[] { 0.98, 0.981, 0.9811, 0.97 };
     for (int i = 0; i < level.Length; i++)
     {
         double         es = METHOD.expectedShortfallFromUnsorted(level[i], DATA_123);
         QuantileResult r  = METHOD.expectedShortfallDetailsFromUnsorted(level[i], DATA_123);
         assertEquals(r.Value, es, TOLERANCE_QUANTILE);
         assertEquals(r.Indices.Length, r.Weights.size());
         double qExpected = 0.0;
         for (int j = 0; j < r.Indices.Length; j++)
         {   // Recompute ES from details
             qExpected += DATA_123.get(r.Indices[j]) * r.Weights.get(j);
         }
         assertEquals(qExpected, es, TOLERANCE_QUANTILE);
     }
 }
        /// <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)));
        }
        public virtual void es_weights_indices_test()
        {
            QuantileResult esAbove            = QUANTILE_INDEX_ABOVE.expectedShortfallResultFromUnsorted(LEVEL2, UNSORTED_100);
            double         expectedValueAbove = 0d;
            double         sumWeightsAbove    = 0d;

            for (int i = 0; i < esAbove.Indices.Length; i++)
            {
                expectedValueAbove += UNSORTED_100.get(esAbove.Indices[i]) * esAbove.Weights.get(i);
                sumWeightsAbove    += esAbove.Weights.get(i);
            }
            assertEquals(esAbove.Indices.Length, esAbove.Weights.size());
            assertEquals(sumWeightsAbove, 1d, TOL);
            assertEquals(esAbove.Value, expectedValueAbove, TOL);

            QuantileResult esNearest            = QUANTILE_NEAREST_INDEX.expectedShortfallResultFromUnsorted(LEVEL2, UNSORTED_100);
            double         expectedValueNearest = 0d;
            double         sumWeightsNearest    = 0d;

            for (int i = 0; i < esNearest.Indices.Length; i++)
            {
                expectedValueNearest += UNSORTED_100.get(esNearest.Indices[i]) * esNearest.Weights.get(i);
                sumWeightsNearest    += esNearest.Weights.get(i);
            }
            assertEquals(esNearest.Indices.Length, esNearest.Weights.size());
            assertEquals(sumWeightsNearest, 1d, TOL);
            assertEquals(esNearest.Value, expectedValueNearest, TOL);

            QuantileResult esSample            = QUANTILE_SAMPLE1_NEAREST_INDEX.expectedShortfallResultFromUnsorted(LEVEL2, UNSORTED_100);
            double         expectedValueSample = 0d;
            double         sumWeightsSample    = 0d;

            for (int i = 0; i < esSample.Indices.Length; i++)
            {
                expectedValueSample += UNSORTED_100.get(esSample.Indices[i]) * esSample.Weights.get(i);
                sumWeightsSample    += esSample.Weights.get(i);
            }
            assertEquals(esSample.Indices.Length, esSample.Weights.size());
            assertEquals(sumWeightsSample, 1d, TOL);
            assertEquals(esSample.Value, expectedValueSample, TOL);

            QuantileResult esSampleInterp            = QUANTILE_SAMPLE_INTERPOLATION.expectedShortfallResultFromUnsorted(LEVEL2, UNSORTED_100);
            double         expectedValueSampleInterp = 0d;
            double         sumWeightsSampleInterp    = 0d;

            for (int i = 0; i < esSampleInterp.Indices.Length; i++)
            {
                expectedValueSampleInterp += UNSORTED_100.get(esSampleInterp.Indices[i]) * esSampleInterp.Weights.get(i);
                sumWeightsSampleInterp    += esSampleInterp.Weights.get(i);
            }
            assertEquals(esSampleInterp.Indices.Length, esSampleInterp.Weights.size());
            assertEquals(sumWeightsSampleInterp, 1d, TOL);
            assertEquals(esSampleInterp.Value, expectedValueSampleInterp, TOL);

            QuantileResult esSample1Interp            = QUANTILE_SAMPLE1_INTERPOLATION.expectedShortfallResultFromUnsorted(LEVEL2, UNSORTED_100);
            double         expectedValueSample1Interp = 0d;
            double         sumWeightsSample1Interp    = 0d;

            for (int i = 0; i < esSample1Interp.Indices.Length; i++)
            {
                expectedValueSample1Interp += UNSORTED_100.get(esSample1Interp.Indices[i]) * esSample1Interp.Weights.get(i);
                sumWeightsSample1Interp    += esSample1Interp.Weights.get(i);
            }
            assertEquals(esSample1Interp.Indices.Length, esSample1Interp.Weights.size());
            assertEquals(sumWeightsSample1Interp, 1d, TOL);
            assertEquals(esSample1Interp.Value, expectedValueSample1Interp, TOL);

            QuantileResult esMidInterp            = QUANTILE_MIDWAY_INTERPOLATION.expectedShortfallResultFromUnsorted(LEVEL2, UNSORTED_100);
            double         expectedValueMidInterp = 0d;
            double         sumWeightsMidInterp    = 0d;

            for (int i = 0; i < esMidInterp.Indices.Length; i++)
            {
                expectedValueMidInterp += UNSORTED_100.get(esMidInterp.Indices[i]) * esMidInterp.Weights.get(i);
                sumWeightsMidInterp    += esMidInterp.Weights.get(i);
            }
            assertEquals(esMidInterp.Indices.Length, esMidInterp.Weights.size());
            assertEquals(sumWeightsMidInterp, 1d, TOL);
            assertEquals(esMidInterp.Value, expectedValueMidInterp, TOL);
        }