Example #1
0
 @SuppressWarnings("unchecked")
 @Test
 public void testConstantSurface() {
   Surface<Double, Double, Double> s1 = ConstantDoublesSurface.from(4.);
   Surface<Double, Double, Double> s2 = cycleObject(Surface.class, s1);
   assertEquals(s1, s2);
   s1 = ConstantDoublesSurface.from(4., "NAME");
   s2 = cycleObject(Surface.class, s1);
   assertEquals(s1, s2);
 }
 private StandardOptionDataBundle getModifiedDataBundle(
     final StandardOptionDataBundle data, final double p) {
   final double t = DateUtils.getDifferenceInYears(DATE, EXPIRY);
   final double spot = Math.pow(data.getSpot(), p);
   double sigma = data.getVolatility(t, STRIKE);
   final double b = p * (data.getCostOfCarry() + (p - 1) * sigma * sigma * 0.5);
   sigma *= p;
   return new StandardOptionDataBundle(
       CURVE, b, new VolatilitySurface(ConstantDoublesSurface.from(sigma)), spot, DATE);
 }
 @Test
 public void test() {
   ProductOptionDefinition option = new ProductOptionDefinition(15000, EXPIRY1, true);
   StandardTwoAssetOptionDataBundle data =
       new StandardTwoAssetOptionDataBundle(
           R,
           B1,
           B2,
           new VolatilitySurface(ConstantDoublesSurface.from(0.2)),
           new VolatilitySurface(ConstantDoublesSurface.from(0.3)),
           S1,
           S2,
           -0.5,
           DATE);
   assertEquals(MODEL.getPricingFunction(option).evaluate(data), 0.0028, EPS);
   data =
       data.withFirstVolatilitySurface(new VolatilitySurface(ConstantDoublesSurface.from(0.3)))
           .withCorrelation(0);
   assertEquals(MODEL.getPricingFunction(option).evaluate(data), 2.4026, EPS);
   option = new ProductOptionDefinition(15000, EXPIRY2, true);
   assertEquals(MODEL.getPricingFunction(option).evaluate(data), 266.1594, EPS);
 }
public class FloatingStrikeLookbackOptionDefinitionTest {
  private static final ZonedDateTime DATE = DateUtils.getUTCDate(2010, 6, 1);
  private static final Expiry EXPIRY = new Expiry(DATE);
  private static final FloatingStrikeLookbackOptionDefinition CALL =
      new FloatingStrikeLookbackOptionDefinition(EXPIRY, true);
  private static final FloatingStrikeLookbackOptionDefinition PUT =
      new FloatingStrikeLookbackOptionDefinition(EXPIRY, false);
  private static final double SPOT = 100;
  private static final double DIFF = 10;
  private static final DoubleTimeSeries<?> HIGH_TS =
      new FastArrayIntDoubleTimeSeries(
          DateTimeNumericEncoding.DATE_DDMMYYYY,
          new int[] {20100529, 20100530, 20100531},
          new double[] {SPOT, SPOT + DIFF, SPOT});
  private static final DoubleTimeSeries<?> LOW_TS =
      new FastArrayIntDoubleTimeSeries(
          DateTimeNumericEncoding.DATE_DDMMYYYY,
          new int[] {20100529, 20100530, 20100531},
          new double[] {SPOT, SPOT - DIFF, SPOT});
  private static final StandardOptionWithSpotTimeSeriesDataBundle HIGH_DATA =
      new StandardOptionWithSpotTimeSeriesDataBundle(
          new YieldCurve(ConstantDoublesCurve.from(0.1)),
          0.05,
          new VolatilitySurface(ConstantDoublesSurface.from(0.2)),
          SPOT,
          DateUtils.getUTCDate(2010, 6, 1),
          HIGH_TS);
  private static final StandardOptionWithSpotTimeSeriesDataBundle LOW_DATA =
      new StandardOptionWithSpotTimeSeriesDataBundle(
          new YieldCurve(ConstantDoublesCurve.from(0.1)),
          0.05,
          new VolatilitySurface(ConstantDoublesSurface.from(0.2)),
          SPOT,
          DateUtils.getUTCDate(2010, 6, 1),
          LOW_TS);

  @Test(expectedExceptions = IllegalArgumentException.class)
  public void testNullDataBundle() {
    CALL.getPayoffFunction().getPayoff(null, null);
  }

  @Test(expectedExceptions = IllegalArgumentException.class)
  public void testNullTS() {
    CALL.getPayoffFunction().getPayoff(HIGH_DATA.withSpotTimeSeries(null), null);
  }

  @Test
  public void testExercise() {
    assertFalse(CALL.getExerciseFunction().shouldExercise(HIGH_DATA, null));
    assertFalse(CALL.getExerciseFunction().shouldExercise(LOW_DATA, null));
    assertFalse(PUT.getExerciseFunction().shouldExercise(HIGH_DATA, null));
    assertFalse(PUT.getExerciseFunction().shouldExercise(LOW_DATA, null));
  }

  @Test
  public void testPayoff() {
    final double eps = 1e-15;
    OptionPayoffFunction<StandardOptionWithSpotTimeSeriesDataBundle> payoff =
        CALL.getPayoffFunction();
    assertEquals(payoff.getPayoff(LOW_DATA, 0.), DIFF, eps);
    assertEquals(payoff.getPayoff(HIGH_DATA, 0.), 0, eps);
    payoff = PUT.getPayoffFunction();
    assertEquals(payoff.getPayoff(LOW_DATA, 0.), 0, eps);
    assertEquals(payoff.getPayoff(HIGH_DATA, 0.), DIFF, eps);
  }

  @Test
  public void testEqualsAndHashCode() {
    final OptionDefinition call1 = new FloatingStrikeLookbackOptionDefinition(EXPIRY, true);
    final OptionDefinition put1 = new FloatingStrikeLookbackOptionDefinition(EXPIRY, false);
    final OptionDefinition call2 =
        new FloatingStrikeLookbackOptionDefinition(
            new Expiry(DateUtils.getDateOffsetWithYearFraction(DATE, 3)), true);
    final OptionDefinition put2 =
        new FloatingStrikeLookbackOptionDefinition(
            new Expiry(DateUtils.getDateOffsetWithYearFraction(DATE, 3)), false);
    assertFalse(CALL.equals(PUT));
    assertEquals(call1, CALL);
    assertEquals(put1, PUT);
    assertEquals(call1.hashCode(), CALL.hashCode());
    assertEquals(put1.hashCode(), PUT.hashCode());
    assertFalse(call2.equals(CALL));
    assertFalse(put2.equals(PUT));
  }
}
public class AsymmetricPowerOptionModelTest {
  private static final double B = 0.02;
  private static final double SPOT = 10;
  private static final double STRIKE = 100;
  private static final ZonedDateTime DATE = DateUtils.getUTCDate(2009, 1, 1);
  private static final Expiry EXPIRY =
      new Expiry(DateUtils.getDateOffsetWithYearFraction(DATE, 0.5));
  private static final YieldAndDiscountCurve CURVE =
      new YieldCurve(ConstantDoublesCurve.from(0.08));
  private static final VolatilitySurface SURFACE =
      new VolatilitySurface(ConstantDoublesSurface.from(0.1));
  private static final StandardOptionDataBundle BUNDLE =
      new StandardOptionDataBundle(CURVE, B, SURFACE, SPOT, DATE);
  private static final AnalyticOptionModel<
          AsymmetricPowerOptionDefinition, StandardOptionDataBundle>
      MODEL = new AsymmetricPowerOptionModel();
  private static final AnalyticOptionModel<OptionDefinition, StandardOptionDataBundle> BS_MODEL =
      new BlackScholesMertonModel();
  private static final Set<Greek> REQUIRED_GREEKS = Collections.singleton(Greek.FAIR_PRICE);
  private static final double EPS = 1e-4;

  @Test(expectedExceptions = IllegalArgumentException.class)
  public void testNullDefinition() {
    MODEL.getPricingFunction(null);
  }

  @Test(expectedExceptions = IllegalArgumentException.class)
  public void testNullData() {
    MODEL
        .getPricingFunction(new AsymmetricPowerOptionDefinition(STRIKE, EXPIRY, 1, true))
        .evaluate((StandardOptionDataBundle) null);
  }

  @Test
  public void test() {
    assertEquals(getPrice(1.9, true), 0.3102, EPS);
    assertEquals(getPrice(1.95, true), 1.9320, EPS);
    assertEquals(getPrice(2., true), 6.7862, EPS);
    assertEquals(getPrice(2.05, true), 15.8587, EPS);
    assertEquals(getPrice(2.1, true), 28.4341, EPS);
    assertEquals(getPrice(1.9, false), 18.2738, EPS);
    assertEquals(getPrice(1.95, false), 10.2890, EPS);
    assertEquals(getPrice(2., false), 4.3539, EPS);
    assertEquals(getPrice(2.05, false), 1.3089, EPS);
    assertEquals(getPrice(2.1, false), 0.2745, EPS);

    for (int i = 0; i < 5; i++) {
      final double power = 1.9 + 0.05 * i;
      assertEquals(getPrice(power, true), getBSPrice(power, true), EPS);
      assertEquals(getPrice(power, false), getBSPrice(power, false), EPS);
    }
  }

  private double getPrice(final double power, final boolean isCall) {
    return MODEL
        .getGreeks(getDefinition(power, isCall), BUNDLE, REQUIRED_GREEKS)
        .get(Greek.FAIR_PRICE);
  }

  private double getBSPrice(final double power, final boolean isCall) {
    final StandardOptionDataBundle bsBundle = getModifiedDataBundle(BUNDLE, power);
    return BS_MODEL
        .getGreeks(getDefinition(power, isCall), bsBundle, REQUIRED_GREEKS)
        .get(Greek.FAIR_PRICE);
  }

  private AsymmetricPowerOptionDefinition getDefinition(final double power, final boolean isCall) {
    return new AsymmetricPowerOptionDefinition(STRIKE, EXPIRY, power, isCall);
  }

  private StandardOptionDataBundle getModifiedDataBundle(
      final StandardOptionDataBundle data, final double p) {
    final double t = DateUtils.getDifferenceInYears(DATE, EXPIRY);
    final double spot = Math.pow(data.getSpot(), p);
    double sigma = data.getVolatility(t, STRIKE);
    final double b = p * (data.getCostOfCarry() + (p - 1) * sigma * sigma * 0.5);
    sigma *= p;
    return new StandardOptionDataBundle(
        CURVE, b, new VolatilitySurface(ConstantDoublesSurface.from(sigma)), spot, DATE);
  }
}
public class GapOptionDefinitionTest {
  private static final double DELTA = 10;
  private static final double STRIKE = 50;
  private static final Expiry EXPIRY = new Expiry(DateUtils.getUTCDate(2010, 1, 1));
  private static final boolean IS_CALL = true;
  private static final double PAYOFF_STRIKE = 55;
  private static final GapOptionDefinition CALL =
      new GapOptionDefinition(STRIKE, EXPIRY, true, PAYOFF_STRIKE);
  private static final GapOptionDefinition PUT =
      new GapOptionDefinition(STRIKE, EXPIRY, false, PAYOFF_STRIKE);
  private static final StandardOptionDataBundle DATA =
      new StandardOptionDataBundle(
          new YieldCurve(ConstantDoublesCurve.from(0.03)),
          0.03,
          new VolatilitySurface(ConstantDoublesSurface.from(0.2)),
          STRIKE,
          DateUtils.getUTCDate(2009, 1, 1));

  @Test(expectedExceptions = IllegalArgumentException.class)
  public void testNegativePayoffStrike() {
    new GapOptionDefinition(STRIKE, EXPIRY, IS_CALL, -PAYOFF_STRIKE);
  }

  @Test(expectedExceptions = IllegalArgumentException.class)
  public void testNullData() {
    CALL.getPayoffFunction().getPayoff(null, null);
  }

  @Test
  public void test() {
    GapOptionDefinition other = new GapOptionDefinition(STRIKE, EXPIRY, true, PAYOFF_STRIKE);
    assertEquals(other, CALL);
    assertEquals(other.hashCode(), CALL.hashCode());
    other = new GapOptionDefinition(STRIKE + 1, EXPIRY, true, PAYOFF_STRIKE);
    assertFalse(other.equals(CALL));
    other =
        new GapOptionDefinition(
            STRIKE, new Expiry(DateUtils.getUTCDate(2010, 3, 1)), true, PAYOFF_STRIKE);
    assertFalse(other.equals(CALL));
    other = new GapOptionDefinition(STRIKE, EXPIRY, false, PAYOFF_STRIKE);
    assertFalse(other.equals(CALL));
    other = new GapOptionDefinition(STRIKE, EXPIRY, true, PAYOFF_STRIKE + 1);
    assertFalse(other.equals(CALL));
  }

  @Test
  public void testExerciseFunction() {
    StandardOptionDataBundle data = DATA.withSpot(STRIKE + DELTA);
    assertFalse(CALL.getExerciseFunction().shouldExercise(data, null));
    assertFalse(PUT.getExerciseFunction().shouldExercise(data, null));
    data = DATA.withSpot(STRIKE - DELTA);
    assertFalse(CALL.getExerciseFunction().shouldExercise(data, null));
    assertFalse(PUT.getExerciseFunction().shouldExercise(data, null));
  }

  @Test
  public void testPayoffFunction() {
    assertEquals(CALL.getPayoffFunction().getPayoff(DATA, null), 0, 0);
    assertEquals(PUT.getPayoffFunction().getPayoff(DATA, null), 0, 0);
    double spot = STRIKE + DELTA;
    StandardOptionDataBundle data = DATA.withSpot(spot);
    assertEquals(CALL.getPayoffFunction().getPayoff(data, null), spot - PAYOFF_STRIKE, 0);
    assertEquals(PUT.getPayoffFunction().getPayoff(data, null), 0, 0);
    spot = STRIKE - DELTA;
    data = DATA.withSpot(spot);
    assertEquals(CALL.getPayoffFunction().getPayoff(data, null), 0, 0);
    assertEquals(PUT.getPayoffFunction().getPayoff(data, null), PAYOFF_STRIKE - spot, 0);
  }
}