/*
Copyright (C) 2011 Richard Gomes
This source code is release under the BSD License.
This file is part of JQuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://jquantlib.org/
JQuantLib is free software: you can redistribute it and/or modify it
under the terms of the JQuantLib license. You should have received a
copy of the license along with this program; if not, please email
. The license is also available online at
.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
JQuantLib is based on QuantLib. http://quantlib.org/
When applicable, the original copyright notice follows this notice.
*/
package org.jquantlib.termstructures;
import java.util.Arrays;
import org.jquantlib.QL;
import org.jquantlib.lang.exceptions.LibraryException;
import org.jquantlib.lang.reflect.ReflectConstants;
import org.jquantlib.math.interpolations.Interpolation;
import org.jquantlib.math.interpolations.Interpolation.Interpolator;
import org.jquantlib.math.interpolations.factories.Linear;
import org.jquantlib.math.matrixutilities.Array;
import org.jquantlib.math.solvers1D.Brent;
import org.jquantlib.termstructures.yieldcurves.PiecewiseCurve;
import org.jquantlib.termstructures.yieldcurves.PiecewiseYieldCurve;
import org.jquantlib.termstructures.yieldcurves.Traits;
import org.jquantlib.time.Date;
/**
* Universal piecewise-term-structure boostrapper.
*
* @author Richard Gomes
*/
//FIXME: This class needs full code review
public class IterativeBootstrap implements Bootstrap {
//
// private fields
//
private boolean validCurve;
private PiecewiseCurve ts;
private RateHelper[] instruments;
private Traits traits;
private Interpolator interpolator;
private Interpolation interpolation;
//
// final private fields
//
final private Class> typeCurve;
//
// public constructors
//
public IterativeBootstrap(final Class> typeCurve) {
QL.validateExperimentalMode();
if (typeCurve==null) {
throw new LibraryException("null PiecewiseCurve"); // TODO: message
}
if (!PiecewiseCurve.class.isAssignableFrom(typeCurve)) {
throw new LibraryException(ReflectConstants.WRONG_ARGUMENT_TYPE);
}
this.typeCurve = typeCurve;
this.validCurve = false;
this.ts = null;
}
//
// implements Bootstrap
//
@Override
public void setup(final Curve ts) {
QL.ensure (ts != null, "TermStructure cannot be null");
if (!this.typeCurve.isAssignableFrom(ts.getClass())) {
throw new LibraryException(ReflectConstants.WRONG_ARGUMENT_TYPE);
}
this.ts = ts;
this.interpolator = ts.interpolator();
this.interpolation = ts.interpolation();
this.traits = ts.traits();
this.instruments = ts.instruments();
final int n = instruments.length;
QL.require(n+1 >= ts.interpolator().requiredPoints(), "not enough instruments provided");
for (int i=0; i0) {
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;
}
// exit conditions
double improvement = 0.0;
for (int i=1; i
Ads help maintain this website.