@Override public void calibrate(final DATA_TYPE data) { computeCalibrationPrice(data); _calibrationObjective.setMulticurves(data.getMulticurveProvider()); final int nbInstruments = getBasket().size(); final RidderSingleRootFinder rootFinder = new RidderSingleRootFinder( _calibrationObjective.getFunctionValueAccuracy(), _calibrationObjective.getVariableAbsoluteAccuracy()); final BracketRoot bracketer = new BracketRoot(); for (int loopins = 0; loopins < nbInstruments; loopins++) { final InstrumentDerivative instrument = getBasket().get(loopins); _calibrationObjective.setInstrument(instrument); _calibrationObjective.setPrice(getCalibrationPrices().get(loopins)); final double[] range = bracketer.getBracketedPoints( _calibrationObjective, _calibrationObjective.getMinimumParameter(), _calibrationObjective.getMaximumParameter()); rootFinder.getRoot(_calibrationObjective, range[0], range[1]); if (loopins < nbInstruments - 1) { ((SuccessiveRootFinderHullWhiteCalibrationObjective) _calibrationObjective) .setNextCalibrationTime(_calibrationTimes.get(loopins)); } } }
/** {@inheritDoc} */ @Override public IsdaCompliantCreditCurve calibrateCreditCurve( CdsAnalytic[] cds, double[] premiums, IsdaCompliantYieldCurve yieldCurve, double[] pointsUpfront) { ArgChecker.noNulls(cds, "null CDSs"); ArgChecker.notEmpty(premiums, "empty fractionalSpreads"); ArgChecker.notEmpty(pointsUpfront, "empty pointsUpfront"); ArgChecker.notNull(yieldCurve, "null yieldCurve"); int n = cds.length; ArgChecker.isTrue(n == premiums.length, "Number of CDSs does not match number of spreads"); ArgChecker.isTrue( n == pointsUpfront.length, "Number of CDSs does not match number of pointsUpfront"); double proStart = cds[0].getEffectiveProtectionStart(); for (int i = 1; i < n; i++) { ArgChecker.isTrue( proStart == cds[i].getEffectiveProtectionStart(), "all CDSs must has same protection start"); ArgChecker.isTrue( cds[i].getProtectionEnd() > cds[i - 1].getProtectionEnd(), "protection end must be ascending"); } // use continuous premiums as initial guess double[] guess = new double[n]; double[] t = new double[n]; for (int i = 0; i < n; i++) { t[i] = cds[i].getProtectionEnd(); guess[i] = (premiums[i] + pointsUpfront[i] / t[i]) / cds[i].getLGD(); } IsdaCompliantCreditCurve creditCurve = new IsdaCompliantCreditCurve(t, guess); for (int i = 0; i < n; i++) { Pricer pricer = new Pricer(cds[i], yieldCurve, t, premiums[i], pointsUpfront[i]); Function1D<Double, Double> func = pricer.getPointFunction(i, creditCurve); switch (getArbHanding()) { case Ignore: { try { double[] bracket = BRACKER.getBracketedPoints( func, 0.8 * guess[i], 1.25 * guess[i], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY); double zeroRate = bracket[0] > bracket[1] ? ROOTFINDER.getRoot(func, bracket[1], bracket[0]) : ROOTFINDER.getRoot(func, bracket[0], bracket[1]); // Negative guess handled creditCurve = creditCurve.withRate(zeroRate, i); } catch ( MathException e) { // handling bracketing failure due to small survival probability if (Math.abs(func.evaluate(creditCurve.getZeroRateAtIndex(i - 1))) < 1.e-12) { creditCurve = creditCurve.withRate(creditCurve.getZeroRateAtIndex(i - 1), i); } else { throw new MathException(e); } } break; } case Fail: { double minValue = i == 0 ? 0.0 : creditCurve.getRTAtIndex(i - 1) / creditCurve.getTimeAtIndex(i); if (i > 0 && func.evaluate(minValue) > 0.0) { // can never fail on the first spread StringBuilder msg = new StringBuilder(); if (pointsUpfront[i] == 0.0) { msg.append("The par spread of " + premiums[i] + " at index " + i); } else { msg.append( "The premium of " + premiums[i] + "and points up-front of " + pointsUpfront[i] + " at index " + i); } msg.append( " is an arbitrage; cannot fit a curve with positive forward hazard rate. "); throw new IllegalArgumentException(msg.toString()); } guess[i] = Math.max(minValue, guess[i]); double[] bracket = BRACKER.getBracketedPoints( func, guess[i], 1.2 * guess[i], minValue, Double.POSITIVE_INFINITY); double zeroRate = ROOTFINDER.getRoot(func, bracket[0], bracket[1]); creditCurve = creditCurve.withRate(zeroRate, i); break; } case ZeroHazardRate: { double minValue = i == 0 ? 0.0 : creditCurve.getRTAtIndex(i - 1) / creditCurve.getTimeAtIndex(i); if (i > 0 && func.evaluate(minValue) > 0.0) { // can never fail on the first spread creditCurve = creditCurve.withRate(minValue, i); } else { guess[i] = Math.max(minValue, guess[i]); double[] bracket = BRACKER.getBracketedPoints( func, guess[i], 1.2 * guess[i], minValue, Double.POSITIVE_INFINITY); double zeroRate = ROOTFINDER.getRoot(func, bracket[0], bracket[1]); creditCurve = creditCurve.withRate(zeroRate, i); } break; } default: throw new IllegalArgumentException("unknow case " + getArbHanding()); } } return creditCurve; }