InterpolatedMulticurveBundleFn implements DiscountingMulticurveBundleFn { @Override public Result<MulticurveBundle> generateBundle( Environment env, CurveConstructionConfiguration curveConfig, Map<CurveConstructionConfiguration, Result<MulticurveBundle>> requiredCurves) { Result<Boolean> result = Result.success(true); ZonedDateTime now = env.getValuationTime(); MulticurveProviderDiscount curveBundle = new MulticurveProviderDiscount(new FXMatrix()); LinkedHashMap<String, Pair<CurveBuildingBlock, DoubleMatrix2D>> unitBundles = new LinkedHashMap<>(); for (CurveGroupConfiguration group: curveConfig.getCurveGroups()) { for (Entry<AbstractCurveDefinition, List<? extends CurveTypeConfiguration>> entry: group.resolveTypesForCurves().entrySet()) { LinkedHashMap<String, Pair<Integer, Integer>> unitMap = new LinkedHashMap<>(); int totalNodes = 0; AbstractCurveDefinition curve = entry.getKey(); Result<AbstractCurveSpecification> curveSpecResult = _curveSpecificationProvider.getCurveSpecification(env, curve); if (curveSpecResult.isSuccess()) { InterpolatedCurveSpecification specification = (InterpolatedCurveSpecification) curveSpecResult.getValue(); Result<Map<ExternalIdBundle, Double>> marketDataResult = _curveSpecificationMarketDataProvider.requestData(env, specification); if (marketDataResult.getStatus() == SuccessStatus.SUCCESS) { SnapshotDataBundle snapshot = createSnapshotDataBundle(marketDataResult.getValue()); Set<CurveNodeWithIdentifier> nodes = specification.getNodes(); int n = nodes.size(); double[] ttm = new double[n]; double[] yields = new double[n]; double[][] jacobian = new double[n][n]; int i = 0; int compoundPeriodsPerYear = 0; int nNodesForCurve = specification.getNodes().size(); boolean isYield = false; for (CurveNodeWithIdentifier node: nodes) { CurveNode curveNode = node.getCurveNode(); if (curveNode instanceof ContinuouslyCompoundedRateNode) { if (i == 0) { isYield = true; } else { if (!isYield) { throw new OpenGammaRuntimeException("Expected only continuously-compounded rate nodes, found " + curveNode); } } } else if (curveNode instanceof DiscountFactorNode) { if (i == 0) { isYield = false; } else { if (isYield) { throw new OpenGammaRuntimeException("Expected only discount factor nodes, found " + curveNode); } } } else if (curveNode instanceof PeriodicallyCompoundedRateNode) { if (i == 0) { compoundPeriodsPerYear = ((PeriodicallyCompoundedRateNode) curveNode).getCompoundingPeriodsPerYear(); isYield = true; } else { if (!isYield) { throw new OpenGammaRuntimeException("Was expecting only periodically compounded nodes; have " + curveNode); } } } else { throw new OpenGammaRuntimeException("Can only handle discount factor or continuously-compounded rate nodes; have " + curveNode); } Tenor maturity = curveNode.getResolvedMaturity(); ttm[i] = TimeCalculator.getTimeBetween(now, now.plus(maturity.getPeriod())); Double yield = snapshot.getDataPoint(node.getIdentifier()); if (yield == null) { throw new OpenGammaRuntimeException("Could not get market data value for " + node); } yields[i] = yield; jacobian[i][i] = 1; i++; } Interpolator1D interpolator = CombinedInterpolatorExtrapolatorFactory.getInterpolator(specification.getInterpolatorName(), specification.getLeftExtrapolatorName(), specification.getRightExtrapolatorName()); String curveName = curve.getName(); InterpolatedDoublesCurve rawCurve = InterpolatedDoublesCurve.from(ttm, yields, interpolator, curveName); YieldAndDiscountCurve discountCurve; if (compoundPeriodsPerYear != 0 && isYield) { discountCurve = YieldPeriodicCurve.from(compoundPeriodsPerYear, rawCurve); } else if (isYield) { discountCurve = new YieldCurve(curveName, rawCurve); } else { discountCurve = new DiscountCurve(curveName, rawCurve); } for (CurveTypeConfiguration type: entry.getValue()) { if (type instanceof DiscountingCurveTypeConfiguration) { Currency currency = Currency.parse(((DiscountingCurveTypeConfiguration) type).getReference()); curveBundle.setCurve(currency, discountCurve); } else if (type instanceof IborCurveTypeConfiguration) { curveBundle.setCurve(createIborIndex((IborCurveTypeConfiguration) type), discountCurve); } else if (type instanceof OvernightCurveTypeConfiguration) { curveBundle.setCurve(createIndexON((OvernightCurveTypeConfiguration) type), discountCurve); } else { throw new OpenGammaRuntimeException("Unsupported curve type configuration " + type); } } unitMap.put(curveName, Pairs.of(totalNodes, nNodesForCurve)); unitBundles.put(curveName, Pairs.of(new CurveBuildingBlock(unitMap), new DoubleMatrix2D(jacobian))); totalNodes += nNodesForCurve; } else { result = Result.failure(result, marketDataResult); } } else { result = Result.failure(result, curveSpecResult); } } } if (result.isSuccess()) { return Result.success(new MulticurveBundle(curveBundle, new CurveBuildingBlockBundle(unitBundles))); } else { return Result.failure(result); } } InterpolatedMulticurveBundleFn(CurveSpecificationFn curveSpecificationProvider,
                                        CurveSpecificationMarketDataFn curveSpecificationMarketDataProvider); @Override Result<MulticurveBundle> generateBundle(
     Environment env, CurveConstructionConfiguration curveConfig,
     Map<CurveConstructionConfiguration, Result<MulticurveBundle>> requiredCurves); @Override Result<ImpliedDepositCurveData> extractImpliedDepositCurveData(
      Environment env, CurveConstructionConfiguration curveConfig,
      Map<CurveConstructionConfiguration, Result<MulticurveBundle>> builtCurves);  }
@Test public void testUSD() { Result<MulticurveBundle> bundle = _multicurveBundleFn.generateBundle( _environment, _usdDiscountingCCC, ImmutableMap.<CurveConstructionConfiguration, Result<MulticurveBundle>>of()); assertTrue("Curve bundle result failed", bundle.isSuccess()); MulticurveBundle value = bundle.getValue(); MulticurveProviderDiscount multicurve = value.getMulticurveProvider(); double expectedDF = 1.0; for (Tenor tenor : s_tenors) { double time = TimeCalculator.getTimeBetween(_environment.getValuationTime(), _environment.getValuationTime().plus(tenor.getPeriod())); ExternalIdBundle id = ExternalIdBundle.of("Ticker", tenor.toFormattedString().substring(1)); RawId<Double> marketDataId = RawId.of(id); Result<Double> result = _environment.getMarketDataBundle().get(marketDataId, Double.class); expectedDF = result.getValue(); double actualDF = multicurve.getDiscountFactor(Currency.USD, time); assertEquals("USD DF for tenor " + tenor + " (" + tenor.toFormattedString() + ") mismatch", expectedDF, actualDF, 10E-6); } double actualDF = multicurve.getDiscountFactor(Currency.USD, 10000d); assertEquals("Right extrapolation not flat", expectedDF, actualDF, 10E-6); }