class ZSpreadCalculator {

  public Map<String, List<DoublesPair>> calculatePriceSensitivityToCurve(final Annuity<? extends Payment> annuity, final T curves, final double zSpread) {
    ArgumentChecker.notNull(annuity, "annuity");
    ArgumentChecker.notNull(curves, "curves");

    final MultipleCurrencyMulticurveSensitivity pvss = annuity.accept(_pvSensitivityCalculator, curves);
    final Set<Currency> currencies = pvss.getCurrencies();
    if (currencies.size() != 1) {
      throw new IllegalStateException("Had more than one currency in result: " + pvss.getCurrencies());
    }
    final MulticurveSensitivity sensitivities = pvss.getSensitivity(Iterables.getOnlyElement(currencies));
    if (Double.doubleToLongBits(zSpread) == 0) {
      return sensitivities.getYieldDiscountingSensitivities();
    }
    final Map<String, List<DoublesPair>> result = new HashMap<>();
    for (final Map.Entry<String, List<DoublesPair>> entry : sensitivities.getYieldDiscountingSensitivities().entrySet()) {
      final List<DoublesPair> unadjusted = entry.getValue();
      final ArrayList<DoublesPair> adjusted = new ArrayList<>(unadjusted.size());
      for (final DoublesPair pair : unadjusted) {
        final DoublesPair newPair = DoublesPair.of(pair.first, pair.second * Math.exp(-zSpread * pair.first));
        adjusted.add(newPair);
      }
      result.put(entry.getKey(), adjusted);
    }
    return result;
  }

  public  ZSpreadCalculator(final InstrumentDerivativeVisitor<T, MultipleCurrencyAmount> pvCalculator,
      final InstrumentDerivativeVisitor<T, MultipleCurrencyMulticurveSensitivity> pvSensitivityCalculator);

}