@SuppressWarnings("unused") @Test public void limitTest() { 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 double modStrikeLimit = INDEX_COUPON + fwdCDX.getLGD() / fwdAnnuity; final double vol = 0.4; final double payLargeSpLimit = fwdAnnuity * BlackFormulaRepository.price(fwdSpread, modStrikeLimit, timeToExpiry, vol, true); final double recLargeSpLimit = fwdAnnuity * BlackFormulaRepository.price(fwdSpread, modStrikeLimit, timeToExpiry, vol, false); final double largeStrikeSp = 75.0; final double payLargeStrikeSp = pricerWithFwd.getOptionPriceForSpreadQuotedIndex(largeStrikeSp, vol, true); final double recLargeStrikeSp = pricerWithFwd.getOptionPriceForSpreadQuotedIndex(largeStrikeSp, vol, false); assertEquals(payLargeSpLimit, payLargeStrikeSp, 1.e-12); assertEquals( recLargeSpLimit, recLargeStrikeSp, 1.e-3); // larger strike spread ends up with failure in root-finding /** Exception expected */ final double negativeTime = -0.5; try { new BlackIndexOptionPricer( fwdCDX, negativeTime, YIELD_CURVE, INDEX_COUPON, fwdSpread, fwdAnnuity); throw new RuntimeException(); } catch (final Exception e) { assertEquals("timeToExpiry must be positive. Value given " + negativeTime, e.getMessage()); } try { new BlackIndexOptionPricer( fwdStartingCDX, timeToExpiry, YIELD_CURVE, INDEX_COUPON, fwdSpread, fwdAnnuity); throw new RuntimeException(); } catch (final Exception e) { assertEquals("fwdCDS should be a Forward CDS", e.getMessage()); } final double negativeCoupon = -150.0 * 1.0e-4; try { new BlackIndexOptionPricer( fwdCDX, timeToExpiry, YIELD_CURVE, negativeCoupon, fwdSpread, fwdAnnuity); throw new RuntimeException(); } catch (final Exception e) { assertEquals("indexCoupon must be positive", e.getMessage()); } final double negativeFwdSp = -0.5; try { new BlackIndexOptionPricer( fwdCDX, timeToExpiry, YIELD_CURVE, INDEX_COUPON, negativeFwdSp, fwdAnnuity); throw new RuntimeException(); } catch (final Exception e) { assertEquals("defaultAdjustedFwdSpread must be positive", e.getMessage()); } final double negativeAnn = -0.3; try { new BlackIndexOptionPricer( fwdCDX, timeToExpiry, YIELD_CURVE, INDEX_COUPON, fwdSpread, negativeAnn); throw new RuntimeException(); } catch (final Exception e) { assertEquals("pvFwdAnnuity must be positive", e.getMessage()); } final double largeAnn = fwdCDX.getProtectionEnd() * 2.0; try { new BlackIndexOptionPricer( fwdCDX, timeToExpiry, YIELD_CURVE, INDEX_COUPON, fwdSpread, largeAnn); throw new RuntimeException(); } catch (final Exception e) { assertEquals( "Value of annuity of " + largeAnn + " is greater than length (in years) of forward CDS. Annuity should be given for unit notional", e.getMessage()); } final double smallStrike = -0.9; try { pricerWithFwd.getOptionPriceForPriceQuotedIndex(smallStrike, vol, true); throw new RuntimeException(); } catch (final Exception e) { assertTrue(e instanceof IllegalArgumentException); } final double largeStrike = 0.9; try { pricerWithFwd.getOptionPriceForPriceQuotedIndex(largeStrike, vol, true); throw new RuntimeException(); } catch (final Exception e) { assertTrue(e instanceof IllegalArgumentException); } try { pricerWithFwd.getOptionPriceForSpreadQuotedIndex(smallStrike, vol, true); throw new RuntimeException(); } catch (final Exception e) { assertTrue(e instanceof IllegalArgumentException); } }