package com.opengamma.sesame.web.pricing;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.opengamma.core.link.ConfigLink;
import com.opengamma.engine.marketdata.spec.MarketDataSpecification;
import com.opengamma.engine.marketdata.spec.MarketDataSpecificationParser;
import com.opengamma.financial.analytics.curve.exposure.ExposureFunctions;
import com.opengamma.financial.currency.CurrencyMatrix;
import com.opengamma.sesame.CurveSelector;
import com.opengamma.sesame.CurveSelectorMulticurveBundleFn;
import com.opengamma.sesame.DiscountingMulticurveCombinerFn;
import com.opengamma.sesame.MarketExposureSelector;
import com.opengamma.sesame.OutputNames;
import com.opengamma.sesame.config.ViewColumn;
import com.opengamma.sesame.config.ViewConfig;
import com.opengamma.sesame.engine.CalculationArguments;
import com.opengamma.sesame.engine.ResultItem;
import com.opengamma.sesame.engine.ResultRow;
import com.opengamma.sesame.engine.Results;
import com.opengamma.sesame.engine.ViewRunner;
import com.opengamma.sesame.irs.DefaultInterestRateSwapConverterFn;
import com.opengamma.sesame.irs.DiscountingInterestRateSwapCalculatorFactory;
import com.opengamma.sesame.irs.DiscountingInterestRateSwapFn;
import com.opengamma.sesame.irs.InterestRateSwapCalculatorFactory;
import com.opengamma.sesame.irs.InterestRateSwapConverterFn;
import com.opengamma.sesame.irs.InterestRateSwapFn;
import com.opengamma.sesame.marketdata.DefaultHistoricalMarketDataFn;
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.sesame.trade.InterestRateSwapTrade;
import com.opengamma.sesame.web.curves.CurveBundleResource;
import com.opengamma.util.ArgumentChecker;
import org.joda.beans.Bean;
import org.joda.beans.ser.JodaBeanSer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.ZonedDateTime;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.List;
import java.util.Set;
import static com.opengamma.sesame.config.ConfigBuilder.argument;
import static com.opengamma.sesame.config.ConfigBuilder.arguments;
import static com.opengamma.sesame.config.ConfigBuilder.column;
import static com.opengamma.sesame.config.ConfigBuilder.config;
import static com.opengamma.sesame.config.ConfigBuilder.configureView;
import static com.opengamma.sesame.config.ConfigBuilder.function;
import static com.opengamma.sesame.config.ConfigBuilder.implementations;
/**
* REST endpoint to price a swap
*/
@Path("swappricing")
public class SwapPricingResource {
/**
* Builds market data in response to specified requirements
*/
private final MarketDataEnvironmentFactory _environmentFactory;
private final ViewRunner _viewRunner;
private final String _currencyMatrix;
private static final Logger s_logger = LoggerFactory.getLogger(CurveBundleResource.class);
/**
* @param environmentFactory builds market data in response to specified requirements
* @param viewRunner
*/
public SwapPricingResource(MarketDataEnvironmentFactory environmentFactory, ViewRunner viewRunner, String currencyMatrix) {
_viewRunner = ArgumentChecker.notNull(viewRunner, "viewRunnerFactory");
_environmentFactory = ArgumentChecker.notNull(environmentFactory, "environmentFactory");
_currencyMatrix = currencyMatrix;
}
@POST
@Path("{bundle}/{spec}/{exposureFns}")
public String priceSwap(@PathParam("bundle") String bundle,
@PathParam("spec") String spec,
@PathParam("exposureFns") String exposureFns,
String input) throws UnsupportedEncodingException {
List<InterestRateSwapTrade> portfolio;
Bean trade = JodaBeanSer.COMPACT.jsonReader().read(input);
try {
portfolio = ImmutableList.<InterestRateSwapTrade>of((InterestRateSwapTrade) trade);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Error in submitted trade: " + e);
}
Results swapResults = getSwapPv(portfolio, spec, bundle, URLDecoder.decode(exposureFns, "UTF-8"));
ResultRow row = swapResults.get(0);
ResultItem resultItem = row.get(swapResults.getColumnIndex(OutputNames.PRESENT_VALUE));
String swapPv = resultItem.getResult().getValue().toString();
return swapPv;
}
@POST
@Path("json/{bundle}/{spec}/{exposureFns}")
@Produces("application/json")
public String priceSwapJson(@PathParam("bundle") String bundle,
@PathParam("spec") String spec,
@PathParam("exposureFns") String exposureFns,
String input) throws UnsupportedEncodingException {
List<InterestRateSwapTrade> portfolio;
Bean trade = JodaBeanSer.COMPACT.jsonReader().read(input);
try {
portfolio = ImmutableList.<InterestRateSwapTrade>of((InterestRateSwapTrade) trade);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Error in submitted trade: " + e);
}
Results swapResults = getSwapPv(portfolio, spec, bundle, URLDecoder.decode(exposureFns, "UTF-8"));
String res = JodaBeanSer.PRETTY.jsonWriter().write(swapResults);
return res;
}
private Results getSwapPv(List<InterestRateSwapTrade> portfolio, String spec, String bundle, String exposureFunctions) {
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);
CalculationArguments calculationArguments =
CalculationArguments.builder()
.valuationTime(ZonedDateTime.now())
.marketDataSpecification(marketDataSpec)
.build();
ConfigLink<ExposureFunctions> exposureFns = ConfigLink.resolvable(exposureFunctions, ExposureFunctions.class);
ConfigLink<CurrencyMatrix> currencyMatrix = ConfigLink.resolvable(_currencyMatrix, CurrencyMatrix.class);
ViewConfig viewConfig = createViewConfig(exposureFns, currencyMatrix);
Results results = _viewRunner.runView(viewConfig, calculationArguments, marketData, portfolio);
return results;
}
private ViewConfig createViewConfig(ConfigLink<ExposureFunctions> exposureConfig, ConfigLink<CurrencyMatrix> currencyMatrixLink) {
return
configureView(
"IRS Remote view",
createInterestRateSwapViewColumn(OutputNames.PRESENT_VALUE,
exposureConfig,
currencyMatrixLink),
createInterestRateSwapViewColumn(OutputNames.PAY_LEG_PRESENT_VALUE,
exposureConfig,
currencyMatrixLink),
createInterestRateSwapViewColumn(OutputNames.RECEIVE_LEG_PRESENT_VALUE,
exposureConfig,
currencyMatrixLink),
createInterestRateSwapViewColumn(OutputNames.PAR_RATE,
exposureConfig,
currencyMatrixLink),
createInterestRateSwapViewColumn(OutputNames.PAY_LEG_CASH_FLOWS,
exposureConfig,
currencyMatrixLink),
createInterestRateSwapViewColumn(OutputNames.RECEIVE_LEG_CASH_FLOWS,
exposureConfig,
currencyMatrixLink));
}
private ViewColumn createInterestRateSwapViewColumn(String output,
ConfigLink<ExposureFunctions> exposureConfig,
ConfigLink<CurrencyMatrix> currencyMatrixLink) {
ArgumentChecker.notNull(output, "output");
ArgumentChecker.notNull(exposureConfig, "exposureConfig");
ArgumentChecker.notNull(currencyMatrixLink, "currencyMatrixLink");
return
column(
output,
config(
arguments(
function(
MarketExposureSelector.class,
argument("exposureFunctions", exposureConfig)),
function(
DefaultHistoricalMarketDataFn.class,
argument("currencyMatrix", currencyMatrixLink))),
implementations(
CurveSelector.class, MarketExposureSelector.class,
DiscountingMulticurveCombinerFn.class, CurveSelectorMulticurveBundleFn.class,
InterestRateSwapFn.class, DiscountingInterestRateSwapFn.class,
InterestRateSwapConverterFn.class, DefaultInterestRateSwapConverterFn.class,
InterestRateSwapCalculatorFactory.class, DiscountingInterestRateSwapCalculatorFactory.class)));
}
}