This example fits a discount curve over a set of bonds with a number of methods.
#include <ql/qldefines.hpp>
#ifdef BOOST_MSVC
#  include <ql/auto_link.hpp>
#endif
#include <ql/termstructures/yield/fittedbonddiscountcurve.hpp>
#include <ql/termstructures/yield/piecewiseyieldcurve.hpp>
#include <ql/termstructures/yield/flatforward.hpp>
#include <ql/termstructures/yield/bondhelpers.hpp>
#include <ql/termstructures/yield/nonlinearfittingmethods.hpp>
#include <ql/pricingengines/bond/bondfunctions.hpp>
#include <ql/time/calendars/target.hpp>
#include <ql/time/daycounters/simpledaycounter.hpp>
#include <boost/timer.hpp>
#include <iostream>
#include <iomanip>
#include <boost/make_shared.hpp>
#define LENGTH(a) (sizeof(a)/sizeof(a[0]))
#if defined(QL_ENABLE_SESSIONS)
}
#endif
             const std::vector<Date>& dates,
    QL_REQUIRE(dates.size() >= 2, "at least two dates are required");
    for (
Size i=1; i<dates.size(); ++i) {
         QL_REQUIRE(dt>=0.0, "unsorted dates");
        sum += yts.
discount(dates[i]) * dt;
    }
    Real result = yts.discount(dates.front()) - yts.discount(dates.back());
     return result/sum;
}
void printOutput(const std::string& tag,
                 const boost::shared_ptr<FittedBondDiscountCurve>& curve) {
    cout << tag << endl;
    cout << "reference date : "
         << curve->referenceDate()
         << endl;
    cout << "number of iterations : "
         << curve->fitResults().numberOfIterations()
         << endl
         << endl;
}
int main(int, char* []) {
    try {
        boost::timer timer;
        const Size numberOfBonds = 15;
         Real cleanPrice[numberOfBonds];
         for (
Size i=0; i<numberOfBonds; i++) {
             cleanPrice[i]=100.0;
        }
        std::vector< boost::shared_ptr<SimpleQuote> > quote;
        for (
Size i=0; i<numberOfBonds; i++) {
             boost::shared_ptr<SimpleQuote> cp(
new SimpleQuote(cleanPrice[i]));
            quote.push_back(cp);
        }
        for (
Size i=0; i<numberOfBonds; i++) {
             quoteHandle[i].
linkTo(quote[i]);
        }
        Integer lengths[] = { 2, 4, 6, 8, 10, 12, 14, 16,
                               18, 20, 22, 24, 26, 28, 30 };
        Real coupons[] = { 0.0200, 0.0225, 0.0250, 0.0275, 0.0300,
                            0.0325, 0.0350, 0.0375, 0.0400, 0.0425,
                           0.0450, 0.0475, 0.0500, 0.0525, 0.0550 };
        Settings::instance().evaluationDate() = today;
        
        
        Date bondSettlementDate = calendar.
advance(today, bondSettlementDays*Days);
         cout << endl;
        cout << "Today's date: " << today << endl;
        cout << "Bonds' settlement date: " << bondSettlementDate << endl;
        cout << "Calculating fit for 15 bonds....." << endl << endl;
        std::vector<boost::shared_ptr<BondHelper> > instrumentsA;
        std::vector<boost::shared_ptr<RateHelper> > instrumentsB;
        for (
Size j=0; j<LENGTH(lengths); j++) {
             Date maturity = calendar.
advance(bondSettlementDate, lengths[j]*Years);
                               calendar, accrualConvention, accrualConvention,
                              DateGeneration::Backward, false);
            boost::shared_ptr<BondHelper> helperA(
                                             bondSettlementDays,
                                             100.0,
                                             schedule,
                                             std::vector<Rate>(1,coupons[j]),
                                             dc,
                                             convention,
                                             redemption));
            boost::shared_ptr<RateHelper> helperB(
                                             bondSettlementDays,
                                             100.0,
                                             schedule,
                                             std::vector<Rate>(1, coupons[j]),
                                             dc,
                                             convention,
                                             redemption));
            instrumentsA.push_back(helperA);
            instrumentsB.push_back(helperB);
        }
        bool constrainAtZero = true;
        Real tolerance = 1.0e-10;
         boost::shared_ptr<YieldTermStructure> ts0 (
                                                          calendar,
                                                          instrumentsB,
                                                          dc));
        boost::shared_ptr<FittedBondDiscountCurve> ts1 (
                                              calendar,
                                              instrumentsA,
                                              dc,
                                              exponentialSplines,
                                              tolerance,
                                              max));
        printOutput("(a) exponential splines", ts1);
        boost::shared_ptr<FittedBondDiscountCurve> ts2 (
                                                calendar,
                                                instrumentsA,
                                                dc,
                                                simplePolynomial,
                                                tolerance,
                                                max));
        printOutput("(b) simple polynomial", ts2);
        boost::shared_ptr<FittedBondDiscountCurve> ts3 (
                                                    calendar,
                                                    instrumentsA,
                                                    dc,
                                                    nelsonSiegel,
                                                    tolerance,
                                                    max));
        printOutput("(c) Nelson-Siegel", ts3);
        
        
        Time knots[] =  { -30.0, -20.0,  0.0,  5.0, 10.0, 15.0,
                            20.0,  25.0, 30.0, 40.0, 50.0 };
        std::vector<Time> knotVector;
        for (
Size i=0; i< LENGTH(knots); i++) {
             knotVector.push_back(knots[i]);
        }
        boost::shared_ptr<FittedBondDiscountCurve> ts4 (
                                                   calendar,
                                                   instrumentsA,
                                                   dc,
                                                   cubicBSplines,
                                                   tolerance,
                                                   max));
        printOutput("(d) cubic B-splines", ts4);
        boost::shared_ptr<FittedBondDiscountCurve> ts5 (
                                                    calendar,
                                                    instrumentsA,
                                                    dc,
                                                    svensson,
                                                    tolerance,
                                                    max));
        printOutput("(e) Svensson", ts5);
            boost::make_shared<FlatForward>(
                                    curveSettlementDays, calendar, 0.01, dc));
                                    boost::make_shared<NelsonSiegelFitting>(),
                                    discountCurve);
        boost::shared_ptr<FittedBondDiscountCurve> ts6 (
                                                    calendar,
                                                    instrumentsA,
                                                    dc,
                                                    nelsonSiegelSpread,
                                                    tolerance,
                                                    max));
        printOutput("(f) Nelson-Siegel spreaded", ts6);
        cout << "Output par rates for each curve. In this case, "
             << endl
             << "par rates should equal coupons for these par bonds."
             << endl
             << endl;
        cout << setw(6) << "tenor" << " | "
             << setw(6) << "coupon" << " | "
             << setw(6) << "bstrap" << " | "
             << setw(6) << "(a)" << " | "
             << setw(6) << "(b)" << " | "
             << setw(6) << "(c)" << " | "
             << setw(6) << "(d)" << " | "
             << setw(6) << "(e)" << " | "
             << setw(6) << "(f)" << endl;
        for (
Size i=0; i<instrumentsA.size(); i++) {
             std::vector<boost::shared_ptr<CashFlow> > cfs =
                instrumentsA[i]->bond()->cashflows();
            Size cfSize = instrumentsA[i]->bond()->cashflows().size();
             std::vector<Date> keyDates;
            keyDates.push_back(bondSettlementDate);
            for (
Size j=0; j<cfSize-1; j++) {
                 if (!cfs[j]->hasOccurred(bondSettlementDate, false)) {
                    Date myDate =  cfs[j]->date();
                     keyDates.push_back(myDate);
                }
            }
            cout << setw(6) << fixed << setprecision(3) << tenor << " | "
                 << setw(6) << fixed << setprecision(3)
                 << 100.*coupons[i] << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts0,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts1,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts2,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts3,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts4,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts5,keyDates,dc)  << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts6,keyDates,dc) << endl;
        }
        cout << endl << endl << endl;
        cout << "Now add 23 months to today. Par rates should be "  << endl
             << "automatically recalculated because today's date "  << endl
             << "changes.  Par rates will NOT equal coupons (YTM "  << endl
             << "will, with the correct compounding), but the "     << endl
             << "piecewise yield curve par rates can be used as "   << endl
             << "a benchmark for correct par rates."
             << endl
             << endl;
        today = calendar.
advance(origToday,23,Months,convention);
        Settings::instance().evaluationDate() = today;
        bondSettlementDate = calendar.
advance(today, bondSettlementDays*Days);
        printOutput("(a) exponential splines", ts1);
        printOutput("(b) simple polynomial", ts2);
        printOutput("(c) Nelson-Siegel", ts3);
        printOutput("(d) cubic B-splines", ts4);
        printOutput("(e) Svensson", ts5);
        printOutput("(f) Nelson-Siegel spreaded", ts6);
        cout << endl
             << endl;
        cout << setw(6) << "tenor" << " | "
             << setw(6) << "coupon" << " | "
             << setw(6) << "bstrap" << " | "
             << setw(6) << "(a)" << " | "
             << setw(6) << "(b)" << " | "
             << setw(6) << "(c)" << " | "
             << setw(6) << "(d)" << " | "
             << setw(6) << "(e)" << " | "
             << setw(6) << "(f)" << endl;
        for (
Size i=0; i<instrumentsA.size(); i++) {
             std::vector<boost::shared_ptr<CashFlow> > cfs =
                instrumentsA[i]->bond()->cashflows();
            Size cfSize = instrumentsA[i]->bond()->cashflows().size();
             std::vector<Date> keyDates;
            keyDates.push_back(bondSettlementDate);
            for (
Size j=0; j<cfSize-1; j++) {
                 if (!cfs[j]->hasOccurred(bondSettlementDate, false)) {
                    Date myDate =  cfs[j]->date();
                     keyDates.push_back(myDate);
                }
            }
            cout << setw(6) << fixed << setprecision(3) << tenor << " | "
                 << setw(6) << fixed << setprecision(3)
                 << 100.*coupons[i] << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts0,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts1,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts2,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts3,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts4,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts5,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts6,keyDates,dc) << endl;
        }
        cout << endl << endl << endl;
        cout << "Now add one more month, for a total of two years " << endl
             << "from the original date. The first instrument is "  << endl
             << "now expired and par rates should again equal "     << endl
             << "coupon values, since clean prices did not change."
             << endl
             << endl;
        instrumentsA.erase(instrumentsA.begin(),
                           instrumentsA.begin()+1);
        instrumentsB.erase(instrumentsB.begin(),
                           instrumentsB.begin()+1);
        today = calendar.
advance(origToday,24,Months,convention);
        Settings::instance().evaluationDate() = today;
        bondSettlementDate = calendar.
advance(today, bondSettlementDays*Days);
        boost::shared_ptr<YieldTermStructure> ts00 (
                                                          calendar,
                                                          instrumentsB,
                                                          dc));
        boost::shared_ptr<FittedBondDiscountCurve> ts11 (
                                              calendar,
                                              instrumentsA,
                                              dc,
                                              exponentialSplines,
                                              tolerance,
                                              max));
        printOutput("(a) exponential splines", ts11);
        boost::shared_ptr<FittedBondDiscountCurve> ts22 (
                                                calendar,
                                                instrumentsA,
                                                dc,
                                                simplePolynomial,
                                                tolerance,
                                                max));
        printOutput("(b) simple polynomial", ts22);
        boost::shared_ptr<FittedBondDiscountCurve> ts33 (
                                                    calendar,
                                                    instrumentsA,
                                                    dc,
                                                    nelsonSiegel,
                                                    tolerance,
                                                    max));
        printOutput("(c) Nelson-Siegel", ts33);
        boost::shared_ptr<FittedBondDiscountCurve> ts44 (
                                                   calendar,
                                                   instrumentsA,
                                                   dc,
                                                   cubicBSplines,
                                                   tolerance,
                                                   max));
        printOutput("(d) cubic B-splines", ts44);
        boost::shared_ptr<FittedBondDiscountCurve> ts55 (
                                                   calendar,
                                                   instrumentsA,
                                                   dc,
                                                   svensson,
                                                   tolerance,
                                                   max));
        printOutput("(e) Svensson", ts55);
        boost::shared_ptr<FittedBondDiscountCurve> ts66 (
                                                    calendar,
                                                    instrumentsA,
                                                    dc,
                                                    nelsonSiegelSpread,
                                                    tolerance,
                                                    max));
        printOutput("(f) Nelson-Siegel spreaded", ts66);
        cout << setw(6) << "tenor" << " | "
             << setw(6) << "coupon" << " | "
             << setw(6) << "bstrap" << " | "
             << setw(6) << "(a)" << " | "
             << setw(6) << "(b)" << " | "
             << setw(6) << "(c)" << " | "
             << setw(6) << "(d)" << " | "
             << setw(6) << "(e)" << " | "
             << setw(6) << "(f)" << endl;
        for (
Size i=0; i<instrumentsA.size(); i++) {
             std::vector<boost::shared_ptr<CashFlow> > cfs =
                instrumentsA[i]->bond()->cashflows();
            Size cfSize = instrumentsA[i]->bond()->cashflows().size();
             std::vector<Date> keyDates;
            keyDates.push_back(bondSettlementDate);
            for (
Size j=0; j<cfSize-1; j++) {
                 if (!cfs[j]->hasOccurred(bondSettlementDate, false)) {
                    Date myDate =  cfs[j]->date();
                     keyDates.push_back(myDate);
                }
            }
            cout << setw(6) << fixed << setprecision(3) << tenor << " | "
                 << setw(6) << fixed << setprecision(3)
                 << 100.*coupons[i+1] << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts00,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts11,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts22,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts33,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts44,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts55,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts66,keyDates,dc) << endl;
        }
        cout << endl << endl << endl;
        cout << "Now decrease prices by a small amount, corresponding"  << endl
             << "to a theoretical five basis point parallel + shift of" << endl
             << "the yield curve. Because bond quotes change, the new " << endl
             << "par rates should be recalculated automatically."
             << endl
             << endl;
        for (
Size k=0; k<LENGTH(lengths)-1; k++) {
             Real P = instrumentsA[k]->quote()->value();
             const Bond& b = *instrumentsA[k]->bond();
             Rate ytm = BondFunctions::yield(b, P,
                                             dc, Compounded, frequency,
                                            today);
            Time dur = BondFunctions::duration(b, ytm,
                                                dc, Compounded, frequency,
                                               Duration::Modified,
                                               today);
            const Real bpsChange = 5.;
             
            Real deltaP = -dur * P * (bpsChange/10000.);
             quote[k+1]->setValue(P + deltaP);
        }
        cout << setw(6) << "tenor" << " | "
             << setw(6) << "coupon" << " | "
             << setw(6) << "bstrap" << " | "
             << setw(6) << "(a)" << " | "
             << setw(6) << "(b)" << " | "
             << setw(6) << "(c)" << " | "
             << setw(6) << "(d)" << " | "
             << setw(6) << "(e)" << " | "
             << setw(6) << "(f)" << endl;
        for (
Size i=0; i<instrumentsA.size(); i++) {
             std::vector<boost::shared_ptr<CashFlow> > cfs =
                instrumentsA[i]->bond()->cashflows();
            Size cfSize = instrumentsA[i]->bond()->cashflows().size();
             std::vector<Date> keyDates;
            keyDates.push_back(bondSettlementDate);
            for (
Size j=0; j<cfSize-1; j++) {
                 if (!cfs[j]->hasOccurred(bondSettlementDate, false)) {
                    Date myDate =  cfs[j]->date();
                     keyDates.push_back(myDate);
                }
            }
            cout << setw(6) << fixed << setprecision(3) << tenor << " | "
                 << setw(6) << fixed << setprecision(3)
                 << 100.*coupons[i+1] << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts00,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts11,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts22,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts33,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts44,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts55,keyDates,dc) << " | "
                 
                 << setw(6) << fixed << setprecision(3)
                 << 100.*parRate(*ts66,keyDates,dc) << endl;
        }
        double seconds = timer.elapsed();
        seconds -= hours * 3600;
        seconds -= minutes * 60;
        std::cout << " \nRun completed in ";
        if (hours > 0)
            std::cout << hours << " h ";
        if (hours > 0 || minutes > 0)
            std::cout << minutes << " m ";
        std::cout << std::fixed << std::setprecision(0)
                  << seconds << " s\n" << std::endl;
        return 0;
    } catch (std::exception& e) {
        cerr << e.what() << endl;
        return 1;
    } catch (...) {
        cerr << "unknown error" << endl;
        return 1;
    }
}