JohnsonSUDeltaGammaVaRCalculator implements VaRCalculator<NormalVaRParameters, T> { @SuppressWarnings("unchecked") @Override public VaRCalculationResult evaluate(final NormalVaRParameters parameters, final T... data) { ArgumentChecker.notNull(parameters, "parameters"); ArgumentChecker.notNull(data, "data"); final double k = _kurtosisCalculator.evaluate(data); if (k < 0) { throw new IllegalArgumentException("Johnson SU distribution cannot be used for data with negative excess kurtosis"); } final double mult = parameters.getTimeScaling(); final double z = parameters.getZ(); final double t = _skewCalculator.evaluate(data); final double mu = _meanCalculator.evaluate(data) * mult * mult; final double sigma = _stdCalculator.evaluate(data) * mult; if (t == 0 && k == 0) { return new VaRCalculationResult(z * sigma - mu, null); } final double wUpper = Math.sqrt(Math.sqrt(2 * (k + 2)) - 1); final double wLower = Math.max(getW0(t), getW1(k + 3)); final double w = ROOT_FINDER.getRoot(getFunction(t, k), wLower, wUpper); final double w2 = w * w; final double l = 4 + 2 * (w2 - (k + 6) / (w2 + 2 * w + 3)); if (l < 0) { throw new IllegalArgumentException("Tried to find the square root of a negative number"); } final double m = -2 + Math.sqrt(l); if (m == 0 || (m < 0 && w > -1) || (m > 0 && w < -1) || (w - 1 - m) < 0) { throw new IllegalArgumentException("Invalid parameters"); } final double sign = Math.signum(t); final double u = Math.sqrt(Math.log(w)); final double v = Math.sqrt((w + 1) * (w - 1 - m) / (2 * w * m)); final double omega = -sign * TrigonometricFunctionUtils.asinh(v); final double delta = 1. / u; final double gamma = omega / u; final double lambda = sigma / (w - 1) * Math.sqrt(2 * m / (w + 1)); final double ksi = mu - sign * sigma * Math.sqrt(w - 1 - m) / (w - 1); return new VaRCalculationResult(-lambda * Math.sinh((-z - gamma) / delta) - ksi, null); } JohnsonSUDeltaGammaVaRCalculator(final Function<T, Double> meanCalculator, final Function<T, Double> stdCalculator,
      final Function<T, Double> skewCalculator, final Function<T, Double> kurtosisCalculator); Function<T, Double> getMeanCalculator(); Function<T, Double> getStdCalculator(); Function<T, Double> getSkewCalculator(); Function<T, Double> getKurtosisCalculator(); @SuppressWarnings("unchecked") @Override VaRCalculationResult evaluate(final NormalVaRParameters parameters, final T... data); @Override int hashCode(); @Override boolean equals(final Object obj);  }
@Test(expectedExceptions = IllegalArgumentException.class) public void testNullData() { F.evaluate(PARAMETERS, (Double[]) null); }
@Test(expectedExceptions = IllegalArgumentException.class) public void testNullParameters() { F.evaluate(null, 1.); }
@Test(expectedExceptions = IllegalArgumentException.class) public void testNegativeKurtosis() { final Function<Double, Double> k = new MyFunction(-0.4); final JohnsonSUDeltaGammaVaRCalculator<Double> f = new JohnsonSUDeltaGammaVaRCalculator<>(MEAN, STD, SKEW, k); f.evaluate(PARAMETERS, 0.); }
@Test public void testNormal() { final Function<Double, Double> zero = new MyFunction(0.0); final NormalLinearVaRCalculator<Double> normal = new NormalLinearVaRCalculator<>(MEAN, STD); final JohnsonSUDeltaGammaVaRCalculator<Double> f = new JohnsonSUDeltaGammaVaRCalculator<>(MEAN, STD, zero, zero); assertEquals(normal.evaluate(PARAMETERS, 0.).getVaRValue(), f.evaluate(PARAMETERS, 0.).getVaRValue(), 1e-9); }
@Test public void test() { assertEquals(F.evaluate(PARAMETERS, 0.).getVaRValue(), 0.1376, 1e-4); }