예제 #1
0
void InflationCPICapFloorTest::cpicapfloorpricer() {

    CommonVars common;
    Real nominal = 1.0;
    boost::shared_ptr<CPICapFloorTermPriceSurface> cpiCFpriceSurf(new InterpolatedCPICapFloorTermPriceSurface
                                                    <Bilinear>(nominal,
                                                               common.baseZeroRate,
                                                               common.observationLag,
                                                               common.calendar,
                                                               common.convention,
                                                               common.dcZCIIS,
                                                               common.hii,
                                                               common.nominalUK,
                                                               common.cStrikesUK,
                                                               common.fStrikesUK,
                                                               common.cfMaturitiesUK,
                                                               *(common.cPriceUK),
                                                               *(common.fPriceUK)));

    common.cpiCFsurfUK = cpiCFpriceSurf;

    // interpolation pricer first
    // N.B. no new instrument required but we do need a new pricer

    Date startDate = Settings::instance().evaluationDate();
    Date maturity(startDate + Period(3,Years));
    Calendar fixCalendar = UnitedKingdom(), payCalendar = UnitedKingdom();
    BusinessDayConvention fixConvention(Unadjusted), payConvention(ModifiedFollowing);
    Rate strike(0.03);
    Real baseCPI = common.hii->fixing(fixCalendar.adjust(startDate-common.observationLag,fixConvention));
    CPI::InterpolationType observationInterpolation = CPI::AsIndex;
    CPICapFloor aCap(Option::Call,
                     nominal,
                     startDate,   // start date of contract (only)
                     baseCPI,
                     maturity,    // this is pre-adjustment!
                     fixCalendar,
                     fixConvention,
                     payCalendar,
                     payConvention,
                     strike,
                     common.hii,
                     common.observationLag,
                     observationInterpolation);

    Handle<CPICapFloorTermPriceSurface> cpiCFsurfUKh(common.cpiCFsurfUK);
    boost::shared_ptr<PricingEngine>engine(new InterpolatingCPICapFloorEngine(cpiCFsurfUKh));

    aCap.setPricingEngine(engine);

    Date d = common.cpiCFsurfUK->cpiOptionDateFromTenor(Period(3,Years));


    Real cached = cpiCFsurfUKh->capPrice(d, strike);
    QL_REQUIRE(fabs(cached - aCap.NPV())<1e-10,"InterpolatingCPICapFloorEngine does not reproduce cached price: "
               << cached << " vs " << aCap.NPV());

    // remove circular refernce
    common.hcpi.linkTo(boost::shared_ptr<ZeroInflationTermStructure>());
}
예제 #2
0
    AverageBMALeg::operator Leg() const {

        QL_REQUIRE(!notionals_.empty(), "no notional given");

        Leg cashflows;

        // the following is not always correct
        Calendar calendar = schedule_.calendar();

        Date refStart, start, refEnd, end;
        Date paymentDate;

        Size n = schedule_.size()-1;
        for (Size i=0; i<n; ++i) {
            refStart = start = schedule_.date(i);
            refEnd   =   end = schedule_.date(i+1);
            paymentDate = calendar.adjust(end, paymentAdjustment_);
            if (i == 0 && schedule_.hasIsRegular() && !schedule_.isRegular(i+1)
                && schedule_.hasTenor())
                refStart = calendar.adjust(end - schedule_.tenor(),
                                           paymentAdjustment_);
            if (i == n-1 && schedule_.hasIsRegular() && !schedule_.isRegular(i+1)
                && schedule_.hasTenor())
                refEnd = calendar.adjust(start + schedule_.tenor(),
                                         paymentAdjustment_);

            cashflows.push_back(ext::shared_ptr<CashFlow>(new
                AverageBMACoupon(paymentDate,
                                 detail::get(notionals_, i, notionals_.back()),
                                 start, end,
                                 index_,
                                 detail::get(gearings_, i, 1.0),
                                 detail::get(spreads_, i, 0.0),
                                 refStart, refEnd,
                                 paymentDayCounter_)));
        }

        return cashflows;
    }
예제 #3
0
    CmsSpreadRangeAccrualLeg::operator Leg() const {

        QL_REQUIRE(!notionals_.empty(), "no notional given");

        Size n = schedule_.size()-1;
        QL_REQUIRE(notionals_.size() <= n,
                   "too many nominals (" << notionals_.size() <<
                   "), only " << n << " required");
        QL_REQUIRE(fixingDays_.size() <= n,
                   "too many fixingDays (" << fixingDays_.size() <<
                   "), only " << n << " required");
        QL_REQUIRE(gearings_.size()<=n,
                   "too many gearings (" << gearings_.size() <<
                   "), only " << n << " required");
        QL_REQUIRE(spreads_.size()<=n,
                   "too many spreads (" << spreads_.size() <<
                   "), only " << n << " required");
        QL_REQUIRE(lowerTriggers_.size()<=n,
                   "too many lowerTriggers (" << lowerTriggers_.size() <<
                   "), only " << n << " required");
        QL_REQUIRE(upperTriggers_.size()<=n,
                   "too many upperTriggers (" << upperTriggers_.size() <<
                   "), only " << n << " required");

        Leg leg(n);

        // the following is not always correct
        Calendar calendar = schedule_.calendar();

        Date refStart, start, refEnd, end;
        Date paymentDate;
        std::vector<boost::shared_ptr<Schedule> > observationsSchedules;

        for (Size i=0; i<n; ++i) {
            refStart = start = schedule_.date(i);
            refEnd   =   end = schedule_.date(i+1);
            paymentDate = calendar.adjust(end, paymentAdjustment_);
            if (i==0   && !schedule_.isRegular(i+1)) {
                BusinessDayConvention bdc = schedule_.businessDayConvention();
                refStart = calendar.adjust(end - schedule_.tenor(), bdc);
            }
            if (i==n-1 && !schedule_.isRegular(i+1)) {
                BusinessDayConvention bdc = schedule_.businessDayConvention();
                refEnd = calendar.adjust(start + schedule_.tenor(), bdc);
            }
            if (detail::get(gearings_, i, 1.0) == 0.0) { // fixed coupon
                leg.push_back(boost::shared_ptr<CashFlow>(new
                    FixedRateCoupon(paymentDate,
                                    detail::get(notionals_, i, Null<Real>()),
                                    detail::get(spreads_, i, 0.0),
                                    paymentDayCounter_,
                                    start, end, refStart, refEnd)));
            } else { // floating coupon
                observationsSchedules.push_back(
                    boost::shared_ptr<Schedule>(new
                        Schedule(start, end,
                                 observationTenor_, calendar,
                                 observationConvention_,
                                 observationConvention_,
                                 DateGeneration::Forward, false)));

                    leg.push_back(boost::shared_ptr<CashFlow>(new
                       CmsSpreadRangeAccrualCoupon(
                            paymentDate,
                            detail::get(notionals_, i, Null<Real>()),
                            index_,
                            start, end,
                            detail::get(fixingDays_, i, 2),
                            paymentDayCounter_,
                            detail::get(gearings_, i, 1.0),
                            detail::get(spreads_, i, 0.0),
                            refStart, refEnd,
                            observationsSchedules.back(),
                            detail::get(lowerTriggers_, i, Null<Rate>()),
                            detail::get(upperTriggers_, i, Null<Rate>()))));
            }
        }
        return leg;
    }
예제 #4
0
    yoyInflationLeg::operator Leg() const {

        Size n = schedule_.size()-1;
        QL_REQUIRE(!notionals_.empty(), "no notional given");
        QL_REQUIRE(notionals_.size() <= n,
                   "too many nominals (" << notionals_.size() <<
                   "), only " << n << " required");
        QL_REQUIRE(gearings_.size()<=n,
                   "too many gearings (" << gearings_.size() <<
                   "), only " << n << " required");
        QL_REQUIRE(spreads_.size()<=n,
                   "too many spreads (" << spreads_.size() <<
                   "), only " << n << " required");
        QL_REQUIRE(caps_.size()<=n,
                   "too many caps (" << caps_.size() <<
                   "), only " << n << " required");
        QL_REQUIRE(floors_.size()<=n,
                   "too many floors (" << floors_.size() <<
                   "), only " << n << " required");

        Leg leg; leg.reserve(n);

        Calendar calendar = paymentCalendar_;

        Date refStart, start, refEnd, end;

        for (Size i=0; i<n; ++i) {
            refStart = start = schedule_.date(i);
            refEnd   =   end = schedule_.date(i+1);
            Date paymentDate = calendar.adjust(end, paymentAdjustment_);
            if (i==0 && schedule_.hasIsRegular() && !schedule_.isRegular(i+1)) {
                BusinessDayConvention bdc = schedule_.businessDayConvention();
                refStart = schedule_.calendar().adjust(end - schedule_.tenor(), bdc);
            }
            if (i==n-1 && schedule_.hasIsRegular() && !schedule_.isRegular(i+1)) {
                BusinessDayConvention bdc = schedule_.businessDayConvention();
                refEnd = schedule_.calendar().adjust(start + schedule_.tenor(), bdc);
            }
            if (detail::get(gearings_, i, 1.0) == 0.0) { // fixed coupon
                leg.push_back(ext::shared_ptr<CashFlow>(new
                            FixedRateCoupon(paymentDate,
                            detail::get(notionals_, i, 1.0),
                            detail::effectiveFixedRate(spreads_,caps_,
                                    floors_,i),
                                    paymentDayCounter_,
                                    start, end, refStart, refEnd)));
            } else { // yoy inflation coupon
                if (detail::noOption(caps_, floors_, i)) { // just swaplet
                    ext::shared_ptr<YoYInflationCoupon> coup(new
                            YoYInflationCoupon(
                            paymentDate,
                            detail::get(notionals_, i, 1.0),
                            start, end,
                            detail::get(fixingDays_, i, 0),
                            index_,
                            observationLag_,
                            paymentDayCounter_,
                            detail::get(gearings_, i, 1.0),
                            detail::get(spreads_, i, 0.0),
                            refStart, refEnd));

                    // in this case you can set a pricer
                    // straight away because it only provides computation - not data
                    ext::shared_ptr<YoYInflationCouponPricer> pricer(
                                            new YoYInflationCouponPricer);
                    coup->setPricer(pricer);
                    leg.push_back(ext::dynamic_pointer_cast<CashFlow>(coup));



                } else {    // cap/floorlet
                    leg.push_back(ext::shared_ptr<CashFlow>(new
                            CappedFlooredYoYInflationCoupon(
                            paymentDate,
                            detail::get(notionals_, i, 1.0),
                            start, end,
                            detail::get(fixingDays_, i, 0),
                            index_,
                            observationLag_,
                            paymentDayCounter_,
                            detail::get(gearings_, i, 1.0),
                            detail::get(spreads_, i, 0.0),
                            detail::get(caps_,   i, Null<Rate>()),
                            detail::get(floors_, i, Null<Rate>()),
                            refStart, refEnd)));
                }
            }
        }

        return leg;
    }
예제 #5
0
int main(int, char* []) {

    try {

        boost::timer timer;
        std::cout << std::endl;

        Calendar calendar = TARGET();
        Date todaysDate(19, March, 2014);
        // must be a business day
        todaysDate = calendar.adjust(todaysDate);

        Settings::instance().evaluationDate() = todaysDate;


        /* --------------------------------------------------------------
                        SET UP BASKET PORTFOLIO
        -------------------------------------------------------------- */
        // build curves and issuers into a basket of ten names
        std::vector<Real> hazardRates;
        hazardRates += 
        //  0.01, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9;        
            0.001, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09;        
        //  0.01,  0.01,  0.01,  0.01, 0.01,  0.01,  0.01,  0.01,  0.01,  0.01;        
        std::vector<std::string> names;
        for(Size i=0; i<hazardRates.size(); i++)
            names.push_back(std::string("Acme") + 
                boost::lexical_cast<std::string>(i));
        std::vector<Handle<DefaultProbabilityTermStructure> > defTS;
        for(Size i=0; i<hazardRates.size(); i++) {
            defTS.push_back(Handle<DefaultProbabilityTermStructure>(
                boost::make_shared<FlatHazardRate>(0, TARGET(), hazardRates[i], 
                    Actual365Fixed())));
            defTS.back()->enableExtrapolation();
        }
        std::vector<Issuer> issuers;
        for(Size i=0; i<hazardRates.size(); i++) {
            std::vector<QuantLib::Issuer::key_curve_pair> curves(1, 
                std::make_pair(NorthAmericaCorpDefaultKey(
                    EURCurrency(), QuantLib::SeniorSec,
                    Period(), 1. // amount threshold
                    ), defTS[i]));
            issuers.push_back(Issuer(curves));
        }

        boost::shared_ptr<Pool> thePool = boost::make_shared<Pool>();
        for(Size i=0; i<hazardRates.size(); i++)
            thePool->add(names[i], issuers[i], NorthAmericaCorpDefaultKey(
                    EURCurrency(), QuantLib::SeniorSec, Period(), 1.));

        std::vector<DefaultProbKey> defaultKeys(hazardRates.size(), 
            NorthAmericaCorpDefaultKey(EURCurrency(), SeniorSec, Period(), 1.));
        boost::shared_ptr<Basket> theBskt = boost::make_shared<Basket>(
            todaysDate, 
            names, std::vector<Real>(hazardRates.size(), 100.), thePool,
         //   0.0, 0.78);
            0.03, .06);

        /* --------------------------------------------------------------
                        SET UP DEFAULT LOSS MODELS
        -------------------------------------------------------------- */

        std::vector<Real> recoveries(hazardRates.size(), 0.4);

        Date calcDate(TARGET().advance(Settings::instance().evaluationDate(), 
            Period(60, Months)));
        Real factorValue = 0.05;
        std::vector<std::vector<Real> > fctrsWeights(hazardRates.size(), 
            std::vector<Real>(1, std::sqrt(factorValue)));

        // --- LHP model --------------------------
        boost::shared_ptr<DefaultLossModel> lmGLHP(
            boost::make_shared<GaussianLHPLossModel>(
                fctrsWeights[0][0] * fctrsWeights[0][0], recoveries));
        theBskt->setLossModel(lmGLHP);

        std::cout << "GLHP Expected 10-Yr Losses: "  << std::endl;
        std::cout << theBskt->expectedTrancheLoss(calcDate) << std::endl;

        // --- G Binomial model --------------------
        boost::shared_ptr<GaussianConstantLossLM> ktLossLM(
            boost::make_shared<GaussianConstantLossLM>(fctrsWeights, 
            recoveries, LatentModelIntegrationType::GaussianQuadrature, 
            GaussianCopulaPolicy::initTraits()));
        boost::shared_ptr<DefaultLossModel> lmBinomial(
            boost::make_shared<GaussianBinomialLossModel>(ktLossLM));
        theBskt->setLossModel(lmBinomial);

        std::cout << "Gaussian Binomial Expected 10-Yr Losses: "  << std::endl;
        std::cout << theBskt->expectedTrancheLoss(calcDate) << std::endl;

        // --- T Binomial model --------------------
        TCopulaPolicy::initTraits initT;
        initT.tOrders = std::vector<Integer>(2, 3);
        boost::shared_ptr<TConstantLossLM> ktTLossLM(
            boost::make_shared<TConstantLossLM>(fctrsWeights, 
            recoveries, 
            //LatentModelIntegrationType::GaussianQuadrature,
              LatentModelIntegrationType::Trapezoid,
            initT));
        boost::shared_ptr<DefaultLossModel> lmTBinomial(
            boost::make_shared<TBinomialLossModel>(ktTLossLM));
        theBskt->setLossModel(lmTBinomial);

        std::cout << "T Binomial Expected 10-Yr Losses: "  << std::endl;
        std::cout << theBskt->expectedTrancheLoss(calcDate) << std::endl;

        // --- G Inhomogeneous model ---------------
        boost::shared_ptr<GaussianConstantLossLM> gLM(
            boost::make_shared<GaussianConstantLossLM>(fctrsWeights, 
            recoveries,
            LatentModelIntegrationType::GaussianQuadrature,
            // g++ requires this when using make_shared
            GaussianCopulaPolicy::initTraits()));

        Size numBuckets = 100;
        boost::shared_ptr<DefaultLossModel> inhomogeneousLM(
            boost::make_shared<IHGaussPoolLossModel>(gLM, numBuckets));
        theBskt->setLossModel(inhomogeneousLM);

        std::cout << "G Inhomogeneous Expected 10-Yr Losses: "  << std::endl;
        std::cout << theBskt->expectedTrancheLoss(calcDate) << std::endl;

        // --- G Random model ---------------------
        // Gaussian random joint default model:
        Size numSimulations = 100000;
        // Size numCoresUsed = 4;
        // Sobol, many cores
        boost::shared_ptr<DefaultLossModel> rdlmG(
            boost::make_shared<RandomDefaultLM<GaussianCopulaPolicy, 
            RandomSequenceGenerator<
                BoxMullerGaussianRng<MersenneTwisterUniformRng> > > >(gLM, 
                    recoveries, numSimulations, 1.e-6, 2863311530));
        //boost::shared_ptr<DefaultLossModel> rdlmG(
        //    boost::make_shared<RandomDefaultLM<GaussianCopulaPolicy> >(gLM, 
        //        recoveries, numSimulations, 1.e-6, 2863311530));
        theBskt->setLossModel(rdlmG);

        std::cout << "Random G Expected 10-Yr Losses: "  << std::endl;
        std::cout << theBskt->expectedTrancheLoss(calcDate) << std::endl;

        // --- StudentT Random model ---------------------
        // Sobol, many cores
        boost::shared_ptr<DefaultLossModel> rdlmT(
            boost::make_shared<RandomDefaultLM<TCopulaPolicy, 
            RandomSequenceGenerator<
                PolarStudentTRng<MersenneTwisterUniformRng> > > >(ktTLossLM, 
                    recoveries, numSimulations, 1.e-6, 2863311530));
        //boost::shared_ptr<DefaultLossModel> rdlmT(
        //    boost::make_shared<RandomDefaultLM<TCopulaPolicy> >(ktTLossLM, 
        //        recoveries, numSimulations, 1.e-6, 2863311530));
        theBskt->setLossModel(rdlmT);

        std::cout << "Random T Expected 10-Yr Losses: "  << std::endl;
        std::cout << theBskt->expectedTrancheLoss(calcDate) << std::endl;


        // Spot Loss latent model: 
        std::vector<std::vector<Real> > fctrsWeightsRR(2 * hazardRates.size(), 
            std::vector<Real>(1, std::sqrt(factorValue)));
        Real modelA = 2.2;
        boost::shared_ptr<GaussianSpotLossLM> sptLG(new GaussianSpotLossLM(
            fctrsWeightsRR, recoveries, modelA,
            LatentModelIntegrationType::GaussianQuadrature,
            GaussianCopulaPolicy::initTraits()));
        boost::shared_ptr<TSpotLossLM> sptLT(new TSpotLossLM(fctrsWeightsRR, 
            recoveries, modelA,
            LatentModelIntegrationType::GaussianQuadrature, initT));


        // --- G Random Loss model ---------------------
        // Gaussian random joint default model:
        // Sobol, many cores
        boost::shared_ptr<DefaultLossModel> rdLlmG(
            boost::make_shared<RandomLossLM<GaussianCopulaPolicy> >(sptLG, 
                numSimulations, 1.e-6, 2863311530));
        theBskt->setLossModel(rdLlmG);

        std::cout << "Random Loss G Expected 10-Yr Losses: "  << std::endl;
        std::cout << theBskt->expectedTrancheLoss(calcDate) << std::endl;

        // --- T Random Loss model ---------------------
        // Gaussian random joint default model:
        // Sobol, many cores
        boost::shared_ptr<DefaultLossModel> rdLlmT(
            boost::make_shared<RandomLossLM<TCopulaPolicy> >(sptLT, 
                numSimulations, 1.e-6, 2863311530));
        theBskt->setLossModel(rdLlmT);

        std::cout << "Random Loss T Expected 10-Yr Losses: "  << std::endl;
        std::cout << theBskt->expectedTrancheLoss(calcDate) << std::endl;





        // Base Correlation model set up to test cocherence with base LHP model
        std::vector<Period> bcTenors;
        bcTenors.push_back(Period(1, Years));
        bcTenors.push_back(Period(5, Years));
        std::vector<Real> bcLossPercentages;
        bcLossPercentages.push_back(0.03);
        bcLossPercentages.push_back(0.12);
        std::vector<std::vector<Handle<Quote> > > correls;
        // 
        std::vector<Handle<Quote> > corr1Y;
        // 3%
        corr1Y.push_back(Handle<Quote>(boost::shared_ptr<Quote>(
            new SimpleQuote(fctrsWeights[0][0] * fctrsWeights[0][0]))));
        // 12%
        corr1Y.push_back(Handle<Quote>(boost::shared_ptr<Quote>(
            new SimpleQuote(fctrsWeights[0][0] * fctrsWeights[0][0]))));
        correls.push_back(corr1Y);
        std::vector<Handle<Quote> > corr2Y;
        // 3%
        corr2Y.push_back(Handle<Quote>(boost::shared_ptr<Quote>(
            new SimpleQuote(fctrsWeights[0][0] * fctrsWeights[0][0]))));
        // 12%
        corr2Y.push_back(Handle<Quote>(boost::shared_ptr<Quote>(
            new SimpleQuote(fctrsWeights[0][0] * fctrsWeights[0][0]))));
        correls.push_back(corr2Y);
        boost::shared_ptr<BaseCorrelationTermStructure<BilinearInterpolation> > 
          correlSurface(
            new BaseCorrelationTermStructure<BilinearInterpolation>(
                // first one would do, all should be the same.
                defTS[0]->settlementDays(),
                defTS[0]->calendar(),
                Unadjusted,
                bcTenors,
                bcLossPercentages,
                correls,
                Actual365Fixed()
            )
        );
        Handle<BaseCorrelationTermStructure<BilinearInterpolation> > 
            correlHandle(correlSurface);
        boost::shared_ptr<DefaultLossModel> bcLMG_LHP_Bilin(
            boost::make_shared<GaussianLHPFlatBCLM>(correlHandle, recoveries,
                GaussianCopulaPolicy::initTraits()));

        theBskt->setLossModel(bcLMG_LHP_Bilin);

        std::cout << "Base Correlation GLHP Expected 10-Yr Losses: "  
            << std::endl;
        std::cout << theBskt->expectedTrancheLoss(calcDate) << std::endl;


        Real seconds  = timer.elapsed();
        Integer hours = Integer(seconds/3600);
        seconds -= hours * 3600;
        Integer minutes = Integer(seconds/60);
        seconds -= minutes * 60;
        cout << "Run completed in ";
        if (hours > 0)
            cout << hours << " h ";
        if (hours > 0 || minutes > 0)
            cout << minutes << " m ";
        cout << fixed << setprecision(0)
             << seconds << " s" << endl;

        return 0;
    } catch (exception& e) {
        cerr << e.what() << endl;
        return 1;
    } catch (...) {
        cerr << "unknown error" << endl;
        return 1;
    }
}
예제 #6
0
void ShortRateModelTest::testSwaps() {
    BOOST_TEST_MESSAGE("Testing Hull-White swap pricing against known values...");

    SavedSettings backup;
    IndexHistoryCleaner cleaner;

    Date today = Settings::instance().evaluationDate();
    Calendar calendar = TARGET();
    today = calendar.adjust(today);
    Settings::instance().evaluationDate() = today;

    Date settlement = calendar.advance(today,2,Days);

    Date dates[] = {
        settlement,
        calendar.advance(settlement,1,Weeks),
        calendar.advance(settlement,1,Months),
        calendar.advance(settlement,3,Months),
        calendar.advance(settlement,6,Months),
        calendar.advance(settlement,9,Months),
        calendar.advance(settlement,1,Years),
        calendar.advance(settlement,2,Years),
        calendar.advance(settlement,3,Years),
        calendar.advance(settlement,5,Years),
        calendar.advance(settlement,10,Years),
        calendar.advance(settlement,15,Years)
    };
    DiscountFactor discounts[] = {
        1.0,
        0.999258,
        0.996704,
        0.990809,
        0.981798,
        0.972570,
        0.963430,
        0.929532,
        0.889267,
        0.803693,
        0.596903,
        0.433022
    };

    Handle<YieldTermStructure> termStructure(
       boost::shared_ptr<YieldTermStructure>(
           new DiscountCurve(
               std::vector<Date>(dates,dates+LENGTH(dates)),
               std::vector<DiscountFactor>(discounts,
                                           discounts+LENGTH(discounts)),
               Actual365Fixed())));

    boost::shared_ptr<HullWhite> model(new HullWhite(termStructure));

    Integer start[] = { -3, 0, 3 };
    Integer length[] = { 2, 5, 10 };
    Rate rates[] = { 0.02, 0.04, 0.06 };
    boost::shared_ptr<IborIndex> euribor(new Euribor6M(termStructure));

    boost::shared_ptr<PricingEngine> engine(
                                        new TreeVanillaSwapEngine(model,120));

    #if defined(QL_USE_INDEXED_COUPON)
    Real tolerance = 4.0e-3;
    #else
    Real tolerance = 1.0e-8;
    #endif

    for (Size i=0; i<LENGTH(start); i++) {

        Date startDate = calendar.advance(settlement,start[i],Months);
        if (startDate < today) {
            Date fixingDate = calendar.advance(startDate,-2,Days);
            TimeSeries<Real> pastFixings;
            pastFixings[fixingDate] = 0.03;
            IndexManager::instance().setHistory(euribor->name(),
                                                pastFixings);
        }

        for (Size j=0; j<LENGTH(length); j++) {

            Date maturity = calendar.advance(startDate,length[i],Years);
            Schedule fixedSchedule(startDate, maturity, Period(Annual),
                                   calendar, Unadjusted, Unadjusted,
                                   DateGeneration::Forward, false);
            Schedule floatSchedule(startDate, maturity, Period(Semiannual),
                                   calendar, Following, Following,
                                   DateGeneration::Forward, false);
            for (Size k=0; k<LENGTH(rates); k++) {

                VanillaSwap swap(VanillaSwap::Payer, 1000000.0,
                                 fixedSchedule, rates[k], Thirty360(),
                                 floatSchedule, euribor, 0.0, Actual360());
                swap.setPricingEngine(boost::shared_ptr<PricingEngine>(
                                   new DiscountingSwapEngine(termStructure)));
                Real expected = swap.NPV();
                swap.setPricingEngine(engine);
                Real calculated = swap.NPV();

                Real error = std::fabs((expected-calculated)/expected);
                if (error > tolerance) {
                    BOOST_ERROR("Failed to reproduce swap NPV:"
                                << QL_FIXED << std::setprecision(9)
                                << "\n    calculated: " << calculated
                                << "\n    expected:   " << expected
                                << QL_SCIENTIFIC
                                << "\n    rel. error: " << error);
                }
            }
        }
    }
}
예제 #7
0
void CreditDefaultSwapTest::testFairUpfront() {

    BOOST_TEST_MESSAGE(
        "Testing fair-upfront calculation for credit-default swaps...");

    SavedSettings backup;

    // Initialize curves
    Calendar calendar = TARGET();
    Date today = calendar.adjust(Date::todaysDate());
    Settings::instance().evaluationDate() = today;

    Handle<Quote> hazardRate = Handle<Quote>(
                ext::shared_ptr<Quote>(new SimpleQuote(0.01234)));
    RelinkableHandle<DefaultProbabilityTermStructure> probabilityCurve;
    probabilityCurve.linkTo(
        ext::shared_ptr<DefaultProbabilityTermStructure>(
                   new FlatHazardRate(0, calendar, hazardRate, Actual360())));

    RelinkableHandle<YieldTermStructure> discountCurve;
    discountCurve.linkTo(ext::shared_ptr<YieldTermStructure>(
                            new FlatForward(today,0.06,Actual360())));

    // Build the schedule
    Date issueDate = today;
    Date maturity = calendar.advance(issueDate, 10, Years);
    BusinessDayConvention convention = Following;

    Schedule schedule =
        MakeSchedule().from(issueDate)
                      .to(maturity)
                      .withFrequency(Quarterly)
                      .withCalendar(calendar)
                      .withTerminationDateConvention(convention)
                      .withRule(DateGeneration::TwentiethIMM);

    // Build the CDS
    Rate fixedRate = 0.05;
    Rate upfront = 0.001;
    DayCounter dayCount = Actual360();
    Real notional = 10000.0;
    Real recoveryRate = 0.4;

    ext::shared_ptr<PricingEngine> engine(
          new MidPointCdsEngine(probabilityCurve, recoveryRate,
                                discountCurve, true));

    CreditDefaultSwap cds(Protection::Seller, notional, upfront, fixedRate,
                          schedule, convention, dayCount, true, true);
    cds.setPricingEngine(engine);

    Rate fairUpfront = cds.fairUpfront();

    CreditDefaultSwap fairCds(Protection::Seller, notional,
                              fairUpfront, fixedRate,
                              schedule, convention, dayCount, true, true);
    fairCds.setPricingEngine(engine);

    Real fairNPV = fairCds.NPV();
    Real tolerance = 1e-10;

    if (std::fabs(fairNPV) > tolerance)
        BOOST_ERROR(
            "Failed to reproduce null NPV with calculated fair upfront\n"
            << "    calculated upfront: " << io::rate(fairUpfront) << "\n"
            << "    calculated NPV:     " << fairNPV);

    // same with null upfront to begin with
    upfront = 0.0;
    CreditDefaultSwap cds2(Protection::Seller, notional, upfront, fixedRate,
                           schedule, convention, dayCount, true, true);
    cds2.setPricingEngine(engine);

    fairUpfront = cds2.fairUpfront();

    CreditDefaultSwap fairCds2(Protection::Seller, notional,
                               fairUpfront, fixedRate,
                               schedule, convention, dayCount, true, true);
    fairCds2.setPricingEngine(engine);

    fairNPV = fairCds2.NPV();

    if (std::fabs(fairNPV) > tolerance)
        BOOST_ERROR(
            "Failed to reproduce null NPV with calculated fair upfront\n"
            << "    calculated upfront: " << io::rate(fairUpfront) << "\n"
            << "    calculated NPV:     " << fairNPV);
}
예제 #8
0
void InflationTest::testYYTermStructure() {
    BOOST_MESSAGE("Testing year-on-year inflation term structure...");

    SavedSettings backup;

    // try the YY UK
    Calendar calendar = UnitedKingdom();
    BusinessDayConvention bdc = ModifiedFollowing;
    Date evaluationDate(13, August, 2007);
    evaluationDate = calendar.adjust(evaluationDate);
    Settings::instance().evaluationDate() = evaluationDate;


    // fixing data
    Date from(1, January, 2005);
    Date to(13, August, 2007);
    Schedule rpiSchedule = MakeSchedule().from(from).to(to)
    .withTenor(1*Months)
    .withCalendar(UnitedKingdom())
    .withConvention(ModifiedFollowing);
    Real fixData[] = { 189.9, 189.9, 189.6, 190.5, 191.6, 192.0,
        192.2, 192.2, 192.6, 193.1, 193.3, 193.6,
        194.1, 193.4, 194.2, 195.0, 196.5, 197.7,
        198.5, 198.5, 199.2, 200.1, 200.4, 201.1,
        202.7, 201.6, 203.1, 204.4, 205.4, 206.2,
        207.3, -999.0, -999 };

    RelinkableHandle<YoYInflationTermStructure> hy;
    bool interp = false;
    boost::shared_ptr<YYUKRPIr> iir(new YYUKRPIr(interp, hy));
    for (Size i=0; i<rpiSchedule.size();i++) {
        iir->addFixing(rpiSchedule[i], fixData[i]);
    }



    boost::shared_ptr<YieldTermStructure> nominalTS = nominalTermStructure();

    // now build the YoY inflation curve
    Datum yyData[] = {
        { Date(13, August, 2008), 2.95 },
        { Date(13, August, 2009), 2.95 },
        { Date(13, August, 2010), 2.93 },
        { Date(15, August, 2011), 2.955 },
        { Date(13, August, 2012), 2.945 },
        { Date(13, August, 2013), 2.985 },
        { Date(13, August, 2014), 3.01 },
        { Date(13, August, 2015), 3.035 },
        { Date(13, August, 2016), 3.055 },  // note that
        { Date(13, August, 2017), 3.075 },  // some dates will be on
        { Date(13, August, 2019), 3.105 },  // holidays but the payment
        { Date(15, August, 2022), 3.135 },  // calendar will roll them
        { Date(13, August, 2027), 3.155 },
        { Date(13, August, 2032), 3.145 },
        { Date(13, August, 2037), 3.145 }
    };

    Period observationLag = Period(2,Months);
    DayCounter dc = Thirty360();

    // now build the helpers ...
    std::vector<boost::shared_ptr<BootstrapHelper<YoYInflationTermStructure> > > helpers =
    makeHelpers<YoYInflationTermStructure,YearOnYearInflationSwapHelper,
    YoYInflationIndex>(yyData, LENGTH(yyData), iir,
                        observationLag,
                        calendar, bdc, dc);

    Rate baseYYRate = yyData[0].rate/100.0;
    boost::shared_ptr<PiecewiseYoYInflationCurve<Linear> > pYYTS(
        new PiecewiseYoYInflationCurve<Linear>(
                evaluationDate, calendar, dc, observationLag,
                iir->frequency(),iir->interpolated(), baseYYRate,
                Handle<YieldTermStructure>(nominalTS), helpers));
    pYYTS->recalculate();

    // validation
    // yoy swaps should reprice to zero
    // yy rates should not equal yySwap rates
    Real eps = 0.000001;
    // usual swap engine
    Handle<YieldTermStructure> hTS(nominalTS);
    boost::shared_ptr<PricingEngine> sppe(new DiscountingSwapEngine(hTS));

    // make sure that the index has the latest yoy term structure
    hy.linkTo(pYYTS);

    for (Size j = 1; j < LENGTH(yyData); j++) {

        from = nominalTS->referenceDate();
        to = yyData[j].date;
        Schedule yoySchedule = MakeSchedule().from(from).to(to)
        .withConvention(Unadjusted) // fixed leg gets calendar from
        .withCalendar(calendar)     // schedule
        .withTenor(1*Years)
        .backwards()
        ;

        YearOnYearInflationSwap yyS2(YearOnYearInflationSwap::Payer,
                                        1000000.0,
                                        yoySchedule,//fixed schedule, but same as yoy
                                        yyData[j].rate/100.0,
                                        dc,
                                        yoySchedule,
                                        iir,
                                        observationLag,
                                        0.0,        //spread on index
                                        dc,
                                        UnitedKingdom());

        yyS2.setPricingEngine(sppe);



        BOOST_CHECK_MESSAGE(fabs(yyS2.NPV())<eps,"fresh yoy swap NPV!=0 from TS "
                <<"swap quote for pt " << j
                << ", is " << yyData[j].rate/100.0
                <<" vs YoY rate "<< pYYTS->yoyRate(yyData[j].date-observationLag)
                <<" at quote date "<<(yyData[j].date-observationLag)
                <<", NPV of a fresh yoy swap is " << yyS2.NPV()
                <<"\n      fair rate " << yyS2.fairRate()
                <<" payment "<<yyS2.paymentConvention());
    }

    Size jj=3;
    for (Size k = 0; k < 14; k++) {

        from = nominalTS->referenceDate() - k*Months;
        to = yyData[jj].date - k*Months;
        Schedule yoySchedule = MakeSchedule().from(from).to(to)
        .withConvention(Unadjusted) // fixed leg gets calendar from
        .withCalendar(calendar)     // schedule
        .withTenor(1*Years)
        .backwards()
        ;

        YearOnYearInflationSwap yyS3(YearOnYearInflationSwap::Payer,
                                    1000000.0,
                                    yoySchedule,//fixed schedule, but same as yoy
                                    yyData[jj].rate/100.0,
                                    dc,
                                    yoySchedule,
                                    iir,
                                    observationLag,
                                    0.0,        //spread on index
                                    dc,
                                    UnitedKingdom());

        yyS3.setPricingEngine(sppe);

        BOOST_CHECK_MESSAGE(fabs(yyS3.NPV())< 20000.0,
                            "unexpected size of aged YoY swap, aged "
                            <<k<<" months: YY aged NPV = " << yyS3.NPV()
                            <<", legs "<< yyS3.legNPV(0) << " and " << yyS3.legNPV(1)
                            );
    }

}
예제 #9
0
파일: CDS.cpp 프로젝트: FlyCatZout/QuantLib
int main(int, char* []) {

    try {

        boost::timer timer;
        std::cout << std::endl;

        /*********************
         ***  MARKET DATA  ***
         *********************/

        Calendar calendar = TARGET();
        Date todaysDate(15, May, 2007);
        // must be a business day
        todaysDate = calendar.adjust(todaysDate);

        Settings::instance().evaluationDate() = todaysDate;

        // dummy curve
        boost::shared_ptr<Quote> flatRate(new SimpleQuote(0.01));
        Handle<YieldTermStructure> tsCurve(
            boost::shared_ptr<FlatForward>(
                new FlatForward(todaysDate, Handle<Quote>(flatRate),
                                Actual365Fixed())));

        /*
          In Lehmans Brothers "guide to exotic credit derivatives"
          p. 32 there's a simple case, zero flat curve with a flat CDS
          curve with constant market spreads of 150 bp and RR = 50%
          corresponds to a flat 3% hazard rate. The implied 1-year
          survival probability is 97.04% and the 2-years is 94.18%
        */

        // market
        Real recovery_rate = 0.5;
        Real quoted_spreads[] = { 0.0150, 0.0150, 0.0150, 0.0150 };
        vector<Period> tenors;
        tenors.push_back(3*Months);
        tenors.push_back(6*Months);
        tenors.push_back(1*Years);
        tenors.push_back(2*Years);
        vector<Date> maturities;
        for (Size i=0; i<4; i++) {
            maturities.push_back(calendar.adjust(todaysDate + tenors[i],
                                                 Following));
        }

        std::vector<boost::shared_ptr<DefaultProbabilityHelper> > instruments;
        for (Size i=0; i<4; i++) {
            instruments.push_back(boost::shared_ptr<DefaultProbabilityHelper>(
                                      new SpreadCdsHelper(
                                          Handle<Quote>(boost::shared_ptr<Quote>(
                                                  new SimpleQuote(quoted_spreads[i]))),
                                          tenors[i],
                                          0,
                                          calendar,
                                          Quarterly,
                                          Following,
                                          DateGeneration::TwentiethIMM,
                                          Actual365Fixed(),
                                          recovery_rate,
                                          tsCurve)));
        }

        // Bootstrap hazard rates
        boost::shared_ptr<PiecewiseDefaultCurve<HazardRate, BackwardFlat> >
        hazardRateStructure(
            new PiecewiseDefaultCurve<HazardRate, BackwardFlat>(
                todaysDate,
                instruments,
                Actual365Fixed()));
        vector<pair<Date, Real> > hr_curve_data = hazardRateStructure->nodes();

        cout << "Calibrated hazard rate values: " << endl ;
        for (Size i=0; i<hr_curve_data.size(); i++) {
            cout << "hazard rate on " << hr_curve_data[i].first << " is "
                 << hr_curve_data[i].second << endl;
        }
        cout << endl;

        cout << "Some survival probability values: " << endl ;
        cout << "1Y survival probability: "
             << io::percent(hazardRateStructure->survivalProbability(
                                todaysDate + 1*Years))
             << endl
             << "               expected: "
             << io::percent(0.9704)
             << endl;
        cout << "2Y survival probability: "
             << io::percent(hazardRateStructure->survivalProbability(
                                todaysDate + 2*Years))
             << endl
             << "               expected: "
             << io::percent(0.9418)
             << endl;

        cout << endl << endl;

        // reprice instruments
        Real nominal = 1000000.0;
        Handle<DefaultProbabilityTermStructure> probability(hazardRateStructure);
        boost::shared_ptr<PricingEngine> engine(
            new MidPointCdsEngine(probability, recovery_rate, tsCurve));

        Schedule cdsSchedule =
            MakeSchedule().from(todaysDate).to(maturities[0])
            .withFrequency(Quarterly)
            .withCalendar(calendar)
            .withTerminationDateConvention(Unadjusted)
            .withRule(DateGeneration::TwentiethIMM);
        CreditDefaultSwap cds_3m(Protection::Seller,
                                 nominal,
                                 quoted_spreads[0],
                                 cdsSchedule,
                                 Following,
                                 Actual365Fixed());

        cdsSchedule =
            MakeSchedule().from(todaysDate).to(maturities[1])
            .withFrequency(Quarterly)
            .withCalendar(calendar)
            .withTerminationDateConvention(Unadjusted)
            .withRule(DateGeneration::TwentiethIMM);
        CreditDefaultSwap cds_6m(Protection::Seller,
                                 nominal,
                                 quoted_spreads[1],
                                 cdsSchedule,
                                 Following,
                                 Actual365Fixed());

        cdsSchedule =
            MakeSchedule().from(todaysDate).to(maturities[2])
            .withFrequency(Quarterly)
            .withCalendar(calendar)
            .withTerminationDateConvention(Unadjusted)
            .withRule(DateGeneration::TwentiethIMM);
        CreditDefaultSwap cds_1y(Protection::Seller,
                                 nominal,
                                 quoted_spreads[2],
                                 cdsSchedule,
                                 Following,
                                 Actual365Fixed());

        cdsSchedule =
            MakeSchedule().from(todaysDate).to(maturities[3])
            .withFrequency(Quarterly)
            .withCalendar(calendar)
            .withTerminationDateConvention(Unadjusted)
            .withRule(DateGeneration::TwentiethIMM);
        CreditDefaultSwap cds_2y(Protection::Seller,
                                 nominal,
                                 quoted_spreads[3],
                                 cdsSchedule,
                                 Following,
                                 Actual365Fixed());

        cds_3m.setPricingEngine(engine);
        cds_6m.setPricingEngine(engine);
        cds_1y.setPricingEngine(engine);
        cds_2y.setPricingEngine(engine);

        cout << "Repricing of quoted CDSs employed for calibration: " << endl;
        cout << "3M fair spread: " << io::rate(cds_3m.fairSpread()) << endl
             << "   NPV:         " << cds_3m.NPV() << endl
             << "   default leg: " << cds_3m.defaultLegNPV() << endl
             << "   coupon leg:  " << cds_3m.couponLegNPV() << endl
             << endl;

        cout << "6M fair spread: " << io::rate(cds_6m.fairSpread()) << endl
             << "   NPV:         " << cds_6m.NPV() << endl
             << "   default leg: " << cds_6m.defaultLegNPV() << endl
             << "   coupon leg:  " << cds_6m.couponLegNPV() << endl
             << endl;

        cout << "1Y fair spread: " << io::rate(cds_1y.fairSpread()) << endl
             << "   NPV:         " << cds_1y.NPV() << endl
             << "   default leg: " << cds_1y.defaultLegNPV() << endl
             << "   coupon leg:  " << cds_1y.couponLegNPV() << endl
             << endl;

        cout << "2Y fair spread: " << io::rate(cds_2y.fairSpread()) << endl
             << "   NPV:         " << cds_2y.NPV() << endl
             << "   default leg: " << cds_2y.defaultLegNPV() << endl
             << "   coupon leg:  " << cds_2y.couponLegNPV() << endl
             << endl;

        cout << endl << endl;

        Real seconds  = timer.elapsed();
        Integer hours = Integer(seconds/3600);
        seconds -= hours * 3600;
        Integer minutes = Integer(seconds/60);
        seconds -= minutes * 60;
        cout << "Run completed in ";
        if (hours > 0)
            cout << hours << " h ";
        if (hours > 0 || minutes > 0)
            cout << minutes << " m ";
        cout << fixed << setprecision(0)
             << seconds << " s" << endl;

        return 0;
    } catch (exception& e) {
        cerr << e.what() << endl;
        return 1;
    } catch (...) {
        cerr << "unknown error" << endl;
        return 1;
    }
}
예제 #10
0
    FixedRateLeg::operator Leg() const {

        QL_REQUIRE(!couponRates_.empty(), "no coupon rates given");
        QL_REQUIRE(!notionals_.empty(), "no notional given");

        Leg leg;
        leg.reserve(schedule_.size()-1);

        Calendar schCalendar = schedule_.calendar();

        // first period might be short or long
        Date start = schedule_.date(0), end = schedule_.date(1);
        Date paymentDate = calendar_.adjust(end, paymentAdjustment_);
        Date exCouponDate;
        InterestRate rate = couponRates_[0];
        Real nominal = notionals_[0];

        if (exCouponPeriod_ != Period())
        {
            exCouponDate = exCouponCalendar_.advance(paymentDate,
                                                     -exCouponPeriod_,
                                                     exCouponAdjustment_,
                                                     exCouponEndOfMonth_);
        }

        if (schedule_.isRegular(1)) {
            QL_REQUIRE(firstPeriodDC_.empty() ||
                       firstPeriodDC_ == rate.dayCounter(),
                       "regular first coupon "
                       "does not allow a first-period day count");
            shared_ptr<CashFlow> temp(new
                FixedRateCoupon(paymentDate, nominal, rate,
                                start, end, start, end, exCouponDate));
            leg.push_back(temp);
        } else {
            Date ref = end - schedule_.tenor();
            ref = schCalendar.adjust(ref, schedule_.businessDayConvention());
            InterestRate r(rate.rate(),
                           firstPeriodDC_.empty() ? rate.dayCounter()
                                                  : firstPeriodDC_,
                           rate.compounding(), rate.frequency());
            leg.push_back(shared_ptr<CashFlow>(new
                FixedRateCoupon(paymentDate, nominal, r,
                                start, end, ref, end, exCouponDate)));
        }
        // regular periods
        for (Size i=2; i<schedule_.size()-1; ++i) {
            start = end; end = schedule_.date(i);
            paymentDate = calendar_.adjust(end, paymentAdjustment_);
            if (exCouponPeriod_ != Period())
            {
                exCouponDate = exCouponCalendar_.advance(paymentDate,
                                                         -exCouponPeriod_,
                                                         exCouponAdjustment_,
                                                         exCouponEndOfMonth_);
            }
            if ((i-1) < couponRates_.size())
                rate = couponRates_[i-1];
            else
                rate = couponRates_.back();
            if ((i-1) < notionals_.size())
                nominal = notionals_[i-1];
            else
                nominal = notionals_.back();
            leg.push_back(shared_ptr<CashFlow>(new
                FixedRateCoupon(paymentDate, nominal, rate,
                                start, end, start, end, exCouponDate)));
        }
        if (schedule_.size() > 2) {
            // last period might be short or long
            Size N = schedule_.size();
            start = end; end = schedule_.date(N-1);
            paymentDate = calendar_.adjust(end, paymentAdjustment_);
            if (exCouponPeriod_ != Period())
            {
                exCouponDate = exCouponCalendar_.advance(paymentDate,
                                                         -exCouponPeriod_,
                                                         exCouponAdjustment_,
                                                         exCouponEndOfMonth_);
            }
            if ((N-2) < couponRates_.size())
                rate = couponRates_[N-2];
            else
                rate = couponRates_.back();
            if ((N-2) < notionals_.size())
                nominal = notionals_[N-2];
            else
                nominal = notionals_.back();
            InterestRate r(rate.rate(),
                           lastPeriodDC_.empty() ? rate.dayCounter()
                                                 : lastPeriodDC_,
                           rate.compounding(), rate.frequency());
            if (schedule_.isRegular(N - 1)) {
                leg.push_back(shared_ptr<CashFlow>(new
                    FixedRateCoupon(paymentDate, nominal, r,
                                    start, end, start, end, exCouponDate)));
            } else {
                Date ref = start + schedule_.tenor();
                ref = schCalendar.adjust(ref, schedule_.businessDayConvention());
                leg.push_back(shared_ptr<CashFlow>(new
                    FixedRateCoupon(paymentDate, nominal, r,
                                    start, end, start, ref, exCouponDate)));
            }
        }
        return leg;
    }
예제 #11
0
파일: Bonds.cpp 프로젝트: 21hub/QuantLib
int main(int, char* []) {

    try {

        boost::timer timer;
        std::cout << std::endl;

        /*********************
         ***  MARKET DATA  ***
         *********************/

        Calendar calendar = TARGET();

        Date settlementDate(18, September, 2008);
        // must be a business day
        settlementDate = calendar.adjust(settlementDate);

        Integer fixingDays = 3;
        Natural settlementDays = 3;

        Date todaysDate = calendar.advance(settlementDate, -fixingDays, Days);
        // nothing to do with Date::todaysDate
        Settings::instance().evaluationDate() = todaysDate;

        std::cout << "Today: " << todaysDate.weekday()
        << ", " << todaysDate << std::endl;

        std::cout << "Settlement date: " << settlementDate.weekday()
        << ", " << settlementDate << std::endl;


        // Building of the bonds discounting yield curve

        /*********************
         ***  RATE HELPERS ***
         *********************/

        // RateHelpers are built from the above quotes together with
        // other instrument dependant infos.  Quotes are passed in
        // relinkable handles which could be relinked to some other
        // data source later.

        // Common data

        // ZC rates for the short end
         Rate zc3mQuote=0.0096;
         Rate zc6mQuote=0.0145;
         Rate zc1yQuote=0.0194;

         boost::shared_ptr<Quote> zc3mRate(new SimpleQuote(zc3mQuote));
         boost::shared_ptr<Quote> zc6mRate(new SimpleQuote(zc6mQuote));
         boost::shared_ptr<Quote> zc1yRate(new SimpleQuote(zc1yQuote));

         DayCounter zcBondsDayCounter = Actual365Fixed();

         boost::shared_ptr<RateHelper> zc3m(new DepositRateHelper(
                 Handle<Quote>(zc3mRate),
                 3*Months, fixingDays,
                 calendar, ModifiedFollowing,
                 true, zcBondsDayCounter));
         boost::shared_ptr<RateHelper> zc6m(new DepositRateHelper(
                 Handle<Quote>(zc6mRate),
                 6*Months, fixingDays,
                 calendar, ModifiedFollowing,
                 true, zcBondsDayCounter));
         boost::shared_ptr<RateHelper> zc1y(new DepositRateHelper(
                 Handle<Quote>(zc1yRate),
                 1*Years, fixingDays,
                 calendar, ModifiedFollowing,
                 true, zcBondsDayCounter));

        // setup bonds
        Real redemption = 100.0;

        const Size numberOfBonds = 5;

        Date issueDates[] = {
                Date (15, March, 2005),
                Date (15, June, 2005),
                Date (30, June, 2006),
                Date (15, November, 2002),
                Date (15, May, 1987)
        };

        Date maturities[] = {
                Date (31, August, 2010),
                Date (31, August, 2011),
                Date (31, August, 2013),
                Date (15, August, 2018),
                Date (15, May, 2038)
        };

        Real couponRates[] = {
                0.02375,
                0.04625,
                0.03125,
                0.04000,
                0.04500
        };

        Real marketQuotes[] = {
                100.390625,
                106.21875,
                100.59375,
                101.6875,
                102.140625
        };

        std::vector< boost::shared_ptr<SimpleQuote> > quote;
        for (Size i=0; i<numberOfBonds; i++) {
            boost::shared_ptr<SimpleQuote> cp(new SimpleQuote(marketQuotes[i]));
            quote.push_back(cp);
        }

        RelinkableHandle<Quote> quoteHandle[numberOfBonds];
        for (Size i=0; i<numberOfBonds; i++) {
            quoteHandle[i].linkTo(quote[i]);
        }

        // Definition of the rate helpers
        std::vector<boost::shared_ptr<BondHelper> > bondsHelpers;

        for (Size i=0; i<numberOfBonds; i++) {

            Schedule schedule(issueDates[i], maturities[i], Period(Semiannual), UnitedStates(UnitedStates::GovernmentBond),
                    Unadjusted, Unadjusted, DateGeneration::Backward, false);

            boost::shared_ptr<FixedRateBondHelper> bondHelper(new FixedRateBondHelper(
                    quoteHandle[i],
                    settlementDays,
                    100.0,
                    schedule,
                    std::vector<Rate>(1,couponRates[i]),
                    ActualActual(ActualActual::Bond),
                    Unadjusted,
                    redemption,
                    issueDates[i]));

            // the above could also be done by creating a
            // FixedRateBond instance and writing:
            //
            // boost::shared_ptr<BondHelper> bondHelper(
            //         new BondHelper(quoteHandle[i], bond));
            //
            // This would also work for bonds that still don't have a
            // specialized helper, such as floating-rate bonds.


            bondsHelpers.push_back(bondHelper);
        }

        /*********************
         **  CURVE BUILDING **
         *********************/

         // Any DayCounter would be fine.
         // ActualActual::ISDA ensures that 30 years is 30.0
         DayCounter termStructureDayCounter =
             ActualActual(ActualActual::ISDA);

         double tolerance = 1.0e-15;

         // A depo-bond curve
         std::vector<boost::shared_ptr<RateHelper> > bondInstruments;

         // Adding the ZC bonds to the curve for the short end
         bondInstruments.push_back(zc3m);
         bondInstruments.push_back(zc6m);
         bondInstruments.push_back(zc1y);

         // Adding the Fixed rate bonds to the curve for the long end
         for (Size i=0; i<numberOfBonds; i++) {
             bondInstruments.push_back(bondsHelpers[i]);
         }

         boost::shared_ptr<YieldTermStructure> bondDiscountingTermStructure(
                 new PiecewiseYieldCurve<Discount,LogLinear>(
                         settlementDate, bondInstruments,
                         termStructureDayCounter,
                         tolerance));

         // Building of the Libor forecasting curve
         // deposits
         Rate d1wQuote=0.043375;
         Rate d1mQuote=0.031875;
         Rate d3mQuote=0.0320375;
         Rate d6mQuote=0.03385;
         Rate d9mQuote=0.0338125;
         Rate d1yQuote=0.0335125;
         // swaps
         Rate s2yQuote=0.0295;
         Rate s3yQuote=0.0323;
         Rate s5yQuote=0.0359;
         Rate s10yQuote=0.0412;
         Rate s15yQuote=0.0433;


         /********************
          ***    QUOTES    ***
          ********************/

         // SimpleQuote stores a value which can be manually changed;
         // other Quote subclasses could read the value from a database
         // or some kind of data feed.

         // deposits
         boost::shared_ptr<Quote> d1wRate(new SimpleQuote(d1wQuote));
         boost::shared_ptr<Quote> d1mRate(new SimpleQuote(d1mQuote));
         boost::shared_ptr<Quote> d3mRate(new SimpleQuote(d3mQuote));
         boost::shared_ptr<Quote> d6mRate(new SimpleQuote(d6mQuote));
         boost::shared_ptr<Quote> d9mRate(new SimpleQuote(d9mQuote));
         boost::shared_ptr<Quote> d1yRate(new SimpleQuote(d1yQuote));
         // swaps
         boost::shared_ptr<Quote> s2yRate(new SimpleQuote(s2yQuote));
         boost::shared_ptr<Quote> s3yRate(new SimpleQuote(s3yQuote));
         boost::shared_ptr<Quote> s5yRate(new SimpleQuote(s5yQuote));
         boost::shared_ptr<Quote> s10yRate(new SimpleQuote(s10yQuote));
         boost::shared_ptr<Quote> s15yRate(new SimpleQuote(s15yQuote));

         /*********************
          ***  RATE HELPERS ***
          *********************/

         // RateHelpers are built from the above quotes together with
         // other instrument dependant infos.  Quotes are passed in
         // relinkable handles which could be relinked to some other
         // data source later.

         // deposits
         DayCounter depositDayCounter = Actual360();

         boost::shared_ptr<RateHelper> d1w(new DepositRateHelper(
                 Handle<Quote>(d1wRate),
                 1*Weeks, fixingDays,
                 calendar, ModifiedFollowing,
                 true, depositDayCounter));
         boost::shared_ptr<RateHelper> d1m(new DepositRateHelper(
                 Handle<Quote>(d1mRate),
                 1*Months, fixingDays,
                 calendar, ModifiedFollowing,
                 true, depositDayCounter));
         boost::shared_ptr<RateHelper> d3m(new DepositRateHelper(
                 Handle<Quote>(d3mRate),
                 3*Months, fixingDays,
                 calendar, ModifiedFollowing,
                 true, depositDayCounter));
         boost::shared_ptr<RateHelper> d6m(new DepositRateHelper(
                 Handle<Quote>(d6mRate),
                 6*Months, fixingDays,
                 calendar, ModifiedFollowing,
                 true, depositDayCounter));
         boost::shared_ptr<RateHelper> d9m(new DepositRateHelper(
                 Handle<Quote>(d9mRate),
                 9*Months, fixingDays,
                 calendar, ModifiedFollowing,
                 true, depositDayCounter));
         boost::shared_ptr<RateHelper> d1y(new DepositRateHelper(
                 Handle<Quote>(d1yRate),
                 1*Years, fixingDays,
                 calendar, ModifiedFollowing,
                 true, depositDayCounter));

         // setup swaps
         Frequency swFixedLegFrequency = Annual;
         BusinessDayConvention swFixedLegConvention = Unadjusted;
         DayCounter swFixedLegDayCounter = Thirty360(Thirty360::European);
         boost::shared_ptr<IborIndex> swFloatingLegIndex(new Euribor6M);

         const Period forwardStart(1*Days);

         boost::shared_ptr<RateHelper> s2y(new SwapRateHelper(
                 Handle<Quote>(s2yRate), 2*Years,
                 calendar, swFixedLegFrequency,
                 swFixedLegConvention, swFixedLegDayCounter,
                 swFloatingLegIndex, Handle<Quote>(),forwardStart));
         boost::shared_ptr<RateHelper> s3y(new SwapRateHelper(
                 Handle<Quote>(s3yRate), 3*Years,
                 calendar, swFixedLegFrequency,
                 swFixedLegConvention, swFixedLegDayCounter,
                 swFloatingLegIndex, Handle<Quote>(),forwardStart));
         boost::shared_ptr<RateHelper> s5y(new SwapRateHelper(
                 Handle<Quote>(s5yRate), 5*Years,
                 calendar, swFixedLegFrequency,
                 swFixedLegConvention, swFixedLegDayCounter,
                 swFloatingLegIndex, Handle<Quote>(),forwardStart));
         boost::shared_ptr<RateHelper> s10y(new SwapRateHelper(
                 Handle<Quote>(s10yRate), 10*Years,
                 calendar, swFixedLegFrequency,
                 swFixedLegConvention, swFixedLegDayCounter,
                 swFloatingLegIndex, Handle<Quote>(),forwardStart));
         boost::shared_ptr<RateHelper> s15y(new SwapRateHelper(
                 Handle<Quote>(s15yRate), 15*Years,
                 calendar, swFixedLegFrequency,
                 swFixedLegConvention, swFixedLegDayCounter,
                 swFloatingLegIndex, Handle<Quote>(),forwardStart));


         /*********************
          **  CURVE BUILDING **
          *********************/

         // Any DayCounter would be fine.
         // ActualActual::ISDA ensures that 30 years is 30.0

         // A depo-swap curve
         std::vector<boost::shared_ptr<RateHelper> > depoSwapInstruments;
         depoSwapInstruments.push_back(d1w);
         depoSwapInstruments.push_back(d1m);
         depoSwapInstruments.push_back(d3m);
         depoSwapInstruments.push_back(d6m);
         depoSwapInstruments.push_back(d9m);
         depoSwapInstruments.push_back(d1y);
         depoSwapInstruments.push_back(s2y);
         depoSwapInstruments.push_back(s3y);
         depoSwapInstruments.push_back(s5y);
         depoSwapInstruments.push_back(s10y);
         depoSwapInstruments.push_back(s15y);
         boost::shared_ptr<YieldTermStructure> depoSwapTermStructure(
                 new PiecewiseYieldCurve<Discount,LogLinear>(
                         settlementDate, depoSwapInstruments,
                         termStructureDayCounter,
                         tolerance));

         // Term structures that will be used for pricing:
         // the one used for discounting cash flows
         RelinkableHandle<YieldTermStructure> discountingTermStructure;
         // the one used for forward rate forecasting
         RelinkableHandle<YieldTermStructure> forecastingTermStructure;

         /*********************
          * BONDS TO BE PRICED *
          **********************/

         // Common data
         Real faceAmount = 100;

         // Pricing engine
         boost::shared_ptr<PricingEngine> bondEngine(
                 new DiscountingBondEngine(discountingTermStructure));

         // Zero coupon bond
         ZeroCouponBond zeroCouponBond(
                 settlementDays,
                 UnitedStates(UnitedStates::GovernmentBond),
                 faceAmount,
                 Date(15,August,2013),
                 Following,
                 Real(116.92),
                 Date(15,August,2003));

         zeroCouponBond.setPricingEngine(bondEngine);

         // Fixed 4.5% US Treasury Note
         Schedule fixedBondSchedule(Date(15, May, 2007),
                 Date(15,May,2017), Period(Semiannual),
                 UnitedStates(UnitedStates::GovernmentBond),
                 Unadjusted, Unadjusted, DateGeneration::Backward, false);

         FixedRateBond fixedRateBond(
                 settlementDays,
                 faceAmount,
                 fixedBondSchedule,
                 std::vector<Rate>(1, 0.045),
                 ActualActual(ActualActual::Bond),
                 ModifiedFollowing,
                 100.0, Date(15, May, 2007));

         fixedRateBond.setPricingEngine(bondEngine);

         // Floating rate bond (3M USD Libor + 0.1%)
         // Should and will be priced on another curve later...

         RelinkableHandle<YieldTermStructure> liborTermStructure;
         const boost::shared_ptr<IborIndex> libor3m(
                 new USDLibor(Period(3,Months),liborTermStructure));
         libor3m->addFixing(Date(17, July, 2008),0.0278625);

         Schedule floatingBondSchedule(Date(21, October, 2005),
                 Date(21, October, 2010), Period(Quarterly),
                 UnitedStates(UnitedStates::NYSE),
                 Unadjusted, Unadjusted, DateGeneration::Backward, true);

         FloatingRateBond floatingRateBond(
                 settlementDays,
                 faceAmount,
                 floatingBondSchedule,
                 libor3m,
                 Actual360(),
                 ModifiedFollowing,
                 Natural(2),
                 // Gearings
                 std::vector<Real>(1, 1.0),
                 // Spreads
                 std::vector<Rate>(1, 0.001),
                 // Caps
                 std::vector<Rate>(),
                 // Floors
                 std::vector<Rate>(),
                 // Fixing in arrears
                 true,
                 Real(100.0),
                 Date(21, October, 2005));

         floatingRateBond.setPricingEngine(bondEngine);

         // Coupon pricers
         boost::shared_ptr<IborCouponPricer> pricer(new BlackIborCouponPricer);

         // optionLet volatilities
         Volatility volatility = 0.0;
         Handle<OptionletVolatilityStructure> vol;
         vol = Handle<OptionletVolatilityStructure>(
                 boost::shared_ptr<OptionletVolatilityStructure>(new
                         ConstantOptionletVolatility(
                                 settlementDays,
                                 calendar,
                                 ModifiedFollowing,
                                 volatility,
                                 Actual365Fixed())));

         pricer->setCapletVolatility(vol);
         setCouponPricer(floatingRateBond.cashflows(),pricer);

         // Yield curve bootstrapping
         forecastingTermStructure.linkTo(depoSwapTermStructure);
         discountingTermStructure.linkTo(bondDiscountingTermStructure);

         // We are using the depo & swap curve to estimate the future Libor rates
         liborTermStructure.linkTo(depoSwapTermStructure);

         /***************
          * BOND PRICING *
          ****************/

         std::cout << std::endl;

         // write column headings
         Size widths[] = { 18, 10, 10, 10 };

         std::cout << std::setw(widths[0]) <<  "                 "
         << std::setw(widths[1]) << "ZC"
         << std::setw(widths[2]) << "Fixed"
         << std::setw(widths[3]) << "Floating"
         << std::endl;

         std::string separator = " | ";
         Size width = widths[0]
                             + widths[1]
                                      + widths[2]
                                               + widths[3];
         std::string rule(width, '-'), dblrule(width, '=');
         std::string tab(8, ' ');

         std::cout << rule << std::endl;

         std::cout << std::fixed;
         std::cout << std::setprecision(2);

         std::cout << std::setw(widths[0]) << "Net present value"
         << std::setw(widths[1]) << zeroCouponBond.NPV()
         << std::setw(widths[2]) << fixedRateBond.NPV()
         << std::setw(widths[3]) << floatingRateBond.NPV()
         << std::endl;

         std::cout << std::setw(widths[0]) << "Clean price"
         << std::setw(widths[1]) << zeroCouponBond.cleanPrice()
         << std::setw(widths[2]) << fixedRateBond.cleanPrice()
         << std::setw(widths[3]) << floatingRateBond.cleanPrice()
         << std::endl;

         std::cout << std::setw(widths[0]) << "Dirty price"
         << std::setw(widths[1]) << zeroCouponBond.dirtyPrice()
         << std::setw(widths[2]) << fixedRateBond.dirtyPrice()
         << std::setw(widths[3]) << floatingRateBond.dirtyPrice()
         << std::endl;

         std::cout << std::setw(widths[0]) << "Accrued coupon"
         << std::setw(widths[1]) << zeroCouponBond.accruedAmount()
         << std::setw(widths[2]) << fixedRateBond.accruedAmount()
         << std::setw(widths[3]) << floatingRateBond.accruedAmount()
         << std::endl;

         std::cout << std::setw(widths[0]) << "Previous coupon"
         << std::setw(widths[1]) << "N/A" // zeroCouponBond
         << std::setw(widths[2]) << io::rate(fixedRateBond.previousCouponRate())
         << std::setw(widths[3]) << io::rate(floatingRateBond.previousCouponRate())
         << std::endl;

         std::cout << std::setw(widths[0]) << "Next coupon"
         << std::setw(widths[1]) << "N/A" // zeroCouponBond
         << std::setw(widths[2]) << io::rate(fixedRateBond.nextCouponRate())
         << std::setw(widths[3]) << io::rate(floatingRateBond.nextCouponRate())
         << std::endl;

         std::cout << std::setw(widths[0]) << "Yield"
         << std::setw(widths[1])
         << io::rate(zeroCouponBond.yield(Actual360(),Compounded,Annual))
         << std::setw(widths[2])
         << io::rate(fixedRateBond.yield(Actual360(),Compounded,Annual))
         << std::setw(widths[3])
         << io::rate(floatingRateBond.yield(Actual360(),Compounded,Annual))
         << std::endl;

         std::cout << std::endl;

         // Other computations
         std::cout << "Sample indirect computations (for the floating rate bond): " << std::endl;
         std::cout << rule << std::endl;

         std::cout << "Yield to Clean Price: "
         << floatingRateBond.cleanPrice(floatingRateBond.yield(Actual360(),Compounded,Annual),Actual360(),Compounded,Annual,settlementDate) << std::endl;

         std::cout << "Clean Price to Yield: "
         << io::rate(floatingRateBond.yield(floatingRateBond.cleanPrice(),Actual360(),Compounded,Annual,settlementDate)) << std::endl;

         /* "Yield to Price"
            "Price to Yield" */

         double seconds = timer.elapsed();
         Integer hours = int(seconds/3600);
         seconds -= hours * 3600;
         Integer minutes = int(seconds/60);
         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) {
        std::cerr << e.what() << std::endl;
        return 1;
    } catch (...) {
        std::cerr << "unknown error" << std::endl;
        return 1;
    }
}
void qlHazardRateFactory::calculate()
{
    try {

        TiXmlDocument document;
        document.Parse(instInfo_.c_str(), 0, TIXML_ENCODING_UTF8);
        TiXmlNode* rootNode = document.FirstChild("defaultCurveCalculation");

        Settings::instance().evaluationDate() =
            strToDate(rootNode->FirstChildElement("evaluationTime")->GetText());

        DayCounter daycounter = Actual365Fixed();

        TiXmlElement* pricingParametorNode = rootNode->FirstChildElement("pricingParameter");
        TiXmlElement* referenceCurveNode = pricingParametorNode->FirstChildElement("referenceCurves");

        Calendar calendar = SouthKorea();

        Date refereceDate = Settings::instance().evaluationDate();

        // must be a business day
        refereceDate = calendar.adjust(refereceDate);

        // dummy curve
        boost::shared_ptr<Quote> flatRate(new SimpleQuote(0.01));

        //Handle<YieldTermStructure> tsCurve(
        //      boost::shared_ptr<FlatForward>(
        //              new FlatForward(todaysDate, Handle<Quote>(flatRate),
        //                              Actual365Fixed())));


        TiXmlNode* pricingParametorNode = document.FirstChild("pricingParameter");

        TiXmlElement* referenceCurveNode = pricingParametorNode->FirstChildElement("referenceCurves");

        std::vector<boost::shared_ptr<HazardRateStructure>> hazardRateCurves;

        TiXmlElement* tsNode = referenceCurveNode->FirstChildElement("termstructure");

        if(tsNode)
        {
            for(tsNode; tsNode; tsNode = tsNode->NextSiblingElement("termstructure"))
            {
                hazardRateCurves.push_back(this->hazardRateTS(tsNode));
            }
        }

        TiXmlNode* yieldNode = document.FirstChild("yieldNode");

        qlYieldTermStructureFactory yieldTsFactory = qlYieldTermStructureFactory();
        this->tsCurve_ = yieldTsFactory.yieldTSHandle(yieldNode);

        // outputTenor Build
        std::vector<Period> outputTenors;
        Size outputNum = outputTenors.size();

        qlTimeUnitFactory tuFactory = qlTimeUnitFactory();
        TiXmlElement* outputTenorNode = pricingParametorNode->FirstChildElement("outputCurveTemplate");

        TiXmlElement* tenorNode = outputTenorNode->FirstChildElement("tenorList");

        if(tenorNode)
        {
            for(tenorNode; tenorNode; tenorNode = tenorNode->NextSiblingElement("tenor"))
            {
                outputTenors.push_back(tuFactory.timeUnit(tenorNode));
            }
        }

        //compositeCalculation

        boost::shared_ptr<DefaultProbabilityTermStructure> copulaHazardTS =
            boost::shared_ptr<DefaultProbabilityTermStructure>(new CopulaHazardRate<ProbabilityOfAtLeastNEvents,Linear>(
                        dates,hazardRateCurves,0.9,1,50));



        //result


        for (Size i=0 ; i<outputNum ; ++i)
        {
            dates_.push_back(calendar.advance(refereceDate,outputTenors[i]));
            dateTimes_.push_back(daycounter.yearFraction(refereceDate,dates_[i]));
            data_.push_back(copulaHazardTS->defaultProbability(dateTimes_[i]));

        }

        // makeXml

        this->buildResultXml();

        //this->buildResultXml(inst_->additionalResults());

    } catch (std::exception& e) {
        std::cerr << e.what() << std::endl;
    } catch (...) {
        std::cerr << "unknown error" << std::endl;
    }


}
예제 #13
0
PiecewiseYieldCurve<Discount, LogLinear>* create_yield_curve() {

    Calendar calendar = UnitedStates();
    Date settlementDate(4, January, 2012);
    // must be a business day
    settlementDate = calendar.adjust(settlementDate);

    Integer fixingDays = 2;
    Date todaysDate = calendar.advance(settlementDate, -fixingDays, Days);

    Settings::instance().evaluationDate() = todaysDate;

    std::cout << "Today: " << todaysDate.weekday()
              << ", " << todaysDate << std::endl;

    std::cout << "Settlement date: " << settlementDate.weekday()
              << ", " << settlementDate << std::endl;

    // Data source: Bloomberg as of 12/30/2011
    // deposits
    Rate d1wQuote=0.00208200;
    Rate d2wQuote=0.00243500;
    Rate d1mQuote=0.00295300;
    Rate d2mQuote=0.00427100;
    Rate d3mQuote=0.00581000;
    // futures
    Real fut1Quote=99.2950;
    Real fut2Quote=99.2650;
    Real fut3Quote=99.2450;
    Real fut4Quote=99.2500;
    Real fut5Quote=99.2350;
    Real fut6Quote=99.2100;
    Real fut7Quote=99.1550;
    Real fut8Quote=99.1550;
    // swaps
    Rate s2yQuote=0.00726000;
    Rate s3yQuote=0.00820400;
    Rate s4yQuote=0.01006500;
    Rate s5yQuote=0.01224500;
    Rate s6yQuote=0.01449100;
    Rate s7yQuote=0.01643100;
    Rate s8yQuote=0.01802800;
    Rate s9yQuote=0.01932400;
    Rate s10yQuote=0.02027000;
    Rate s12yQuote=0.02227100;
    Rate s15yQuote=0.02401600;

    /*
    // Data source: Bloomberg as of 01/31/2012
    // deposits
    Rate d1wQuote=0.00196500;
    Rate d2wQuote=0.00225500;
    Rate d1mQuote=0.00264750;
    Rate d2mQuote=0.00394450;
    Rate d2mQuote=0.00000000;
    // futures
    Real fut1Quote=99.5450;
    Real fut2Quote=99.5400;
    Real fut3Quote=99.5200;
    Real fut4Quote=99.5000;
    Real fut5Quote=99.4950;
    Real fut6Quote=99.4750;
    Real fut7Quote=99.4450;
    Real fut8Quote=99.4000;
    // swaps
    Rate s2yQuote=0.00512500000;
    Rate s3yQuote=0.00590500000;
    Rate s4yQuote=0.00764500000;
    Rate s5yQuote=0.00988000000;
    Rate s6yQuote=0.01228000000;
    Rate s7yQuote=0.01449000000;
    Rate s8yQuote=0.01630500000;
    Rate s9yQuote=0.01782600000;
    Rate s10yQuote=0.01915000000;
    Rate s12yQuote=0.02126000000;
    Rate s15yQuote=0.02340300000;
    */


    /********************
     ***    QUOTES    ***
     ********************/

    // deposits
    boost::shared_ptr<Quote> d1wRate(new SimpleQuote(d1wQuote));
    boost::shared_ptr<Quote> d2wRate(new SimpleQuote(d2wQuote));
    boost::shared_ptr<Quote> d1mRate(new SimpleQuote(d1mQuote));
    boost::shared_ptr<Quote> d2mRate(new SimpleQuote(d2mQuote));
    boost::shared_ptr<Quote> d3mRate(new SimpleQuote(d3mQuote));
    // futures
    boost::shared_ptr<Quote> fut1Price(new SimpleQuote(fut1Quote));
    boost::shared_ptr<Quote> fut2Price(new SimpleQuote(fut2Quote));
    boost::shared_ptr<Quote> fut3Price(new SimpleQuote(fut3Quote));
    boost::shared_ptr<Quote> fut4Price(new SimpleQuote(fut4Quote));
    boost::shared_ptr<Quote> fut5Price(new SimpleQuote(fut5Quote));
    boost::shared_ptr<Quote> fut6Price(new SimpleQuote(fut6Quote));
    boost::shared_ptr<Quote> fut7Price(new SimpleQuote(fut7Quote));
    boost::shared_ptr<Quote> fut8Price(new SimpleQuote(fut8Quote));
    // swaps
    boost::shared_ptr<Quote> s2yRate(new SimpleQuote(s2yQuote));
    boost::shared_ptr<Quote> s3yRate(new SimpleQuote(s3yQuote));
    boost::shared_ptr<Quote> s4yRate(new SimpleQuote(s4yQuote));
    boost::shared_ptr<Quote> s5yRate(new SimpleQuote(s5yQuote));
    boost::shared_ptr<Quote> s6yRate(new SimpleQuote(s6yQuote));
    boost::shared_ptr<Quote> s7yRate(new SimpleQuote(s7yQuote));
    boost::shared_ptr<Quote> s8yRate(new SimpleQuote(s8yQuote));
    boost::shared_ptr<Quote> s9yRate(new SimpleQuote(s9yQuote));
    boost::shared_ptr<Quote> s10yRate(new SimpleQuote(s10yQuote));
    boost::shared_ptr<Quote> s12yRate(new SimpleQuote(s12yQuote));
    boost::shared_ptr<Quote> s15yRate(new SimpleQuote(s15yQuote));


    /*********************
     ***  RATE HELPERS ***
     *********************/

    // deposits
    DayCounter depositDayCounter = Actual360();

    boost::shared_ptr<RateHelper> d1w(new DepositRateHelper(
        Handle<Quote>(d1wRate),
        1*Weeks, fixingDays,
        calendar, ModifiedFollowing,
        true, depositDayCounter));
    boost::shared_ptr<RateHelper> d2w(new DepositRateHelper(
        Handle<Quote>(d2wRate),
        2*Weeks, fixingDays,
        calendar, ModifiedFollowing,
        true, depositDayCounter));
    boost::shared_ptr<RateHelper> d1m(new DepositRateHelper(
        Handle<Quote>(d1mRate),
        1*Months, fixingDays,
        calendar, ModifiedFollowing,
        true, depositDayCounter));
    boost::shared_ptr<RateHelper> d2m(new DepositRateHelper(
        Handle<Quote>(d2mRate),
        2*Months, fixingDays,
        calendar, ModifiedFollowing,
        true, depositDayCounter));
    boost::shared_ptr<RateHelper> d3m(new DepositRateHelper(
        Handle<Quote>(d3mRate),
        3*Months, fixingDays,
        calendar, ModifiedFollowing,
        true, depositDayCounter));

    // setup futures
    // Rate convexityAdjustment = 0.0;
    Integer futMonths = 3;
    Date imm = IMM::nextDate(settlementDate);
    std::cout << "imm1 = " << imm << std::endl;
    boost::shared_ptr<RateHelper> fut1(new FuturesRateHelper(
        Handle<Quote>(fut1Price),
        imm,
        futMonths, calendar, ModifiedFollowing,
        true, depositDayCounter));
    imm = IMM::nextDate(imm+1);
    std::cout << "imm2 = " << imm << std::endl;
    boost::shared_ptr<RateHelper> fut2(new FuturesRateHelper(
        Handle<Quote>(fut2Price),
        imm,
        futMonths, calendar, ModifiedFollowing,
        true, depositDayCounter));
    imm = IMM::nextDate(imm+1);
    std::cout << "imm3 = " << imm << std::endl;
    boost::shared_ptr<RateHelper> fut3(new FuturesRateHelper(
        Handle<Quote>(fut3Price),
        imm,
        futMonths, calendar, ModifiedFollowing,
        true, depositDayCounter));
    imm = IMM::nextDate(imm+1);
    std::cout << "imm4 = " << imm << std::endl;
    boost::shared_ptr<RateHelper> fut4(new FuturesRateHelper(
        Handle<Quote>(fut4Price),
        imm,
        futMonths, calendar, ModifiedFollowing,
        true, depositDayCounter));
    imm = IMM::nextDate(imm+1);
    std::cout << "imm5 = " << imm << std::endl;
    boost::shared_ptr<RateHelper> fut5(new FuturesRateHelper(
        Handle<Quote>(fut5Price),
        imm,
        futMonths, calendar, ModifiedFollowing,
        true, depositDayCounter));
    imm = IMM::nextDate(imm+1);
    std::cout << "imm6 = " << imm << std::endl;
    boost::shared_ptr<RateHelper> fut6(new FuturesRateHelper(
        Handle<Quote>(fut6Price),
        imm,
        futMonths, calendar, ModifiedFollowing,
        true, depositDayCounter));
    imm = IMM::nextDate(imm+1);
    std::cout << "imm7 = " << imm << std::endl;
    boost::shared_ptr<RateHelper> fut7(new FuturesRateHelper(
        Handle<Quote>(fut7Price),
        imm,
        futMonths, calendar, ModifiedFollowing,
        true, depositDayCounter));
    imm = IMM::nextDate(imm+1);
    std::cout << "imm8 = " << imm << std::endl;
    boost::shared_ptr<RateHelper> fut8(new FuturesRateHelper(
        Handle<Quote>(fut8Price),
        imm,
        futMonths, calendar, ModifiedFollowing,
        true, depositDayCounter));


    // setup swaps
    Frequency swFixedLegFrequency = Annual;
    BusinessDayConvention swFixedLegConvention = Unadjusted;
    DayCounter swFixedLegDayCounter = Thirty360(Thirty360::USA);
    RelinkableHandle<YieldTermStructure> liborTermStructure;
    boost::shared_ptr<IborIndex> swFloatingLegIndex(new USDLibor(Period(3, Months), liborTermStructure));

    boost::shared_ptr<RateHelper> s2y(new SwapRateHelper(
        Handle<Quote>(s2yRate), 2*Years,
        calendar, swFixedLegFrequency,
        swFixedLegConvention, swFixedLegDayCounter,
        swFloatingLegIndex));
    boost::shared_ptr<RateHelper> s3y(new SwapRateHelper(
        Handle<Quote>(s3yRate), 3*Years,
        calendar, swFixedLegFrequency,
        swFixedLegConvention, swFixedLegDayCounter,
        swFloatingLegIndex));
    boost::shared_ptr<RateHelper> s4y(new SwapRateHelper(
        Handle<Quote>(s4yRate), 4*Years,
        calendar, swFixedLegFrequency,
        swFixedLegConvention, swFixedLegDayCounter,
        swFloatingLegIndex));
    boost::shared_ptr<RateHelper> s5y(new SwapRateHelper(
        Handle<Quote>(s5yRate), 5*Years,
        calendar, swFixedLegFrequency,
        swFixedLegConvention, swFixedLegDayCounter,
        swFloatingLegIndex));
    boost::shared_ptr<RateHelper> s6y(new SwapRateHelper(
        Handle<Quote>(s6yRate), 6*Years,
        calendar, swFixedLegFrequency,
        swFixedLegConvention, swFixedLegDayCounter,
        swFloatingLegIndex));
    boost::shared_ptr<RateHelper> s7y(new SwapRateHelper(
        Handle<Quote>(s7yRate), 7*Years,
        calendar, swFixedLegFrequency,
        swFixedLegConvention, swFixedLegDayCounter,
        swFloatingLegIndex));
    boost::shared_ptr<RateHelper> s8y(new SwapRateHelper(
        Handle<Quote>(s8yRate), 8*Years,
        calendar, swFixedLegFrequency,
        swFixedLegConvention, swFixedLegDayCounter,
        swFloatingLegIndex));
    boost::shared_ptr<RateHelper> s9y(new SwapRateHelper(
        Handle<Quote>(s9yRate), 9*Years,
        calendar, swFixedLegFrequency,
        swFixedLegConvention, swFixedLegDayCounter,
        swFloatingLegIndex));
    boost::shared_ptr<RateHelper> s10y(new SwapRateHelper(
        Handle<Quote>(s10yRate), 10*Years,
        calendar, swFixedLegFrequency,
        swFixedLegConvention, swFixedLegDayCounter,
        swFloatingLegIndex));
    boost::shared_ptr<RateHelper> s12y(new SwapRateHelper(
        Handle<Quote>(s12yRate), 12*Years,
        calendar, swFixedLegFrequency,
        swFixedLegConvention, swFixedLegDayCounter,
        swFloatingLegIndex));
    boost::shared_ptr<RateHelper> s15y(new SwapRateHelper(
        Handle<Quote>(s15yRate), 15*Years,
        calendar, swFixedLegFrequency,
        swFixedLegConvention, swFixedLegDayCounter,
        swFloatingLegIndex));


    /*********************
     **  CURVE BUILDING **
     *********************/

    DayCounter termStructureDayCounter =
        ActualActual(ActualActual::ISDA);

    double tolerance = 1.0e-15;

    // A depo-futures-swap curve
    std::vector<boost::shared_ptr<RateHelper> > depoFutSwapInstruments;
    depoFutSwapInstruments.push_back(d1w);
    depoFutSwapInstruments.push_back(d2w);
    depoFutSwapInstruments.push_back(d1m);
    depoFutSwapInstruments.push_back(d2m);
    depoFutSwapInstruments.push_back(d3m);
    depoFutSwapInstruments.push_back(fut1);
    depoFutSwapInstruments.push_back(fut2);
    depoFutSwapInstruments.push_back(fut3);
    depoFutSwapInstruments.push_back(fut4);
    depoFutSwapInstruments.push_back(fut5);
    depoFutSwapInstruments.push_back(fut6);
    depoFutSwapInstruments.push_back(fut7);
    depoFutSwapInstruments.push_back(fut8);
    depoFutSwapInstruments.push_back(s3y);
    depoFutSwapInstruments.push_back(s4y);
    depoFutSwapInstruments.push_back(s5y);
    depoFutSwapInstruments.push_back(s6y);
    depoFutSwapInstruments.push_back(s7y);
    depoFutSwapInstruments.push_back(s8y);
    depoFutSwapInstruments.push_back(s9y);
    depoFutSwapInstruments.push_back(s10y);
    depoFutSwapInstruments.push_back(s12y);
    depoFutSwapInstruments.push_back(s15y);
    /*boost::shared_ptr<YieldTermStructure> depoFutSwapTermStructure(
        new PiecewiseYieldCurve<Discount, LogLinear>(
                                    settlementDate, depoFutSwapInstruments,
                                    termStructureDayCounter,
                                    tolerance));*/
    PiecewiseYieldCurve<Discount, LogLinear>* depoFutSwapTermStructure 
        = new PiecewiseYieldCurve<Discount, LogLinear>(
                                    settlementDate, depoFutSwapInstruments,
                                    termStructureDayCounter,
                                    tolerance);

    Date date1 = Date(29, May, 2012);
    Real df1 = depoFutSwapTermStructure->discount(date1);
    Date date2 = Date(16, Aug, 2013);
    Real df2 = depoFutSwapTermStructure->discount(date2);

    Size widths[] = { 35, 14, 14 };
    std::cout << std::setw(widths[0]) << std::left << "Date" 
              << std::setw(widths[1]) << std::left << "Disc. Factor" 
              << std::endl;
    std::cout << std::setw(widths[0]) << std::left << date1 
              << std::setw(widths[1]) << std::left << df1 
              << std::endl;
    std::cout << std::setw(widths[0]) << std::left << date2 
              << std::setw(widths[1]) << std::left << df2 
              << std::endl;

    return depoFutSwapTermStructure;
}
예제 #14
0
void MainWindow::showSwapNPV()
{
    //ui->lineEdit_SwapNPV->setText(tr("1000000000"));
    //ui->lineEdit_SwapFairRate->setText(QString::number(3.141659));
    //ui->lineEdit_SwapFairSpread->setText(QString::number(2.68796451));


    /*********************
    ***  MARKET DATA  ***
    *********************/

    Calendar calendar = TARGET();

    /////■ Date settlementDate(22, September, 2004);
    QDate qtFormSettlementDate = ui->dateEdit_settlementDate->date();
    QuantLib::Date settlementDate(22, September, 2004);
    if(!qtFormSettlementDate.isNull() && qtFormSettlementDate.isValid()) {
        QuantLib::Date settlementDate_(qtFormSettlementDate.day(), (QuantLib::Month)(qtFormSettlementDate.month()), qtFormSettlementDate.year());
        settlementDate = settlementDate_;
    }

    // must be a business day
    settlementDate = calendar.adjust(settlementDate);

    Integer fixingDays = 2;
    Date todaysDate = calendar.advance(settlementDate, -fixingDays, Days);
    // nothing to do with Date::todaysDate
    Settings::instance().evaluationDate() = todaysDate;


    todaysDate = Settings::instance().evaluationDate();
    std::cout << "Today: " << todaysDate.weekday()
              << ", " << todaysDate << std::endl;

    std::cout << "Settlement date: " << settlementDate.weekday()
              << ", " << settlementDate << std::endl;

    // deposits
    Rate d1wQuote=0.0382;
    d1wQuote = static_cast<Rate>(ui->tableWidget_RatesDeposites->item(-1,1)->text().toDouble()*0.01);
    Rate d1mQuote=0.0372;
    d1mQuote = static_cast<Rate>(ui->tableWidget_RatesDeposites->item(0,1)->text().toDouble()*0.01);
    Rate d3mQuote=0.0363;
    d3mQuote = static_cast<Rate>(ui->tableWidget_RatesDeposites->item(1,1)->text().toDouble()*0.01);
    Rate d6mQuote=0.0353;
    d6mQuote = static_cast<Rate>(ui->tableWidget_RatesDeposites->item(2,1)->text().toDouble()*0.01);
    Rate d9mQuote=0.0348;
    d9mQuote = static_cast<Rate>(ui->tableWidget_RatesDeposites->item(3,1)->text().toDouble()*0.01);
    Rate d1yQuote=0.0345;
    d1yQuote = static_cast<Rate>(ui->tableWidget_RatesDeposites->item(4,1)->text().toDouble()*0.01);

    // FRAs
    Rate fra3x6Quote=0.037125;
    fra3x6Quote = static_cast<Rate>(ui->tableWidget_RatesFRAs->item(-1,1)->text().toDouble()*0.01);
    Rate fra6x9Quote=0.037125;
    fra6x9Quote = static_cast<Rate>(ui->tableWidget_RatesFRAs->item(0,1)->text().toDouble()*0.01);
    Rate fra6x12Quote=0.037125;
    fra6x12Quote = static_cast<Rate>(ui->tableWidget_RatesFRAs->item(1,1)->text().toDouble()*0.01);

    // futures
    Real fut1Quote=96.2875;
    fut1Quote = static_cast<Real>(ui->tableWidget_RatesFutures->item(-1,1)->text().toDouble());
    Real fut2Quote=96.7875;
    fut2Quote = static_cast<Real>(ui->tableWidget_RatesFutures->item(0,1)->text().toDouble());
    Real fut3Quote=96.9875;
    fut3Quote = static_cast<Real>(ui->tableWidget_RatesFutures->item(1,1)->text().toDouble());
    Real fut4Quote=96.6875;
    fut4Quote = static_cast<Real>(ui->tableWidget_RatesFutures->item(2,1)->text().toDouble());
    Real fut5Quote=96.4875;
    fut5Quote = static_cast<Real>(ui->tableWidget_RatesFutures->item(3,1)->text().toDouble());
    Real fut6Quote=96.3875;
    fut6Quote = static_cast<Real>(ui->tableWidget_RatesFutures->item(4,1)->text().toDouble());
    Real fut7Quote=96.2875;
    fut7Quote = static_cast<Real>(ui->tableWidget_RatesFutures->item(5,1)->text().toDouble());
    Real fut8Quote=96.0875;
    fut8Quote = static_cast<Real>(ui->tableWidget_RatesFutures->item(6,1)->text().toDouble());

    // swaps
    Rate s2yQuote=0.037125;
    s2yQuote = static_cast<Rate>(ui->tableWidget_RatesSwaps->item(-1,1)->text().toDouble()*0.01);
    Rate s3yQuote=0.0398;
    s3yQuote = static_cast<Rate>(ui->tableWidget_RatesSwaps->item(0,1)->text().toDouble()*0.01);
    Rate s5yQuote=0.0443;
    s5yQuote = static_cast<Rate>(ui->tableWidget_RatesSwaps->item(1,1)->text().toDouble()*0.01);
    Rate s10yQuote=0.05165;
    s10yQuote = static_cast<Rate>(ui->tableWidget_RatesSwaps->item(2,1)->text().toDouble()*0.01);
    Rate s15yQuote=0.055175;
    s15yQuote = static_cast<Rate>(ui->tableWidget_RatesSwaps->item(3,1)->text().toDouble()*0.01);


    /********************
    ***    QUOTES    ***
    ********************/

    // SimpleQuote stores a value which can be manually changed;
    // other Quote subclasses could read the value from a database
    // or some kind of data feed.

    // deposits
    boost::shared_ptr<Quote> d1wRate(new SimpleQuote(d1wQuote));
    boost::shared_ptr<Quote> d1mRate(new SimpleQuote(d1mQuote));
    boost::shared_ptr<Quote> d3mRate(new SimpleQuote(d3mQuote));
    boost::shared_ptr<Quote> d6mRate(new SimpleQuote(d6mQuote));
    boost::shared_ptr<Quote> d9mRate(new SimpleQuote(d9mQuote));
    boost::shared_ptr<Quote> d1yRate(new SimpleQuote(d1yQuote));
    // FRAs
    boost::shared_ptr<Quote> fra3x6Rate(new SimpleQuote(fra3x6Quote));
    boost::shared_ptr<Quote> fra6x9Rate(new SimpleQuote(fra6x9Quote));
    boost::shared_ptr<Quote> fra6x12Rate(new SimpleQuote(fra6x12Quote));
    // futures
    boost::shared_ptr<Quote> fut1Price(new SimpleQuote(fut1Quote));
    boost::shared_ptr<Quote> fut2Price(new SimpleQuote(fut2Quote));
    boost::shared_ptr<Quote> fut3Price(new SimpleQuote(fut3Quote));
    boost::shared_ptr<Quote> fut4Price(new SimpleQuote(fut4Quote));
    boost::shared_ptr<Quote> fut5Price(new SimpleQuote(fut5Quote));
    boost::shared_ptr<Quote> fut6Price(new SimpleQuote(fut6Quote));
    boost::shared_ptr<Quote> fut7Price(new SimpleQuote(fut7Quote));
    boost::shared_ptr<Quote> fut8Price(new SimpleQuote(fut8Quote));
    // swaps
    boost::shared_ptr<Quote> s2yRate(new SimpleQuote(s2yQuote));
    boost::shared_ptr<Quote> s3yRate(new SimpleQuote(s3yQuote));
    boost::shared_ptr<Quote> s5yRate(new SimpleQuote(s5yQuote));
    boost::shared_ptr<Quote> s10yRate(new SimpleQuote(s10yQuote));
    boost::shared_ptr<Quote> s15yRate(new SimpleQuote(s15yQuote));


    /*********************
    	***  RATE HELPERS ***
    	*********************/

    // RateHelpers are built from the above quotes together with
    // other instrument dependant infos.  Quotes are passed in
    // relinkable handles which could be relinked to some other
    // data source later.

    // deposits
    DayCounter depositDayCounter = Actual360();

    boost::shared_ptr<RateHelper> d1w(new DepositRateHelper(
                                          Handle<Quote>(d1wRate),
                                          1*Weeks, fixingDays,
                                          calendar, ModifiedFollowing,
                                          true, depositDayCounter));
    boost::shared_ptr<RateHelper> d1m(new DepositRateHelper(
                                          Handle<Quote>(d1mRate),
                                          1*Months, fixingDays,
                                          calendar, ModifiedFollowing,
                                          true, depositDayCounter));
    boost::shared_ptr<RateHelper> d3m(new DepositRateHelper(
                                          Handle<Quote>(d3mRate),
                                          3*Months, fixingDays,
                                          calendar, ModifiedFollowing,
                                          true, depositDayCounter));
    boost::shared_ptr<RateHelper> d6m(new DepositRateHelper(
                                          Handle<Quote>(d6mRate),
                                          6*Months, fixingDays,
                                          calendar, ModifiedFollowing,
                                          true, depositDayCounter));
    boost::shared_ptr<RateHelper> d9m(new DepositRateHelper(
                                          Handle<Quote>(d9mRate),
                                          9*Months, fixingDays,
                                          calendar, ModifiedFollowing,
                                          true, depositDayCounter));
    boost::shared_ptr<RateHelper> d1y(new DepositRateHelper(
                                          Handle<Quote>(d1yRate),
                                          1*Years, fixingDays,
                                          calendar, ModifiedFollowing,
                                          true, depositDayCounter));


    // setup FRAs
    boost::shared_ptr<RateHelper> fra3x6(new FraRateHelper(
            Handle<Quote>(fra3x6Rate),
            3, 6, fixingDays, calendar, ModifiedFollowing,
            true, depositDayCounter));
    boost::shared_ptr<RateHelper> fra6x9(new FraRateHelper(
            Handle<Quote>(fra6x9Rate),
            6, 9, fixingDays, calendar, ModifiedFollowing,
            true, depositDayCounter));
    boost::shared_ptr<RateHelper> fra6x12(new FraRateHelper(
            Handle<Quote>(fra6x12Rate),
            6, 12, fixingDays, calendar, ModifiedFollowing,
            true, depositDayCounter));


    // setup futures
    // Rate convexityAdjustment = 0.0;
    Integer futMonths = 3;
    Date imm = IMM::nextDate(settlementDate);
    boost::shared_ptr<RateHelper> fut1(new FuturesRateHelper(
                                           Handle<Quote>(fut1Price),
                                           imm,
                                           futMonths, calendar, ModifiedFollowing,
                                           true, depositDayCounter));
    imm = IMM::nextDate(imm+1);
    boost::shared_ptr<RateHelper> fut2(new FuturesRateHelper(
                                           Handle<Quote>(fut2Price),
                                           imm,
                                           futMonths, calendar, ModifiedFollowing,
                                           true, depositDayCounter));
    imm = IMM::nextDate(imm+1);
    boost::shared_ptr<RateHelper> fut3(new FuturesRateHelper(
                                           Handle<Quote>(fut3Price),
                                           imm,
                                           futMonths, calendar, ModifiedFollowing,
                                           true, depositDayCounter));
    imm = IMM::nextDate(imm+1);
    boost::shared_ptr<RateHelper> fut4(new FuturesRateHelper(
                                           Handle<Quote>(fut4Price),
                                           imm,
                                           futMonths, calendar, ModifiedFollowing,
                                           true, depositDayCounter));
    imm = IMM::nextDate(imm+1);
    boost::shared_ptr<RateHelper> fut5(new FuturesRateHelper(
                                           Handle<Quote>(fut5Price),
                                           imm,
                                           futMonths, calendar, ModifiedFollowing,
                                           true, depositDayCounter));
    imm = IMM::nextDate(imm+1);
    boost::shared_ptr<RateHelper> fut6(new FuturesRateHelper(
                                           Handle<Quote>(fut6Price),
                                           imm,
                                           futMonths, calendar, ModifiedFollowing,
                                           true, depositDayCounter));
    imm = IMM::nextDate(imm+1);
    boost::shared_ptr<RateHelper> fut7(new FuturesRateHelper(
                                           Handle<Quote>(fut7Price),
                                           imm,
                                           futMonths, calendar, ModifiedFollowing,
                                           true, depositDayCounter));
    imm = IMM::nextDate(imm+1);
    boost::shared_ptr<RateHelper> fut8(new FuturesRateHelper(
                                           Handle<Quote>(fut8Price),
                                           imm,
                                           futMonths, calendar, ModifiedFollowing,
                                           true, depositDayCounter));


    // setup swaps
    Frequency swFixedLegFrequency = Annual;
    BusinessDayConvention swFixedLegConvention = Unadjusted;
    DayCounter swFixedLegDayCounter = Thirty360(Thirty360::European);
    boost::shared_ptr<IborIndex> swFloatingLegIndex(new Euribor6M);

    boost::shared_ptr<RateHelper> s2y(new SwapRateHelper(
                                          Handle<Quote>(s2yRate), 2*Years,
                                          calendar, swFixedLegFrequency,
                                          swFixedLegConvention, swFixedLegDayCounter,
                                          swFloatingLegIndex));
    boost::shared_ptr<RateHelper> s3y(new SwapRateHelper(
                                          Handle<Quote>(s3yRate), 3*Years,
                                          calendar, swFixedLegFrequency,
                                          swFixedLegConvention, swFixedLegDayCounter,
                                          swFloatingLegIndex));
    boost::shared_ptr<RateHelper> s5y(new SwapRateHelper(
                                          Handle<Quote>(s5yRate), 5*Years,
                                          calendar, swFixedLegFrequency,
                                          swFixedLegConvention, swFixedLegDayCounter,
                                          swFloatingLegIndex));
    boost::shared_ptr<RateHelper> s10y(new SwapRateHelper(
                                           Handle<Quote>(s10yRate), 10*Years,
                                           calendar, swFixedLegFrequency,
                                           swFixedLegConvention, swFixedLegDayCounter,
                                           swFloatingLegIndex));
    boost::shared_ptr<RateHelper> s15y(new SwapRateHelper(
                                           Handle<Quote>(s15yRate), 15*Years,
                                           calendar, swFixedLegFrequency,
                                           swFixedLegConvention, swFixedLegDayCounter,
                                           swFloatingLegIndex));


    /*********************
    	**  CURVE BUILDING **
    	*********************/

    // Any DayCounter would be fine.
    // ActualActual::ISDA ensures that 30 years is 30.0
    DayCounter termStructureDayCounter =
        ActualActual(ActualActual::ISDA);


    double tolerance = 1.0e-15;

    // A depo-swap curve
    std::vector<boost::shared_ptr<RateHelper> > depoSwapInstruments;
    depoSwapInstruments.push_back(d1w);
    depoSwapInstruments.push_back(d1m);
    depoSwapInstruments.push_back(d3m);
    depoSwapInstruments.push_back(d6m);
    depoSwapInstruments.push_back(d9m);
    depoSwapInstruments.push_back(d1y);
    depoSwapInstruments.push_back(s2y);
    depoSwapInstruments.push_back(s3y);
    depoSwapInstruments.push_back(s5y);
    depoSwapInstruments.push_back(s10y);
    depoSwapInstruments.push_back(s15y);
    boost::shared_ptr<YieldTermStructure> depoSwapTermStructure(
        new PiecewiseYieldCurve<Discount,LogLinear>(
            settlementDate, depoSwapInstruments,
            termStructureDayCounter,
            tolerance));


    // A depo-futures-swap curve
    std::vector<boost::shared_ptr<RateHelper> > depoFutSwapInstruments;
    depoFutSwapInstruments.push_back(d1w);
    depoFutSwapInstruments.push_back(d1m);
    depoFutSwapInstruments.push_back(fut1);
    depoFutSwapInstruments.push_back(fut2);
    depoFutSwapInstruments.push_back(fut3);
    depoFutSwapInstruments.push_back(fut4);
    depoFutSwapInstruments.push_back(fut5);
    depoFutSwapInstruments.push_back(fut6);
    depoFutSwapInstruments.push_back(fut7);
    depoFutSwapInstruments.push_back(fut8);
    depoFutSwapInstruments.push_back(s3y);
    depoFutSwapInstruments.push_back(s5y);
    depoFutSwapInstruments.push_back(s10y);
    depoFutSwapInstruments.push_back(s15y);
    boost::shared_ptr<YieldTermStructure> depoFutSwapTermStructure(
        new PiecewiseYieldCurve<Discount,LogLinear>(
            settlementDate, depoFutSwapInstruments,
            termStructureDayCounter,
            tolerance));


    // A depo-FRA-swap curve
    std::vector<boost::shared_ptr<RateHelper> > depoFRASwapInstruments;
    depoFRASwapInstruments.push_back(d1w);
    depoFRASwapInstruments.push_back(d1m);
    depoFRASwapInstruments.push_back(d3m);
    depoFRASwapInstruments.push_back(fra3x6);
    depoFRASwapInstruments.push_back(fra6x9);
    depoFRASwapInstruments.push_back(fra6x12);
    depoFRASwapInstruments.push_back(s2y);
    depoFRASwapInstruments.push_back(s3y);
    depoFRASwapInstruments.push_back(s5y);
    depoFRASwapInstruments.push_back(s10y);
    depoFRASwapInstruments.push_back(s15y);
    boost::shared_ptr<YieldTermStructure> depoFRASwapTermStructure(
        new PiecewiseYieldCurve<Discount,LogLinear>(
            settlementDate, depoFRASwapInstruments,
            termStructureDayCounter,
            tolerance));


    // Term structures that will be used for pricing:
    // the one used for discounting cash flows
    RelinkableHandle<YieldTermStructure> discountingTermStructure;
    // the one used for forward rate forecasting
    RelinkableHandle<YieldTermStructure> forecastingTermStructure;


    /*********************
    * SWAPS TO BE PRICED *
    **********************/

    // constant nominal 1,000,000 Euro
    /////■ Real nominal = 1000000.0;
    Real nominal = static_cast<Real>(ui->doubleSpinBox_Notional->value());

    // fixed leg
    /////■ Frequency fixedLegFrequency = Annual;
    Frequency fixedLegFrequency = Annual;
    /////■ BusinessDayConvention fixedLegConvention = Unadjusted;
    BusinessDayConvention fixedLegConvention = Unadjusted;
    /////■ DayCounter fixedLegDayCounter = Thirty360(Thirty360::European);
    DayCounter fixedLegDayCounter = Thirty360(Thirty360::European);
    /////■ Rate fixedRate = 0.04;
    Rate fixedRate = static_cast<Real>((ui->doubleSpinBox_fixedRate->value())*0.01);

    // floating leg
    /////■ Frequency floatingLegFrequency = Semiannual;
    Frequency floatingLegFrequency = Semiannual;
    int comboBoxFloatingLegFrequency = ui->comboBox_FloatingLegFrequency->currentIndex();
    switch(comboBoxFloatingLegFrequency) {
    case 0: // Semiannual
        floatingLegFrequency = Semiannual;
        break;
    case 1: // Annual
        floatingLegFrequency = Annual;
        break;
    case 2: // Quarterly
        floatingLegFrequency = Quarterly;
        break;
    }

    /////■ BusinessDayConvention floatingLegConvention = ModifiedFollowing;
    BusinessDayConvention floatingLegConvention = ModifiedFollowing;
    /////■ DayCounter floatingLegDayCounter = Actual360();
    DayCounter floatingLegDayCounter = Actual360();

    boost::shared_ptr<IborIndex> euriborIndex(
        new Euribor6M(forecastingTermStructure));
    /////■ Spread spread = 0.0;
    Spread spread = static_cast<Spread>((ui->doubleSpinBox_spread->value())*0.01);
    /////■ Integer lenghtInYears = 5;
    Integer lenghtInYears =  (Integer)(ui->doubleSpinBox_lenghtInYears->value());
    /////■ VanillaSwap::Type swapType = VanillaSwap::Payer;
    int comboBoxPayerReceiver = ui->comboBox_swapType->currentIndex();
    VanillaSwap::Type swapType = VanillaSwap::Receiver;
    switch(comboBoxPayerReceiver) {
    case 0: // Fix Payer
        swapType = VanillaSwap::Payer;
        break; // VanillaSwap::Payer=1
    case 1: // Fix Receiver
        swapType = VanillaSwap::Receiver;
        break; // VanillaSwap::Receiver=-1
    }

    Date maturity = settlementDate + lenghtInYears*Years;
    Schedule fixedSchedule(settlementDate, maturity,
                           Period(fixedLegFrequency),
                           calendar, fixedLegConvention,
                           fixedLegConvention,
                           DateGeneration::Forward, false);
    Schedule floatSchedule(settlementDate, maturity,
                           Period(floatingLegFrequency),
                           calendar, floatingLegConvention,
                           floatingLegConvention,
                           DateGeneration::Forward, false);
    VanillaSwap spot5YearSwap(swapType, nominal,
                              fixedSchedule, fixedRate, fixedLegDayCounter,
                              floatSchedule, euriborIndex, spread,
                              floatingLegDayCounter);

    Date fwdStart = calendar.advance(settlementDate, 1, Years);
    Date fwdMaturity = fwdStart + lenghtInYears*Years;
    Schedule fwdFixedSchedule(fwdStart, fwdMaturity,
                              Period(fixedLegFrequency),
                              calendar, fixedLegConvention,
                              fixedLegConvention,
                              DateGeneration::Forward, false);
    Schedule fwdFloatSchedule(fwdStart, fwdMaturity,
                              Period(floatingLegFrequency),
                              calendar, floatingLegConvention,
                              floatingLegConvention,
                              DateGeneration::Forward, false);
    VanillaSwap oneYearForward5YearSwap(swapType, nominal,
                                        fwdFixedSchedule, fixedRate, fixedLegDayCounter,
                                        fwdFloatSchedule, euriborIndex, spread,
                                        floatingLegDayCounter);


    /***************
    * SWAP PRICING *
    ****************/

    Real NPV;
    Rate fairRate;
    Spread fairSpread;

    boost::shared_ptr<PricingEngine> swapEngine(
        new DiscountingSwapEngine(discountingTermStructure));

    spot5YearSwap.setPricingEngine(swapEngine);
    oneYearForward5YearSwap.setPricingEngine(swapEngine);

    int swapTermStructureType(0);
    swapTermStructureType = ui->comboBox_TermStructureType->currentIndex();
    //QMessageBox msgBoxTmp(this); msgBoxTmp.setText(QString::number(swapTermStructureType)); msgBoxTmp.exec();
    switch(swapTermStructureType) {
    case 0:
        forecastingTermStructure.linkTo(depoSwapTermStructure);
        discountingTermStructure.linkTo(depoSwapTermStructure);
        break;
    case 1:
        forecastingTermStructure.linkTo(depoFutSwapTermStructure);
        discountingTermStructure.linkTo(depoFutSwapTermStructure);
        break;
    case 2:
        forecastingTermStructure.linkTo(depoFRASwapTermStructure);
        discountingTermStructure.linkTo(depoFRASwapTermStructure);
        break;
    }

    NPV = spot5YearSwap.NPV();
    fairRate = spot5YearSwap.fairRate();
    fairSpread = spot5YearSwap.fairSpread();


    ui->lineEdit_SwapNPV->setText(QString::number(static_cast<double>(NPV),'f'));
    ui->lineEdit_SwapFairRate->setText(QString::number(static_cast<double>(fairRate*100.0),'f'));
    ui->lineEdit_SwapFairSpread->setText(QString::number(static_cast<double>(fairSpread*100.0),'f'));


}
예제 #15
0
int main(int, char* []) {

    try {

        boost::timer timer;
        std::cout << std::endl;

        Option::Type type(Option::Put);
        Real underlying = 36.0;
        Real spreadRate = 0.005;

        Spread dividendYield = 0.02;
        Rate riskFreeRate = 0.06;
        Volatility volatility = 0.20;

        Integer settlementDays = 3;
        Integer length = 5;
        Real redemption = 100.0;
        Real conversionRatio = redemption/underlying; // at the money

        // set up dates/schedules
        Calendar calendar = TARGET();
        Date today = calendar.adjust(Date::todaysDate());

        Settings::instance().evaluationDate() = today;
        Date settlementDate = calendar.advance(today, settlementDays, Days);
        Date exerciseDate = calendar.advance(settlementDate, length, Years);
        Date issueDate = calendar.advance(exerciseDate, -length, Years);

        BusinessDayConvention convention = ModifiedFollowing;

        Frequency frequency = Annual;

        Schedule schedule(issueDate, exerciseDate,
                          Period(frequency), calendar,
                          convention, convention,
                          DateGeneration::Backward, false);

        DividendSchedule dividends;
        CallabilitySchedule callability;

        std::vector<Real> coupons(1, 0.05);

        DayCounter bondDayCount = Thirty360();

        Integer callLength[] = { 2, 4 };  // Call dates, years 2, 4.
        Integer putLength[] = { 3 }; // Put dates year 3

        Real callPrices[] = { 101.5, 100.85 };
        Real putPrices[]= { 105.0 };

        // Load call schedules
        for (Size i=0; i<LENGTH(callLength); i++) {
            callability.push_back(
                   boost::shared_ptr<Callability>(
                       new SoftCallability(Callability::Price(
                                                   callPrices[i],
                                                   Callability::Price::Clean),
                                           schedule.date(callLength[i]),
                                           1.20)));
        }

        for (Size j=0; j<LENGTH(putLength); j++) {
            callability.push_back(
                   boost::shared_ptr<Callability>(
                           new Callability(Callability::Price(
                                                   putPrices[j],
                                                   Callability::Price::Clean),
                                           Callability::Put,
                                           schedule.date(putLength[j]))));
        }

        // Assume dividends are paid every 6 months.
        for (Date d = today + 6*Months; d < exerciseDate; d += 6*Months) {
            dividends.push_back(
                      boost::shared_ptr<Dividend>(new FixedDividend(1.0, d)));
        }

        DayCounter dayCounter = Actual365Fixed();
        Time maturity = dayCounter.yearFraction(settlementDate,
                                                exerciseDate);

        std::cout << "option type = "  << type << std::endl;
        std::cout << "Time to maturity = "        << maturity
                  << std::endl;
        std::cout << "Underlying price = "        << underlying
                  << std::endl;
        std::cout << "Risk-free interest rate = " << io::rate(riskFreeRate)
                  << std::endl;
        std::cout << "Dividend yield = " << io::rate(dividendYield)
                  << std::endl;
        std::cout << "Volatility = " << io::volatility(volatility)
                  << std::endl;
        std::cout << std::endl;

        std::string method;
        std::cout << std::endl ;

        // write column headings
        Size widths[] = { 35, 14, 14 };
        Size totalWidth = widths[0] + widths[1] + widths[2];
        std::string rule(totalWidth, '-'), dblrule(totalWidth, '=');

        std::cout << dblrule << std::endl;
        std::cout << "Tsiveriotis-Fernandes method" << std::endl;
        std::cout << dblrule << std::endl;
        std::cout << std::setw(widths[0]) << std::left << "Tree type"
                  << std::setw(widths[1]) << std::left << "European"
                  << std::setw(widths[1]) << std::left << "American"
                  << std::endl;
        std::cout << rule << std::endl;

        boost::shared_ptr<Exercise> exercise(
                                          new EuropeanExercise(exerciseDate));
        boost::shared_ptr<Exercise> amExercise(
                                          new AmericanExercise(settlementDate,
                                                               exerciseDate));

        Handle<Quote> underlyingH(
            boost::shared_ptr<Quote>(new SimpleQuote(underlying)));

        Handle<YieldTermStructure> flatTermStructure(
            boost::shared_ptr<YieldTermStructure>(
                new FlatForward(settlementDate, riskFreeRate, dayCounter)));

        Handle<YieldTermStructure> flatDividendTS(
            boost::shared_ptr<YieldTermStructure>(
                new FlatForward(settlementDate, dividendYield, dayCounter)));

        Handle<BlackVolTermStructure> flatVolTS(
            boost::shared_ptr<BlackVolTermStructure>(
                new BlackConstantVol(settlementDate, calendar,
                                     volatility, dayCounter)));


        boost::shared_ptr<BlackScholesMertonProcess> stochasticProcess(
                              new BlackScholesMertonProcess(underlyingH,
                                                            flatDividendTS,
                                                            flatTermStructure,
                                                            flatVolTS));

        Size timeSteps = 801;

        Handle<Quote> creditSpread(
                       boost::shared_ptr<Quote>(new SimpleQuote(spreadRate)));

        boost::shared_ptr<Quote> rate(new SimpleQuote(riskFreeRate));

        Handle<YieldTermStructure> discountCurve(
                boost::shared_ptr<YieldTermStructure>(
                    new FlatForward(today, Handle<Quote>(rate), dayCounter)));

        boost::shared_ptr<PricingEngine> engine(
                  new BinomialConvertibleEngine<JarrowRudd>(stochasticProcess,
                                                            timeSteps));

        ConvertibleFixedCouponBond europeanBond(
                            exercise, conversionRatio, dividends, callability,
                            creditSpread, issueDate, settlementDays,
                            coupons, bondDayCount, schedule, redemption);
        europeanBond.setPricingEngine(engine);

        ConvertibleFixedCouponBond americanBond(
                          amExercise, conversionRatio, dividends, callability,
                          creditSpread, issueDate, settlementDays,
                          coupons, bondDayCount, schedule, redemption);
        americanBond.setPricingEngine(engine);

        method = "Jarrow-Rudd";
        europeanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
                  new BinomialConvertibleEngine<JarrowRudd>(stochasticProcess,
                                                            timeSteps)));
        americanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
                  new BinomialConvertibleEngine<JarrowRudd>(stochasticProcess,
                                                            timeSteps)));
        std::cout << std::setw(widths[0]) << std::left << method
                  << std::fixed
                  << std::setw(widths[1]) << std::left << europeanBond.NPV()
                  << std::setw(widths[2]) << std::left << americanBond.NPV()
                  << std::endl;

        method = "Cox-Ross-Rubinstein";
        europeanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
           new BinomialConvertibleEngine<CoxRossRubinstein>(stochasticProcess,
                                                            timeSteps)));
        americanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
           new BinomialConvertibleEngine<CoxRossRubinstein>(stochasticProcess,
                                                            timeSteps)));
        std::cout << std::setw(widths[0]) << std::left << method
                  << std::fixed
                  << std::setw(widths[1]) << std::left << europeanBond.NPV()
                  << std::setw(widths[2]) << std::left << americanBond.NPV()
                  << std::endl;

        method = "Additive equiprobabilities";
        europeanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
                   new BinomialConvertibleEngine<AdditiveEQPBinomialTree>(
                                                            stochasticProcess,
                                                            timeSteps)));
        americanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
                   new BinomialConvertibleEngine<AdditiveEQPBinomialTree>(
                                                            stochasticProcess,
                                                            timeSteps)));
        std::cout << std::setw(widths[0]) << std::left << method
                  << std::fixed
                  << std::setw(widths[1]) << std::left << europeanBond.NPV()
                  << std::setw(widths[2]) << std::left << americanBond.NPV()
                  << std::endl;

        method = "Trigeorgis";
        europeanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
                  new BinomialConvertibleEngine<Trigeorgis>(stochasticProcess,
                                                            timeSteps)));
        americanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
                  new BinomialConvertibleEngine<Trigeorgis>(stochasticProcess,
                                                            timeSteps)));
        std::cout << std::setw(widths[0]) << std::left << method
                  << std::fixed
                  << std::setw(widths[1]) << std::left << europeanBond.NPV()
                  << std::setw(widths[2]) << std::left << americanBond.NPV()
                  << std::endl;

        method = "Tian";
        europeanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
                        new BinomialConvertibleEngine<Tian>(stochasticProcess,
                                                            timeSteps)));
        americanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
                        new BinomialConvertibleEngine<Tian>(stochasticProcess,
                                                            timeSteps)));
        std::cout << std::setw(widths[0]) << std::left << method
                  << std::fixed
                  << std::setw(widths[1]) << std::left << europeanBond.NPV()
                  << std::setw(widths[2]) << std::left << americanBond.NPV()
                  << std::endl;

        method = "Leisen-Reimer";
        europeanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
                new BinomialConvertibleEngine<LeisenReimer>(stochasticProcess,
                                                            timeSteps)));
        americanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
                new BinomialConvertibleEngine<LeisenReimer>(stochasticProcess,
                                                            timeSteps)));
        std::cout << std::setw(widths[0]) << std::left << method
                  << std::fixed
                  << std::setw(widths[1]) << std::left << europeanBond.NPV()
                  << std::setw(widths[2]) << std::left << americanBond.NPV()
                  << std::endl;

        method = "Joshi";
        europeanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
                      new BinomialConvertibleEngine<Joshi4>(stochasticProcess,
                                                            timeSteps)));
        americanBond.setPricingEngine(boost::shared_ptr<PricingEngine>(
                      new BinomialConvertibleEngine<Joshi4>(stochasticProcess,
                                                            timeSteps)));
        std::cout << std::setw(widths[0]) << std::left << method
                  << std::fixed
                  << std::setw(widths[1]) << std::left << europeanBond.NPV()
                  << std::setw(widths[2]) << std::left << americanBond.NPV()
                  << std::endl;

        std::cout << dblrule << std::endl;

        Real seconds = timer.elapsed();
        Integer hours = int(seconds/3600);
        seconds -= hours * 3600;
        Integer minutes = int(seconds/60);
        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) {
        std::cerr << e.what() << std::endl;
        return 1;
    } catch (...) {
        std::cerr << "unknown error" << std::endl;
        return 1;
    }

}
예제 #16
0
void QtSwap::qtswap() {

    try {

        boost::timer timer;
        std::cout << std::endl;

        /*********************
         ***  MARKET DATA  ***
         *********************/

        Calendar calendar = TARGET();
        Date settlementDate(22, September, 2004);
        // must be a business day
        settlementDate = calendar.adjust(settlementDate);

        Integer fixingDays = 2;
        Date todaysDate = calendar.advance(settlementDate, -fixingDays, Days);
        // nothing to do with Date::todaysDate
        Settings::instance().evaluationDate() = todaysDate;


        todaysDate = Settings::instance().evaluationDate();
        std::cout << "Today: " << todaysDate.weekday()
                  << ", " << todaysDate << std::endl;

        std::cout << "Settlement date: " << settlementDate.weekday()
                  << ", " << settlementDate << std::endl;

        // deposits
        Rate d1wQuote=0.0382;
        Rate d1mQuote=0.0372;
        Rate d3mQuote=0.0363;
        Rate d6mQuote=0.0353;
        Rate d9mQuote=0.0348;
        Rate d1yQuote=0.0345;
        // FRAs
        Rate fra3x6Quote=0.037125;
        Rate fra6x9Quote=0.037125;
        Rate fra6x12Quote=0.037125;
        // futures
        Real fut1Quote=96.2875;
        Real fut2Quote=96.7875;
        Real fut3Quote=96.9875;
        Real fut4Quote=96.6875;
        Real fut5Quote=96.4875;
        Real fut6Quote=96.3875;
        Real fut7Quote=96.2875;
        Real fut8Quote=96.0875;
        // swaps
        Rate s2yQuote=0.037125;
        Rate s3yQuote=0.0398;
        Rate s5yQuote=0.0443;
        Rate s10yQuote=0.05165;
        Rate s15yQuote=0.055175;


        /********************
         ***    QUOTES    ***
         ********************/

        // SimpleQuote stores a value which can be manually changed;
        // other Quote subclasses could read the value from a database
        // or some kind of data feed.

        // deposits
        boost::shared_ptr<Quote> d1wRate(new SimpleQuote(d1wQuote));
        boost::shared_ptr<Quote> d1mRate(new SimpleQuote(d1mQuote));
        boost::shared_ptr<Quote> d3mRate(new SimpleQuote(d3mQuote));
        boost::shared_ptr<Quote> d6mRate(new SimpleQuote(d6mQuote));
        boost::shared_ptr<Quote> d9mRate(new SimpleQuote(d9mQuote));
        boost::shared_ptr<Quote> d1yRate(new SimpleQuote(d1yQuote));
        // FRAs
        boost::shared_ptr<Quote> fra3x6Rate(new SimpleQuote(fra3x6Quote));
        boost::shared_ptr<Quote> fra6x9Rate(new SimpleQuote(fra6x9Quote));
        boost::shared_ptr<Quote> fra6x12Rate(new SimpleQuote(fra6x12Quote));
        // futures
        boost::shared_ptr<Quote> fut1Price(new SimpleQuote(fut1Quote));
        boost::shared_ptr<Quote> fut2Price(new SimpleQuote(fut2Quote));
        boost::shared_ptr<Quote> fut3Price(new SimpleQuote(fut3Quote));
        boost::shared_ptr<Quote> fut4Price(new SimpleQuote(fut4Quote));
        boost::shared_ptr<Quote> fut5Price(new SimpleQuote(fut5Quote));
        boost::shared_ptr<Quote> fut6Price(new SimpleQuote(fut6Quote));
        boost::shared_ptr<Quote> fut7Price(new SimpleQuote(fut7Quote));
        boost::shared_ptr<Quote> fut8Price(new SimpleQuote(fut8Quote));
        // swaps
        boost::shared_ptr<Quote> s2yRate(new SimpleQuote(s2yQuote));
        boost::shared_ptr<Quote> s3yRate(new SimpleQuote(s3yQuote));
        boost::shared_ptr<Quote> s5yRate(new SimpleQuote(s5yQuote));
        boost::shared_ptr<Quote> s10yRate(new SimpleQuote(s10yQuote));
        boost::shared_ptr<Quote> s15yRate(new SimpleQuote(s15yQuote));


        /*********************
         ***  RATE HELPERS ***
         *********************/

        // RateHelpers are built from the above quotes together with
        // other instrument dependant infos.  Quotes are passed in
        // relinkable handles which could be relinked to some other
        // data source later.

        // deposits
        DayCounter depositDayCounter = Actual360();

        boost::shared_ptr<RateHelper> d1w(new DepositRateHelper(
                                              Handle<Quote>(d1wRate),
                                              1*Weeks, fixingDays,
                                              calendar, ModifiedFollowing,
                                              true, depositDayCounter));
        boost::shared_ptr<RateHelper> d1m(new DepositRateHelper(
                                              Handle<Quote>(d1mRate),
                                              1*Months, fixingDays,
                                              calendar, ModifiedFollowing,
                                              true, depositDayCounter));
        boost::shared_ptr<RateHelper> d3m(new DepositRateHelper(
                                              Handle<Quote>(d3mRate),
                                              3*Months, fixingDays,
                                              calendar, ModifiedFollowing,
                                              true, depositDayCounter));
        boost::shared_ptr<RateHelper> d6m(new DepositRateHelper(
                                              Handle<Quote>(d6mRate),
                                              6*Months, fixingDays,
                                              calendar, ModifiedFollowing,
                                              true, depositDayCounter));
        boost::shared_ptr<RateHelper> d9m(new DepositRateHelper(
                                              Handle<Quote>(d9mRate),
                                              9*Months, fixingDays,
                                              calendar, ModifiedFollowing,
                                              true, depositDayCounter));
        boost::shared_ptr<RateHelper> d1y(new DepositRateHelper(
                                              Handle<Quote>(d1yRate),
                                              1*Years, fixingDays,
                                              calendar, ModifiedFollowing,
                                              true, depositDayCounter));


        // setup FRAs
        boost::shared_ptr<RateHelper> fra3x6(new FraRateHelper(
                Handle<Quote>(fra3x6Rate),
                3, 6, fixingDays, calendar, ModifiedFollowing,
                true, depositDayCounter));
        boost::shared_ptr<RateHelper> fra6x9(new FraRateHelper(
                Handle<Quote>(fra6x9Rate),
                6, 9, fixingDays, calendar, ModifiedFollowing,
                true, depositDayCounter));
        boost::shared_ptr<RateHelper> fra6x12(new FraRateHelper(
                Handle<Quote>(fra6x12Rate),
                6, 12, fixingDays, calendar, ModifiedFollowing,
                true, depositDayCounter));


        // setup futures
        // Rate convexityAdjustment = 0.0;
        Integer futMonths = 3;
        Date imm = IMM::nextDate(settlementDate);
        boost::shared_ptr<RateHelper> fut1(new FuturesRateHelper(
                                               Handle<Quote>(fut1Price),
                                               imm,
                                               futMonths, calendar, ModifiedFollowing,
                                               true, depositDayCounter));
        imm = IMM::nextDate(imm+1);
        boost::shared_ptr<RateHelper> fut2(new FuturesRateHelper(
                                               Handle<Quote>(fut2Price),
                                               imm,
                                               futMonths, calendar, ModifiedFollowing,
                                               true, depositDayCounter));
        imm = IMM::nextDate(imm+1);
        boost::shared_ptr<RateHelper> fut3(new FuturesRateHelper(
                                               Handle<Quote>(fut3Price),
                                               imm,
                                               futMonths, calendar, ModifiedFollowing,
                                               true, depositDayCounter));
        imm = IMM::nextDate(imm+1);
        boost::shared_ptr<RateHelper> fut4(new FuturesRateHelper(
                                               Handle<Quote>(fut4Price),
                                               imm,
                                               futMonths, calendar, ModifiedFollowing,
                                               true, depositDayCounter));
        imm = IMM::nextDate(imm+1);
        boost::shared_ptr<RateHelper> fut5(new FuturesRateHelper(
                                               Handle<Quote>(fut5Price),
                                               imm,
                                               futMonths, calendar, ModifiedFollowing,
                                               true, depositDayCounter));
        imm = IMM::nextDate(imm+1);
        boost::shared_ptr<RateHelper> fut6(new FuturesRateHelper(
                                               Handle<Quote>(fut6Price),
                                               imm,
                                               futMonths, calendar, ModifiedFollowing,
                                               true, depositDayCounter));
        imm = IMM::nextDate(imm+1);
        boost::shared_ptr<RateHelper> fut7(new FuturesRateHelper(
                                               Handle<Quote>(fut7Price),
                                               imm,
                                               futMonths, calendar, ModifiedFollowing,
                                               true, depositDayCounter));
        imm = IMM::nextDate(imm+1);
        boost::shared_ptr<RateHelper> fut8(new FuturesRateHelper(
                                               Handle<Quote>(fut8Price),
                                               imm,
                                               futMonths, calendar, ModifiedFollowing,
                                               true, depositDayCounter));


        // setup swaps
        Frequency swFixedLegFrequency = Annual;
        BusinessDayConvention swFixedLegConvention = Unadjusted;
        DayCounter swFixedLegDayCounter = Thirty360(Thirty360::European);
        boost::shared_ptr<IborIndex> swFloatingLegIndex(new Euribor6M);

        boost::shared_ptr<RateHelper> s2y(new SwapRateHelper(
                                              Handle<Quote>(s2yRate), 2*Years,
                                              calendar, swFixedLegFrequency,
                                              swFixedLegConvention, swFixedLegDayCounter,
                                              swFloatingLegIndex));
        boost::shared_ptr<RateHelper> s3y(new SwapRateHelper(
                                              Handle<Quote>(s3yRate), 3*Years,
                                              calendar, swFixedLegFrequency,
                                              swFixedLegConvention, swFixedLegDayCounter,
                                              swFloatingLegIndex));
        boost::shared_ptr<RateHelper> s5y(new SwapRateHelper(
                                              Handle<Quote>(s5yRate), 5*Years,
                                              calendar, swFixedLegFrequency,
                                              swFixedLegConvention, swFixedLegDayCounter,
                                              swFloatingLegIndex));
        boost::shared_ptr<RateHelper> s10y(new SwapRateHelper(
                                               Handle<Quote>(s10yRate), 10*Years,
                                               calendar, swFixedLegFrequency,
                                               swFixedLegConvention, swFixedLegDayCounter,
                                               swFloatingLegIndex));
        boost::shared_ptr<RateHelper> s15y(new SwapRateHelper(
                                               Handle<Quote>(s15yRate), 15*Years,
                                               calendar, swFixedLegFrequency,
                                               swFixedLegConvention, swFixedLegDayCounter,
                                               swFloatingLegIndex));


        /*********************
         **  CURVE BUILDING **
         *********************/

        // Any DayCounter would be fine.
        // ActualActual::ISDA ensures that 30 years is 30.0
        DayCounter termStructureDayCounter =
            ActualActual(ActualActual::ISDA);


        double tolerance = 1.0e-15;

        // A depo-swap curve
        std::vector<boost::shared_ptr<RateHelper> > depoSwapInstruments;
        depoSwapInstruments.push_back(d1w);
        depoSwapInstruments.push_back(d1m);
        depoSwapInstruments.push_back(d3m);
        depoSwapInstruments.push_back(d6m);
        depoSwapInstruments.push_back(d9m);
        depoSwapInstruments.push_back(d1y);
        depoSwapInstruments.push_back(s2y);
        depoSwapInstruments.push_back(s3y);
        depoSwapInstruments.push_back(s5y);
        depoSwapInstruments.push_back(s10y);
        depoSwapInstruments.push_back(s15y);
        boost::shared_ptr<YieldTermStructure> depoSwapTermStructure(
            new PiecewiseYieldCurve<Discount,LogLinear>(
                settlementDate, depoSwapInstruments,
                termStructureDayCounter,
                tolerance));


        // A depo-futures-swap curve
        std::vector<boost::shared_ptr<RateHelper> > depoFutSwapInstruments;
        depoFutSwapInstruments.push_back(d1w);
        depoFutSwapInstruments.push_back(d1m);
        depoFutSwapInstruments.push_back(fut1);
        depoFutSwapInstruments.push_back(fut2);
        depoFutSwapInstruments.push_back(fut3);
        depoFutSwapInstruments.push_back(fut4);
        depoFutSwapInstruments.push_back(fut5);
        depoFutSwapInstruments.push_back(fut6);
        depoFutSwapInstruments.push_back(fut7);
        depoFutSwapInstruments.push_back(fut8);
        depoFutSwapInstruments.push_back(s3y);
        depoFutSwapInstruments.push_back(s5y);
        depoFutSwapInstruments.push_back(s10y);
        depoFutSwapInstruments.push_back(s15y);
        boost::shared_ptr<YieldTermStructure> depoFutSwapTermStructure(
            new PiecewiseYieldCurve<Discount,LogLinear>(
                settlementDate, depoFutSwapInstruments,
                termStructureDayCounter,
                tolerance));


        // A depo-FRA-swap curve
        std::vector<boost::shared_ptr<RateHelper> > depoFRASwapInstruments;
        depoFRASwapInstruments.push_back(d1w);
        depoFRASwapInstruments.push_back(d1m);
        depoFRASwapInstruments.push_back(d3m);
        depoFRASwapInstruments.push_back(fra3x6);
        depoFRASwapInstruments.push_back(fra6x9);
        depoFRASwapInstruments.push_back(fra6x12);
        depoFRASwapInstruments.push_back(s2y);
        depoFRASwapInstruments.push_back(s3y);
        depoFRASwapInstruments.push_back(s5y);
        depoFRASwapInstruments.push_back(s10y);
        depoFRASwapInstruments.push_back(s15y);
        boost::shared_ptr<YieldTermStructure> depoFRASwapTermStructure(
            new PiecewiseYieldCurve<Discount,LogLinear>(
                settlementDate, depoFRASwapInstruments,
                termStructureDayCounter,
                tolerance));


        // Term structures that will be used for pricing:
        // the one used for discounting cash flows
        RelinkableHandle<YieldTermStructure> discountingTermStructure;
        // the one used for forward rate forecasting
        RelinkableHandle<YieldTermStructure> forecastingTermStructure;


        /*********************
        * SWAPS TO BE PRICED *
        **********************/

        // constant nominal 1,000,000 Euro
        Real nominal = 1000000.0;
        // fixed leg
        Frequency fixedLegFrequency = Annual;
        BusinessDayConvention fixedLegConvention = Unadjusted;
        BusinessDayConvention floatingLegConvention = ModifiedFollowing;
        DayCounter fixedLegDayCounter = Thirty360(Thirty360::European);
        Rate fixedRate = 0.04;
        DayCounter floatingLegDayCounter = Actual360();

        // floating leg
        Frequency floatingLegFrequency = Semiannual;
        boost::shared_ptr<IborIndex> euriborIndex(
            new Euribor6M(forecastingTermStructure));
        Spread spread = 0.0;

        Integer lenghtInYears = 5;
        VanillaSwap::Type swapType = VanillaSwap::Payer;

        Date maturity = settlementDate + lenghtInYears*Years;
        Schedule fixedSchedule(settlementDate, maturity,
                               Period(fixedLegFrequency),
                               calendar, fixedLegConvention,
                               fixedLegConvention,
                               DateGeneration::Forward, false);
        Schedule floatSchedule(settlementDate, maturity,
                               Period(floatingLegFrequency),
                               calendar, floatingLegConvention,
                               floatingLegConvention,
                               DateGeneration::Forward, false);

        VanillaSwap spot5YearSwap(swapType, nominal,
                                  fixedSchedule, fixedRate, fixedLegDayCounter,
                                  floatSchedule, euriborIndex, spread,
                                  floatingLegDayCounter);

        Date fwdStart = calendar.advance(settlementDate, 1, Years);
        Date fwdMaturity = fwdStart + lenghtInYears*Years;
        Schedule fwdFixedSchedule(fwdStart, fwdMaturity,
                                  Period(fixedLegFrequency),
                                  calendar, fixedLegConvention,
                                  fixedLegConvention,
                                  DateGeneration::Forward, false);
        Schedule fwdFloatSchedule(fwdStart, fwdMaturity,
                                  Period(floatingLegFrequency),
                                  calendar, floatingLegConvention,
                                  floatingLegConvention,
                                  DateGeneration::Forward, false);
        VanillaSwap oneYearForward5YearSwap(swapType, nominal,
                                            fwdFixedSchedule, fixedRate, fixedLegDayCounter,
                                            fwdFloatSchedule, euriborIndex, spread,
                                            floatingLegDayCounter);


        /***************
        * SWAP PRICING *
        ****************/

        // utilities for reporting
        std::vector<std::string> headers(4);
        headers[0] = "term structure";
        headers[1] = "net present value";
        headers[2] = "fair spread";
        headers[3] = "fair fixed rate";
        std::string separator = " | ";
        Size width = headers[0].size() + separator.size()
                     + headers[1].size() + separator.size()
                     + headers[2].size() + separator.size()
                     + headers[3].size() + separator.size() - 1;
        std::string rule(width, '-'), dblrule(width, '=');
        std::string tab(8, ' ');

        // calculations
        std::cout << dblrule << std::endl;
        std::cout <<  "5-year market swap-rate = "
                  << std::setprecision(2) << io::rate(s5yRate->value())
                  << std::endl;
        std::cout << dblrule << std::endl;

        std::cout << tab << "5-years swap paying "
                  << io::rate(fixedRate) << std::endl;
        std::cout << headers[0] << separator
                  << headers[1] << separator
                  << headers[2] << separator
                  << headers[3] << separator << std::endl;
        std::cout << rule << std::endl;

        Real NPV;
        Rate fairRate;
        Spread fairSpread;

        boost::shared_ptr<PricingEngine> swapEngine(
            new DiscountingSwapEngine(discountingTermStructure));

        spot5YearSwap.setPricingEngine(swapEngine);
        oneYearForward5YearSwap.setPricingEngine(swapEngine);

        // Of course, you're not forced to really use different curves
        forecastingTermStructure.linkTo(depoSwapTermStructure);
        discountingTermStructure.linkTo(depoSwapTermStructure);

        NPV = spot5YearSwap.NPV();
        fairSpread = spot5YearSwap.fairSpread();
        fairRate = spot5YearSwap.fairRate();

        std::cout << std::setw(headers[0].size())
                  << "depo-swap" << separator;
        std::cout << std::setw(headers[1].size())
                  << std::fixed << std::setprecision(2) << NPV << separator;
        std::cout << std::setw(headers[2].size())
                  << io::rate(fairSpread) << separator;
        std::cout << std::setw(headers[3].size())
                  << io::rate(fairRate) << separator;
        std::cout << std::endl;


        // let's check that the 5 years swap has been correctly re-priced
        QL_REQUIRE(std::fabs(fairRate-s5yQuote)<1e-8,
                   "5-years swap mispriced by "
                   << io::rate(std::fabs(fairRate-s5yQuote)));


        forecastingTermStructure.linkTo(depoFutSwapTermStructure);
        discountingTermStructure.linkTo(depoFutSwapTermStructure);

        NPV = spot5YearSwap.NPV();
        fairSpread = spot5YearSwap.fairSpread();
        fairRate = spot5YearSwap.fairRate();

        std::cout << std::setw(headers[0].size())
                  << "depo-fut-swap" << separator;
        std::cout << std::setw(headers[1].size())
                  << std::fixed << std::setprecision(2) << NPV << separator;
        std::cout << std::setw(headers[2].size())
                  << io::rate(fairSpread) << separator;
        std::cout << std::setw(headers[3].size())
                  << io::rate(fairRate) << separator;
        std::cout << std::endl;

        QL_REQUIRE(std::fabs(fairRate-s5yQuote)<1e-8,
                   "5-years swap mispriced!");


        forecastingTermStructure.linkTo(depoFRASwapTermStructure);
        discountingTermStructure.linkTo(depoFRASwapTermStructure);

        NPV = spot5YearSwap.NPV();
        fairSpread = spot5YearSwap.fairSpread();
        fairRate = spot5YearSwap.fairRate();

        std::cout << std::setw(headers[0].size())
                  << "depo-FRA-swap" << separator;
        std::cout << std::setw(headers[1].size())
                  << std::fixed << std::setprecision(2) << NPV << separator;
        std::cout << std::setw(headers[2].size())
                  << io::rate(fairSpread) << separator;
        std::cout << std::setw(headers[3].size())
                  << io::rate(fairRate) << separator;
        std::cout << std::endl;

        QL_REQUIRE(std::fabs(fairRate-s5yQuote)<1e-8,
                   "5-years swap mispriced!");


        std::cout << rule << std::endl;

        // now let's price the 1Y forward 5Y swap

        std::cout << tab << "5-years, 1-year forward swap paying "
                  << io::rate(fixedRate) << std::endl;
        std::cout << headers[0] << separator
                  << headers[1] << separator
                  << headers[2] << separator
                  << headers[3] << separator << std::endl;
        std::cout << rule << std::endl;


        forecastingTermStructure.linkTo(depoSwapTermStructure);
        discountingTermStructure.linkTo(depoSwapTermStructure);

        NPV = oneYearForward5YearSwap.NPV();
        fairSpread = oneYearForward5YearSwap.fairSpread();
        fairRate = oneYearForward5YearSwap.fairRate();

        std::cout << std::setw(headers[0].size())
                  << "depo-swap" << separator;
        std::cout << std::setw(headers[1].size())
                  << std::fixed << std::setprecision(2) << NPV << separator;
        std::cout << std::setw(headers[2].size())
                  << io::rate(fairSpread) << separator;
        std::cout << std::setw(headers[3].size())
                  << io::rate(fairRate) << separator;
        std::cout << std::endl;


        forecastingTermStructure.linkTo(depoFutSwapTermStructure);
        discountingTermStructure.linkTo(depoFutSwapTermStructure);

        NPV = oneYearForward5YearSwap.NPV();
        fairSpread = oneYearForward5YearSwap.fairSpread();
        fairRate = oneYearForward5YearSwap.fairRate();

        std::cout << std::setw(headers[0].size())
                  << "depo-fut-swap" << separator;
        std::cout << std::setw(headers[1].size())
                  << std::fixed << std::setprecision(2) << NPV << separator;
        std::cout << std::setw(headers[2].size())
                  << io::rate(fairSpread) << separator;
        std::cout << std::setw(headers[3].size())
                  << io::rate(fairRate) << separator;
        std::cout << std::endl;


        forecastingTermStructure.linkTo(depoFRASwapTermStructure);
        discountingTermStructure.linkTo(depoFRASwapTermStructure);

        NPV = oneYearForward5YearSwap.NPV();
        fairSpread = oneYearForward5YearSwap.fairSpread();
        fairRate = oneYearForward5YearSwap.fairRate();

        std::cout << std::setw(headers[0].size())
                  << "depo-FRA-swap" << separator;
        std::cout << std::setw(headers[1].size())
                  << std::fixed << std::setprecision(2) << NPV << separator;
        std::cout << std::setw(headers[2].size())
                  << io::rate(fairSpread) << separator;
        std::cout << std::setw(headers[3].size())
                  << io::rate(fairRate) << separator;
        std::cout << std::endl;


        // now let's say that the 5-years swap rate goes up to 4.60%.
        // A smarter market element--say, connected to a data source-- would
        // notice the change itself. Since we're using SimpleQuotes,
        // we'll have to change the value manually--which forces us to
        // downcast the handle and use the SimpleQuote
        // interface. In any case, the point here is that a change in the
        // value contained in the Quote triggers a new bootstrapping
        // of the curve and a repricing of the swap.

        boost::shared_ptr<SimpleQuote> fiveYearsRate =
            boost::dynamic_pointer_cast<SimpleQuote>(s5yRate);
        fiveYearsRate->setValue(0.0460);

        std::cout << dblrule << std::endl;
        std::cout <<  "5-year market swap-rate = "
                  << io::rate(s5yRate->value()) << std::endl;
        std::cout << dblrule << std::endl;

        std::cout << tab << "5-years swap paying "
                  << io::rate(fixedRate) << std::endl;
        std::cout << headers[0] << separator
                  << headers[1] << separator
                  << headers[2] << separator
                  << headers[3] << separator << std::endl;
        std::cout << rule << std::endl;

        // now get the updated results
        forecastingTermStructure.linkTo(depoSwapTermStructure);
        discountingTermStructure.linkTo(depoSwapTermStructure);

        NPV = spot5YearSwap.NPV();
        fairSpread = spot5YearSwap.fairSpread();
        fairRate = spot5YearSwap.fairRate();

        std::cout << std::setw(headers[0].size())
                  << "depo-swap" << separator;
        std::cout << std::setw(headers[1].size())
                  << std::fixed << std::setprecision(2) << NPV << separator;
        std::cout << std::setw(headers[2].size())
                  << io::rate(fairSpread) << separator;
        std::cout << std::setw(headers[3].size())
                  << io::rate(fairRate) << separator;
        std::cout << std::endl;

        QL_REQUIRE(std::fabs(fairRate-s5yRate->value())<1e-8,
                   "5-years swap mispriced!");


        forecastingTermStructure.linkTo(depoFutSwapTermStructure);
        discountingTermStructure.linkTo(depoFutSwapTermStructure);

        NPV = spot5YearSwap.NPV();
        fairSpread = spot5YearSwap.fairSpread();
        fairRate = spot5YearSwap.fairRate();

        std::cout << std::setw(headers[0].size())
                  << "depo-fut-swap" << separator;
        std::cout << std::setw(headers[1].size())
                  << std::fixed << std::setprecision(2) << NPV << separator;
        std::cout << std::setw(headers[2].size())
                  << io::rate(fairSpread) << separator;
        std::cout << std::setw(headers[3].size())
                  << io::rate(fairRate) << separator;
        std::cout << std::endl;

        QL_REQUIRE(std::fabs(fairRate-s5yRate->value())<1e-8,
                   "5-years swap mispriced!");


        forecastingTermStructure.linkTo(depoFRASwapTermStructure);
        discountingTermStructure.linkTo(depoFRASwapTermStructure);

        NPV = spot5YearSwap.NPV();
        fairSpread = spot5YearSwap.fairSpread();
        fairRate = spot5YearSwap.fairRate();

        std::cout << std::setw(headers[0].size())
                  << "depo-FRA-swap" << separator;
        std::cout << std::setw(headers[1].size())
                  << std::fixed << std::setprecision(2) << NPV << separator;
        std::cout << std::setw(headers[2].size())
                  << io::rate(fairSpread) << separator;
        std::cout << std::setw(headers[3].size())
                  << io::rate(fairRate) << separator;
        std::cout << std::endl;

        QL_REQUIRE(std::fabs(fairRate-s5yRate->value())<1e-8,
                   "5-years swap mispriced!");

        std::cout << rule << std::endl;

        // the 1Y forward 5Y swap changes as well

        std::cout << tab << "5-years, 1-year forward swap paying "
                  << io::rate(fixedRate) << std::endl;
        std::cout << headers[0] << separator
                  << headers[1] << separator
                  << headers[2] << separator
                  << headers[3] << separator << std::endl;
        std::cout << rule << std::endl;


        forecastingTermStructure.linkTo(depoSwapTermStructure);
        discountingTermStructure.linkTo(depoSwapTermStructure);

        NPV = oneYearForward5YearSwap.NPV();
        fairSpread = oneYearForward5YearSwap.fairSpread();
        fairRate = oneYearForward5YearSwap.fairRate();

        std::cout << std::setw(headers[0].size())
                  << "depo-swap" << separator;
        std::cout << std::setw(headers[1].size())
                  << std::fixed << std::setprecision(2) << NPV << separator;
        std::cout << std::setw(headers[2].size())
                  << io::rate(fairSpread) << separator;
        std::cout << std::setw(headers[3].size())
                  << io::rate(fairRate) << separator;
        std::cout << std::endl;


        forecastingTermStructure.linkTo(depoFutSwapTermStructure);
        discountingTermStructure.linkTo(depoFutSwapTermStructure);

        NPV = oneYearForward5YearSwap.NPV();
        fairSpread = oneYearForward5YearSwap.fairSpread();
        fairRate = oneYearForward5YearSwap.fairRate();

        std::cout << std::setw(headers[0].size())
                  << "depo-fut-swap" << separator;
        std::cout << std::setw(headers[1].size())
                  << std::fixed << std::setprecision(2) << NPV << separator;
        std::cout << std::setw(headers[2].size())
                  << io::rate(fairSpread) << separator;
        std::cout << std::setw(headers[3].size())
                  << io::rate(fairRate) << separator;
        std::cout << std::endl;


        forecastingTermStructure.linkTo(depoFRASwapTermStructure);
        discountingTermStructure.linkTo(depoFRASwapTermStructure);

        NPV = oneYearForward5YearSwap.NPV();
        fairSpread = oneYearForward5YearSwap.fairSpread();
        fairRate = oneYearForward5YearSwap.fairRate();

        std::cout << std::setw(headers[0].size())
                  << "depo-FRA-swap" << separator;
        std::cout << std::setw(headers[1].size())
                  << std::fixed << std::setprecision(2) << NPV << separator;
        std::cout << std::setw(headers[2].size())
                  << io::rate(fairSpread) << separator;
        std::cout << std::setw(headers[3].size())
                  << io::rate(fairRate) << separator;
        std::cout << std::endl;

        Real seconds = timer.elapsed();
        Integer hours = int(seconds/3600);
        seconds -= hours * 3600;
        Integer minutes = int(seconds/60);
        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;

    } catch (std::exception& e) {
        std::cerr << e.what() << std::endl;
    } catch (...) {
        std::cerr << "unknown error" << std::endl;
    }
}
예제 #17
0
void InflationTest::testZeroTermStructure() {
    BOOST_MESSAGE("Testing zero inflation term structure...");

    SavedSettings backup;

    // try the Zero UK
    Calendar calendar = UnitedKingdom();
    BusinessDayConvention bdc = ModifiedFollowing;
    Date evaluationDate(13, August, 2007);
    evaluationDate = calendar.adjust(evaluationDate);
    Settings::instance().evaluationDate() = evaluationDate;

    // fixing data
    Date from(1, January, 2005);
    Date to(13, August, 2007);
    Schedule rpiSchedule = MakeSchedule().from(from).to(to)
    .withTenor(1*Months)
    .withCalendar(UnitedKingdom())
    .withConvention(ModifiedFollowing);

    Real fixData[] = { 189.9, 189.9, 189.6, 190.5, 191.6, 192.0,
        192.2, 192.2, 192.6, 193.1, 193.3, 193.6,
        194.1, 193.4, 194.2, 195.0, 196.5, 197.7,
        198.5, 198.5, 199.2, 200.1, 200.4, 201.1,
        202.7, 201.6, 203.1, 204.4, 205.4, 206.2,
        207.3, 206.1,  -999.0 };

    RelinkableHandle<ZeroInflationTermStructure> hz;
    bool interp = false;
    boost::shared_ptr<UKRPI> iiUKRPI(new UKRPI(interp, hz));
    for (Size i=0; i<rpiSchedule.size();i++) {
        iiUKRPI->addFixing(rpiSchedule[i], fixData[i]);
    }

    boost::shared_ptr<ZeroInflationIndex> ii = boost::dynamic_pointer_cast<ZeroInflationIndex>(iiUKRPI);
    boost::shared_ptr<YieldTermStructure> nominalTS = nominalTermStructure();

    // now build the zero inflation curve
    Datum zcData[] = {
        { Date(13, August, 2008), 2.93 },
        { Date(13, August, 2009), 2.95 },
        { Date(13, August, 2010), 2.965 },
        { Date(15, August, 2011), 2.98 },
        { Date(13, August, 2012), 3.0 },
        { Date(13, August, 2014), 3.06 },
        { Date(13, August, 2017), 3.175 },
        { Date(13, August, 2019), 3.243 },
        { Date(15, August, 2022), 3.293 },
        { Date(14, August, 2027), 3.338 },
        { Date(13, August, 2032), 3.348 },
        { Date(15, August, 2037), 3.348 },
        { Date(13, August, 2047), 3.308 },
        { Date(13, August, 2057), 3.228 }
    };

    Period observationLag = Period(2,Months);
    DayCounter dc = Thirty360();
    Frequency frequency = Monthly;
    std::vector<boost::shared_ptr<BootstrapHelper<ZeroInflationTermStructure> > > helpers =
    makeHelpers<ZeroInflationTermStructure,ZeroCouponInflationSwapHelper,
                ZeroInflationIndex>(zcData, LENGTH(zcData), ii,
                                    observationLag,
                                    calendar, bdc, dc);

    Rate baseZeroRate = zcData[0].rate/100.0;
    boost::shared_ptr<PiecewiseZeroInflationCurve<Linear> > pZITS(
                        new PiecewiseZeroInflationCurve<Linear>(
                        evaluationDate, calendar, dc, observationLag,
                        frequency, ii->interpolated(), baseZeroRate,
                        Handle<YieldTermStructure>(nominalTS), helpers));
    pZITS->recalculate();

    // first check that the zero rates on the curve match the data
    // and that the helpers give the correct impled rates
    const Real eps = 0.00000001;
    bool forceLinearInterpolation = false;
    for (Size i=0; i<LENGTH(zcData); i++) {
        BOOST_REQUIRE_MESSAGE(std::fabs(zcData[i].rate/100.0
            - pZITS->zeroRate(zcData[i].date, observationLag, forceLinearInterpolation)) < eps,
            "ZITS zeroRate != instrument "
            << pZITS->zeroRate(zcData[i].date, observationLag, forceLinearInterpolation)
            << " vs " << zcData[i].rate/100.0
            << " interpolation: " << ii->interpolated()
            << " forceLinearInterpolation " << forceLinearInterpolation);
        BOOST_REQUIRE_MESSAGE(std::fabs(helpers[i]->impliedQuote()
            - zcData[i].rate/100.0) < eps,
            "ZITS implied quote != instrument "
            << helpers[i]->impliedQuote()
            << " vs " << zcData[i].rate/100.0);
    }


    // now test the forecasting capability of the index.
    hz.linkTo(pZITS);
    from = hz->baseDate();
    to = hz->maxDate()-1*Months; // a bit of margin for adjustments
    Schedule testIndex = MakeSchedule().from(from).to(to)
                            .withTenor(1*Months)
                            .withCalendar(UnitedKingdom())
                            .withConvention(ModifiedFollowing);


    // we are testing UKRPI which is not interpolated
    Date bd = hz->baseDate();
    Real bf = ii->fixing(bd);
    for (Size i=0; i<testIndex.size();i++) {
        Date d = testIndex[i];
        Real z = hz->zeroRate(d, Period(0,Days));
        Real t = hz->dayCounter().yearFraction(bd, d);
        if(!ii->interpolated()) // because fixing constant over period
            t = hz->dayCounter().yearFraction(bd,
                inflationPeriod(d, ii->frequency()).first);
        Real calc = bf * pow( 1+z, t);
        if (t<=0)
            calc = ii->fixing(d,false); // still historical
        if (std::fabs(calc - ii->fixing(d,true))/10000.0 > eps)
            BOOST_ERROR("ZC index does not forecast correctly for date " << d
                        << " from base date " << bd
                        << " with fixing " << bf
                        << ", correct:  " << calc
                        << ", fix: " << ii->fixing(d,true)
                        << ", t " << t);
    }


    //===========================================================================================
    // Test zero-inflation-indexed (i.e. cpi ratio) cashflow
    // just ordinary indexed cashflow with a zero inflation index

    Date baseDate(1, January, 2006);
    Date fixDate(1, August, 2014);
    Date payDate=UnitedKingdom().adjust(fixDate+Period(3,Months),ModifiedFollowing);
    boost::shared_ptr<Index> ind = boost::dynamic_pointer_cast<Index>(ii);
    BOOST_REQUIRE_MESSAGE(ind,"dynamic_pointer_cast to Index from InflationIndex failed");

    Real notional = 1000000.0;//1m
    IndexedCashFlow iicf(notional,ind,baseDate,fixDate,payDate);
    Real correctIndexed = ii->fixing(iicf.fixingDate())/ii->fixing(iicf.baseDate());
    Real calculatedIndexed = iicf.amount()/iicf.notional();
    BOOST_REQUIRE_MESSAGE(std::fabs(correctIndexed - calculatedIndexed) < eps,
               "IndexedCashFlow indexing wrong: " << calculatedIndexed << " vs correct = "
               << correctIndexed);


    //===========================================================================================
    // Test zero coupon swap

    // first make one ...

    boost::shared_ptr<ZeroInflationIndex> zii = boost::dynamic_pointer_cast<ZeroInflationIndex>(ii);
    BOOST_REQUIRE_MESSAGE(zii,"dynamic_pointer_cast to ZeroInflationIndex from UKRPI failed");
    ZeroCouponInflationSwap nzcis(ZeroCouponInflationSwap::Payer,
                                     1000000.0,
                                     evaluationDate,
                                     zcData[6].date,    // end date = maturity
                                     calendar, bdc, dc, zcData[6].rate/100.0, // fixed rate
                                     zii, observationLag);

    // N.B. no coupon pricer because it is not a coupon, effect of inflation curve via
    //      inflation curve attached to the inflation index.
    Handle<YieldTermStructure> hTS(nominalTS);
    boost::shared_ptr<PricingEngine> sppe(new DiscountingSwapEngine(hTS));
    nzcis.setPricingEngine(sppe);

    // ... and price it, should be zero
    BOOST_CHECK_MESSAGE(fabs(nzcis.NPV())<0.00001,"ZCIS does not reprice to zero "
                        << nzcis.NPV()
                        << evaluationDate << " to " << zcData[6].date << " becoming " << nzcis.maturityDate()
                        << " rate " << zcData[6].rate
                        << " fixed leg " << nzcis.legNPV(0)
                        << " indexed-predicted inflated leg " << nzcis.legNPV(1)
                        << " discount " << nominalTS->discount(nzcis.maturityDate())
                        );


    //===========================================================================================
    // Test multiplicative seasonality in price
    //

    //Seasonality factors NOT normalized
    //and UKRPI is not interpolated
    Date trueBaseDate = inflationPeriod(hz->baseDate(), ii->frequency()).second;
    Date seasonallityBaseDate(31,January,trueBaseDate.year());
    std::vector<Rate> seasonalityFactors(12);
    seasonalityFactors[0] = 1.003245;
    seasonalityFactors[1] = 1.000000;
    seasonalityFactors[2] = 0.999715;
    seasonalityFactors[3] = 1.000495;
    seasonalityFactors[4] = 1.000929;
    seasonalityFactors[5] = 0.998687;
    seasonalityFactors[6] = 0.995949;
    seasonalityFactors[7] = 0.994682;
    seasonalityFactors[8] = 0.995949;
    seasonalityFactors[9] = 1.000519;
    seasonalityFactors[10] = 1.003705;
    seasonalityFactors[11] = 1.004186;

    //Creating two different seasonality objects
    //
    boost::shared_ptr<MultiplicativePriceSeasonality> seasonality_1(new MultiplicativePriceSeasonality());
    std::vector<Rate> seasonalityFactors_1(12, 1.0);
    seasonality_1->set(seasonallityBaseDate,Monthly,seasonalityFactors_1);

    boost::shared_ptr<MultiplicativePriceSeasonality> seasonality_real(
        new MultiplicativePriceSeasonality(seasonallityBaseDate,Monthly,seasonalityFactors));
    //Testing seasonality correction when seasonality factors are = 1
    //
    Rate fixing[] = {
        ii->fixing(Date(14,January  ,2013),true),
        ii->fixing(Date(14,February ,2013),true),
        ii->fixing(Date(14,March    ,2013),true),
        ii->fixing(Date(14,April    ,2013),true),
        ii->fixing(Date(14,May      ,2013),true),
        ii->fixing(Date(14,June     ,2013),true),
        ii->fixing(Date(14,July     ,2013),true),
        ii->fixing(Date(14,August   ,2013),true),
        ii->fixing(Date(14,September,2013),true),
        ii->fixing(Date(14,October  ,2013),true),
        ii->fixing(Date(14,November ,2013),true),
        ii->fixing(Date(14,December ,2013),true)
    };

    hz->setSeasonality(seasonality_1);
    QL_REQUIRE(hz->hasSeasonality(),"[44] incorrectly believes NO seasonality correction");

    Rate seasonalityFixing_1[] = {
        ii->fixing(Date(14,January  ,2013),true),
        ii->fixing(Date(14,February ,2013),true),
        ii->fixing(Date(14,March    ,2013),true),
        ii->fixing(Date(14,April    ,2013),true),
        ii->fixing(Date(14,May      ,2013),true),
        ii->fixing(Date(14,June     ,2013),true),
        ii->fixing(Date(14,July     ,2013),true),
        ii->fixing(Date(14,August   ,2013),true),
        ii->fixing(Date(14,September,2013),true),
        ii->fixing(Date(14,October  ,2013),true),
        ii->fixing(Date(14,November ,2013),true),
        ii->fixing(Date(14,December ,2013),true)

    };

    for(int i=0;i<12;i++){
        if(std::fabs(fixing[i] - seasonalityFixing_1[i]) > eps) {
            BOOST_ERROR("Seasonality doesn't work correctly when seasonality factors are set = 1");
        }
    }

    //Testing seasonality correction when seasonality factors are different from 1
    //
    //0.998687 is the seasonality factor corresponding to June (the base CPI curve month)
    //
    Rate expectedFixing[] = {
        ii->fixing(Date(14,January  ,2013),true) * 1.003245/0.998687,
        ii->fixing(Date(14,February ,2013),true) * 1.000000/0.998687,
        ii->fixing(Date(14,March    ,2013),true) * 0.999715/0.998687,
        ii->fixing(Date(14,April    ,2013),true) * 1.000495/0.998687,
        ii->fixing(Date(14,May      ,2013),true) * 1.000929/0.998687,
        ii->fixing(Date(14,June     ,2013),true) * 0.998687/0.998687,
        ii->fixing(Date(14,July     ,2013),true) * 0.995949/0.998687,
        ii->fixing(Date(14,August   ,2013),true) * 0.994682/0.998687,
        ii->fixing(Date(14,September,2013),true) * 0.995949/0.998687,
        ii->fixing(Date(14,October  ,2013),true) * 1.000519/0.998687,
        ii->fixing(Date(14,November ,2013),true) * 1.003705/0.998687,
        ii->fixing(Date(14,December ,2013),true) * 1.004186/0.998687
    };

    hz->setSeasonality(seasonality_real);

    Rate seasonalityFixing_real[] = {
        ii->fixing(Date(14,January  ,2013),true),
        ii->fixing(Date(14,February ,2013),true),
        ii->fixing(Date(14,March    ,2013),true),
        ii->fixing(Date(14,April    ,2013),true),
        ii->fixing(Date(14,May      ,2013),true),
        ii->fixing(Date(14,June     ,2013),true),
        ii->fixing(Date(14,July     ,2013),true),
        ii->fixing(Date(14,August   ,2013),true),
        ii->fixing(Date(14,September,2013),true),
        ii->fixing(Date(14,October  ,2013),true),
        ii->fixing(Date(14,November ,2013),true),
        ii->fixing(Date(14,December ,2013),true)
    };

    for(int i=0;i<12;i++){
        if(std::fabs(expectedFixing[i] - seasonalityFixing_real[i]) > 0.01) {
            BOOST_ERROR("Seasonality doesn't work correctly when considering seasonality factors != 1 "
                        << expectedFixing[i] << " vs " << seasonalityFixing_real[i]);
        }
    }

    //Testing Unset function
    //
    QL_REQUIRE(hz->hasSeasonality(),"[4] incorrectly believes NO seasonality correction");
    hz->setSeasonality();
    QL_REQUIRE(!hz->hasSeasonality(),"[5] incorrectly believes HAS seasonality correction");

    Rate seasonalityFixing_unset[] = {
        ii->fixing(Date(14,January  ,2013),true),
        ii->fixing(Date(14,February ,2013),true),
        ii->fixing(Date(14,March    ,2013),true),
        ii->fixing(Date(14,April    ,2013),true),
        ii->fixing(Date(14,May      ,2013),true),
        ii->fixing(Date(14,June     ,2013),true),
        ii->fixing(Date(14,July     ,2013),true),
        ii->fixing(Date(14,August   ,2013),true),
        ii->fixing(Date(14,September,2013),true),
        ii->fixing(Date(14,October  ,2013),true),
        ii->fixing(Date(14,November ,2013),true),
        ii->fixing(Date(14,December ,2013),true)
    };

    for(int i=0;i<12;i++){
        if(std::fabs(seasonalityFixing_unset[i] - seasonalityFixing_1[i]) > eps) {
            BOOST_ERROR("UnsetSeasonality doesn't work correctly "
                        << seasonalityFixing_unset[i] << " vs " << seasonalityFixing_1[i]);
        }
    }



    //==============================================================================
    // now do an INTERPOLATED index, i.e. repeat everything on a fake version of
    // UKRPI (to save making another term structure)

    bool interpYES = true;
    boost::shared_ptr<UKRPI> iiUKRPIyes(new UKRPI(interpYES, hz));
    for (Size i=0; i<rpiSchedule.size();i++) {
        iiUKRPIyes->addFixing(rpiSchedule[i], fixData[i]);
    }

    boost::shared_ptr<ZeroInflationIndex> iiyes
        = boost::dynamic_pointer_cast<ZeroInflationIndex>(iiUKRPIyes);

    // now build the zero inflation curve
    // same data, bigger lag or it will be a self-contradiction
    Period observationLagyes = Period(3,Months);
    std::vector<boost::shared_ptr<BootstrapHelper<ZeroInflationTermStructure> > > helpersyes =
    makeHelpers<ZeroInflationTermStructure,ZeroCouponInflationSwapHelper,
    ZeroInflationIndex>(zcData, LENGTH(zcData), iiyes,
                        observationLagyes,
                        calendar, bdc, dc);

    boost::shared_ptr<PiecewiseZeroInflationCurve<Linear> > pZITSyes(
            new PiecewiseZeroInflationCurve<Linear>(
            evaluationDate, calendar, dc, observationLagyes,
            frequency, iiyes->interpolated(), baseZeroRate,
            Handle<YieldTermStructure>(nominalTS), helpersyes));
    pZITSyes->recalculate();

    // first check that the zero rates on the curve match the data
    // and that the helpers give the correct impled rates
    forceLinearInterpolation = false;   // still
    for (Size i=0; i<LENGTH(zcData); i++) {
        BOOST_CHECK_MESSAGE(std::fabs(zcData[i].rate/100.0
                    - pZITSyes->zeroRate(zcData[i].date, observationLagyes, forceLinearInterpolation)) < eps,
                    "ZITS INTERPOLATED zeroRate != instrument "
                    << pZITSyes->zeroRate(zcData[i].date, observationLagyes, forceLinearInterpolation)
                    << " date " << zcData[i].date << " observationLagyes " << observationLagyes
                    << " vs " << zcData[i].rate/100.0
                    << " interpolation: " << iiyes->interpolated()
                    << " forceLinearInterpolation " << forceLinearInterpolation);
        BOOST_CHECK_MESSAGE(std::fabs(helpersyes[i]->impliedQuote()
                        - zcData[i].rate/100.0) < eps,
                    "ZITS INTERPOLATED implied quote != instrument "
                    << helpersyes[i]->impliedQuote()
                    << " vs " << zcData[i].rate/100.0);
    }


    //======================================================================================
    // now test the forecasting capability of the index.
    hz.linkTo(pZITSyes);
    from = hz->baseDate()+1*Months; // to avoid historical linear bit for rest of base month
    to = hz->maxDate()-1*Months; // a bit of margin for adjustments
    testIndex = MakeSchedule().from(from).to(to)
    .withTenor(1*Months)
    .withCalendar(UnitedKingdom())
    .withConvention(ModifiedFollowing);

    // we are testing UKRPI which is FAKE interpolated for testing here
    bd = hz->baseDate();
    bf = iiyes->fixing(bd);
    for (Size i=0; i<testIndex.size();i++) {
        Date d = testIndex[i];
        Real z = hz->zeroRate(d, Period(0,Days));
        Real t = hz->dayCounter().yearFraction(bd, d);
        Real calc = bf * pow( 1+z, t);
        if (t<=0) calc = iiyes->fixing(d); // still historical
        if (std::fabs(calc - iiyes->fixing(d)) > eps)
            BOOST_ERROR("ZC INTERPOLATED index does not forecast correctly for date " << d
                        << " from base date " << bd
                        << " with fixing " << bf
                        << ", correct:  " << calc
                        << ", fix: " << iiyes->fixing(d)
                        << ", t " << t
                        << ", zero " << z);
    }



    //===========================================================================================
    // Test zero coupon swap

    boost::shared_ptr<ZeroInflationIndex> ziiyes = boost::dynamic_pointer_cast<ZeroInflationIndex>(iiyes);
    BOOST_REQUIRE_MESSAGE(ziiyes,"dynamic_pointer_cast to ZeroInflationIndex from UKRPI-I failed");
    ZeroCouponInflationSwap nzcisyes(ZeroCouponInflationSwap::Payer,
                                     1000000.0,
                                     evaluationDate,
                                     zcData[6].date,    // end date = maturity
                                     calendar, bdc, dc, zcData[6].rate/100.0, // fixed rate
                                     ziiyes, observationLagyes);

    // N.B. no coupon pricer because it is not a coupon, effect of inflation curve via
    //      inflation curve attached to the inflation index.
    nzcisyes.setPricingEngine(sppe);

    // ... and price it, should be zero
    BOOST_CHECK_MESSAGE(fabs(nzcisyes.NPV())<0.00001,"ZCIS-I does not reprice to zero "
                        << nzcisyes.NPV()
                        << evaluationDate << " to " << zcData[6].date << " becoming " << nzcisyes.maturityDate()
                        << " rate " << zcData[6].rate
                        << " fixed leg " << nzcisyes.legNPV(0)
                        << " indexed-predicted inflated leg " << nzcisyes.legNPV(1)
                        << " discount " << nominalTS->discount(nzcisyes.maturityDate())
                        );

}
    /* Generally inflation indices are available with a lag of 1month
       and then observed with a lag of 2-3 months depending whether
       they use an interpolated fixing or not.  Here, we make the
       swap use the interpolation of the index to avoid incompatibilities.
    */
    ZeroCouponInflationSwap::ZeroCouponInflationSwap(
        Type type,
        Real nominal,
        const Date& startDate,  // start date of contract (only)
        const Date& maturity,   // this is pre-adjustment!
        const Calendar& fixCalendar,
        BusinessDayConvention fixConvention,
        const DayCounter& dayCounter,
        Rate fixedRate,
        const boost::shared_ptr<ZeroInflationIndex> &infIndex,
        const Period& observationLag,
        bool adjustInfObsDates,
        Calendar infCalendar,
        BusinessDayConvention infConvention)
    : Swap(2), type_(type), nominal_(nominal), fixedRate_(fixedRate),
    infIndex_(infIndex), observationLag_(observationLag), dayCounter_(dayCounter) {
        // first check compatibility of index and swap definitions
        if (infIndex_->interpolated()) {
            Period pShift(infIndex_->frequency());
            QL_REQUIRE(observationLag_ - pShift > infIndex_->availabilityLag(),
                       "inconsistency between swap observation of index " << observationLag_ <<
                       " index availability " << infIndex_->availabilityLag() <<
                       " interpolated index period " << pShift <<
                       " and index availability " << infIndex_->availabilityLag() <<
                       " need (obsLag-index period) > availLag");
        } else {
            QL_REQUIRE(infIndex_->availabilityLag() < observationLag_,
                       "index tries to observe inflation fixings that do not yet exist: "
                       << " availability lag " << infIndex_->availabilityLag()
                       << " versus obs lag = " << observationLag_);
        }

        if (infCalendar==Calendar()) infCalendar = fixCalendar;
        if (infConvention==BusinessDayConvention()) infConvention = fixConvention;

        if (adjustInfObsDates) {
            baseDate_ = infCalendar.adjust(startDate - observationLag_, infConvention);
            obsDate_ = infCalendar.adjust(maturity - observationLag_, infConvention);
        } else {
            baseDate_ = startDate - observationLag_;
            obsDate_ = maturity - observationLag_;
        }

        Date infPayDate = infCalendar.adjust(maturity, infConvention);
        Date fixedPayDate = fixCalendar.adjust(maturity, fixConvention);

        // At this point the index may not be able to forecast
        // i.e. do not want to force the existence of an inflation
        // term structure before allowing users to create instruments.
        Real T = inflationYearFraction(infIndex_->frequency(), infIndex_->interpolated(),
                                       dayCounter_, baseDate_, obsDate_);
        // N.B. the -1.0 is because swaps only exchange growth, not notionals as well
        Real fixedAmount = nominal * ( std::pow(1.0 + fixedRate, T) - 1.0 );

        legs_[0].push_back(boost::shared_ptr<CashFlow>(
            new SimpleCashFlow(fixedAmount, fixedPayDate)));
        bool growthOnly = true;
        legs_[1].push_back(boost::shared_ptr<CashFlow>(
            new IndexedCashFlow(nominal,infIndex,baseDate_,obsDate_,infPayDate,growthOnly)));

        for (Size j=0; j<2; ++j) {
            for (Leg::iterator i = legs_[j].begin(); i!= legs_[j].end(); ++i)
                registerWith(*i);
        }

        switch (type_) {
            case Payer:
                payer_[0] = +1.0;
                payer_[1] = -1.0;
                break;
            case Receiver:
                payer_[0] = -1.0;
                payer_[1] = +1.0;
                break;
            default:
                QL_FAIL("Unknown zero-inflation-swap type");
        }

    }
예제 #19
0
    CPILeg::operator Leg() const {

        QL_REQUIRE(!notionals_.empty(), "no notional given");
        Size n = schedule_.size()-1;
        Calendar calendar = schedule_.calendar();
        Leg leg;
        leg.reserve(n+1);   // +1 for notional, we always have some sort ...
        if (n>0) {
            QL_REQUIRE(!fixedRates_.empty() || !spreads_.empty(),
                       "no fixedRates or spreads given");

            Date refStart, start, refEnd, end;

            for (Size i=0; i<n; ++i) {
                refStart = start = schedule_.date(i);
                refEnd   =   end = schedule_.date(i+1);
                Date paymentDate = calendar.adjust(end, paymentAdjustment_);
                if (i==0   && !schedule_.isRegular(i+1)) {
                    BusinessDayConvention bdc = schedule_.businessDayConvention();
                    refStart = schedule_.calendar().adjust(end - schedule_.tenor(), bdc);
                }
                if (i==n-1 && !schedule_.isRegular(i+1)) {
                    BusinessDayConvention bdc = schedule_.businessDayConvention();
                    refEnd = schedule_.calendar().adjust(start + schedule_.tenor(), bdc);
                }
                if (detail::get(fixedRates_, i, 1.0) == 0.0) { // fixed coupon
                    leg.push_back(boost::shared_ptr<CashFlow>
                                  (new FixedRateCoupon
                                   (paymentDate, detail::get(notionals_, i, 0.0),
                                    detail::effectiveFixedRate(spreads_,caps_,floors_,i),
                                    paymentDayCounter_, start, end, refStart, refEnd)));
                } else { // zero inflation coupon
                    if (detail::noOption(caps_, floors_, i)) { // just swaplet
                        boost::shared_ptr<CPICoupon> coup;

                        coup = boost::shared_ptr<CPICoupon>
                            (new CPICoupon(baseCPI_,    // all have same base for ratio
                                     paymentDate,
                                     detail::get(notionals_, i, 0.0),
                                     start, end,
                                     detail::get(fixingDays_, i, 0.0),
                                     index_, observationLag_,
                                     observationInterpolation_,
                                     paymentDayCounter_,
                                     detail::get(fixedRates_, i, 0.0),
                                     detail::get(spreads_, i, 0.0),
                                     refStart, refEnd));

                        // in this case you can set a pricer
                        // straight away because it only provides computation - not data
                        boost::shared_ptr<CPICouponPricer> pricer
                            (new CPICouponPricer);
                        coup->setPricer(pricer);
                        leg.push_back(boost::dynamic_pointer_cast<CashFlow>(coup));

                    } else  {     // cap/floorlet
                        QL_FAIL("caps/floors on CPI coupons not implemented.");
                    }
                }
            }
        }

        // in CPI legs you always have a notional flow of some sort
        Date paymentDate = calendar.adjust(schedule_.date(n), paymentAdjustment_);
        Date fixingDate = paymentDate - observationLag_;
        boost::shared_ptr<CashFlow> xnl(new CPICashFlow
                          (detail::get(notionals_, n, 0.0), index_,
                           Date(), // is fake, i.e. you do not have one
                           baseCPI_, fixingDate, paymentDate,
                           subtractInflationNominal_, observationInterpolation_,
                           index_->frequency())
                         );
        leg.push_back(xnl);


        return leg;
    }
예제 #20
0
void CreditDefaultSwapTest::testImpliedHazardRate() {

    BOOST_TEST_MESSAGE("Testing implied hazard-rate for credit-default swaps...");

    SavedSettings backup;

    // Initialize curves
    Calendar calendar = TARGET();
    Date today = calendar.adjust(Date::todaysDate());
    Settings::instance().evaluationDate() = today;

    Rate h1 = 0.30, h2 = 0.40;
    DayCounter dayCounter = Actual365Fixed();

    std::vector<Date> dates(3);
    std::vector<Real> hazardRates(3);
    dates[0] = today;
    hazardRates[0] = h1;

    dates[1] = today + 5*Years;
    hazardRates[1] = h1;

    dates[2] = today + 10*Years;
    hazardRates[2] = h2;

    RelinkableHandle<DefaultProbabilityTermStructure> probabilityCurve;
    probabilityCurve.linkTo(ext::shared_ptr<DefaultProbabilityTermStructure>(
                    new InterpolatedHazardRateCurve<BackwardFlat>(dates,
                                                                  hazardRates,
                                                                  dayCounter)));

    RelinkableHandle<YieldTermStructure> discountCurve;
    discountCurve.linkTo(ext::shared_ptr<YieldTermStructure>(
                            new FlatForward(today,0.03,Actual360())));


    Frequency frequency = Semiannual;
    BusinessDayConvention convention = ModifiedFollowing;

    Date issueDate = calendar.advance(today, -6, Months);
    Rate fixedRate = 0.0120;
    DayCounter cdsDayCount = Actual360();
    Real notional = 10000.0;
    Real recoveryRate = 0.4;

    Rate latestRate = Null<Rate>();
    for (Integer n=6; n<=10; ++n) {

        Date maturity = calendar.advance(issueDate, n, Years);
        Schedule schedule(issueDate, maturity, Period(frequency), calendar,
                          convention, convention,
                          DateGeneration::Forward, false);

        CreditDefaultSwap cds(Protection::Seller, notional, fixedRate,
                              schedule, convention, cdsDayCount,
                              true, true);
        cds.setPricingEngine(ext::shared_ptr<PricingEngine>(
                         new MidPointCdsEngine(probabilityCurve,
                                               recoveryRate, discountCurve)));

        Real NPV = cds.NPV();
        Rate flatRate = cds.impliedHazardRate(NPV, discountCurve,
                                              dayCounter,
                                              recoveryRate);

        if (flatRate < h1 || flatRate > h2) {
            BOOST_ERROR("implied hazard rate outside expected range\n"
                        << "    maturity: " << n << " years\n"
                        << "    expected minimum: " << h1 << "\n"
                        << "    expected maximum: " << h2 << "\n"
                        << "    implied rate:     " << flatRate);
        }

        if (n > 6 && flatRate < latestRate) {
            BOOST_ERROR("implied hazard rate decreasing with swap maturity\n"
                        << "    maturity: " << n << " years\n"
                        << "    previous rate: " << latestRate << "\n"
                        << "    implied rate:  " << flatRate);
        }

        latestRate = flatRate;

        RelinkableHandle<DefaultProbabilityTermStructure> probability;
        probability.linkTo(ext::shared_ptr<DefaultProbabilityTermStructure>(
         new FlatHazardRate(
           today,
           Handle<Quote>(ext::shared_ptr<Quote>(new SimpleQuote(flatRate))),
           dayCounter)));

        CreditDefaultSwap cds2(Protection::Seller, notional, fixedRate,
                               schedule, convention, cdsDayCount,
                               true, true);
        cds2.setPricingEngine(ext::shared_ptr<PricingEngine>(
                               new MidPointCdsEngine(probability,recoveryRate,
                                                     discountCurve)));

        Real NPV2 = cds2.NPV();
        Real tolerance = 1.0;
        if (std::fabs(NPV-NPV2) > tolerance) {
            BOOST_ERROR("failed to reproduce NPV with implied rate\n"
                        << "    expected:   " << NPV << "\n"
                        << "    calculated: " << NPV2);
        }
    }
}