<commit_before>/**
 * 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.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.Month;
import org.threeten.bp.ZoneId;
import org.threeten.bp.ZonedDateTime;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.opengamma.DataNotFoundException;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.analytics.financial.credit.PriceType;
import com.opengamma.analytics.financial.credit.bumpers.SpreadBumpType;
import com.opengamma.analytics.financial.credit.creditdefaultswap.definition.legacy.LegacyVanillaCreditDefaultSwapDefinition;
import com.opengamma.analytics.financial.credit.creditdefaultswap.greeks.vanilla.CS01CreditDefaultSwap;
import com.opengamma.analytics.financial.credit.isdayieldcurve.ISDADateCurve;
import com.opengamma.analytics.math.curve.NodalTenorDoubleCurve;
import com.opengamma.core.holiday.HolidaySource;
import com.opengamma.core.holiday.impl.WeekendHolidaySource;
import com.opengamma.core.region.Region;
import com.opengamma.core.region.RegionSource;
import com.opengamma.engine.ComputationTarget;
import com.opengamma.engine.function.AbstractFunction;
import com.opengamma.engine.function.FunctionCompilationContext;
import com.opengamma.engine.function.FunctionExecutionContext;
import com.opengamma.engine.function.FunctionInputs;
import com.opengamma.engine.target.ComputationTargetType;
import com.opengamma.engine.value.ComputedValue;
import com.opengamma.engine.value.ValueProperties;
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.financial.analytics.conversion.CreditDefaultSwapSecurityConverter;
import com.opengamma.financial.analytics.model.cds.ISDAFunctionConstants;
import com.opengamma.financial.security.FinancialSecurityTypes;
import com.opengamma.financial.security.cds.CreditDefaultSwapSecurity;
import com.opengamma.financial.security.cds.LegacyVanillaCDSSecurity;
import com.opengamma.id.ExternalId;
import com.opengamma.id.ExternalIdBundle;
import com.opengamma.id.ObjectId;
import com.opengamma.id.UniqueId;
import com.opengamma.id.VersionCorrection;
import com.opengamma.master.region.ManageableRegion;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.async.AsynchronousExecution;
import com.opengamma.util.credit.CreditCurveIdentifier;
import com.opengamma.util.i18n.Country;
import com.opengamma.util.money.Currency;
import com.opengamma.util.time.DateUtils;
import com.opengamma.util.time.Tenor;

/**
 * Function to calculate the bucketed CS01 for a given CDS instrument.
 */
public class ISDABucketedCS01VanillaCDSFunction extends AbstractFunction.NonCompiledInvoker {

  private CreditDefaultSwapSecurityConverter _converter;
  private static final CS01CreditDefaultSwap CALCULATOR = new CS01CreditDefaultSwap(); // the calculator
  private static final Logger s_logger = LoggerFactory.getLogger(ISDABucketedCS01VanillaCDSFunction.class);

  // should this be pulled in from somewhere else?
  private static final Collection<ZonedDateTime> BUCKET_DATES = new ArrayList<>();
  private static Set<Month> s_imm_MONTHS = ImmutableSet.of(Month.MARCH, Month.JUNE, Month.SEPTEMBER, Month.DECEMBER);

  //FIXME: Derive these instead of hardcoding
  static {
    BUCKET_DATES.add(DateUtils.getUTCDate(2013, 9, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2014, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2015, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2016, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2017, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2018, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2019, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2020, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2021, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2022, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2023, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2028, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2033, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2043, 3, 20));
  }

  private final ZonedDateTime[] BUCKET_DATES_ARRAY = BUCKET_DATES.toArray(new ZonedDateTime[BUCKET_DATES.size()]);

  public ISDABucketedCS01VanillaCDSFunction() {
  }

  @Override
  public void init(final FunctionCompilationContext context) {
    // using hardcoded region and calendar for now
    final HolidaySource holidaySource = new WeekendHolidaySource(); //OpenGammaCompilationContext.getHolidaySource(context);
    @SuppressWarnings("synthetic-access")
    final RegionSource regionSource = new TestRegionSource(getTestRegion()); //OpenGammaCompilationContext.getRegionSource(context);
    _converter = new CreditDefaultSwapSecurityConverter(holidaySource, regionSource);
  }

  @Override
  public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs,
      final ComputationTarget target, final Set<ValueRequirement> desiredValues) throws AsynchronousExecution {
    final ZonedDateTime now = ZonedDateTime.now(executionContext.getValuationClock());

    final LegacyVanillaCDSSecurity security = (LegacyVanillaCDSSecurity) target.getSecurity();
    final LegacyVanillaCreditDefaultSwapDefinition cds = _converter.visitLegacyVanillaCDSSecurity(security);
    final ValueRequirement desiredValue = Iterables.getOnlyElement(desiredValues);

    // get the market spread bump to apply to all tenors
    final Object spreadObject = inputs.getValue(ValueRequirementNames.BUCKETED_SPREADS);
    final NodalTenorDoubleCurve spreadCurve = (NodalTenorDoubleCurve) spreadObject;
    final double[] spreads = getSpreadCurve(cds, spreadCurve); // get spread for this cds

    // get the isda curve
    final Object isdaObject = inputs.getValue(ValueRequirementNames.YIELD_CURVE);
    if (isdaObject == null) {
      throw new OpenGammaRuntimeException("Couldn't get isda curve");
    }
    final ISDADateCurve isdaCurve = (ISDADateCurve) isdaObject;

    // Compute the bucketed CS01 for this CDS
    double[] bucketedCS01;
    try {
      bucketedCS01 = CALCULATOR.getCS01BucketedCreditDefaultSwap(now, cds, isdaCurve, BUCKET_DATES_ARRAY, spreads, 1.0, SpreadBumpType.ADDITIVE_BUCKETED,
          PriceType.CLEAN); // take values from requirements
    } catch (Exception ex) {
      s_logger.error("Exception thrown during calculation: " + ex.getClass().getSimpleName() + ": " + ex.getMessage());
      throw ex;
    }

    final ValueProperties properties = desiredValue.getConstraints().copy().get();
    final ValueSpecification spec = new ValueSpecification(ValueRequirementNames.BUCKETED_CS01, target.toSpecification(), properties);
    return Collections.singleton(new ComputedValue(spec, bucketedCS01));
  }

  /**
   * 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
   * @return the spread curve for the given cds
   */<commit_msg>Modify non-IMM maturity cds's start date<commit_after>/**
 * 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.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.Month;
import org.threeten.bp.ZoneId;
import org.threeten.bp.ZonedDateTime;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.opengamma.DataNotFoundException;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.analytics.financial.credit.PriceType;
import com.opengamma.analytics.financial.credit.bumpers.SpreadBumpType;
import com.opengamma.analytics.financial.credit.creditdefaultswap.definition.legacy.LegacyVanillaCreditDefaultSwapDefinition;
import com.opengamma.analytics.financial.credit.creditdefaultswap.greeks.vanilla.CS01CreditDefaultSwap;
import com.opengamma.analytics.financial.credit.isdayieldcurve.ISDADateCurve;
import com.opengamma.analytics.math.curve.NodalTenorDoubleCurve;
import com.opengamma.core.holiday.HolidaySource;
import com.opengamma.core.holiday.impl.WeekendHolidaySource;
import com.opengamma.core.region.Region;
import com.opengamma.core.region.RegionSource;
import com.opengamma.engine.ComputationTarget;
import com.opengamma.engine.function.AbstractFunction;
import com.opengamma.engine.function.FunctionCompilationContext;
import com.opengamma.engine.function.FunctionExecutionContext;
import com.opengamma.engine.function.FunctionInputs;
import com.opengamma.engine.target.ComputationTargetType;
import com.opengamma.engine.value.ComputedValue;
import com.opengamma.engine.value.ValueProperties;
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.financial.analytics.conversion.CreditDefaultSwapSecurityConverter;
import com.opengamma.financial.analytics.model.cds.ISDAFunctionConstants;
import com.opengamma.financial.security.FinancialSecurityTypes;
import com.opengamma.financial.security.cds.CreditDefaultSwapSecurity;
import com.opengamma.financial.security.cds.LegacyVanillaCDSSecurity;
import com.opengamma.id.ExternalId;
import com.opengamma.id.ExternalIdBundle;
import com.opengamma.id.ObjectId;
import com.opengamma.id.UniqueId;
import com.opengamma.id.VersionCorrection;
import com.opengamma.master.region.ManageableRegion;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.async.AsynchronousExecution;
import com.opengamma.util.credit.CreditCurveIdentifier;
import com.opengamma.util.i18n.Country;
import com.opengamma.util.money.Currency;
import com.opengamma.util.time.DateUtils;
import com.opengamma.util.time.Tenor;

/**
 * Function to calculate the bucketed CS01 for a given CDS instrument.
 */
public class ISDABucketedCS01VanillaCDSFunction extends AbstractFunction.NonCompiledInvoker {

  private CreditDefaultSwapSecurityConverter _converter;
  private static final CS01CreditDefaultSwap CALCULATOR = new CS01CreditDefaultSwap(); // the calculator
  private static final Logger s_logger = LoggerFactory.getLogger(ISDABucketedCS01VanillaCDSFunction.class);

  // should this be pulled in from somewhere else?
  private static final Collection<ZonedDateTime> BUCKET_DATES = new ArrayList<>();
  private static Set<Month> s_imm_MONTHS = ImmutableSet.of(Month.MARCH, Month.JUNE, Month.SEPTEMBER, Month.DECEMBER);

  //FIXME: Derive these instead of hardcoding
  static {
    BUCKET_DATES.add(DateUtils.getUTCDate(2013, 9, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2014, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2015, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2016, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2017, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2018, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2019, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2020, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2021, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2022, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2023, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2028, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2033, 3, 20));
    BUCKET_DATES.add(DateUtils.getUTCDate(2043, 3, 20));
  }

  private final ZonedDateTime[] BUCKET_DATES_ARRAY = BUCKET_DATES.toArray(new ZonedDateTime[BUCKET_DATES.size()]);

  public ISDABucketedCS01VanillaCDSFunction() {
  }

  @Override
  public void init(final FunctionCompilationContext context) {
    // using hardcoded region and calendar for now
    final HolidaySource holidaySource = new WeekendHolidaySource(); //OpenGammaCompilationContext.getHolidaySource(context);
    @SuppressWarnings("synthetic-access")
    final RegionSource regionSource = new TestRegionSource(getTestRegion()); //OpenGammaCompilationContext.getRegionSource(context);
    _converter = new CreditDefaultSwapSecurityConverter(holidaySource, regionSource);
  }

  @Override
  public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs,
      final ComputationTarget target, final Set<ValueRequirement> desiredValues) throws AsynchronousExecution {
    final ZonedDateTime now = ZonedDateTime.now(executionContext.getValuationClock());

    final LegacyVanillaCDSSecurity security = (LegacyVanillaCDSSecurity) target.getSecurity();
    LegacyVanillaCreditDefaultSwapDefinition cds = _converter.visitLegacyVanillaCDSSecurity(security);
    final ValueRequirement desiredValue = Iterables.getOnlyElement(desiredValues);

    // get the market spread bump to apply to all tenors
    final Object spreadObject = inputs.getValue(ValueRequirementNames.BUCKETED_SPREADS);
    final NodalTenorDoubleCurve spreadCurve = (NodalTenorDoubleCurve) spreadObject;
    final double[] spreads = getSpreadCurve(cds, spreadCurve); // get spread for this cds

    // get the isda curve
    final Object isdaObject = inputs.getValue(ValueRequirementNames.YIELD_CURVE);
    if (isdaObject == null) {
      throw new OpenGammaRuntimeException("Couldn't get isda curve");
    }
    final ISDADateCurve isdaCurve = (ISDADateCurve) isdaObject;

    cds = modifyIfNonIMM(now, cds);

    // Compute the bucketed CS01 for this CDS
    double[] bucketedCS01;
    try {
      bucketedCS01 = CALCULATOR.getCS01BucketedCreditDefaultSwap(now, cds, isdaCurve, BUCKET_DATES_ARRAY, spreads, 1.0, SpreadBumpType.ADDITIVE_BUCKETED,
          PriceType.CLEAN); // take values from requirements
    } catch (Exception ex) {
      s_logger.error("Exception thrown during calculation: " + ex.getClass().getSimpleName() + ": " + ex.getMessage());
      throw ex;
    }

    final ValueProperties properties = desiredValue.getConstraints().copy().get();
    final ValueSpecification spec = new ValueSpecification(ValueRequirementNames.BUCKETED_CS01, target.toSpecification(), properties);
    return Collections.singleton(new ComputedValue(spec, bucketedCS01));
  }

  /**
   * @param now
   * @param cds
   * @param spreadCurve
   * @return
   */
  private LegacyVanillaCreditDefaultSwapDefinition modifyIfNonIMM(final ZonedDateTime now, LegacyVanillaCreditDefaultSwapDefinition cds) {
    if (!isIMMDate(cds.getMaturityDate())) {
      cds = cds.withStartDate(now);
    }
    return cds;
  }

  /**
   * 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
   * @return the spread curve for the given cds
   */
{'fraction_non_alphanumeric': 0.09363081617086194, 'fraction_numerical': 0.01703534197813374, 'mean_word_length': 5.632799325463743, 'pattern_counts': {'":': 2, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4946497', 'n_tokens_mistral': 5148, 'n_tokens_neox': 4935, 'n_words': 953}