/** * Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.sesame.web.curves; import java.util.HashMap; import java.util.Map; import java.util.Set; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import org.apache.commons.lang.ArrayUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.threeten.bp.ZonedDateTime; import com.google.common.collect.ImmutableSet; import com.google.gson.Gson; import com.opengamma.analytics.financial.instrument.index.IborIndex; import com.opengamma.analytics.financial.instrument.index.IndexON; import com.opengamma.analytics.financial.model.interestrate.curve.DiscountCurve; import com.opengamma.analytics.financial.model.interestrate.curve.YieldAndDiscountCurve; import com.opengamma.analytics.financial.model.interestrate.curve.YieldCurve; import com.opengamma.analytics.financial.provider.description.interestrate.MulticurveProviderDiscount; import com.opengamma.engine.marketdata.spec.MarketDataSpecification; import com.opengamma.engine.marketdata.spec.MarketDataSpecificationParser; import com.opengamma.sesame.MulticurveBundle; import com.opengamma.sesame.marketdata.MarketDataEnvironment; import com.opengamma.sesame.marketdata.MarketDataEnvironmentBuilder; import com.opengamma.sesame.marketdata.MarketDataRequirement; import com.opengamma.sesame.marketdata.MulticurveId; import com.opengamma.sesame.marketdata.SingleValueRequirement; import com.opengamma.sesame.marketdata.builders.MarketDataEnvironmentFactory; import com.opengamma.sesame.marketdata.scenarios.SingleScenarioDefinition; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.money.Currency; /** * REST endpoint to obtain a curve bundle */ @Path("curvebundle/{bundle}/{spec}") public class CurveBundleResource { /** Builds market data in response to specified requirements */ private final MarketDataEnvironmentFactory _environmentFactory; private static final Logger s_logger = LoggerFactory.getLogger(CurveBundleResource.class); /** * @param environmentFactory builds market data in response to specified requirements */ public CurveBundleResource(MarketDataEnvironmentFactory environmentFactory) { _environmentFactory = ArgumentChecker.notNull(environmentFactory, "environmentFactory"); } /** * Rest endpoint to obtain curve bundle data * @param bundle the name of the bundle * @param spec the market data specification in the format {type}:{name/id} * @return a json representation of the bundle, split into discounting, forward ON and forward Ibor Curves */ @GET @Produces("application/json") public String buildCurveBundle(@PathParam("bundle") String bundle, @PathParam("spec") String spec) { MarketDataSpecification marketDataSpec = MarketDataSpecificationParser.parse(spec); ZonedDateTime valuationTime = ZonedDateTime.now(); MarketDataEnvironment suppliedData = MarketDataEnvironmentBuilder.empty(); MulticurveId multicurveId = MulticurveId.of(bundle); SingleValueRequirement requirement = SingleValueRequirement.of(multicurveId); Set<MarketDataRequirement> requirements = ImmutableSet.<MarketDataRequirement>of(requirement); SingleScenarioDefinition perturbations = SingleScenarioDefinition.base(); MarketDataEnvironment marketData = _environmentFactory.build(suppliedData, requirements, perturbations, marketDataSpec, valuationTime); MulticurveBundle curveBundle = (MulticurveBundle) marketData.getData().get(requirement); MulticurveProviderDiscount multicurveProvider = curveBundle.getMulticurveProvider(); Map<Currency, YieldAndDiscountCurve> discountingCurves = multicurveProvider.getDiscountingCurves(); Map<IndexON, YieldAndDiscountCurve> forwardONCurves = multicurveProvider.getForwardONCurves(); Map<IborIndex, YieldAndDiscountCurve> forwardIborCurves = multicurveProvider.getForwardIborCurves(); Map<String, Map<String, Object>> discounting = new HashMap<>(); Map<String, Map<String, Object>> forwardON = new HashMap<>(); Map<String, Map<String, Object>> forwardIbor = new HashMap<>(); for (Map.Entry<Currency, YieldAndDiscountCurve> entry : discountingCurves.entrySet()) { discounting.put(entry.getKey().getCode(), getCurveData(entry.getValue())); } for (Map.Entry<IndexON, YieldAndDiscountCurve> entry : forwardONCurves.entrySet()) { forwardON.put(entry.getKey().toString(), getCurveData(entry.getValue())); } for (Map.Entry<IborIndex, YieldAndDiscountCurve> entry : forwardIborCurves.entrySet()) { forwardIbor.put(entry.getKey().toString(), getCurveData(entry.getValue())); } Map<String, Map> curves = new HashMap<>(); curves.put("discounting", discounting); curves.put("forwardOn", forwardON); curves.put("forwardIbor", forwardIbor); Gson gson = new Gson(); return gson.toJson(curves); } private Map<String, Object> getCurveData(YieldAndDiscountCurve curve) { Double[] tenors; Double[] rates; Map<String, Object> data = new HashMap<>(); try { if (curve instanceof YieldCurve) { tenors = ((YieldCurve) curve).getCurve().getXData(); rates = ((YieldCurve) curve).getCurve().getYData(); } else if (curve instanceof DiscountCurve) { tenors = ((DiscountCurve) curve).getCurve().getXData(); rates = ((DiscountCurve) curve).getCurve().getYData(); } else { tenors = new Double[0]; rates = new Double[0]; s_logger.error(curve.getName() + " is in instance of " + curve.getClass() + " CurveBundleResource only " + "supports YieldCurve and DiscountCurve instances of YieldAndDiscountCurve"); } } catch (UnsupportedOperationException e) { throw new IllegalArgumentException("Curve type: " + curve.getClass().getName() + ", does not support " + "the ability to get X or Y data", e); } data.put("name", curve.getName()); data.put("x", ArrayUtils.toPrimitive(tenors)); data.put("y", ArrayUtils.toPrimitive(rates)); return data; } }