com.opengamma.strata.measure.credit.CdsTradeCalculationFunction.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.strata.measure.credit.CdsTradeCalculationFunction.java

Source

/**
 * Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.strata.measure.credit;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.opengamma.strata.basics.ReferenceData;
import com.opengamma.strata.basics.currency.Currency;
import com.opengamma.strata.calc.Measure;
import com.opengamma.strata.calc.runner.CalculationFunction;
import com.opengamma.strata.calc.runner.CalculationParameters;
import com.opengamma.strata.calc.runner.FunctionRequirements;
import com.opengamma.strata.collect.result.FailureReason;
import com.opengamma.strata.collect.result.Result;
import com.opengamma.strata.data.MarketDataId;
import com.opengamma.strata.data.scenario.ScenarioMarketData;
import com.opengamma.strata.measure.Measures;
import com.opengamma.strata.pricer.credit.IsdaIndexCreditCurveInputsId;
import com.opengamma.strata.pricer.credit.IsdaIndexRecoveryRateId;
import com.opengamma.strata.pricer.credit.IsdaSingleNameCreditCurveInputsId;
import com.opengamma.strata.pricer.credit.IsdaSingleNameRecoveryRateId;
import com.opengamma.strata.pricer.credit.IsdaYieldCurveInputsId;
import com.opengamma.strata.product.credit.Cds;
import com.opengamma.strata.product.credit.CdsTrade;
import com.opengamma.strata.product.credit.IndexReferenceInformation;
import com.opengamma.strata.product.credit.ReferenceInformation;
import com.opengamma.strata.product.credit.ResolvedCdsTrade;
import com.opengamma.strata.product.credit.SingleNameReferenceInformation;

/**
 * Perform calculations on a single {@code CdsTrade} for each of a set of scenarios.
 * <p>
 * The supported built-in measures are:
 * <ul>
 *   <li>{@linkplain Measures#PRESENT_VALUE Present value}
 *   <li>{@linkplain CreditMeasures#IR01_PARALLEL_ZERO Scalar IR01, based on zero rates}
 *   <li>{@linkplain CreditMeasures#IR01_BUCKETED_ZERO Vector curve node IR01, based on zero rates}
 *   <li>{@linkplain CreditMeasures#IR01_PARALLEL_PAR Scalar IR01, based on par interest rates}
 *   <li>{@linkplain CreditMeasures#IR01_BUCKETED_PAR Vector curve node IR01, based on par interest rates}
 *   <li>{@linkplain CreditMeasures#CS01_PARALLEL_PAR Scalar CS01, based on credit par rates}
 *   <li>{@linkplain CreditMeasures#CS01_BUCKETED_PAR Vector curve node CS01, based on credit par rates}
 *   <li>{@linkplain CreditMeasures#CS01_PARALLEL_HAZARD Scalar CS01, based on hazard rates}
 *   <li>{@linkplain CreditMeasures#CS01_BUCKETED_HAZARD Vector curve node CS01, based on hazard rates}
 *   <li>{@linkplain CreditMeasures#RECOVERY01 Recovery01}
 *   <li>{@linkplain CreditMeasures#JUMP_TO_DEFAULT Jump to Default}
 *   <li>{@linkplain Measures#PAR_RATE Par rate}
 *   <li>{@linkplain Measures#RESOLVED_TARGET Resolved trade}
 * </ul>
 * <p>
 * The "natural" currency is the currency of the fee leg.
 */
public class CdsTradeCalculationFunction implements CalculationFunction<CdsTrade> {

    /**
     * The calculations by measure.
     */
    private static final ImmutableMap<Measure, SingleMeasureCalculation> CALCULATORS = ImmutableMap
            .<Measure, SingleMeasureCalculation>builder()
            .put(Measures.PRESENT_VALUE, CdsMeasureCalculations::presentValue)
            .put(CreditMeasures.IR01_PARALLEL_ZERO, CdsMeasureCalculations::ir01ParallelZero)
            .put(CreditMeasures.IR01_BUCKETED_ZERO, CdsMeasureCalculations::ir01BucketedZero)
            .put(CreditMeasures.IR01_PARALLEL_PAR, CdsMeasureCalculations::ir01ParallelPar)
            .put(CreditMeasures.IR01_BUCKETED_PAR, CdsMeasureCalculations::ir01BucketedPar)
            .put(CreditMeasures.CS01_PARALLEL_PAR, CdsMeasureCalculations::cs01ParallelPar)
            .put(CreditMeasures.CS01_BUCKETED_PAR, CdsMeasureCalculations::cs01BucketedPar)
            .put(CreditMeasures.CS01_PARALLEL_HAZARD, CdsMeasureCalculations::cs01ParallelHazard)
            .put(CreditMeasures.CS01_BUCKETED_HAZARD, CdsMeasureCalculations::cs01BucketedHazard)
            .put(CreditMeasures.RECOVERY01, CdsMeasureCalculations::recovery01)
            .put(CreditMeasures.JUMP_TO_DEFAULT, CdsMeasureCalculations::jumpToDefault)
            .put(Measures.PAR_RATE, CdsMeasureCalculations::parRate).put(Measures.RESOLVED_TARGET, (rt, smd) -> rt)
            .build();

    private static final ImmutableSet<Measure> MEASURES = CALCULATORS.keySet();

    /**
     * Creates an instance.
     */
    public CdsTradeCalculationFunction() {
    }

    //-------------------------------------------------------------------------
    @Override
    public Class<CdsTrade> targetType() {
        return CdsTrade.class;
    }

    @Override
    public Set<Measure> supportedMeasures() {
        return MEASURES;
    }

    @Override
    public Optional<String> identifier(CdsTrade target) {
        return target.getInfo().getId().map(id -> id.toString());
    }

    @Override
    public Currency naturalCurrency(CdsTrade trade, ReferenceData refData) {
        return trade.getProduct().getFeeLeg().getPeriodicPayments().getNotional().getCurrency();
    }

    //-------------------------------------------------------------------------
    @Override
    public FunctionRequirements requirements(CdsTrade trade, Set<Measure> measures,
            CalculationParameters parameters, ReferenceData refData) {

        Cds cds = trade.getProduct();

        Currency notionalCurrency = cds.getFeeLeg().getPeriodicPayments().getNotional().getCurrency();
        Currency feeCurrency = cds.getFeeLeg().getUpfrontFee().getCurrency();

        Set<MarketDataId<?>> rateCurveIds = ImmutableSet.of(IsdaYieldCurveInputsId.of(notionalCurrency),
                IsdaYieldCurveInputsId.of(feeCurrency));

        Set<Currency> currencies = ImmutableSet.of(notionalCurrency, feeCurrency);
        ReferenceInformation refInfo = cds.getReferenceInformation();
        if (refInfo instanceof SingleNameReferenceInformation) {
            SingleNameReferenceInformation singleNameRefInfo = (SingleNameReferenceInformation) refInfo;
            Set<MarketDataId<?>> keys = ImmutableSet.of(IsdaSingleNameCreditCurveInputsId.of(singleNameRefInfo),
                    IsdaSingleNameRecoveryRateId.of(singleNameRefInfo));
            return FunctionRequirements.builder().valueRequirements(Sets.union(rateCurveIds, keys))
                    .outputCurrencies(currencies).build();

        } else if (refInfo instanceof IndexReferenceInformation) {
            IndexReferenceInformation indexRefInfo = (IndexReferenceInformation) refInfo;
            Set<MarketDataId<?>> keys = ImmutableSet.of(IsdaIndexCreditCurveInputsId.of(indexRefInfo),
                    IsdaIndexRecoveryRateId.of(indexRefInfo));
            return FunctionRequirements.builder().valueRequirements(Sets.union(rateCurveIds, keys))
                    .outputCurrencies(currencies).build();

        } else {
            throw new IllegalStateException("Unknown reference information type: " + refInfo.getType());
        }
    }

    //-------------------------------------------------------------------------
    @Override
    public Map<Measure, Result<?>> calculate(CdsTrade trade, Set<Measure> measures,
            CalculationParameters parameters, ScenarioMarketData scenarioMarketData, ReferenceData refData) {

        // resolve the trade once for all measures and all scenarios
        ResolvedCdsTrade resolved = trade.resolve(refData);

        // loop around measures, calculating all scenarios for one measure
        Map<Measure, Result<?>> results = new HashMap<>();
        for (Measure measure : measures) {
            results.put(measure, calculate(measure, resolved, scenarioMarketData));
        }
        return results;
    }

    // calculate one measure
    private Result<?> calculate(Measure measure, ResolvedCdsTrade trade, ScenarioMarketData scenarioMarketData) {

        SingleMeasureCalculation calculator = CALCULATORS.get(measure);
        if (calculator == null) {
            return Result.failure(FailureReason.UNSUPPORTED, "Unsupported measure for CdsTrade: {}", measure);
        }
        return Result.of(() -> calculator.calculate(trade, scenarioMarketData));
    }

    //-------------------------------------------------------------------------
    @FunctionalInterface
    interface SingleMeasureCalculation {
        public abstract Object calculate(ResolvedCdsTrade trade, ScenarioMarketData marketData);
    }

}