private InterestRateFutureSecurity createIRFuture() {
   Expiry expiry =
       new Expiry(ZonedDateTime.of(LocalDate.of(2014, 6, 18), LocalTime.of(0, 0), ZoneOffset.UTC));
   String tradingExchange = "";
   String settlementExchange = "";
   Currency currency = Currency.USD;
   double unitAmount = 1000;
   ExternalId underlyingId = InterestRateMockSources.getLiborIndexId();
   String category = "";
   InterestRateFutureSecurity irFuture =
       new InterestRateFutureSecurity(
           expiry,
           tradingExchange,
           settlementExchange,
           currency,
           unitAmount,
           underlyingId,
           category);
   // Need this for time series lookup
   ExternalId irFutureId = ExternalSchemes.syntheticSecurityId("Test future");
   irFuture.setExternalIdBundle(irFutureId.toBundle());
   return irFuture;
 }
/** Tests for interest rate future options analytics functions using the black calculator. */
@Test(groups = TestGroup.UNIT)
public class IRFutureOptionFnTest {

  private static final ZonedDateTime VALUATION_TIME = DateUtils.getUTCDate(2014, 1, 22);
  public static final LocalDate TRADE_DATE = LocalDate.of(2000, 1, 1);
  public static final OffsetTime TRADE_TIME = OffsetTime.of(LocalTime.of(0, 0), ZoneOffset.UTC);
  private static final LocalDate MARKET_DATA_DATE = LocalDate.of(2014, 2, 18);
  private static final double STD_TOLERANCE_PV = 1.0E-3;
  private IRFutureOptionFn _blackIRFutureOptionFn;
  private IRFutureOptionFn _normalIRFutureOptionFn;
  private InterestRateFutureSecurity _irFuture = createIRFuture();
  private IRFutureOptionTrade _irFutureOptionTrade = createIRFutureOptionTrade();
  private FunctionRunner _functionRunner;
  private static final CalculationArguments ARGS =
      CalculationArguments.builder()
          .valuationTime(VALUATION_TIME)
          .marketDataSpecification(LiveMarketDataSpecification.LIVE_SPEC)
          .build();
  private static final Interpolator1D LINEAR_FLAT =
      CombinedInterpolatorExtrapolatorFactory.getInterpolator(
          Interpolator1DFactory.LINEAR,
          Interpolator1DFactory.FLAT_EXTRAPOLATOR,
          Interpolator1DFactory.FLAT_EXTRAPOLATOR);
  private static final GridInterpolator2D INTERPOLATOR_2D =
      new GridInterpolator2D(LINEAR_FLAT, LINEAR_FLAT);
  private static final InterpolatedDoublesSurface TEST_SURFACE =
      InterpolatedDoublesSurface.from(
          new double[] {.1, .2, .3},
          new double[] {.1, .2, .3},
          new double[] {.1, .2, .3},
          INTERPOLATOR_2D);

  private static MarketDataEnvironment createSuppliedData() {
    LocalDateDoubleTimeSeries optionPrice =
        ImmutableLocalDateDoubleTimeSeries.of(VALUATION_TIME.toLocalDate(), 0.975);
    RawId<Double> optionRawId =
        RawId.of(ExternalSchemes.syntheticSecurityId("Test future option").toBundle());
    MarketDataEnvironmentBuilder builder = new MarketDataEnvironmentBuilder();
    builder.add(optionRawId, optionPrice);
    builder.add(VolatilitySurfaceId.of("TestExchange"), new VolatilitySurface(TEST_SURFACE));
    builder.valuationTime(VALUATION_TIME);
    return builder.build();
  }

  @BeforeClass
  public void setUpClass() {

    ImmutableMap<Class<?>, Object> components = generateComponents();
    VersionCorrectionProvider vcProvider = new FixedInstantVersionCorrectionProvider(Instant.now());
    ServiceContext serviceContext =
        ServiceContext.of(components).with(VersionCorrectionProvider.class, vcProvider);
    ThreadLocalServiceContext.init(serviceContext);

    ComponentMap componentMap = ComponentMap.of(components);
    MarketDataSource marketDataSource =
        InterestRateMockSources.createMarketDataSource(MARKET_DATA_DATE, true);
    TestMarketDataFactory marketDataFactory = new TestMarketDataFactory(marketDataSource);
    ConfigLink<CurrencyMatrix> currencyMatrixLink =
        ConfigLink.resolved(componentMap.getComponent(CurrencyMatrix.class));
    List<MarketDataBuilder> builders =
        MarketDataBuilders.standard(componentMap, "dataSource", currencyMatrixLink);

    MarketDataEnvironmentFactory environmentFactory =
        new MarketDataEnvironmentFactory(marketDataFactory, builders);

    _functionRunner = new FunctionRunner(environmentFactory);
    _normalIRFutureOptionFn =
        FunctionModel.build(IRFutureOptionFn.class, normalConfig(), componentMap);
    _blackIRFutureOptionFn =
        FunctionModel.build(IRFutureOptionFn.class, blackConfig(), componentMap);
  }

  private FunctionModelConfig blackConfig() {
    FunctionModelConfig config =
        config(
            arguments(
                function(
                    MarketExposureSelector.class,
                    argument(
                        "exposureFunctions",
                        ConfigLink.resolved(InterestRateMockSources.mockExposureFunctions()))),
                function(
                    RootFinderConfiguration.class,
                    argument("rootFinderAbsoluteTolerance", 1e-9),
                    argument("rootFinderRelativeTolerance", 1e-9),
                    argument("rootFinderMaxIterations", 1000)),
                function(
                    DefaultCurveNodeConverterFn.class,
                    argument("timeSeriesDuration", RetrievalPeriod.of(Period.ofYears(1))))),
            implementations(
                IRFutureOptionFn.class, DefaultIRFutureOptionFn.class,
                IRFutureOptionCalculatorFactory.class, IRFutureOptionBlackCalculatorFactory.class,
                CurveSpecificationMarketDataFn.class, DefaultCurveSpecificationMarketDataFn.class,
                FXMatrixFn.class, DefaultFXMatrixFn.class,
                BlackSTIRFuturesProviderFn.class, TestBlackSTIRFuturesProviderFn.class,
                DiscountingMulticurveCombinerFn.class,
                    ExposureFunctionsDiscountingMulticurveCombinerFn.class,
                CurveDefinitionFn.class, DefaultCurveDefinitionFn.class,
                CurveLabellingFn.class, CurveDefinitionCurveLabellingFn.class,
                CurveSpecificationFn.class, DefaultCurveSpecificationFn.class,
                CurveConstructionConfigurationSource.class,
                    ConfigDBCurveConstructionConfigurationSource.class,
                CurveNodeConverterFn.class, DefaultCurveNodeConverterFn.class,
                HistoricalMarketDataFn.class, DefaultHistoricalMarketDataFn.class,
                FixingsFn.class, DefaultFixingsFn.class,
                MarketDataFn.class, DefaultMarketDataFn.class,
                CurveSelector.class, MarketExposureSelector.class,
                DiscountingMulticurveCombinerFn.class, CurveSelectorMulticurveBundleFn.class));

    return config;
  }

  private FunctionModelConfig normalConfig() {
    FunctionModelConfig config =
        config(
            arguments(
                function(
                    MarketExposureSelector.class,
                    argument(
                        "exposureFunctions",
                        ConfigLink.resolved(InterestRateMockSources.mockExposureFunctions()))),
                function(
                    RootFinderConfiguration.class,
                    argument("rootFinderAbsoluteTolerance", 1e-9),
                    argument("rootFinderRelativeTolerance", 1e-9),
                    argument("rootFinderMaxIterations", 1000)),
                function(
                    TestIRFutureOptionNormalSurfaceProviderFn.class,
                    argument("moneynessOnPrice", false)),
                function(
                    DefaultCurveNodeConverterFn.class,
                    argument("timeSeriesDuration", RetrievalPeriod.of(Period.ofYears(1))))),
            implementations(
                IRFutureOptionFn.class, DefaultIRFutureOptionFn.class,
                IRFutureOptionCalculatorFactory.class, IRFutureOptionNormalCalculatorFactory.class,
                CurveSpecificationMarketDataFn.class, DefaultCurveSpecificationMarketDataFn.class,
                FXMatrixFn.class, DefaultFXMatrixFn.class,
                CurveDefinitionFn.class, DefaultCurveDefinitionFn.class,
                CurveLabellingFn.class, CurveDefinitionCurveLabellingFn.class,
                CurveSpecificationFn.class, DefaultCurveSpecificationFn.class,
                CurveConstructionConfigurationSource.class,
                    ConfigDBCurveConstructionConfigurationSource.class,
                CurveNodeConverterFn.class, DefaultCurveNodeConverterFn.class,
                HistoricalMarketDataFn.class, DefaultHistoricalMarketDataFn.class,
                FixingsFn.class, DefaultFixingsFn.class,
                MarketDataFn.class, DefaultMarketDataFn.class,
                CurveSelector.class, MarketExposureSelector.class,
                IRFutureOptionNormalSurfaceProviderFn.class,
                    TestIRFutureOptionNormalSurfaceProviderFn.class,
                DiscountingMulticurveCombinerFn.class, CurveSelectorMulticurveBundleFn.class));

    return config;
  }

  private ImmutableMap<Class<?>, Object> generateComponents() {
    ImmutableMap.Builder<Class<?>, Object> builder = ImmutableMap.builder();
    for (Map.Entry<Class<?>, Object> entry :
        InterestRateMockSources.generateBaseComponents().entrySet()) {
      Class<?> key = entry.getKey();
      if (key.equals(SecuritySource.class)) {
        appendSecuritySource((SecuritySource) entry.getValue());
      }
      builder.put(key, entry.getValue());
    }
    return builder.build();
  }

  // TODO - this assumes knowledge of the underlying source, should find a better way to do this
  private void appendSecuritySource(SecuritySource source) {
    SecurityMaster master = ((MasterSecuritySource) source).getMaster();
    master.add(new SecurityDocument(_irFuture));
  }

  private InterestRateFutureSecurity createIRFuture() {
    Expiry expiry =
        new Expiry(ZonedDateTime.of(LocalDate.of(2014, 6, 18), LocalTime.of(0, 0), ZoneOffset.UTC));
    String tradingExchange = "";
    String settlementExchange = "";
    Currency currency = Currency.USD;
    double unitAmount = 1000;
    ExternalId underlyingId = InterestRateMockSources.getLiborIndexId();
    String category = "";
    InterestRateFutureSecurity irFuture =
        new InterestRateFutureSecurity(
            expiry,
            tradingExchange,
            settlementExchange,
            currency,
            unitAmount,
            underlyingId,
            category);
    // Need this for time series lookup
    ExternalId irFutureId = ExternalSchemes.syntheticSecurityId("Test future");
    irFuture.setExternalIdBundle(irFutureId.toBundle());
    return irFuture;
  }

  private IRFutureOptionTrade createIRFutureOptionTrade() {

    String exchange = "TestExchange";
    ExerciseType exerciseType = new EuropeanExerciseType();
    double pointValue = Double.NaN;
    boolean margined = true;
    double strike = 0.99;
    OptionType optionType = OptionType.PUT;
    ExternalId irFutureId = Iterables.getOnlyElement(_irFuture.getExternalIdBundle());
    IRFutureOptionSecurity irFutureOption =
        new IRFutureOptionSecurity(
            exchange,
            _irFuture.getExpiry(),
            exerciseType,
            irFutureId,
            pointValue,
            margined,
            _irFuture.getCurrency(),
            strike,
            optionType);
    // Need this for time series lookup
    irFutureOption.setExternalIdBundle(
        ExternalSchemes.syntheticSecurityId("Test future option").toBundle());

    Counterparty counterparty =
        new SimpleCounterparty(ExternalId.of(Counterparty.DEFAULT_SCHEME, "COUNTERPARTY"));
    BigDecimal tradeQuantity = BigDecimal.valueOf(1);
    SimpleTrade trade =
        new SimpleTrade(irFutureOption, tradeQuantity, counterparty, TRADE_DATE, TRADE_TIME);
    trade.setPremium(10.0);
    trade.setPremiumCurrency(Currency.USD);
    return new IRFutureOptionTrade(trade);
  }

  @Test
  public void testBlackPresentValue() {
    Result<MultipleCurrencyAmount> result =
        _functionRunner.runFunction(
            ARGS,
            createSuppliedData(),
            new Function<Environment, Result<MultipleCurrencyAmount>>() {
              @Override
              public Result<MultipleCurrencyAmount> apply(Environment env) {
                return _blackIRFutureOptionFn.calculatePV(env, _irFutureOptionTrade);
              }
            });
    assertSuccess(result);

    MultipleCurrencyAmount mca = result.getValue();
    assertThat(
        mca.getCurrencyAmount(Currency.USD).getAmount(),
        is(closeTo(-972.460677, STD_TOLERANCE_PV)));
  }

  @Test
  public void testBlackBucketedZeroDelta() {
    Result<BucketedCurveSensitivities> result =
        _functionRunner.runFunction(
            ARGS,
            createSuppliedData(),
            new Function<Environment, Result<BucketedCurveSensitivities>>() {
              @Override
              public Result<BucketedCurveSensitivities> apply(Environment env) {
                return _blackIRFutureOptionFn.calculateBucketedZeroIRDelta(
                    env, _irFutureOptionTrade);
              }
            });
    assertSuccess(result);
  }

  @Test
  public void testNormalPresentValue() {
    Result<MultipleCurrencyAmount> result =
        _functionRunner.runFunction(
            ARGS,
            createSuppliedData(),
            new Function<Environment, Result<MultipleCurrencyAmount>>() {
              @Override
              public Result<MultipleCurrencyAmount> apply(Environment env) {
                return _normalIRFutureOptionFn.calculatePV(env, _irFutureOptionTrade);
              }
            });
    assertSuccess(result);
    MultipleCurrencyAmount mca = result.getValue();
    assertThat(
        mca.getCurrencyAmount(Currency.USD).getAmount(),
        is(closeTo(-902.7156551, STD_TOLERANCE_PV)));
  }

  @Test
  public void testNormalPrice() {
    Result<Double> result =
        _functionRunner.runFunction(
            ARGS,
            createSuppliedData(),
            new Function<Environment, Result<Double>>() {
              @Override
              public Result<Double> apply(Environment env) {
                return _normalIRFutureOptionFn.calculateModelPrice(env, _irFutureOptionTrade);
              }
            });
    assertSuccess(result);
    Double price = result.getValue();
    assertThat(price, is(closeTo(0.072284344, STD_TOLERANCE_PV)));
  }

  @Test
  public void testNormalBucketedZeroDelta() {
    Result<BucketedCurveSensitivities> result =
        _functionRunner.runFunction(
            ARGS,
            createSuppliedData(),
            new Function<Environment, Result<BucketedCurveSensitivities>>() {
              @Override
              public Result<BucketedCurveSensitivities> apply(Environment env) {
                return _normalIRFutureOptionFn.calculateBucketedZeroIRDelta(
                    env, _irFutureOptionTrade);
              }
            });
    assertSuccess(result);
  }
}
public class TestPersistentOffsetTimeAsLongAndStringOffset extends DatabaseCapable {

  private static final OffsetTime[] offsetTimes =
      new OffsetTime[] {
        OffsetTime.of(LocalTime.of(12, 10, 31), ZoneOffset.UTC),
        OffsetTime.of(LocalTime.of(23, 7, 43, 120), ZoneOffset.ofHours(2))
      };

  private static EntityManagerFactory factory;

  @BeforeClass
  public static void setup() {
    factory = Persistence.createEntityManagerFactory("test1");
  }

  @AfterClass
  public static void tearDown() {
    factory.close();
  }

  @Test
  public void testPersist() {

    EntityManager manager = factory.createEntityManager();

    manager.getTransaction().begin();

    for (int i = 0; i < offsetTimes.length; i++) {

      OffsetTimeAsLongAndStringOffsetHolder item = new OffsetTimeAsLongAndStringOffsetHolder();
      item.setId(i);
      item.setName("test_" + i);
      item.setOffsetTime(offsetTimes[i]);

      manager.persist(item);
    }

    manager.flush();

    manager.getTransaction().commit();

    manager.close();

    manager = factory.createEntityManager();

    for (int i = 0; i < offsetTimes.length; i++) {

      OffsetTimeAsLongAndStringOffsetHolder item =
          manager.find(OffsetTimeAsLongAndStringOffsetHolder.class, Long.valueOf(i));

      assertNotNull(item);
      assertEquals(i, item.getId());
      assertEquals("test_" + i, item.getName());
      assertEquals(offsetTimes[i], item.getOffsetTime());
    }

    verifyDatabaseTable(
        manager, OffsetTimeAsLongAndStringOffsetHolder.class.getAnnotation(Table.class).name());

    manager.close();
  }
}