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 PointsUpFront getPointsUpfront(
     CDSQuoteConvention quote,
     BuySellProtection buySellProtection,
     ISDACompliantYieldCurve yieldCurve,
     CDSAnalytic analytic,
     ISDACompliantCreditCurve creditCurve) {
   double puf = 0.0;
   if (quote instanceof PointsUpFront) {
     return (PointsUpFront) quote;
   } else if (quote instanceof QuotedSpread) {
     puf =
         POINTS_UP_FRONT_CONVERTER.quotedSpreadToPUF(
             analytic, quote.getCoupon(), yieldCurve, ((QuotedSpread) quote).getQuotedSpread());
   } else if (quote instanceof ParSpread) {
     puf = PRICER.pv(analytic, yieldCurve, creditCurve, ((ParSpread) quote).getCoupon());
   } else {
     throw new OpenGammaRuntimeException("Unknown quote type " + quote);
   }
   // SELL protection reverses directions of legs
   puf = (buySellProtection == BuySellProtection.SELL) ? -puf : puf;
   return new PointsUpFront(quote.getCoupon(), puf);
 }
  @Test
  public void consistencyTest() {
    final double tol = 1.e-12;

    final LocalDate optionExpiry = getNextIMMDate(TRADE_DATE).minusDays(1);
    final double timeToExpiry = ACT365F.yearFraction(TRADE_DATE, optionExpiry);
    final CDSAnalytic fwdCDX = FACTORY.makeCDX(optionExpiry, Period.ofYears(5));
    final CDSAnalytic fwdStartingCDX = fwdCDX.withOffset(timeToExpiry);

    final double[] indexPUF = new double[] {0.0556, 0.0582, 0.0771, 0.0652};
    final CDSAnalytic[] indexCDS = FACTORY.makeCDX(TRADE_DATE, INDEX_PILLARS);

    final IntrinsicIndexDataBundle adjCurves =
        PSA.adjustCurves(indexPUF, indexCDS, INDEX_COUPON, YIELD_CURVE, INTRINSIC_DATA);
    final double fwdSpread =
        INDEX_CAL.defaultAdjustedForwardSpread(
            fwdStartingCDX, timeToExpiry, YIELD_CURVE, adjCurves);
    final double fwdAnnuity = INDEX_CAL.indexAnnuity(fwdStartingCDX, YIELD_CURVE, adjCurves);
    final BlackIndexOptionPricer pricerWithFwd =
        new BlackIndexOptionPricer(
            fwdCDX, timeToExpiry, YIELD_CURVE, INDEX_COUPON, fwdSpread, fwdAnnuity);
    final BlackIndexOptionPricer pricerNoFwd =
        new BlackIndexOptionPricer(fwdCDX, timeToExpiry, YIELD_CURVE, INDEX_COUPON, adjCurves);

    final boolean[] payer = new boolean[] {true, false};
    final double vol = 0.4;
    final double strikeSpread = 0.015;
    final ISDACompliantYieldCurve fwdYC = YIELD_CURVE.withOffset(timeToExpiry);
    final double strikePrice =
        CONVERTER.quotedSpreadToPUF(fwdCDX, INDEX_COUPON, fwdYC, strikeSpread);
    final IndexOptionStrike exPriceAmount = new ExerciseAmount(strikePrice);
    final IndexOptionStrike exSpreadAmount = new SpreadBasedStrike(strikeSpread);

    for (int i = 0; i < 2; ++i) {
      /** Consistency between option pricing methods */
      final double premFromPrice = pricerWithFwd.getOptionPremium(exPriceAmount, vol, payer[i]);
      final double premFromSpread = pricerWithFwd.getOptionPremium(exSpreadAmount, vol, payer[i]);
      final double premFromPriceBare =
          pricerWithFwd.getOptionPriceForPriceQuotedIndex(strikePrice, vol, payer[i]);
      final double premFromSpreadBare =
          pricerWithFwd.getOptionPriceForSpreadQuotedIndex(strikeSpread, vol, payer[i]);
      assertEquals(premFromPrice, premFromSpread, tol);
      assertEquals(premFromSpread, premFromPriceBare, tol);
      assertEquals(premFromPriceBare, premFromSpreadBare, tol);

      /** Consistency between constructors */
      final double PremFromPriceNoFwd = pricerNoFwd.getOptionPremium(exPriceAmount, vol, payer[i]);
      assertEquals(premFromPrice, PremFromPriceNoFwd, tol);

      /** Consistency with implied vol */
      final double vol1 =
          pricerWithFwd.getImpliedVolatility(exPriceAmount, premFromPrice, payer[i]);
      final double vol2 =
          pricerWithFwd.getImpliedVolatility(exSpreadAmount, premFromSpread, payer[i]);
      final double vol3 =
          pricerWithFwd.getImpliedVolForExercisePrice(strikePrice, premFromPriceBare, payer[i]);
      final double vol4 =
          pricerWithFwd.getImpliedVolForSpreadStrike(strikeSpread, premFromSpreadBare, payer[i]);
      assertEquals(vol, vol1, tol);
      assertEquals(vol, vol2, tol);
      assertEquals(vol, vol3, tol);
      assertEquals(vol, vol4, tol);
    }
  }