void FittedBondDiscountCurve::FittingMethod::calculate() {

        FittingCost& costFunction = *costFunction_;
        Constraint constraint = NoConstraint();

        // start with the guess solution, if it exists
        Array x(size(), 0.0);
        if (!curve_->guessSolution_.empty()) {
            x = curve_->guessSolution_;
        }

        Simplex simplex(curve_->simplexLambda_);
        Problem problem(costFunction, constraint, x);

        Natural maxStationaryStateIterations = 100;
        Real rootEpsilon = curve_->accuracy_;
        Real functionEpsilon =  curve_->accuracy_;
        Real gradientNormEpsilon = curve_->accuracy_;

        EndCriteria endCriteria(curve_->maxEvaluations_,
                                maxStationaryStateIterations,
                                rootEpsilon,
                                functionEpsilon,
                                gradientNormEpsilon);

        simplex.minimize(problem,endCriteria);
        solution_ = problem.currentValue();

        numberOfIterations_ = problem.functionEvaluation();
        costValue_ = problem.functionValue();

        // save the results as the guess solution, in case of recalculation
        curve_->guessSolution_ = solution_;
    }
Exemplo n.º 2
0
	HullWhiteTimeDependentParameters calibration_hull_white(
		const Date& evalDate,
		const CapVolData& volData
	)
	{
			boost::shared_ptr<IborIndex> index = volData.index;
			Frequency fixedFreq = volData.fixedFreq;
			DayCounter fixedDC = volData.fixedDC;
			Real FixedA = volData.fixedA;
			std::vector<Real> initialSigma = volData.initialSigma;

			Settings::instance().evaluationDate() = Date( evalDate.serialNumber() );

			Date today  = Settings::instance().evaluationDate();
			std::vector<Date> dates;
			for (Size i=0; i<volData.tenors.size(); ++i){
				dates.push_back(today+volData.tenors[i]*Years);
			}
			dates.back() = today+50*Years;
			std::set<Date> temp(dates.begin(), dates.end());
			dates = std::vector<Date>(temp.begin(), temp.end());

			Handle<YieldTermStructure> rts_hw(index->forwardingTermStructure().currentLink());
			boost::shared_ptr<Generalized_HullWhite> model(new Generalized_HullWhite(rts_hw, dates, initialSigma, FixedA));

			boost::shared_ptr<PricingEngine> engine_hw(new AnalyticCapFloorEngine(model));
			//boost::shared_ptr<PricingEngine> engine_hw(new TreeCapFloorEngine(model, 80));
			std::vector<boost::shared_ptr<CalibrationHelper> > caps;

			for (Size i=0; i<volData.tenors.size(); ++i) {
				boost::shared_ptr<CalibrationHelper> helper(
					new CapHelper(Period(volData.tenors[i], Years),
					Handle<Quote>(boost::shared_ptr<Quote>(new SimpleQuote(volData.vols[i]))),
					index, fixedFreq,
					fixedDC,
					false,
					rts_hw, CalibrationHelper::PriceError));
				helper->setPricingEngine(engine_hw);
				caps.push_back(helper);		
			}

			LevenbergMarquardt optimizationMethod(1.0e-8,1.0e-8,1.0e-8);
			EndCriteria endCriteria(5000, 1000, 1e-8, 1e-8, 1e-8);
			Constraint c = BoundaryConstraint(0.01, 3.0);

			model->calibrate(caps, optimizationMethod, endCriteria, c);
			EndCriteria::Type ecType = model->endCriteria();
			Array xMinCalculated = model->params();
			
			//Real a = xMinCalculated[0];
			//Real sigmar = xMinCalculated[1];
			std::vector<Real> sigma;				
			for (Size i=0; i<xMinCalculated.size(); ++i) {
				sigma.push_back(xMinCalculated[i]);
			}

			return HullWhiteTimeDependentParameters(FixedA, dates, sigma, model, caps);
	}
  void FluctuatingChargePropagator::initialize() {
    if (info_->usesFluctuatingCharges()) {
      if (info_->getNFluctuatingCharges() > 0) {
        hasFlucQ_ = true;
	fqConstraints_ = new FluctuatingChargeConstraints(info_);
	fqConstraints_->setConstrainRegions(fqParams_->getConstrainRegions());
      }
    }
    
    if (!hasFlucQ_) {
      initialized_ = true;
      return;
    }

    // SimInfo::MoleculeIterator i;
    // Molecule::FluctuatingChargeIterator  j;
    // Molecule* mol;
    // Atom* atom;
    //  
    // For single-minima flucq, this ensures a net neutral system, but
    // for multiple minima, this is no longer the right thing to do:
    //
    // for (mol = info_->beginMolecule(i); mol != NULL; 
    //      mol = info_->nextMolecule(i)) {
    //   for (atom = mol->beginFluctuatingCharge(j); atom != NULL;
    //        atom = mol->nextFluctuatingCharge(j)) {
    //     atom->setFlucQPos(0.0);
    //     atom->setFlucQVel(0.0);
    //   }
    // }
    
    FluctuatingChargeObjectiveFunction flucQobjf(info_, forceMan_, 
                                                 fqConstraints_);

    DynamicVector<RealType> initCoords = flucQobjf.setInitialCoords();
    Problem problem(flucQobjf, *(new NoConstraint()), *(new NoStatus()), 
                    initCoords);

    EndCriteria endCriteria(1000, 100, 1e-5, 1e-5, 1e-5);       

    OptimizationMethod* minim = OptimizationFactory::getInstance()->createOptimization("SD", info_);

    DumpStatusFunction dsf(info_);  // we want a dump file written
                                    // every iteration
    minim->minimize(problem, endCriteria);
    cerr << "back from minim\n";
    initialized_ = true;
  }
Exemplo n.º 4
0
    void FittedBondDiscountCurve::FittingMethod::calculate() {

        FittingCost& costFunction = *costFunction_;
        Constraint constraint = NoConstraint();

        // start with the guess solution, if it exists
        Array x(size(), 0.0);
        if (!curve_->guessSolution_.empty()) {
            x = curve_->guessSolution_;
        }

        if(curve_->maxEvaluations_ == 0)
        {
            //Don't calculate, simply use given parameters to provide a fitted curve.
            //This turns the fittedbonddiscountcurve into an evaluator of the parametric
            //curve, for example allowing to use the parameters for a credit spread curve
            //calculated with bonds in one currency to be coupled to a discount curve in 
            //another currency. 
            return;
        }
        
        //workaround for backwards compatibility
        ext::shared_ptr<OptimizationMethod> optimization = optimizationMethod_;
        if(!optimization){
            optimization = ext::make_shared<Simplex>(curve_->simplexLambda_);
        }
        Problem problem(costFunction, constraint, x);

        Real rootEpsilon = curve_->accuracy_;
        Real functionEpsilon =  curve_->accuracy_;
        Real gradientNormEpsilon = curve_->accuracy_;

        EndCriteria endCriteria(curve_->maxEvaluations_,
                                curve_->maxStationaryStateIterations_,
                                rootEpsilon,
                                functionEpsilon,
                                gradientNormEpsilon);

        optimization->minimize(problem,endCriteria);
        solution_ = problem.currentValue();

        numberOfIterations_ = problem.functionEvaluation();
        costValue_ = problem.functionValue();

        // save the results as the guess solution, in case of recalculation
        curve_->guessSolution_ = solution_;
    }
Exemplo n.º 5
0
// [[Rcpp::export]]
Rcpp::List calibrateHullWhiteUsingSwapsEngine(SEXP termStrcDateVec,
                                              SEXP termStrcZeroVec,
                                              SEXP swapDataDF,
                                              SEXP iborDateVec,
                                              SEXP iborZeroVec,
                                              std::string iborType,
                                              QuantLib::Date evalDate) {

    QuantLib::Settings::instance().evaluationDate() = evalDate;

    //set up the HullWhite model       
    QuantLib::Handle<QuantLib::YieldTermStructure> 
        term(rebuildCurveFromZeroRates(termStrcDateVec, termStrcZeroVec));
    boost::shared_ptr<QuantLib::HullWhite> model(new QuantLib::HullWhite(term));        
        
    //set up ibor index
    QuantLib::Handle<QuantLib::YieldTermStructure> 
        indexStrc(rebuildCurveFromZeroRates(iborDateVec, iborZeroVec));    
    boost::shared_ptr<QuantLib::IborIndex> index = buildIborIndex(iborType, indexStrc);
    //process capDataDF
    boost::shared_ptr<QuantLib::PricingEngine> 
        engine(new QuantLib::JamshidianSwaptionEngine(model));
    std::vector<boost::shared_ptr <QuantLib::CalibrationHelper> > swaps;

    Rcpp::DataFrame swapDF(swapDataDF);
    Rcpp::NumericVector i0v = swapDF[0];
    Rcpp::CharacterVector  s1v = swapDF[1];
    Rcpp::NumericVector i2v = swapDF[2];
    Rcpp::CharacterVector s3v = swapDF[3];
    Rcpp::NumericVector d4v = swapDF[4];
    Rcpp::NumericVector i5v = swapDF[5];
    Rcpp::CharacterVector s6v = swapDF[6];
    Rcpp::NumericVector i7v = swapDF[7];
    Rcpp::NumericVector i8v = swapDF[8];
    //std::vector<std::vector<ColDatum> > table = swapDF.getTableData();
    //int nrow = table.size();
    int nrow = i0v.size();
    for (int row=0; row<nrow;row++) {
        QuantLib::Period maturity = periodByTimeUnit(i0v[row], 
                                                     Rcpp::as<std::string>(s1v[row]));
        QuantLib::Period length = periodByTimeUnit(i0v[row], 
                                                   Rcpp::as<std::string>(s3v[row]));
        
        boost::shared_ptr<QuantLib::Quote> vol(new QuantLib::SimpleQuote(d4v[row]));
        
        QuantLib::Period fixedLegTenor = periodByTimeUnit(i5v[row], 
                                                          Rcpp::as<std::string>(s6v[row]));
        QuantLib::DayCounter fixedLegDayCounter = getDayCounter(i7v[row]);
        QuantLib::DayCounter floatingLegDayCounter = getDayCounter(i8v[row]);

        boost::shared_ptr<QuantLib::CalibrationHelper> 
            helper(new QuantLib::SwaptionHelper(maturity, length, 
                                                QuantLib::Handle<QuantLib::Quote>(vol), 
                                                index, 
                                                fixedLegTenor, 
                                                fixedLegDayCounter,
                                                floatingLegDayCounter,
                                                term));
        helper->setPricingEngine(engine);                
        swaps.push_back(helper);
    }
        
    //calibrate the data
    QuantLib::LevenbergMarquardt optimizationMethod(1.0e-8,1.0e-8,1.0e-8);
    QuantLib::EndCriteria endCriteria(10000, 100, 1e-6, 1e-8, 1e-8);
    model->calibrate(swaps, optimizationMethod, endCriteria);
    //EndCriteria::Type ecType = model->endCriteria();
    //return the result
    QuantLib::Array xMinCalculated = model->params();

    return Rcpp::List::create(Rcpp::Named("alpha") = xMinCalculated[0],
                              Rcpp::Named("sigma") = xMinCalculated[1]);
}
Exemplo n.º 6
0
// [[Rcpp::export]]
Rcpp::List calibrateHullWhiteUsingCapsEngine(SEXP termStrcDateVec,
                                             SEXP termStrcZeroVec,
                                             SEXP capDataDF,
                                             SEXP iborDateVec,
                                             SEXP iborZeroVec,
                                             std::string iborType,
                                             QuantLib::Date evalDate) {
	
    QuantLib::Settings::instance().evaluationDate() = evalDate;

    QuantLib::Handle<QuantLib::YieldTermStructure> 
        term(rebuildCurveFromZeroRates(termStrcDateVec, termStrcZeroVec));
        
    //set up ibor index
    QuantLib::Handle<QuantLib::YieldTermStructure> 
        indexStrc(rebuildCurveFromZeroRates(iborDateVec, iborZeroVec));    
    boost::shared_ptr<QuantLib::IborIndex> index = buildIborIndex(iborType, indexStrc);
    //process capDataDF
    std::vector<boost::shared_ptr <QuantLib::CalibrationHelper> > caps;

    Rcpp::DataFrame capDF(capDataDF);
    Rcpp::NumericVector i0v = capDF[0];
    Rcpp::CharacterVector  s1v = capDF[1];
    Rcpp::NumericVector d2v = capDF[2];
    Rcpp::NumericVector i3v = capDF[3];
    Rcpp::NumericVector i4v = capDF[4];
    Rcpp::NumericVector i5v = capDF[5];
    //std::vector<std::vector<ColDatum> > table = capDF.getTableData();
    //int nrow = table.size();
    int nrow = i0v.size();
    for (int row=0; row<nrow;row++) {
        QuantLib::Period p = periodByTimeUnit(i0v[row], Rcpp::as<std::string>(s1v[row]));
        boost::shared_ptr<QuantLib::Quote> vol(new QuantLib::SimpleQuote(d2v[row]));
        QuantLib::DayCounter dc = getDayCounter(i4v[row]);
        boost::shared_ptr<QuantLib::CalibrationHelper> 
            helper(new QuantLib::CapHelper(p, QuantLib::Handle<QuantLib::Quote>(vol), index, 
                                           getFrequency(i3v[row]),
                                           dc,
                                           (i5v[row]==1) ? true : false,
                                           term));
        boost::shared_ptr<QuantLib::BlackCapFloorEngine> 
            engine(new QuantLib::BlackCapFloorEngine(term, d2v[row]));
        
        helper->setPricingEngine(engine);                
        caps.push_back(helper);
    }
        
    //set up the HullWhite model
    boost::shared_ptr<QuantLib::HullWhite> model(new QuantLib::HullWhite(term));
        
    //calibrate the data
    QuantLib::LevenbergMarquardt optimizationMethod(1.0e-8,1.0e-8,1.0e-8);
    QuantLib::EndCriteria endCriteria(10000, 100, 1e-6, 1e-8, 1e-8);
    model->calibrate(caps, optimizationMethod, endCriteria);
    //EndCriteria::Type ecType = model->endCriteria();
    //return the result
    QuantLib::Array xMinCalculated = model->params();

    return Rcpp::List::create(Rcpp::Named("alpha") = xMinCalculated[0],
                              Rcpp::Named("sigma") = xMinCalculated[1]);
}
Exemplo n.º 7
0
	HullWhiteTimeDependentParameters calibration_hull_white(
		const Date& evalDate,
		const SwaptionVolData& volData
		)
	{
			boost::shared_ptr<IborIndex> index = volData.index;
			Frequency fixedFreq = volData.fixedFreq;
			DayCounter fixedDC = volData.fixedDC;
			DayCounter floatingDC = volData.floatingDC;
			Real FixedA = volData.fixedA;
			std::vector<Real> initialSigma = volData.initialSigma;

			Settings::instance().evaluationDate() = Date( evalDate.serialNumber() );

			Date today  = Settings::instance().evaluationDate();
			std::vector<Date> tmpdates;
			for (Size i=0; i<volData.maturities.size(); ++i){
				tmpdates.push_back(today+volData.maturities[i]);
			}
			tmpdates.back() = today+50*Years;

			std::set<Date> dateSet( tmpdates.begin(), tmpdates.end() );
			std::vector<Date> dates( dateSet.begin(), dateSet.end()	);

			Handle<YieldTermStructure> rts_hw(index->forwardingTermStructure().currentLink());
			//boost::shared_ptr<GeneralizedHullWhite> model(new GeneralizedHullWhite(rts_hw, dates, dates, std::vector<Real>(1, FixedA), initialSigma));
			boost::shared_ptr<Generalized_HullWhite> model(new Generalized_HullWhite(rts_hw, dates, initialSigma, FixedA));

			//boost::shared_ptr<PricingEngine> engine_hw(new AnalyticCapFloorEngine(model));
			//boost::shared_ptr<PricingEngine> engine_hw(new TreeSwaptionEngine(model, 100));
			boost::shared_ptr<PricingEngine> engine_hw(new JamshidianSwaptionEngine(model));
			std::vector<boost::shared_ptr<CalibrationHelper> > swaptions;

			for (Size i=0; i<volData.maturities.size(); ++i) {
				boost::shared_ptr<CalibrationHelper> helper(
					new SwaptionHelper(volData.maturities[i],
					volData.lengths[i],
					Handle<Quote>(boost::shared_ptr<Quote>(new SimpleQuote(volData.vols[i]))),
					index, Period(fixedFreq),
					fixedDC, floatingDC,
					rts_hw, CalibrationHelper::PriceError));
				helper->setPricingEngine(engine_hw);
				swaptions.push_back(helper);
			}

			LevenbergMarquardt optimizationMethod(1.0e-8,1.0e-8,1.0e-8);
			EndCriteria endCriteria(50000, 1000, 1e-8, 1e-8, 1e-8);

			model->calibrate(swaptions, optimizationMethod, endCriteria);
			EndCriteria::Type ecType = model->endCriteria();
			Array xMinCalculated = model->params();

			//Real a = xMinCalculated[0];
			//Real sigmar = xMinCalculated[1];
			std::vector<Real> sigma;				
			for (Size i=0; i<xMinCalculated.size(); ++i) {
				sigma.push_back(xMinCalculated[i]);
			}

			return HullWhiteTimeDependentParameters(FixedA, dates, sigma, model, swaptions);
	}
Exemplo n.º 8
0
    SwaptionVolCube1::Cube
    SwaptionVolCube1::sabrCalibration(const Cube& marketVolCube) const {

        const std::vector<Time>& optionTimes = marketVolCube.optionTimes();
        const std::vector<Time>& swapLengths = marketVolCube.swapLengths();
        const std::vector<Date>& optionDates = marketVolCube.optionDates();
        const std::vector<Period>& swapTenors = marketVolCube.swapTenors();
        Matrix alphas(optionTimes.size(), swapLengths.size(),0.);
        Matrix betas(alphas);
        Matrix nus(alphas);
        Matrix rhos(alphas);
        Matrix forwards(alphas);
        Matrix errors(alphas);
        Matrix maxErrors(alphas);
        Matrix endCriteria(alphas);

        const std::vector<Matrix>& tmpMarketVolCube = marketVolCube.points();

        std::vector<Real> strikes(strikeSpreads_.size());
        std::vector<Real> volatilities(strikeSpreads_.size());

        for (Size j=0; j<optionTimes.size(); j++) {
            for (Size k=0; k<swapLengths.size(); k++) {
                Rate atmForward = atmStrike(optionDates[j], swapTenors[k]);
                strikes.clear();
                volatilities.clear();
                for (Size i=0; i<nStrikes_; i++){
                    Real strike = atmForward+strikeSpreads_[i];
                    if(strike>=MINSTRIKE) {
                        strikes.push_back(strike);
                        volatilities.push_back(tmpMarketVolCube[i][j][k]);
                    }
                }

                const std::vector<Real>& guess = parametersGuess_.operator()(
                    optionTimes[j], swapLengths[k]);

                const boost::shared_ptr<SABRInterpolation> sabrInterpolation =
                    boost::shared_ptr<SABRInterpolation>(new
                        SABRInterpolation(strikes.begin(), strikes.end(),
                                          volatilities.begin(),
                                          optionTimes[j], atmForward,
                                          guess[0], guess[1],
                                          guess[2], guess[3],
                                          isParameterFixed_[0],
                                          isParameterFixed_[1],
                                          isParameterFixed_[2],
                                          isParameterFixed_[3],
                                          vegaWeightedSmileFit_,
                                          endCriteria_,
                                          optMethod_,
                                          errorAccept_,
                                          useMaxError_,
                                          maxGuesses_));
                sabrInterpolation->update();

                Real rmsError = sabrInterpolation->rmsError();
                Real maxError = sabrInterpolation->maxError();
                alphas     [j][k] = sabrInterpolation->alpha();
                betas      [j][k] = sabrInterpolation->beta();
                nus        [j][k] = sabrInterpolation->nu();
                rhos       [j][k] = sabrInterpolation->rho();
                forwards   [j][k] = atmForward;
                errors     [j][k] = rmsError;
                maxErrors  [j][k] = maxError;
                endCriteria[j][k] = sabrInterpolation->endCriteria();

                QL_ENSURE(endCriteria[j][k]!=EndCriteria::MaxIterations,
                          "global swaptions calibration failed: "
                          "MaxIterations reached: " << "\n" <<
                          "option maturity = " << optionDates[j] << ", \n" <<
                          "swap tenor = " << swapTenors[k] << ", \n" <<
                          "error = " << io::rate(errors[j][k])  << ", \n" <<
                          "max error = " << io::rate(maxErrors[j][k]) << ", \n" <<
                          "   alpha = " <<  alphas[j][k] << "n" <<
                          "   beta = " <<  betas[j][k] << "\n" <<
                          "   nu = " <<  nus[j][k]   << "\n" <<
                          "   rho = " <<  rhos[j][k]  << "\n"
                          );

                QL_ENSURE(useMaxError_ ? maxError : rmsError < maxErrorTolerance_,
                      "global swaptions calibration failed: "
                      "option tenor " << optionDates[j] <<
                      ", swap tenor " << swapTenors[k] <<
                      (useMaxError_ ? ": max error " : ": error") <<
                      (useMaxError_ ? maxError : rmsError) <<
                          "   alpha = " <<  alphas[j][k] << "n" <<
                          "   beta = " <<  betas[j][k] << "\n" <<
                          "   nu = " <<  nus[j][k]   << "\n" <<
                          "   rho = " <<  rhos[j][k]  << "\n" <<
                      (useMaxError_ ? ": error" : ": max error ") <<
                      (useMaxError_ ? rmsError :maxError)
                );

            }
        }
        Cube sabrParametersCube(optionDates, swapTenors,
                                optionTimes, swapLengths, 8);
        sabrParametersCube.setLayer(0, alphas);
        sabrParametersCube.setLayer(1, betas);
        sabrParametersCube.setLayer(2, nus);
        sabrParametersCube.setLayer(3, rhos);
        sabrParametersCube.setLayer(4, forwards);
        sabrParametersCube.setLayer(5, errors);
        sabrParametersCube.setLayer(6, maxErrors);
        sabrParametersCube.setLayer(7, endCriteria);

        return sabrParametersCube;

    }
Exemplo n.º 9
0
    void LocalBootstrap<Curve>::calculate() const {

        validCurve_ = false;
        Size nInsts = ts_->instruments_.size();

        // ensure rate helpers are sorted
        std::sort(ts_->instruments_.begin(), ts_->instruments_.end(),
                  detail::BootstrapHelperSorter());

        // check that there is no instruments with the same maturity
        for (Size i=1; i<nInsts; ++i) {
            Date m1 = ts_->instruments_[i-1]->latestDate(),
                 m2 = ts_->instruments_[i]->latestDate();
            QL_REQUIRE(m1 != m2,
                       "two instruments have the same maturity ("<< m1 <<")");
        }

        // check that there is no instruments with invalid quote
        for (Size i=0; i<nInsts; ++i)
            QL_REQUIRE(ts_->instruments_[i]->quote()->isValid(),
                       io::ordinal(i+1) << " instrument (maturity: " <<
                       ts_->instruments_[i]->latestDate() <<
                       ") has an invalid quote");

        // setup instruments
        for (Size i=0; i<nInsts; ++i) {
            // don't try this at home!
            // This call creates instruments, and removes "const".
            // There is a significant interaction with observability.
            ts_->instruments_[i]->setTermStructure(const_cast<Curve*>(ts_));
        }
        // set initial guess only if the current curve cannot be used as guess
        if (validCurve_)
            QL_ENSURE(ts_->data_.size() == nInsts+1,
                      "dimension mismatch: expected " << nInsts+1 <<
                      ", actual " << ts_->data_.size());
        else {
            ts_->data_ = std::vector<Rate>(nInsts+1);
            ts_->data_[0] = Traits::initialValue(ts_);
        }

        // calculate dates and times
        ts_->dates_ = std::vector<Date>(nInsts+1);
        ts_->times_ = std::vector<Time>(nInsts+1);
        ts_->dates_[0] = Traits::initialDate(ts_);
        ts_->times_[0] = ts_->timeFromReference(ts_->dates_[0]);
        for (Size i=0; i<nInsts; ++i) {
            ts_->dates_[i+1] = ts_->instruments_[i]->latestDate();
            ts_->times_[i+1] = ts_->timeFromReference(ts_->dates_[i+1]);
            if (!validCurve_)
                ts_->data_[i+1] = ts_->data_[i];
        }

        LevenbergMarquardt solver(ts_->accuracy_,
                                  ts_->accuracy_,
                                  ts_->accuracy_);
        EndCriteria endCriteria(100, 10, 0.00, ts_->accuracy_, 0.00);
        PositiveConstraint posConstraint;
        NoConstraint noConstraint;
        Constraint& solverConstraint = forcePositive_ ?
            static_cast<Constraint&>(posConstraint) :
            static_cast<Constraint&>(noConstraint);

        // now start the bootstrapping.
        Size iInst = localisation_-1;

        Size dataAdjust = Curve::interpolator_type::dataSizeAdjustment;

        do {
            Size initialDataPt = iInst+1-localisation_+dataAdjust;
            Array startArray(localisation_+1-dataAdjust);
            for (Size j = 0; j < startArray.size()-1; ++j)
                startArray[j] = ts_->data_[initialDataPt+j];

            // here we are extending the interpolation a point at a
            // time... but the local interpolator can make an
            // approximation for the final localisation period.
            // e.g. if the localisation is 2, then the first section
            // of the curve will be solved using the first 2
            // instruments... with the local interpolator making
            // suitable boundary conditions.
            ts_->interpolation_ =
                ts_->interpolator_.localInterpolate(
                                              ts_->times_.begin(),
                                              ts_->times_.begin()+(iInst + 2),
                                              ts_->data_.begin(),
                                              localisation_,
                                              ts_->interpolation_,
                                              nInsts+1);

            if (iInst >= localisation_) {
                startArray[localisation_-dataAdjust] =
                    Traits::guess(iInst, ts_, false, 0); // ?
            } else {
                startArray[localisation_-dataAdjust] = ts_->data_[0];
            }

            PenaltyFunction<Curve> currentCost(
                        ts_,
                        initialDataPt,
                        ts_->instruments_.begin() + (iInst - localisation_+1),
                        ts_->instruments_.begin() + (iInst+1));

            Problem toSolve(currentCost, solverConstraint, startArray);

            EndCriteria::Type endType = solver.minimize(toSolve, endCriteria);

            // check the end criteria
            QL_REQUIRE(endType == EndCriteria::StationaryFunctionAccuracy ||
                       endType == EndCriteria::StationaryFunctionValue,
                       "Unable to strip yieldcurve to required accuracy " );
            ++iInst;
        } while ( iInst < nInsts );
        validCurve_ = true;
    }