### Question:
ImpliedTrinomialTreeFxOptionCalibrator { public int getNumberOfSteps() { return nSteps; } ImpliedTrinomialTreeFxOptionCalibrator(int nSteps); int getNumberOfSteps(); RecombiningTrinomialTreeData calibrateTrinomialTree(
      ResolvedFxVanillaOption option,
      RatesProvider ratesProvider,
      BlackFxOptionVolatilities volatilities); RecombiningTrinomialTreeData calibrateTrinomialTree(
      double timeToExpiry,
      CurrencyPair currencyPair,
      RatesProvider ratesProvider,
      BlackFxOptionVolatilities volatilities);  }### Answer:
@Test public void test_recoverVolatility() { int nSteps = TREE_DATA.getNumberOfSteps(); double spot = TREE_DATA.getSpot(); double timeToExpiry = TREE_DATA.getTime(nSteps); double dfDom = RATE_PROVIDER.discountFactors(USD).discountFactor(timeToExpiry); double dfFor = RATE_PROVIDER.discountFactors(EUR).discountFactor(timeToExpiry); double forward = spot * dfFor / dfDom; for (int i = 0; i < 100; ++i) { double strike = spot * (0.8 + 0.004 * i); OptionFunction func = EuropeanVanillaOptionFunction.of(strike, timeToExpiry, PutCall.CALL, nSteps); double price = TREE.optionPrice(func, TREE_DATA); double impliedVol = BlackFormulaRepository.impliedVolatility(price / dfDom, forward, strike, timeToExpiry, true); double orgVol = VOLS.volatility(FX_PRODUCT.getCurrencyPair(), timeToExpiry, strike, forward); assertThat(impliedVol).isCloseTo(orgVol, offset(orgVol * 0.1)); double priceMrkt = TREE.optionPrice(func, TREE_DATA_MRKT); double impliedVolMrkt = BlackFormulaRepository.impliedVolatility(priceMrkt / dfDom, forward, strike, timeToExpiry, true); double orgVolMrkt = VOLS_MRKT.volatility(FX_PRODUCT.getCurrencyPair(), timeToExpiry, strike, forward); assertThat(impliedVolMrkt).isCloseTo(orgVolMrkt, offset(orgVolMrkt * 0.1)); } }