Package com.opengamma.financial.analytics.model.credit

Source Code of com.opengamma.financial.analytics.model.credit.SpreadCurveFunctions

/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.analytics.model.credit;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import org.threeten.bp.LocalDate;
import org.threeten.bp.Period;
import org.threeten.bp.ZonedDateTime;

import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.analytics.financial.credit.PriceType;
import com.opengamma.analytics.financial.credit.creditdefaultswap.StandardCDSQuotingConvention;
import com.opengamma.analytics.financial.credit.creditdefaultswap.definition.legacy.LegacyVanillaCreditDefaultSwapDefinition;
import com.opengamma.analytics.financial.credit.creditdefaultswap.pricing.standard.PresentValueStandardCreditDefaultSwap;
import com.opengamma.analytics.financial.credit.creditdefaultswap.pricing.vanilla.isdanew.CDSAnalytic;
import com.opengamma.analytics.financial.credit.creditdefaultswap.pricing.vanilla.isdanew.CDSQuoteConvention;
import com.opengamma.analytics.financial.credit.creditdefaultswap.pricing.vanilla.isdanew.ISDACompliantYieldCurve;
import com.opengamma.analytics.financial.credit.creditdefaultswap.pricing.vanilla.isdanew.ParSpread;
import com.opengamma.analytics.financial.credit.creditdefaultswap.pricing.vanilla.isdanew.PointsUpFront;
import com.opengamma.analytics.financial.credit.creditdefaultswap.pricing.vanilla.isdanew.PointsUpFrontConverter;
import com.opengamma.analytics.financial.credit.creditdefaultswap.pricing.vanilla.isdanew.QuotedSpread;
import com.opengamma.analytics.financial.credit.isdayieldcurve.ISDADateCurve;
import com.opengamma.analytics.math.curve.NodalTenorDoubleCurve;
import com.opengamma.financial.analytics.model.credit.isdanew.CDSAnalyticConverter;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.time.Tenor;

/**
*
*/
public class SpreadCurveFunctions {

  //private final static PresentValueCreditDefaultSwap cdsPresentValueCalculator = new PresentValueCreditDefaultSwap();
  private static PresentValueStandardCreditDefaultSwap cdsPresentValueCalculator = new PresentValueStandardCreditDefaultSwap();

  private static final Collection<Tenor> BUCKET_TENORS = new ArrayList<>();
  private static final double s_tenminus4 = 1e-4;
  private static final double s_tenminus2 = 1e-2;
  private static PointsUpFrontConverter PUF_converter = new PointsUpFrontConverter();

  static {
    BUCKET_TENORS.add(Tenor.SIX_MONTHS);
    BUCKET_TENORS.add(Tenor.ONE_YEAR);
    BUCKET_TENORS.add(Tenor.TWO_YEARS);
    BUCKET_TENORS.add(Tenor.THREE_YEARS);
    BUCKET_TENORS.add(Tenor.FOUR_YEARS);
    BUCKET_TENORS.add(Tenor.FIVE_YEARS);
    BUCKET_TENORS.add(Tenor.SIX_YEARS);
    BUCKET_TENORS.add(Tenor.SEVEN_YEARS);
    BUCKET_TENORS.add(Tenor.EIGHT_YEARS);
    BUCKET_TENORS.add(Tenor.NINE_YEARS);
    BUCKET_TENORS.add(Tenor.TEN_YEARS);
    BUCKET_TENORS.add(Tenor.of(Period.ofYears(15)));
    BUCKET_TENORS.add(Tenor.of(Period.ofYears(20)));
    BUCKET_TENORS.add(Tenor.of(Period.ofYears(30)));
  }

  public static final ZonedDateTime[] getPillarDates(final ZonedDateTime now, final String inputs) {
    if (inputs == null || inputs.isEmpty()) {
      return getDefaultBuckets(now);
    }
    final List<ZonedDateTime> dates = new ArrayList<>();
    for (final String tenorOrDate : inputs.split(",")) {
      if (tenorOrDate.startsWith("P")) { // tenor
        final Tenor tenor = Tenor.of(Period.parse(tenorOrDate));
        dates.add(IMMDateGenerator.getNextIMMDate(now, tenor));
      } else { // date
        final LocalDate date = LocalDate.parse(tenorOrDate);
        dates.add(date.atStartOfDay(now.getZone()));
      }
    }
    return dates.toArray(new ZonedDateTime[dates.size()]);
  }

  public static final ZonedDateTime[] getPillarDates(final ZonedDateTime now, final Tenor[] tenors) {
    final ZonedDateTime[] dates = new ZonedDateTime[tenors.length];
    for (int i = 0; i < tenors.length; i++) {
      dates[i] = IMMDateGenerator.getNextIMMDate(now, tenors[i]);
    }
    return dates;
  }

  public static final ZonedDateTime[] getDefaultBuckets(final ZonedDateTime now) {
    final ZonedDateTime[] dates = new ZonedDateTime[BUCKET_TENORS.size()];
    int i = 0;
    for (final Tenor tenor : BUCKET_TENORS) {
      dates[i++] = IMMDateGenerator.getNextIMMDate(now, tenor);
    }
    return dates;
  }

  public static final Tenor[] getBuckets(final String inputs) {
    if (inputs == null || inputs.isEmpty()) {
      return BUCKET_TENORS.toArray(new Tenor[BUCKET_TENORS.size()]);
    }
    final List<Tenor> tenors = new ArrayList<>();
    for (final String tenorOrDate : inputs.split(",")) {
      if (tenorOrDate.startsWith("P")) { // tenor
        final Tenor tenor = new Tenor(Period.parse(tenorOrDate));
        tenors.add(tenor);
      } else { // date
        throw new OpenGammaRuntimeException("Unsupported");
      }
    }
    return tenors.toArray(new Tenor[tenors.size()]);
  }

  /**
   * Format the spread curve for a given cds.
   * For IMM dates set all spreads to bucket maturity is in.
   * For non-IMM dates take subset of spreads that correspond to buckets.
   *
   * @param cds the cds security
   * @param spreadCurve the spread curve
   * @param bucketDates the bucket dates
   * @param quoteConvention the quote convention (e.g Spread, points upfront etc)
   * @return the spread curve for the given cds
   */
  @Deprecated
  public static double[] getSpreadCurve(final LegacyVanillaCreditDefaultSwapDefinition cds, final NodalTenorDoubleCurve spreadCurve, final ZonedDateTime[] bucketDates,
      final StandardCDSQuotingConvention quoteConvention, final ZonedDateTime valuationDate, final ISDADateCurve isdaCurve, final ZonedDateTime startDate) {
    ArgumentChecker.notNull(spreadCurve, "spread curve");
    ArgumentChecker.notNull(bucketDates, "bucket dates");
    ArgumentChecker.isTrue(spreadCurve.size() > 0, "spread curve had no values");
    final double[] spreads = new double[bucketDates.length];

    // if IMM date take flat spread from imm curve (all values set to single bucket spread)
    if (IMMDateGenerator.isIMMDate((cds.getMaturityDate()))) {
      // find index of bucket this cds maturity is in - should really implement a custom comparator and do a binary search
      Double spreadRate = spreadCurve.getYData()[0];

      for (final Tenor tenor : spreadCurve.getXData()) {
        final ZonedDateTime bucketDate = startDate.plus(tenor.getPeriod());
        if (!bucketDate.isAfter(cds.getMaturityDate())) {
          spreadRate = spreadCurve.getYValue(tenor);
        } else {
          break; // stop when we find desired bucket
        }
      }
      // If IMM and points upfront calculate spread
      switch (quoteConvention) {
        case SPREAD:
          break;
        case POINTS_UPFRONT:
          // can price type vary?
          //FIXME: Conversion to percentage should happen upstream or in analytics
          spreadRate = cdsPresentValueCalculator.calculateParSpreadFlat(valuationDate, cds, spreadRate / 100.0, new ZonedDateTime[] {cds.getMaturityDate() }, isdaCurve, PriceType.CLEAN);
          break;
        default:
          throw new OpenGammaRuntimeException("Unknown quote convention " + quoteConvention);
      }
      // set all spreads to desired spread
      Arrays.fill(spreads, spreadRate.doubleValue() * s_tenminus4);
      return spreads;
    }

    // non-IMM date take spread from subset of dates that we want
    int i = 0;
    for (final Tenor tenor : spreadCurve.getXData()) {
      final ZonedDateTime bucketDate = startDate.plus(tenor.getPeriod());
      final int index = Arrays.binarySearch(bucketDates, bucketDate);
      if (index >= 0) {
        spreads[i++] = spreadCurve.getYValue(tenor) * s_tenminus4;
      }
    }
    // if spread curve ends before required buckets take last spread entry
    for (int j = spreads.length - 1; j >= 0; j--) {
      final double lastspread = spreadCurve.getYData()[spreadCurve.getYData().length - 1] * s_tenminus4;
      if (spreads[j] == 0) {
        spreads[j] = lastspread;
      } else {
        break;
      }
    }
    return spreads;
  }

  /**
   * Format the spread curve for a given cds.
   * For IMM dates set all spreads to bucket maturity is in.
   * For non-IMM dates take subset of spreads that correspond to buckets.
   *
   * Doesn't handle PUF and non-IMM.
   *
   * @param cds the cds security
   * @param spreadCurve the spread curve
   * @param bucketDates the bucket dates
   * @param quoteConvention the quote convention (e.g Spread, points upfront etc)
   * @return the spread curve for the given cds
   */
  @Deprecated
  public static double[] getSpreadCurve(final LegacyVanillaCreditDefaultSwapDefinition cds, final NodalTenorDoubleCurve spreadCurve, final ZonedDateTime[] bucketDates,
      final StandardCDSQuotingConvention quoteConvention, final ZonedDateTime valuationDate, final ISDACompliantYieldCurve isdaCurve, final ZonedDateTime startDate) {
    ArgumentChecker.notNull(spreadCurve, "spread curve");
    ArgumentChecker.notNull(bucketDates, "bucket dates");
    ArgumentChecker.isTrue(spreadCurve.size() > 0, "spread curve had no values");
    final double[] spreads = new double[bucketDates.length];

    // if IMM date take flat spread from imm curve (all values set to single bucket spread)
    if (IMMDateGenerator.isIMMDate((cds.getMaturityDate()))) {
      // find index of bucket this cds maturity is in - should really implement a custom comparator and do a binary search
      Double spreadRate = spreadCurve.getYData()[0];

      for (final Tenor tenor : spreadCurve.getXData()) {
        final ZonedDateTime bucketDate = startDate.plus(tenor.getPeriod());
        if (!bucketDate.isAfter(cds.getMaturityDate())) {
          spreadRate = spreadCurve.getYValue(tenor);
        } else {
          break; // stop when we find desired bucket
        }
      }
      // If IMM and points upfront calculate spread
      switch (quoteConvention) {
        case SPREAD:
          break;
        case POINTS_UPFRONT:
          // can price type vary?
          //FIXME: Conversion to percentage should happen upstream or in analytics
          final CDSAnalytic analytic = CDSAnalyticConverter.create(cds, valuationDate.toLocalDate());
          spreadRate = PUF_converter.pufToQuotedSpread(analytic, cds.getParSpread() * s_tenminus4, isdaCurve, spreadRate / 100.0);
          break;
        default:
          throw new OpenGammaRuntimeException("Unknown quote convention " + quoteConvention);
      }
      // set all spreads to desired spread
      Arrays.fill(spreads, spreadRate.doubleValue() * s_tenminus4);
      return spreads;
    }

    // non-IMM date take spread from subset of dates that we want
    int i = 0;
    for (final Tenor tenor : spreadCurve.getXData()) {
      final ZonedDateTime bucketDate = startDate.plus(tenor.getPeriod());
      final int index = Arrays.binarySearch(bucketDates, bucketDate);
      if (index >= 0) {
        spreads[i++] = spreadCurve.getYValue(tenor) * s_tenminus4;
      }
    }
    // if spread curve ends before required buckets take last spread entry
    for (int j = spreads.length - 1; j >= 0; j--) {
      final double lastspread = spreadCurve.getYData()[spreadCurve.getYData().length - 1] * s_tenminus4;
      if (spreads[j] == 0) {
        spreads[j] = lastspread;
      } else {
        break;
      }
    }
    return spreads;
  }

  /**
   * Get spread curve for the given tenors
   *
   * @param spreadCurve the spread curve
   * @param bucketDates the bucket dates
   * @param quoteConvention the convention, spread or puf
   * @return the spread curve
   */
  public static double[] getSpreadCurveNew(final NodalTenorDoubleCurve spreadCurve, final ZonedDateTime[] bucketDates,
                                           final ZonedDateTime startDate, final StandardCDSQuotingConvention quoteConvention) {
    ArgumentChecker.notNull(spreadCurve, "spread curve");
    ArgumentChecker.notNull(bucketDates, "bucket dates");
    ArgumentChecker.isTrue(spreadCurve.size() > 0, "spread curve had no values");
    final double[] spreads = new double[bucketDates.length];
    // PUF normalised to 1%, spreads to 1 BP
    final double multiplier = StandardCDSQuotingConvention.POINTS_UPFRONT.equals(quoteConvention) ? s_tenminus2 : s_tenminus4;

    // take spreads from subset of dates that we want
    int i = 0;
    for (final Tenor tenor : spreadCurve.getXData()) {
      final ZonedDateTime bucketDate = startDate.plus(tenor.getPeriod());
      final int index = Arrays.binarySearch(bucketDates, bucketDate);
      if (index >= 0) {
        spreads[i++] = spreadCurve.getYValue(tenor) * multiplier;
      }
    }
    // if spread curve ends before required buckets take last spread entry
    for (int j = spreads.length - 1; j >= 0; j--) {
      final double lastspread = spreadCurve.getYData()[spreadCurve.getYData().length - 1] * multiplier;
      if (spreads[j] == 0) {
        spreads[j] = lastspread;
      } else {
        break;
      }
    }
    return spreads;
  }

  /**
   * Get analytic quote objects for the spread / credit curve.
   * If priced cds matures on an IMM date set spreads to quoted otherwise take them as par.
   *
   * If quoteConvention is SPREAD, set quoted vs. par spread based on IMM maturity
   *
   * @param pricedCDSMaturity the maturity of the priced cds
   * @param values the quotes
   * @param quoteConvention the quote convention e.g. SPREAD or PUF
   * @param normalise control whether to normalise spreads to fractional vlaues
   * @return the cds quote conventions
   */
  public static CDSQuoteConvention[] getQuotes(final ZonedDateTime pricedCDSMaturity, final double[] values, final double coupon, final StandardCDSQuotingConvention quoteConvention, final boolean normalise) {
    final CDSQuoteConvention[] result = new CDSQuoteConvention[values.length];
    // PUF normalised to 1%, spreads to 1 BP
    double multiplier = 1;
    if (normalise) {
      multiplier = StandardCDSQuotingConvention.POINTS_UPFRONT.equals(quoteConvention) ? s_tenminus2 : s_tenminus4;
    }
    for (int i = 0; i < values.length; i++) {
      if (StandardCDSQuotingConvention.SPREAD.equals(quoteConvention)) {
        result[i] = IMMDateGenerator.isIMMDate(pricedCDSMaturity) ? new QuotedSpread(coupon * s_tenminus4, values[i] * multiplier) : new ParSpread(values[i] * multiplier);
      } else if (StandardCDSQuotingConvention.POINTS_UPFRONT.equals(quoteConvention)) {
        result[i] = new PointsUpFront(coupon * s_tenminus4, values[i] * multiplier);
      } else {
        throw new OpenGammaRuntimeException("Unsupported quote type: " + quoteConvention);
      }
    }
    return result;
  }

}
TOP

Related Classes of com.opengamma.financial.analytics.model.credit.SpreadCurveFunctions

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.