public static QuotedSpread getQuotedSpread(
     CDSQuoteConvention quote,
     PointsUpFront puf,
     BuySellProtection buySellProtection,
     ISDACompliantYieldCurve yieldCurve,
     CDSAnalytic analytic) {
   double quotedSpread;
   if (quote instanceof QuotedSpread) {
     return (QuotedSpread) quote;
   } else {
     quotedSpread =
         POINTS_UP_FRONT_CONVERTER.pufToQuotedSpread(
             analytic, puf.getCoupon(), yieldCurve, puf.getPointsUpFront());
   }
   // SELL protection reverses directions of legs
   quotedSpread = (buySellProtection == BuySellProtection.SELL) ? -quotedSpread : quotedSpread;
   return new QuotedSpread(quote.getCoupon(), quotedSpread);
 }
 public double getUpfrontAmount(
     final CDSAnalytic analytic,
     final PointsUpFront puf,
     final double notional,
     final double accPremiumPrim,
     final BuySellProtection buySellProtection) {
   // upfront amount is defined as dirty PV
   double cash = (puf.getPointsUpFront() - accPremiumPrim) * notional;
   // SELL protection reverses directions of legs
   return (buySellProtection == BuySellProtection.SELL) ? -cash : cash;
 }
 public double getCleanPrice(final PointsUpFront puf) {
   return 100.0 * (1 - puf.getPointsUpFront());
 }
  @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 ValueRequirement requirement = desiredValues.iterator().next();
    final ValueProperties properties = requirement.getConstraints().copy().get();

    final LegacyVanillaCDSSecurity security = (LegacyVanillaCDSSecurity) target.getSecurity();
    // LegacyVanillaCreditDefaultSwapDefinition cds =
    // _converter.visitLegacyVanillaCDSSecurity(security);
    final ValueRequirement desiredValue = desiredValues.iterator().next(); // all same constraints

    final String quoteConventionString =
        desiredValue.getConstraint(ISDAFunctionConstants.CDS_QUOTE_CONVENTION);
    final StandardCDSQuotingConvention quoteConvention =
        StandardCDSQuotingConvention.parse(quoteConventionString);

    final CdsRecoveryRateIdentifier recoveryRateIdentifier =
        security.accept(
            new CreditSecurityToRecoveryRateVisitor(executionContext.getSecuritySource()));
    Object recoveryRateObject =
        inputs.getValue(
            new ValueRequirement(
                "PX_LAST",
                ComputationTargetType.PRIMITIVE,
                recoveryRateIdentifier.getExternalId()));
    if (recoveryRateObject == null) {
      throw new OpenGammaRuntimeException("Could not get recovery rate");
      // s_logger.warn("Could not get recovery rate, defaulting to 0.4: " + recoveryRateIdentifier);
      // recoveryRateObject = 0.4;
    }
    final double recoveryRate = (Double) recoveryRateObject;

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

    // spreads
    NodalTenorDoubleCurve spreadObject =
        (NodalTenorDoubleCurve) inputs.getValue(ValueRequirementNames.BUCKETED_SPREADS);
    if (spreadObject == null) {
      throw new OpenGammaRuntimeException("Unable to get spreads");
    }
    final double[] spreads = ArrayUtils.toPrimitive(spreadObject.getYData());
    // final String pillarString = IMMDateGenerator.isIMMDate(security.getMaturityDate()) ?
    // requirement.getConstraint(ISDAFunctionConstants.ISDA_BUCKET_TENORS) :
    // ISDACompliantCreditCurveFunction.NON_IMM_PILLAR_TENORS;
    final ZonedDateTime[] bucketDates =
        SpreadCurveFunctions.getPillarDates(now, spreadObject.getXData());
    final CDSQuoteConvention[] quotes =
        SpreadCurveFunctions.getQuotes(
            security.getMaturityDate(), spreads, security.getParSpread(), quoteConvention, false);

    // spreads
    NodalTenorDoubleCurve pillarObject =
        (NodalTenorDoubleCurve) inputs.getValue(ValueRequirementNames.PILLAR_SPREADS);
    if (pillarObject == null) {
      throw new OpenGammaRuntimeException("Unable to get pillars");
    }

    // CDS analytics for credit curve (possible performance improvement if earlier result obtained)
    // final LegacyVanillaCreditDefaultSwapDefinition curveCDS = cds.withStartDate(now);
    // security.setStartDate(now); // needed for curve instruments
    final CDSAnalytic[] bucketCDSs = new CDSAnalytic[bucketDates.length];
    for (int i = 0; i < bucketCDSs.length; i++) {
      // security.setMaturityDate(bucketDates[i]);
      final CDSAnalyticVisitor visitor =
          new CDSAnalyticVisitor(
              now.toLocalDate(),
              _holidaySource,
              _regionSource,
              security.getStartDate().toLocalDate(),
              bucketDates[i].toLocalDate(),
              recoveryRate);
      bucketCDSs[i] = security.accept(visitor);
    }

    final ZonedDateTime[] pillarDates =
        SpreadCurveFunctions.getPillarDates(now, pillarObject.getXData());
    final CDSAnalytic[] pillarCDSs = new CDSAnalytic[pillarDates.length];
    for (int i = 0; i < pillarCDSs.length; i++) {
      // security.setMaturityDate(bucketDates[i]);
      final CDSAnalyticVisitor visitor =
          new CDSAnalyticVisitor(
              now.toLocalDate(),
              _holidaySource,
              _regionSource,
              security.getStartDate().toLocalDate(),
              pillarDates[i].toLocalDate(),
              recoveryRate);
      pillarCDSs[i] = security.accept(visitor);
    }

    final ISDACompliantCreditCurve creditCurve =
        (ISDACompliantCreditCurve) inputs.getValue(ValueRequirementNames.HAZARD_RATE_CURVE);
    if (creditCurve == null) {
      throw new OpenGammaRuntimeException("Couldnt get credit curve");
    }

    // final CDSAnalytic analytic = CDSAnalyticConverter.create(cds, now.toLocalDate());
    final CDSAnalyticVisitor visitor =
        new CDSAnalyticVisitor(now.toLocalDate(), _holidaySource, _regionSource, recoveryRate);
    final CDSAnalytic analytic = security.accept(visitor);
    final BuySellProtection buySellProtection =
        security.isBuy() ? BuySellProtection.BUY : BuySellProtection.SELL;
    //    final String term = new Tenor(Period.between(security.getStartDate().toLocalDate(),
    // security.getMaturityDate().toLocalDate())).getPeriod().toString();
    //    final Double cdsQuoteDouble = (Double) inputs.getValue(new
    // ValueRequirement(MarketDataRequirementNames.MARKET_VALUE,
    //        ComputationTargetType.PRIMITIVE, ExternalId.of("Tenor", term)));
    final Double cdsQuoteDouble = (Double) inputs.getValue(MarketDataRequirementNames.MARKET_VALUE);
    if (cdsQuoteDouble == null) {
      throw new OpenGammaRuntimeException("Couldn't get spread for " + security);
    }
    final CDSQuoteConvention quote =
        SpreadCurveFunctions.getQuotes(
            security.getMaturityDate(),
            new double[] {cdsQuoteDouble},
            security.getParSpread(),
            quoteConvention,
            true)[0];

    boolean isNonIMMFAndFromPUF =
        !IMMDateLogic.isIMMDate(security.getMaturityDate().toLocalDate())
            && quote instanceof PointsUpFront;
    boolean isNonIMMAndFromSpread =
        !IMMDateLogic.isIMMDate(security.getMaturityDate().toLocalDate())
            && (quote instanceof QuotedSpread || quote instanceof ParSpread);
    int buySellPremiumFactor = security.isBuy() ? -1 : 1;

    final double notional = security.getNotional().getAmount();
    final double coupon = security.getParSpread() * ONE_BPS;
    final PointsUpFront puf =
        getPointsUpfront(quote, buySellProtection, yieldCurve, analytic, creditCurve);
    final double accruedPremiumPrim =
        isNonIMMAndFromSpread || isNonIMMFAndFromPUF ? 0 : analytic.getAccruedPremium(coupon);
    //    final double accruedPremium = isNonIMMAndFromSpread || isNonIMMFAndFromPUF ? 0 :
    // analytic.getAccruedPremium(coupon) * notional * buySellPremiumFactor;
    final double accruedPremium =
        isNonIMMAndFromSpread || isNonIMMFAndFromPUF
            ? 0
            : accruedPremiumPrim * notional * buySellPremiumFactor;
    final int accruedDays =
        isNonIMMAndFromSpread || isNonIMMFAndFromPUF ? 0 : analytic.getAccuredDays();
    final double quotedSpread =
        getQuotedSpread(quote, puf, buySellProtection, yieldCurve, analytic).getQuotedSpread();
    final double upfrontAmount =
        isNonIMMAndFromSpread
            ? 0
            : getUpfrontAmount(analytic, puf, notional, accruedPremiumPrim, buySellProtection);
    final double cleanPV = puf.getPointsUpFront() * notional;
    final double principal = isNonIMMAndFromSpread ? 0 : cleanPV;
    final double cleanPrice = getCleanPrice(puf);
    final TenorLabelledMatrix1D bucketedCS01 =
        getBucketedCS01(
            analytic,
            bucketCDSs,
            spreadObject.getXData(),
            quote,
            notional,
            yieldCurve,
            creditCurve);
    final double parallelCS01 =
        getParallelCS01(
            quote,
            analytic,
            yieldCurve,
            notional,
            pillarCDSs,
            ArrayUtils.toPrimitive(pillarObject.getYData()));

    final Set<ComputedValue> results = Sets.newHashSetWithExpectedSize(_valueRequirements.length);
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.ACCRUED_PREMIUM, target.toSpecification(), properties),
            accruedPremium));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.ACCRUED_DAYS, target.toSpecification(), properties),
            accruedDays));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.QUOTED_SPREAD, target.toSpecification(), properties),
            quotedSpread / ONE_BPS));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.UPFRONT_AMOUNT, target.toSpecification(), properties),
            upfrontAmount));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.DIRTY_PRESENT_VALUE, target.toSpecification(), properties),
            upfrontAmount));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.CLEAN_PRESENT_VALUE, target.toSpecification(), properties),
            cleanPV));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.PRINCIPAL, target.toSpecification(), properties),
            principal));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.CLEAN_PRICE, target.toSpecification(), properties),
            cleanPrice));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.BUCKETED_CS01, target.toSpecification(), properties),
            bucketedCS01));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.PARALLEL_CS01, target.toSpecification(), properties),
            parallelCS01));
    results.add(
        new ComputedValue(
            new ValueSpecification(
                ValueRequirementNames.POINTS_UPFRONT, target.toSpecification(), properties),
            puf.getPointsUpFront()));
    return results;
  }