FFTOptionModel implements OptionModel<EuropeanVanillaOptionDefinition, BlackOptionDataBundle> { @Override public GreekResultCollection getGreeks(final EuropeanVanillaOptionDefinition definition, final BlackOptionDataBundle dataBundle, final Set<Greek> requiredGreeks) { Validate.notNull(definition, "definition"); Validate.notNull(dataBundle, "data bundle"); Validate.notNull(requiredGreeks, "required greeks"); if (!requiredGreeks.contains(Greek.FAIR_PRICE)) { throw new NotImplementedException("Can only calculate fair price at the moment: asked for " + requiredGreeks); } if (requiredGreeks.size() > 1) { s_logger.warn("Can only calculate fair price - ignoring other greeks"); } final ZonedDateTime date = dataBundle.getDate(); final EuropeanVanillaOption option = EuropeanVanillaOption.fromDefinition(definition, date); final BlackFunctionData data = BlackFunctionData.fromDataBundle(dataBundle, definition); double fwd = data.getForward(); double df = data.getDiscountFactor(); double t = option.getTimeToExpiry(); boolean isCall = option.isCall(); double limitSigma = data.getBlackVolatility(); final double[][] prices = PRICER.price(fwd, df, t, isCall, _characteristicExponent, _nStrikes, _maxDeltaMoneyness, limitSigma, _alpha, _tolerance); final int n = prices.length; final double[] k = new double[n]; final double[] price = new double[n]; for (int i = 0; i < n; i++) { k[i] = prices[i][0]; price[i] = prices[i][1]; } final double fairValue = INTERPOLATOR.interpolate(INTERPOLATOR.getDataBundleFromSortedArrays(k, price), definition.getStrike()); final GreekResultCollection result = new GreekResultCollection(); result.put(Greek.FAIR_PRICE, fairValue); return result; } FFTOptionModel(final MartingaleCharacteristicExponent characteristicExponent);  FFTOptionModel(final MartingaleCharacteristicExponent characteristicExponent, final int nStrikes, final double maxDeltaMoneyness, final double alpha, final double tolerance); @Override GreekResultCollection getGreeks(final EuropeanVanillaOptionDefinition definition, final BlackOptionDataBundle dataBundle, final Set<Greek> requiredGreeks);  }
@Test(expectedExceptions = IllegalArgumentException.class) public void testNullDefinition() { FFT_MODEL.getGreeks(null, BLACK_DATA, GREEKS); }
@Test(expectedExceptions = IllegalArgumentException.class) public void testNullData() { FFT_MODEL.getGreeks(ITM_CALL, null, GREEKS); }
@Test(expectedExceptions = IllegalArgumentException.class) public void testNullGreeks() { FFT_MODEL.getGreeks(ITM_CALL, BLACK_DATA, null); }
@Test(expectedExceptions = NotImplementedException.class) public void testWrongGreeks() { FFT_MODEL.getGreeks(ITM_CALL, BLACK_DATA, Sets.newHashSet(Greek.DELTA, Greek.GAMMA)); }
@Test public void testPricing() { GreekResultCollection fftPrice = FFT_MODEL.getGreeks(ITM_CALL, BLACK_DATA, GREEKS); GreekResultCollection bsmPrice = BSM_MODEL.getGreeks(ITM_CALL, BSM_DATA, GREEKS); assertEquals(fftPrice.size(), 1); assertEquals(fftPrice.get(Greek.FAIR_PRICE), bsmPrice.get(Greek.FAIR_PRICE), EPS); fftPrice = FFT_MODEL.getGreeks(OTM_CALL, BLACK_DATA, GREEKS); bsmPrice = BSM_MODEL.getGreeks(OTM_CALL, BSM_DATA, GREEKS); assertEquals(fftPrice.size(), 1); assertEquals(fftPrice.get(Greek.FAIR_PRICE), bsmPrice.get(Greek.FAIR_PRICE), EPS); fftPrice = FFT_MODEL.getGreeks(OTM_PUT, BLACK_DATA, GREEKS); bsmPrice = BSM_MODEL.getGreeks(OTM_PUT, BSM_DATA, GREEKS); assertEquals(fftPrice.size(), 1); assertEquals(fftPrice.get(Greek.FAIR_PRICE), bsmPrice.get(Greek.FAIR_PRICE), EPS); fftPrice = FFT_MODEL.getGreeks(ITM_PUT, BLACK_DATA, GREEKS); bsmPrice = BSM_MODEL.getGreeks(ITM_PUT, BSM_DATA, GREEKS); assertEquals(fftPrice.size(), 1); assertEquals(fftPrice.get(Greek.FAIR_PRICE), bsmPrice.get(Greek.FAIR_PRICE), EPS); }