for (int iteration = 0;; ++iteration) {
// only read safe to use as a reference
final double previousData[] = data.clone(); // TODO: verify if clone() is needed
// restart from the previous interpolation
if (validCurve) {
ts.setInterpolation(interpolator.interpolate(new Array(times), new Array(data)));
}
for (int i=1; i<n+1; ++i) {
/*
for (int k = 0; k < data.size(); ++ k)
{
StringBuilder sb = new StringBuilder ();
sb.append ("Date: ");
sb.append (dates[k]);
sb.append ("\t Time: ");
sb.append (df.format (times.get (k)));
sb.append ("\t Discount: ");
sb.append (df.format (data.get(k)));
QL.debug (sb.toString ());
}
*/
// calculate guess before extending interpolation
// to ensure that any extrapolation is performed
// using the curve bootstrapped so far and no more
final RateHelper instrument = instruments[i-1];
double guess = 0.0;
if (validCurve|| iteration>0) {
guess = ts.data()[i];
} else if (i==1) {
guess = traits.initialGuess();
} else {
// most traits extrapolate
guess = traits.guess(ts, dates[i]);
}
//QL.debug (" Guess : " + ((Double)(guess)).toString());
// bracket
final double min = traits.minValueAfter(i, data);
final double max = traits.maxValueAfter(i, data);
if (guess <= min || guess >= max) {
guess = (min + max) / 2.0;
}
if (! validCurve && iteration == 0) {
// extend interpolation a point at a time
try {
ts.setInterpolation(interpolator.interpolate (new Array(times, i+1), new Array(data)));
} catch (final Exception e) {
// no chance to fix it in a later iteration
if (ts.interpolator().global()) {
throw new LibraryException("no chance to fix it in a later iteration");
}
// otherwise, if the target interpolation is not usable yet
ts.setInterpolation(new Linear().interpolate (new Array(times, i+1), new Array(data)));
}
}
// required because we just changed the data
// is it really required?
ts.interpolation().update();
try {
final BootstrapError error = new BootstrapError(traits, ts, instrument, i);
final double r = solver.solve (error, ts.accuracy(), guess, min, max);
// redundant assignment (as it has been already performed
// by BootstrapError in solve procedure), but safe
data[i] = r;
} catch (final Exception e) {
validCurve = false;
QL.error ("could not bootstrap");
}
}
if (!interpolator.global ()) {
break; // no need for convergence loop
} else if (!validCurve && iteration == 0) {
// ensure the target interpolation is used
ts.setInterpolation(interpolator.interpolate (new Array(times), new Array(data)));
// at least one more iteration is needed to check convergence
continue;
}