/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.sesame; import java.util.ArrayList; import java.util.List; import java.util.Set; import com.opengamma.analytics.financial.forex.method.FXMatrix; import com.opengamma.analytics.financial.provider.curve.CurveBuildingBlockBundle; import com.opengamma.analytics.financial.provider.description.interestrate.MulticurveProviderDiscount; import com.opengamma.analytics.financial.provider.description.interestrate.ProviderUtils; import com.opengamma.sesame.function.scenarios.ScenarioFunction; import com.opengamma.sesame.trade.TradeWrapper; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.result.FailureStatus; import com.opengamma.util.result.Result; import com.opengamma.util.tuple.Pair; import com.opengamma.util.tuple.Pairs; /** * Returns a pre-calibrated curve that should be used for calculations for a trade. * <p> * The curve is taken from the scenario arguments. */ public class PreCalibratedMulticurveFn implements DiscountingMulticurveCombinerFn, ScenarioFunction<PreCalibratedMulticurveArguments, PreCalibratedMulticurveFn> { private final CurveSelector _curveSelector; /** * @param curveSelector provides the names of curves that should be used for a trade */ public PreCalibratedMulticurveFn(CurveSelector curveSelector) { _curveSelector = ArgumentChecker.notNull(curveSelector, "exposureSelector"); } /** * Delegates to {@link #getMulticurveBundle(Environment, TradeWrapper)}. * * @param env the environment used for calculations * @param trade the trade * @param fxMatrix not used * @return the multicurve bundle for the trade */ @Override public Result<Pair<MulticurveProviderDiscount, CurveBuildingBlockBundle>> createMergedMulticurveBundle( Environment env, TradeWrapper trade, FXMatrix fxMatrix) { Result<MulticurveBundle> result = getMulticurveBundle(env, trade); if (!result.isSuccess()) { return Result.failure(result); } MulticurveBundle multicurve = result.getValue(); return Result.success(Pairs.of(multicurve.getMulticurveProvider(), multicurve.getCurveBuildingBlockBundle())); } @Override public Result<MulticurveBundle> getMulticurveBundle(Environment env, TradeWrapper<?> trade) { List<PreCalibratedMulticurveArguments> scenarioArguments = env.getScenarioArguments(this); if (scenarioArguments.size() != 1) { return Result.failure(FailureStatus.MISSING_DATA, "One instance of PreCalibratedMulticurveArguments expected " + "in the scenario arguments, found {}", scenarioArguments.size()); } List<MulticurveProviderDiscount> multicurves = new ArrayList<>(); List<CurveBuildingBlockBundle> blockBundles = new ArrayList<>(); List<Result<?>> failures = new ArrayList<>(); Set<String> curveNames = _curveSelector.getMulticurveNames(trade.getTrade()); if (curveNames.isEmpty()) { return Result.failure(FailureStatus.MISSING_DATA, "No matching curves found for trade: {}", trade); } // TODO it's unclear whether there will ever be multiple curves for a trade - if not this can be simplified if (curveNames.size() == 1) { return scenarioArguments.get(0).getMulticurveBundle(curveNames.iterator().next()); } for (String curveName : curveNames) { Result<MulticurveBundle> multicurve = scenarioArguments.get(0).getMulticurveBundle(curveName); if (multicurve.isSuccess()) { multicurves.add(multicurve.getValue().getMulticurveProvider()); blockBundles.add(multicurve.getValue().getCurveBuildingBlockBundle()); } else { failures.add(multicurve); } } if (!failures.isEmpty()) { return Result.failure(failures); } MulticurveProviderDiscount multicurve = ProviderUtils.mergeDiscountingProviders(multicurves); CurveBuildingBlockBundle mergedBlockBundle = new CurveBuildingBlockBundle(); for (CurveBuildingBlockBundle blockBundle : blockBundles) { mergedBlockBundle.addAll(blockBundle); } return Result.success(new MulticurveBundle(multicurve, mergedBlockBundle)); } @Override public Class<PreCalibratedMulticurveArguments> getArgumentType() { return PreCalibratedMulticurveArguments.class; } }