/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.analytics.ircurve;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.Instant;
import com.google.common.collect.Sets;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.core.marketdatasnapshot.SnapshotDataBundle;
import com.opengamma.core.value.MarketDataRequirementNames;
import com.opengamma.engine.ComputationTarget;
import com.opengamma.engine.ComputationTargetSpecification;
import com.opengamma.engine.function.AbstractFunction;
import com.opengamma.engine.function.CompiledFunctionDefinition;
import com.opengamma.engine.function.FunctionCompilationContext;
import com.opengamma.engine.function.FunctionExecutionContext;
import com.opengamma.engine.function.FunctionInputs;
import com.opengamma.engine.marketdata.ExternalIdBundleResolver;
import com.opengamma.engine.target.ComputationTargetType;
import com.opengamma.engine.value.ComputedValue;
import com.opengamma.engine.value.ValuePropertyNames;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.engine.value.ValueRequirementNames;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.id.ExternalIdBundle;
import com.opengamma.util.money.Currency;
import com.opengamma.util.tuple.Triple;
/**
*
*/
public class YieldCurveMarketDataFunction extends AbstractFunction {
private static final Logger s_logger = LoggerFactory.getLogger(YieldCurveMarketDataFunction.class);
private ValueSpecification _marketDataResult;
private Set<ValueSpecification> _results;
private final YieldCurveFunctionHelper _helper;
public YieldCurveMarketDataFunction(final String currency, final String curveDefinitionName) {
this(Currency.of(currency), curveDefinitionName);
}
public YieldCurveMarketDataFunction(final Currency currency, final String curveDefinitionName) {
_helper = new YieldCurveFunctionHelper(currency, curveDefinitionName);
}
@Override
public void init(final FunctionCompilationContext context) {
_helper.init(context, this);
final ComputationTargetSpecification currencySpec = ComputationTargetSpecification.of(_helper.getCurrency());
_marketDataResult = new ValueSpecification(ValueRequirementNames.YIELD_CURVE_MARKET_DATA, currencySpec,
createValueProperties().with(ValuePropertyNames.CURVE, _helper.getCurveName()).get());
_results = Sets.newHashSet(_marketDataResult);
}
/**
*
*/
private final class CompiledImpl extends AbstractFunction.AbstractInvokingCompiledFunction {
private final Set<ValueRequirement> _requirements;
private CompiledImpl(final Instant earliest, final Instant latest, final Set<ValueRequirement> requirements) {
super(earliest, latest);
_requirements = requirements;
}
@Override
public boolean canHandleMissingRequirements() {
return true;
}
@Override
public boolean canHandleMissingInputs() {
return true;
}
@Override
public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs,
final ComputationTarget target, final Set<ValueRequirement> desiredValues) {
final SnapshotDataBundle map = buildMarketDataMap(executionContext, inputs);
return Sets.newHashSet(new ComputedValue(_marketDataResult, map));
}
@Override
public Set<ValueRequirement> getRequirements(final FunctionCompilationContext context, final ComputationTarget target,
final ValueRequirement desiredValue) {
return _requirements;
}
@Override
public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target) {
return _results;
}
@Override
public ComputationTargetType getTargetType() {
return ComputationTargetType.CURRENCY;
}
@Override
public boolean canApplyTo(final FunctionCompilationContext context, final ComputationTarget target) {
return _helper.getCurrency().equals(target.getValue());
}
}
public static Set<ValueRequirement> buildRequirements(final InterpolatedYieldCurveSpecification specification) {
final Set<ValueRequirement> result = new HashSet<>();
for (final FixedIncomeStripWithIdentifier strip : specification.getStrips()) {
result.add(new ValueRequirement(MarketDataRequirementNames.MARKET_VALUE, ComputationTargetType.PRIMITIVE, strip.getSecurity()));
}
return Collections.unmodifiableSet(result);
}
private static SnapshotDataBundle buildMarketDataMap(final FunctionExecutionContext context, final FunctionInputs inputs) {
final SnapshotDataBundle marketData = new SnapshotDataBundle();
final ExternalIdBundleResolver resolver = new ExternalIdBundleResolver(context.getComputationTargetResolver());
for (final ComputedValue value : inputs.getAllValues()) {
final ExternalIdBundle identifiers = value.getSpecification().getTargetSpecification().accept(resolver);
double rate = (Double) value.getValue();
//TODO this is here because KWCDC Curncy is not normalized
if (rate > 1.1) {
s_logger.error("Normalizing {}, value {}", value.getSpecification(), rate);
s_logger.warn("Performing normalization of rate in YieldCurveMarketDataFunction; if this is being used for anything other than KWCDC Curncy check market data normalization");
rate /= 100;
}
marketData.setDataPoint(identifiers, rate);
}
return marketData;
}
@Override
public CompiledFunctionDefinition compile(final FunctionCompilationContext context, final Instant atInstant) {
try {
_helper.init(context, this);
final Triple<Instant, Instant, InterpolatedYieldCurveSpecification> compile = _helper.compile(context, atInstant, this);
return new CompiledImpl(compile.getFirst(), compile.getSecond(), buildRequirements(compile.getThird()));
} catch (final OpenGammaRuntimeException ogre) {
s_logger.error("Function {} calculating {} on {} couldn't compile, rethrowing...", new Object[] {getShortName(), _helper.getCurveName(), _helper.getCurrency() });
throw ogre;
}
}
}