/**
* Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.math.statistics.descriptive;
import static org.testng.AssertJUnit.assertEquals;
import org.testng.annotations.Test;
public class QuantileCalculationMethodTest {
public static final IndexAboveQuantileMethod QUANTILE_INDEX_ABOVE = IndexAboveQuantileMethod.DEFAULT;
public static final NearestIndexQuantileMethod QUANTILE_NEAREST_INDEX = NearestIndexQuantileMethod.DEFAULT;
public static final SampleInterpolationQuantileMethod QUANTILE_SAMPLE_INTERPOLATION =
SampleInterpolationQuantileMethod.DEFAULT;
public static final SamplePlusOneInterpolationQuantileMethod QUANTILE_SAMPLE1_INTERPOLATION =
SamplePlusOneInterpolationQuantileMethod.DEFAULT;
public static final MidwayInterpolationQuantileMethod QUANTILE_MIDWAY_INTERPOLATION =
MidwayInterpolationQuantileMethod.DEFAULT;
public static final double[] SAMPLE_SORTED_100 = new double[] {
0.0286, 0.0363, 0.0379, 0.0582, 0.0611, 0.0622, 0.0776, 0.0779, 0.0849, 0.0916,
0.1055, 0.1358, 0.1474, 0.1544, 0.1674, 0.1740, 0.1746, 0.1841, 0.1963, 0.1982,
0.2020, 0.2222, 0.2401, 0.2582, 0.2666, 0.2979, 0.2998, 0.3000, 0.3028, 0.3057,
0.3508, 0.3734, 0.3781, 0.4011, 0.4197, 0.4463, 0.4481, 0.4863, 0.4878, 0.4908,
0.4942, 0.5029, 0.5212, 0.5224, 0.5290, 0.5780, 0.5803, 0.5807, 0.5921, 0.6174,
0.6243, 0.6278, 0.6325, 0.6343, 0.6416, 0.6423, 0.6460, 0.6504, 0.6570, 0.6666,
0.6748, 0.6763, 0.6804, 0.6859, 0.6862, 0.7136, 0.7145, 0.7289, 0.7291, 0.7360,
0.7444, 0.7532, 0.7543, 0.7602, 0.7714, 0.8024, 0.8053, 0.8075, 0.8190, 0.8190,
0.8216, 0.8234, 0.8399, 0.8483, 0.8511, 0.8557, 0.8631, 0.8814, 0.8870, 0.8963,
0.9150, 0.9157, 0.9198, 0.9275, 0.9524, 0.9570, 0.9620, 0.9716, 0.9731, 0.9813 };
public static final int SAMPLE_SIZE_100 = SAMPLE_SORTED_100.length;
public static final double[] SAMPLE_SORTED_123 = new double[] {
0.0286, 0.0363, 0.0379, 0.0582, 0.0611, 0.0622, 0.0776, 0.0779, 0.0822, 0.0849,
0.0916, 0.1055, 0.1358, 0.1474, 0.1544, 0.1674, 0.1740, 0.1746, 0.1841, 0.1963,
0.1982, 0.2020, 0.2155, 0.2222, 0.2401, 0.2413, 0.2582, 0.2666, 0.2936, 0.2979,
0.2998, 0.3000, 0.3028, 0.3057, 0.3076, 0.3461, 0.3508, 0.3717, 0.3734, 0.3781,
0.4011, 0.4157, 0.4197, 0.4285, 0.4463, 0.4481, 0.4534, 0.4690, 0.4863, 0.4878,
0.4908, 0.4942, 0.5029, 0.5083, 0.5108, 0.5212, 0.5224, 0.5290, 0.5578, 0.5780,
0.5803, 0.5807, 0.5921, 0.6174, 0.6243, 0.6278, 0.6325, 0.6343, 0.6416, 0.6423,
0.6460, 0.6495, 0.6504, 0.6570, 0.6666, 0.6694, 0.6748, 0.6763, 0.6793, 0.6804,
0.6859, 0.6862, 0.7136, 0.7145, 0.7289, 0.7291, 0.7360, 0.7444, 0.7532, 0.7543,
0.7602, 0.7714, 0.7768, 0.8024, 0.8053, 0.8075, 0.8190, 0.8190, 0.8216, 0.8234,
0.8399, 0.8421, 0.8483, 0.8511, 0.8557, 0.8631, 0.8814, 0.8870, 0.8914, 0.8963,
0.9077, 0.9150, 0.9157, 0.9198, 0.9275, 0.9368, 0.9524, 0.9570, 0.9600, 0.9620,
0.9716, 0.9731, 0.9813 };
public static final int SAMPLE_SIZE_123 = SAMPLE_SORTED_123.length;
public static final double LEVEL = 0.95;
public static final double TOLERANCE_QUANTILE = 1.0E-10;
@Test(expectedExceptions = IllegalArgumentException.class)
public void discrete_wrong_quantile_large() {
QUANTILE_INDEX_ABOVE.quantileFromSorted(1.01, SAMPLE_SORTED_100);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void discrete_wrong_quantile_0() {
QUANTILE_INDEX_ABOVE.quantileFromSorted(0.0, SAMPLE_SORTED_100);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void interpolation_wrong_quantile_1() {
QUANTILE_SAMPLE_INTERPOLATION.quantileFromSorted(1.01, SAMPLE_SORTED_100);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void interpolation_wrong_quantile_0() {
QUANTILE_SAMPLE_INTERPOLATION.quantileFromSorted(0.0, SAMPLE_SORTED_100);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void interpolation_wrong_quantile_small() {
QUANTILE_SAMPLE_INTERPOLATION.quantileFromSorted(1.0E-4, SAMPLE_SORTED_100);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void interpolation_wrong_quantile_large() {
QUANTILE_MIDWAY_INTERPOLATION.quantileFromSorted(1.0 - 1.0E-4, SAMPLE_SORTED_100);
}
@Test
public void index_above_095_100() {
double indexDouble = LEVEL * SAMPLE_SIZE_100;
int indexCeil = (int) Math.ceil(indexDouble);
double quantileExpected = SAMPLE_SORTED_100[indexCeil - 1]; // Java index start at 0.
double quantileComputed = QUANTILE_INDEX_ABOVE.quantileFromSorted(LEVEL, SAMPLE_SORTED_100);
assertEquals(quantileComputed, quantileExpected, TOLERANCE_QUANTILE);
}
@Test
public void index_above_095_123() {
double indexDouble = LEVEL * SAMPLE_SIZE_100;
int indexCeil = (int) Math.ceil(indexDouble);
double quantileExpected = SAMPLE_SORTED_100[indexCeil - 1]; // Java index start at 0.
double quantileComputed = QUANTILE_INDEX_ABOVE.quantileFromSorted(LEVEL, SAMPLE_SORTED_100);
assertEquals(quantileComputed, quantileExpected);
}
/** On sample points, different methods match. */
@Test
public void index_nearest_095_100() {
double quantileExpected = QUANTILE_INDEX_ABOVE.quantileFromSorted(LEVEL, SAMPLE_SORTED_100);
double quantileComputed = QUANTILE_NEAREST_INDEX.quantileFromSorted(LEVEL, SAMPLE_SORTED_100);
assertEquals(quantileComputed, quantileExpected, TOLERANCE_QUANTILE);
}
@Test
public void index_nearest_0951_100() {
double indexDouble = (LEVEL+0.001) * SAMPLE_SIZE_100;
int indexRound = (int) Math.round(indexDouble);
double quantileExpected = SAMPLE_SORTED_100[indexRound - 1]; // Java index start at 0.
double quantileComputed = QUANTILE_NEAREST_INDEX.quantileFromSorted(LEVEL, SAMPLE_SORTED_100);
assertEquals(quantileComputed, quantileExpected, TOLERANCE_QUANTILE);
}
@Test
public void index_nearest_001_100() {
double quantileExpected = SAMPLE_SORTED_100[0]; // Java index start at 0.
double quantileComputed = QUANTILE_NEAREST_INDEX.quantileFromSorted(0.001, SAMPLE_SORTED_100);
assertEquals(quantileComputed, quantileExpected, TOLERANCE_QUANTILE);
}
/** On sample points, different methods match. */
@Test
public void interpolation_sample_095_100() {
double quantileExpected = QUANTILE_NEAREST_INDEX.quantileFromSorted(LEVEL, SAMPLE_SORTED_100);
double quantileComputed = QUANTILE_SAMPLE_INTERPOLATION.quantileFromSorted(LEVEL, SAMPLE_SORTED_100);
assertEquals(quantileComputed, quantileExpected, TOLERANCE_QUANTILE);
}
@Test
public void interpolation_sample_095_123() {
double indexDouble = LEVEL * SAMPLE_SIZE_123;
int indexCeil = (int) Math.ceil(indexDouble);
int indexFloor = (int) Math.floor(indexDouble);
double quantileCeil = SAMPLE_SORTED_123[indexCeil - 1]; // Java index start at 0.
double quantileFloor = SAMPLE_SORTED_123[indexFloor - 1];
double pi = (double) indexFloor / (double) SAMPLE_SIZE_123;
double pi1 = (double) indexCeil / (double) SAMPLE_SIZE_123;
double quantileExpected = quantileFloor + (LEVEL - pi) / (pi1 - pi) * (quantileCeil - quantileFloor);
double quantileComputed = QUANTILE_SAMPLE_INTERPOLATION.quantileFromSorted(LEVEL, SAMPLE_SORTED_123);
assertEquals(quantileComputed, quantileExpected, TOLERANCE_QUANTILE);
}
@Test
public void interpolation_samplePlusOne_095_123() {
double indexDouble = LEVEL * (SAMPLE_SIZE_123 + 1);
int indexCeil = (int) Math.ceil(indexDouble);
int indexFloor = (int) Math.floor(indexDouble);
double quantileCeil = SAMPLE_SORTED_123[indexCeil - 1]; // Java index start at 0.
double quantileFloor = SAMPLE_SORTED_123[indexFloor - 1];
double pi = (double) indexFloor / (double) (SAMPLE_SIZE_123 + 1);
double pi1 = (double) indexCeil / (double) (SAMPLE_SIZE_123 + 1);
double quantileExpected = quantileFloor + (LEVEL - pi) / (pi1 - pi) * (quantileCeil - quantileFloor);
double quantileComputed = QUANTILE_SAMPLE1_INTERPOLATION.quantileFromSorted(LEVEL, SAMPLE_SORTED_123);
assertEquals(quantileComputed, quantileExpected, TOLERANCE_QUANTILE);
}
@Test
public void interpolation_midway_095_123() {
double correction = 0.5;
double indexDouble = LEVEL * SAMPLE_SIZE_123 + correction;
int indexCeil = (int) Math.ceil(indexDouble);
int indexFloor = (int) Math.floor(indexDouble);
double quantileCeil = SAMPLE_SORTED_123[indexCeil - 1]; // Java index start at 0.
double quantileFloor = SAMPLE_SORTED_123[indexFloor - 1];
double pi = (indexFloor - correction) / (double) SAMPLE_SIZE_123;
double pi1 = (indexCeil - correction) / (double) SAMPLE_SIZE_123;
double quantileExpected = quantileFloor + (LEVEL - pi) / (pi1 - pi) * (quantileCeil - quantileFloor);
double quantileComputed = QUANTILE_MIDWAY_INTERPOLATION.quantileFromSorted(LEVEL, SAMPLE_SORTED_123);
assertEquals(quantileComputed, quantileExpected, TOLERANCE_QUANTILE);
}
@Test
public void excel() {
double[] data = new double[] {1.0, 3.0, 2.0, 4.0};
double level = 0.3;
double quantileComputed = ExcelInterpolationQuantileMethod.DEFAULT.quantileFromUnsorted(level, data);
double quantileExpected = 1.9; // From Excel doc
assertEquals(quantileComputed, quantileExpected, TOLERANCE_QUANTILE);
}
}