@Test public void testReturnsWithZeroesInSeries() { final int n = 20; final LocalDate[] times = new LocalDate[n]; final double[] data = new double[n]; final double[] returns = new double[n - 3]; double random; for (int i = 0; i < n - 2; i++) { times[i] = LocalDate.ofEpochDay(i); random = RANDOM.nextDouble(); data[i] = random; if (i > 0) { returns[i - 1] = Math.log(random / data[i - 1]); } } times[n - 2] = LocalDate.ofEpochDay(n - 2); data[n - 2] = 0; times[n - 1] = LocalDate.ofEpochDay(n - 1); data[n - 1] = RANDOM.nextDouble(); final LocalDateDoubleTimeSeries priceTS = ImmutableLocalDateDoubleTimeSeries.of(times, data); final LocalDateDoubleTimeSeries returnTS = ImmutableLocalDateDoubleTimeSeries.of(Arrays.copyOfRange(times, 1, n - 2), returns); final TimeSeriesReturnCalculator strict = new ContinuouslyCompoundedTimeSeriesReturnCalculator(CalculationMode.STRICT); final LocalDateDoubleTimeSeries[] tsArray = new LocalDateDoubleTimeSeries[] {priceTS}; try { strict.evaluate(tsArray); Assert.fail(); } catch (final TimeSeriesException e) { // Expected } final TimeSeriesReturnCalculator lenient = new ContinuouslyCompoundedTimeSeriesReturnCalculator(CalculationMode.LENIENT); assertTrue(lenient.evaluate(tsArray).equals(returnTS)); }
@Test public void test() { boolean isCall; double spot, strike, b, price; Expiry expiry; YieldAndDiscountCurve curve; EuropeanVanillaOptionDefinition definition; StandardOptionDataBundle initialData, data; double sigma = 0.01; for (int i = 0; i < 100; i++) { expiry = new Expiry(DateUtils.getDateOffsetWithYearFraction(DATE, RANDOM.nextDouble() * 2)); sigma += 0.03; spot = 2 * RANDOM.nextDouble() + 10; strike = 2 * RANDOM.nextDouble() + 10; curve = YieldCurve.from(ConstantDoublesCurve.from(RANDOM.nextDouble() / 10)); b = 0; // RANDOM.nextDouble() / 20; isCall = RANDOM.nextDouble() < 0.5 ? true : false; definition = new EuropeanVanillaOptionDefinition(strike, expiry, isCall); initialData = new StandardOptionDataBundle(curve, b, null, spot, DATE); data = new StandardOptionDataBundle( curve, b, new VolatilitySurface(ConstantDoublesSurface.from(sigma)), spot, DATE); price = BSM.getPricingFunction(definition).evaluate(data); assertEquals( sigma, MODEL .getSurface( Collections.<OptionDefinition, Double>singletonMap(definition, price), initialData) .getVolatility(DoublesPair.of(0., 0.)), EPS); } }
static { for (int i = 0; i < N; i++) { X[i][0] = RANDOM.nextDouble(); X[i][1] = RANDOM.nextDouble(); X[i][2] = RANDOM.nextDouble(); } }
@Test public void test() { final int n = 20; final double[][] x = new double[n][5]; final double[] y1 = new double[n]; final double[] y2 = new double[n]; final double[] a1 = new double[] {3.4, 1.2, -0.62, -0.44, 0.65}; final double[] a2 = new double[] {0.98, 3.4, 1.2, -0.62, -0.44, 0.65}; for (int i = 0; i < n; i++) { for (int j = 0; j < 5; j++) { x[i][j] = RANDOM.nextDouble() + (RANDOM.nextDouble() - 0.5) / FACTOR; } y1[i] = a1[0] * x[i][0] + a1[1] * x[i][1] + a1[2] * x[i][2] + a1[3] * x[i][3] + a1[4] * x[i][4] + RANDOM.nextDouble() / FACTOR; y2[i] = a2[0] + a2[1] * x[i][0] + a2[2] * x[i][1] + a2[3] * x[i][2] + a2[4] * x[i][3] + a2[5] * x[i][4] + RANDOM.nextDouble() / FACTOR; } final LeastSquaresRegressionResult result1 = REGRESSION.regress(x, null, y1, false); final LeastSquaresRegressionResult result2 = REGRESSION.regress(x, null, y2, true); assertRegression(result1, a1); assertRegression(result2, a2); final double[] residuals1 = result1.getResiduals(); for (int i = 0; i < n; i++) { assertEquals( y1[i], a1[0] * x[i][0] + a1[1] * x[i][1] + a1[2] * x[i][2] + a1[3] * x[i][3] + a1[4] * x[i][4] + residuals1[i], 10 * EPS); } final double[] residuals2 = result2.getResiduals(); for (int i = 0; i < n; i++) { assertEquals( y2[i], a2[0] + a2[1] * x[i][0] + a2[2] * x[i][1] + a2[3] * x[i][2] + a2[4] * x[i][3] + a2[5] * x[i][4] + residuals2[i], 10 * EPS); } }
@Test public void testReturnsWithDividendsAtDifferentTimes() { final int n = 20; final LocalDate[] times = new LocalDate[n]; final double[] data = new double[n]; final double[] returns = new double[n - 1]; double random; for (int i = 0; i < n; i++) { times[i] = LocalDate.ofEpochDay(i); random = RANDOM.nextDouble(); data[i] = random; if (i > 0) { returns[i - 1] = Math.log(random / data[i - 1]); } } final LocalDateDoubleTimeSeries dividendTS = ImmutableLocalDateDoubleTimeSeries.of( new LocalDate[] {LocalDate.ofEpochDay(300)}, new double[] {3}); final LocalDateDoubleTimeSeries priceTS = ImmutableLocalDateDoubleTimeSeries.of(times, data); final LocalDateDoubleTimeSeries returnTS = ImmutableLocalDateDoubleTimeSeries.of(Arrays.copyOfRange(times, 1, n), returns); assertTrue( CALCULATOR .evaluate(new LocalDateDoubleTimeSeries[] {priceTS, dividendTS}) .equals(returnTS)); }
@Test(expectedExceptions = IllegalArgumentException.class) public void testNullData() { MODEL.getSurface( Collections.<OptionDefinition, Double>singletonMap( new EuropeanVanillaOptionDefinition(RANDOM.nextDouble(), new Expiry(DATE), true), 2.3), null); }
@Test(expectedExceptions = IllegalArgumentException.class) public void wrongLengthTest() { final int nSamples = 10; final List<DoublesPair> points = new ArrayList<>(nSamples); final DoubleMatrix1D x = new DoubleMatrix1D(nSamples + 1); x.getData()[0] = RANDOM.nextDouble(); for (int i = 0; i < nSamples; i++) { final double t = RANDOM.nextDouble() * 20.0; final double k = RANDOM.nextDouble() * 0.15; points.add(DoublesPair.of(t, k)); x.getData()[i + 1] = RANDOM.nextDouble(); } final DiscreteVolatilityFunctionProvider pro = new DiscreteVolatilityFunctionProviderDirect(); final DiscreteVolatilityFunction func = pro.from(points); func.evaluate(x); }
@Test public void test() { double x; final double eps = 1e-5; for (int i = 0; i < 100; i++) { x = RANDOM.nextDouble(); assertEquals(x, F.evaluate(T.getCDF(x)), eps); } }
/** * Number generator that implements the RandomGenerator interface, and returns pseudo-random numbers * drawn from an empirical distribution. This class is primarily a wrapper for the Colt package's * Empirical class. */ public class RandomGenerator_Kernel implements RandomGenerator, Cloneable { private double[] weights = new double[] {.125, .250, .375, .5, .625, .75, .875, 1}; private Empirical emp = new Empirical(weights, Empirical.LINEAR_INTERPOLATION, RandomEngine.makeDefault()); private boolean rotate = true; private double inc = 1d / (weights.length * 2d); /** Returns a clone/copy of the instance. */ @Override public RandomGenerator_Kernel clone() { RandomGenerator_Kernel rgk = new RandomGenerator_Kernel(); rgk.weights = Arrays.copyOf(this.weights, weights.length); rgk.emp = (Empirical) emp.clone(); rgk.rotate = rotate; rgk.inc = inc; return rgk; } /** * Returns the next pseudo-random value from the generator. If the rotate parameter is true, then * the random number is rotated such that the midpoint of the first bin will fall at zero. e.g. If * there are eight bins, and the random number falls in the first bin, .0625 is subtracted from * the number. A modulus of 1 is then applied so that values will remain in the interval zero to * 1. This way, the values can be post-multiplied by tau=2*pi to get an angle. */ @Override public Number getNext() { double val = emp.nextDouble(); return rotate ? (1 + (val - inc)) % 1d : val; } /** * Sets whether probability values should be rotated so that the midpoint of the first bin falls * on zero. * * @param rotate - indicates whether probability values should be rotated. */ public void setRotate(boolean rotate) { this.rotate = rotate; } /** * Sets the weights (and number) of the bins * * @param weights - the pdf to be used to weight the bins */ public void setWeights(double[] weights) { this.weights = weights; inc = 1d / (weights.length * 2d); emp.setState(weights, Empirical.LINEAR_INTERPOLATION); } }
@Override protected DoubleMatrix1D getGlobalStart( final double forward, final double[] strikes, final double expiry, final double[] impliedVols) { final RandomEngine random = getRandom(); final DoubleMatrix1D fitP = getPolynomialFit(forward, strikes, impliedVols); final double a = fitP.getEntry(0); final double b = fitP.getEntry(1); final double c = fitP.getEntry(2); if (Math.abs(b) < 1e-3 && Math.abs(c) < 1e-3) { // almost flat smile final double theta = Math.PI / 2 - 0.01; return new DoubleMatrix1D(a, 0.01, theta, theta); } final double theta = Math.PI / 2 * random.nextDouble(); return new DoubleMatrix1D( a * (0.8 + 0.4 * random.nextDouble()), a * 0.5 * random.nextDouble(), theta, theta); }
@Test public void test() { final int nSamples = 10; final List<DoublesPair> points = new ArrayList<>(nSamples); final DoubleMatrix1D x = new DoubleMatrix1D(nSamples); for (int i = 0; i < nSamples; i++) { final double t = RANDOM.nextDouble() * 20.0; final double k = RANDOM.nextDouble() * 0.15; points.add(DoublesPair.of(t, k)); x.getData()[i] = RANDOM.nextDouble(); } final DiscreteVolatilityFunctionProvider pro = new DiscreteVolatilityFunctionProviderDirect(); final DiscreteVolatilityFunction func = pro.from(points); final DoubleMatrix1D y = func.evaluate(x); AssertMatrix.assertEqualsVectors(x, y, 0.0); final DoubleMatrix2D jac = func.calculateJacobian(x); AssertMatrix.assertEqualsMatrix(new IdentityMatrix(nSamples), jac, 0.0); assertEquals(nSamples, func.getLengthOfDomain()); assertEquals(nSamples, func.getLengthOfRange()); }
@Test public void testNormal() { final ProbabilityDistribution<Double> highDOF = new StudentTDistribution(1000000, ENGINE); final ProbabilityDistribution<Double> normal = new NormalDistribution(0, 1, ENGINE); final double eps = 1e-4; double x; for (int i = 0; i < 100; i++) { x = RANDOM.nextDouble(); assertEquals(highDOF.getCDF(x), normal.getCDF(x), eps); assertEquals(highDOF.getPDF(x), normal.getPDF(x), eps); assertEquals(highDOF.getInverseCDF(x), normal.getInverseCDF(x), eps); } }
@SuppressWarnings("unchecked") @Test public void testReturnsWithZeroesInSeries() { final int n = 20; final long[] times = new long[n]; final double[] data = new double[n]; final double[] returns = new double[n - 3]; double random; for (int i = 0; i < n - 2; i++) { times[i] = i; random = RANDOM.nextDouble(); data[i] = random; if (i > 0) { returns[i - 1] = Math.log(random / data[i - 1]); } } times[n - 2] = n - 2; data[n - 2] = 0; times[n - 1] = n - 1; data[n - 1] = RANDOM.nextDouble(); final DoubleTimeSeries<Long> priceTS = new FastArrayLongDoubleTimeSeries(ENCODING, times, data); final DoubleTimeSeries<Long> returnTS = new FastArrayLongDoubleTimeSeries(ENCODING, Arrays.copyOfRange(times, 1, n - 2), returns); final TimeSeriesReturnCalculator strict = new ContinuouslyCompoundedTimeSeriesReturnCalculator(CalculationMode.STRICT); final DoubleTimeSeries<Long>[] tsArray = new DoubleTimeSeries[] {priceTS}; try { strict.evaluate(tsArray); Assert.fail(); } catch (final TimeSeriesException e) { // Expected } final TimeSeriesReturnCalculator lenient = new ContinuouslyCompoundedTimeSeriesReturnCalculator(CalculationMode.LENIENT); assertTrue(lenient.evaluate(tsArray).equals(returnTS)); }
@Test public void testReturnsWithoutDividends() { final int n = 20; final long[] times = new long[n]; final double[] data = new double[n]; final double[] returns = new double[n - 1]; double random; for (int i = 0; i < n; i++) { times[i] = i; random = RANDOM.nextDouble(); data[i] = random; if (i > 0) { returns[i - 1] = Math.log(random / data[i - 1]); } } final DoubleTimeSeries<Long> priceTS = new FastArrayLongDoubleTimeSeries(ENCODING, times, data); final DoubleTimeSeries<Long> returnTS = new FastArrayLongDoubleTimeSeries(ENCODING, Arrays.copyOfRange(times, 1, n), returns); assertTrue(CALCULATOR.evaluate(new DoubleTimeSeries[] {priceTS}).equals(returnTS)); }