// -------------------------------------------------------------------------
  @Override
  public FunctionRequirements requirements(
      BulletPaymentTrade trade,
      Set<Measure> measures,
      CalculationParameters parameters,
      ReferenceData refData) {

    // extract data from product
    BulletPayment product = trade.getProduct();
    Currency currency = product.getCurrency();

    // use lookup to build requirements
    RatesMarketDataLookup ratesLookup = parameters.getParameter(RatesMarketDataLookup.class);
    return ratesLookup.requirements(currency);
  }
  // -------------------------------------------------------------------------
  @Override
  public Map<Measure, Result<?>> calculate(
      BulletPaymentTrade trade,
      Set<Measure> measures,
      CalculationParameters parameters,
      ScenarioMarketData scenarioMarketData,
      ReferenceData refData) {

    // resolve the trade once for all measures and all scenarios
    ResolvedBulletPaymentTrade resolved = trade.resolve(refData);

    // use lookup to query market data
    RatesMarketDataLookup ratesLookup = parameters.getParameter(RatesMarketDataLookup.class);
    RatesScenarioMarketData marketData = ratesLookup.marketDataView(scenarioMarketData);

    // loop around measures, calculating all scenarios for one measure
    Map<Measure, Result<?>> results = new HashMap<>();
    for (Measure measure : measures) {
      results.put(measure, calculate(measure, resolved, marketData));
    }
    return results;
  }
 @Override
 public Currency naturalCurrency(BulletPaymentTrade trade, ReferenceData refData) {
   return trade.getProduct().getCurrency();
 }
 @Override
 public Optional<String> identifier(BulletPaymentTrade target) {
   return target.getInfo().getId().map(id -> id.toString());
 }