class VolatilitySwapGreeksCalculator {

  public double[] getFXVolatilitySwapGreeks(final VolatilitySwapCalculatorResultWithStrikes result, final FXVolatilitySwap swap, final CarrLeeFXData data) {
    ArgumentChecker.notNull(result, "result");
    ArgumentChecker.notNull(swap, "swap");
    ArgumentChecker.notNull(data, "data");
    final double spot = data.getSpot();
    final double timeToExpiry = swap.getTimeToMaturity();
    ArgumentChecker.isTrue(Doubles.isFinite(timeToExpiry), "timeToExpiry should be finite");
    ArgumentChecker.isTrue(timeToExpiry > 0., "timeToExpiry should be positive");
    ArgumentChecker.isTrue(Doubles.isFinite(spot), "spot should be finite");
    ArgumentChecker.isTrue(spot > 0., "spot should be positive");
    final double domesticDF = data.getMulticurveProvider().getDiscountFactor(swap.getBaseCurrency(), timeToExpiry);
    final double foreignDF = data.getMulticurveProvider().getDiscountFactor(swap.getCounterCurrency(), timeToExpiry);
    final double domesticRate = -Math.log(domesticDF) / timeToExpiry;
    final double foreignRate = -Math.log(foreignDF) / timeToExpiry;
    ArgumentChecker.isTrue(Doubles.isFinite(domesticRate), "domestic rate should be finite");
    ArgumentChecker.isTrue(Doubles.isFinite(foreignRate), "foreign rate should be finite");

    final double[] putStrikes = result.getPutStrikes();
    final double forward = spot * Math.exp((domesticRate - foreignRate) * timeToExpiry);
    final double[] callStrikes = result.getCallStrikes();

    final int nPuts = putStrikes.length;
    final int nCalls = callStrikes.length;
    final SmileDeltaTermStructureParameters smile = data.getVolatilityData();
    final double[] putVols = new double[nPuts];
    final double[] callVols = new double[nCalls];

    for (int i = 0; i < nPuts; ++i) {
      putVols[i] = smile.getVolatility(Triple.of(timeToExpiry, putStrikes[i], forward));
    }
    final double stdVol = smile.getVolatility(Triple.of(timeToExpiry, forward, forward));
    for (int i = 0; i < nCalls; ++i) {
      callVols[i] = smile.getVolatility(Triple.of(timeToExpiry, callStrikes[i], forward));
    }

    return getGreeks(result, spot, putStrikes, callStrikes, timeToExpiry, domesticRate, foreignRate, putVols, stdVol, callVols);
  }

}