Exemplo n.º 1
0
    void SwaptionHelper::performCalculations() const {

        Calendar calendar = index_->fixingCalendar();
        Natural fixingDays = index_->fixingDays();

        Date exerciseDate = exerciseDate_;
        if (exerciseDate == Null<Date>())
            exerciseDate = calendar.advance(termStructure_->referenceDate(),
                                            maturity_,
                                            index_->businessDayConvention());

        Date startDate = calendar.advance(exerciseDate,
                                    fixingDays, Days,
                                    index_->businessDayConvention());

        Date endDate = endDate_;
        if (endDate == Null<Date>())
            endDate = calendar.advance(startDate, length_,
                                       index_->businessDayConvention());

        Schedule fixedSchedule(startDate, endDate, fixedLegTenor_, calendar,
                               index_->businessDayConvention(),
                               index_->businessDayConvention(),
                               DateGeneration::Forward, false);
        Schedule floatSchedule(startDate, endDate, index_->tenor(), calendar,
                               index_->businessDayConvention(),
                               index_->businessDayConvention(),
                               DateGeneration::Forward, false);

        boost::shared_ptr<PricingEngine> swapEngine(
                             new DiscountingSwapEngine(termStructure_, false));

        VanillaSwap::Type type = VanillaSwap::Receiver;

        VanillaSwap temp(VanillaSwap::Receiver, nominal_,
                            fixedSchedule, 0.0, fixedLegDayCounter_,
                            floatSchedule, index_, 0.0, floatingLegDayCounter_);
        temp.setPricingEngine(swapEngine);
        Real forward = temp.fairRate();
        if(strike_ == Null<Real>()) {
            exerciseRate_ = forward;
        }
        else {
            exerciseRate_ = strike_;
            type = strike_ <= forward ? VanillaSwap::Receiver : VanillaSwap::Payer;
            // ensure that calibration instrument is out of the money
        }
        swap_ = boost::shared_ptr<VanillaSwap>(
            new VanillaSwap(type, nominal_,
                            fixedSchedule, exerciseRate_, fixedLegDayCounter_,
                            floatSchedule, index_, 0.0, floatingLegDayCounter_));
        swap_->setPricingEngine(swapEngine);

        boost::shared_ptr<Exercise> exercise(new EuropeanExercise(exerciseDate));

        swaption_ = boost::shared_ptr<Swaption>(new Swaption(swap_, exercise));

        CalibrationHelper::performCalculations();

    }
Exemplo n.º 2
0
 set<Date> AsianContract::getAllBusinessDaysBetween(Date startDate, Date endDate, Calendar calendar)
 {            
     Date averagingStart;
     if (calendar.isBusinessDay(startDate)) 
     {
         averagingStart = startDate;
     }
     else 
     {
         averagingStart = calendar.advance(startDate, 1, Days);
     }
     Date lastDateInAveragingMonth;
     if (calendar.isBusinessDay(endDate))
     {
         lastDateInAveragingMonth = endDate;
     }
     else 
     {
         lastDateInAveragingMonth = calendar.advance(endDate, -1, Days);
     }
     set<Date> averagingDates;
     Date tmp = averagingStart;
     while (tmp <= endDate) 
     {
         averagingDates.insert(tmp);
         tmp = calendar.advance(tmp, 1, Days);
     }
     return averagingDates;
 }
Exemplo n.º 3
0
    void historicalRatesAnalysis(
                SequenceStatistics& statistics,
                std::vector<Date>& skippedDates,
                std::vector<std::string>& skippedDatesErrorMessage,
                const Date& startDate,
                const Date& endDate,
                const Period& step,
                const std::vector<boost::shared_ptr<InterestRateIndex> >& indexes) {

        skippedDates.clear();
        skippedDatesErrorMessage.clear();

        Size nRates = indexes.size();
        statistics.reset(nRates);

        std::vector<Rate> sample(nRates);
        std::vector<Rate> prevSample(nRates);
        std::vector<Rate> sampleDiff(nRates);

        Calendar cal = indexes[0]->fixingCalendar();
        // start with a valid business date
        Date currentDate = cal.advance(startDate, 1*Days, Following);
        bool isFirst = true;
        // Loop over the historical dataset
        for (; currentDate<=endDate;
            currentDate = cal.advance(currentDate, step, Following)) {

            try {
                for (Size i=0; i<nRates; ++i) {
                    Rate fixing = indexes[i]->fixing(currentDate, false);
                    sample[i] = fixing;
                }
            } catch (std::exception& e) {
                skippedDates.push_back(currentDate);
                skippedDatesErrorMessage.push_back(e.what());
                continue;
            }

            // From 2nd step onwards, calculate forward rate
            // relative differences
            if (!isFirst){
                for (Size i=0; i<nRates; ++i)
                    sampleDiff[i] = sample[i]/prevSample[i] -1.0;
                // add observation
                statistics.add(sampleDiff.begin(), sampleDiff.end());
            }
            else
                isFirst = false;

            // Store last calculated forward rates
            std::swap(prevSample, sample);

        }
    }
Exemplo n.º 4
0
static bool test_bond_schedule_today_cython()
{
  Date           today;
  Calendar       calendar;
  FixedRateBond* bond;
  Date          s_date;
  Date          b_date;

  today = Date::todaysDate();
  calendar = TARGET();

   bond = get_bond_for_evaluation_date(today);

  s_date = calendar.advance(today, 3, Days, Following, 0);

  b_date = bond->settlementDate();

  if (s_date != b_date) {
      std::cout << "Dates are not equivalent " 
           << s_date 
           << " vs " 
           << b_date 
           << std::endl;
      return false;
  }
  return true;


}
void DefaultProbabilityCurveTest::testFlatHazardRate() {

    BOOST_TEST_MESSAGE("Testing flat hazard rate...");

    Real hazardRate = 0.0100;
    Handle<Quote> hazardRateQuote = Handle<Quote>(
                boost::shared_ptr<Quote>(new SimpleQuote(hazardRate)));
    DayCounter dayCounter = Actual360();
    Calendar calendar = TARGET();
    Size n = 20;

    double tolerance = 1.0e-10;
    Date today = Settings::instance().evaluationDate();
    Date startDate = today;
    Date endDate = startDate;

    FlatHazardRate flatHazardRate(today, hazardRateQuote, dayCounter);

    for(Size i=0; i<n; i++){
        endDate = calendar.advance(endDate, 1, Years);
        Time t = dayCounter.yearFraction(startDate, endDate);
        Probability probability = 1.0 - std::exp(-hazardRate * t);
        Probability computedProbability = flatHazardRate.defaultProbability(t);

        if (std::fabs(probability - computedProbability) > tolerance)
            BOOST_ERROR(
                "Failed to reproduce probability for flat hazard rate\n"
                << std::setprecision(10)
                << "    calculated probability: " << computedProbability << "\n"
                << "    expected probability:   " << probability);
    }
}
Exemplo n.º 6
0
	CmsSpreadOption::CmsSpreadOption(boost::shared_ptr<Schedule> calculationSchedule,
				int fixingDays,
				boost::shared_ptr<SwapIndex> index1,
				boost::shared_ptr<SwapIndex> index2,
				DayCounter couponDayCounter,
				double strike,
				int flavour) : index1_(index1), index2_(index2),
				couponDayCounter_(couponDayCounter), strike_(strike), flavour_(flavour) {

		calc_ = calculationSchedule->dates();
		Calendar cal = calculationSchedule->calendar();
		BusinessDayConvention bdc = calculationSchedule->businessDayConvention();
		for(int i=1;i<calc_.size();i++) {
			payments_.push_back(calc_[i]);
			Date fix = calc_[i-1];
			fix = cal.advance(fix,-fixingDays,Days,bdc);
			fixings_.push_back(fix);
		}
		rates1_=vector<double>(fixings_.size());
		rates2_=vector<double>(fixings_.size());
		adjustedRates1_=vector<double>(fixings_.size());
		adjustedRates2_=vector<double>(fixings_.size());
		spreads_=vector<double>(fixings_.size());
		areRatesComputed_=vector<bool>(fixings_.size(),false);

		QL_REQUIRE(fixings_.size() == payments_.size() && fixings_.size() == calc_.size()-1,
			"Number of fixings (" << fixings_.size() << "), payments (" << payments_.size() << ") and calculation schedules (" << calc_.size() << ") do not match.");

	}
Exemplo n.º 7
0
 FuturesRateHelper::FuturesRateHelper(Real price,
                                      const Date& iborStartDate,
                                      Natural lengthInMonths,
                                      const Calendar& calendar,
                                      BusinessDayConvention convention,
                                      bool endOfMonth,
                                      const DayCounter& dayCounter,
                                      Rate convAdj,
                                      Futures::Type type)
 : RateHelper(price),
   convAdj_(Handle<Quote>(shared_ptr<Quote>(new SimpleQuote(convAdj))))
 {
     switch (type) {
       case Futures::IMM:
         QL_REQUIRE(IMM::isIMMdate(iborStartDate, false),
             iborStartDate << " is not a valid IMM date");
         break;
       case Futures::ASX:
         QL_REQUIRE(ASX::isASXdate(iborStartDate, false),
             iborStartDate << " is not a valid ASX date");
         break;
       default:
         QL_FAIL("unknown futures type (" << Integer(type) << ")");
     }
     earliestDate_ = iborStartDate;
     latestDate_ = calendar.advance(iborStartDate, lengthInMonths*Months,
                                    convention, endOfMonth);
     yearFraction_ = dayCounter.yearFraction(earliestDate_, latestDate_);
 }
Exemplo n.º 8
0
    void SubPeriodsPricer::initialize(const FloatingRateCoupon& coupon) {
        coupon_ =  dynamic_cast<const SubPeriodsCoupon*>(&coupon);
        QL_REQUIRE(coupon_, "sub-periods coupon required");
        gearing_ = coupon_->gearing();
        spread_ = coupon_->spread();

        Date paymentDate = coupon_->date();

        boost::shared_ptr<IborIndex> index =
            boost::dynamic_pointer_cast<IborIndex>(coupon_->index());
        const Handle<YieldTermStructure>& rateCurve =
            index->forwardingTermStructure();
        discount_ = rateCurve->discount(paymentDate);
        accrualFactor_ = coupon_->accrualPeriod();
        spreadLegValue_ = spread_ * accrualFactor_* discount_;

        startTime_ = coupon_->startTime();
        endTime_ = coupon_->endTime();
        observationTimes_ = coupon_->observationTimes();
        observations_ = coupon_->observations();

        const std::vector<Date>& observationDates =
            coupon_->observationsSchedule()->dates();

        QL_REQUIRE(observationDates.size()==observations_+2,
                   "incompatible size of initialValues vector");

        initialValues_ = std::vector<Real>(observationDates.size(),0.);

        observationCvg_ = std::vector<Real>(observationDates.size(),0.);

        observationIndexStartDates_ =
            std::vector<Date>(observationDates.size());
        observationIndexEndDates_ =
            std::vector<Date>(observationDates.size());

        Calendar calendar = index->fixingCalendar();

        for(Size i=0; i<observationDates.size(); i++) {
            Date fixingDate = calendar.advance(
                                 observationDates[i],
                                 -static_cast<Integer>(coupon_->fixingDays()),
                                 Days);

            initialValues_[i] =
                index->fixing(fixingDate) + coupon_->rateSpread();

            Date fixingValueDate = index->valueDate(fixingDate);
            Date endValueDate = index->maturityDate(fixingValueDate);

            observationIndexStartDates_[i] = fixingValueDate;
            observationIndexEndDates_[i] = endValueDate;

            observationCvg_[i] =
                index->dayCounter().yearFraction(fixingValueDate, endValueDate);
        }
    }
Exemplo n.º 9
0
static FixedRateBond* get_bond_for_evaluation_date(
        Date &in_date
) {
  Date        evaluation_date;
  Calendar    calendar;
  Date        effective_date;
  Date        termination_date;
  Natural     settlement_days;
  Real        face_amount;
  Real        coupon_rate;
  Real        redemption;
  Schedule    fixed_bond_schedule;
  Date        issue_date;

  std::vector<Rate>* coupons;

  FixedRateBond*    bond;

  QL::set_evaluation_date(in_date);

  evaluation_date = QL::get_evaluation_date();

  std::cout << "Current evaluation date:" << evaluation_date << std::endl;

  calendar = QuantLib::TARGET();

  effective_date = Date(10, QuantLib::Jul, 2006);

  termination_date = calendar.advance(
        effective_date, 10, Years, Unadjusted, 0
   );

  settlement_days = 3;
  face_amount = 100.0;
  coupon_rate = 0.05;
  redemption = 100.0;

  fixed_bond_schedule = Schedule(
        effective_date, termination_date, Period(Annual), calendar, 
        ModifiedFollowing, ModifiedFollowing, DateGeneration::Backward, 0
  );

  issue_date = Date(10, Jul, 2006);
    
  coupons = new std::vector<Rate>();

  coupons->push_back(coupon_rate);

  bond = new FixedRateBond(
       settlement_days, face_amount, fixed_bond_schedule, *coupons, 
       ActualActual(ActualActual::ISMA), Following, redemption, issue_date
  );

 return bond;
}
Exemplo n.º 10
0
 FuturesRateHelper::FuturesRateHelper(Real price,
                                      const Date& immDate,
                                      Natural lengthInMonths,
                                      const Calendar& calendar,
                                      BusinessDayConvention convention,
                                      bool endOfMonth,
                                      const DayCounter& dayCounter,
                                      Rate convAdj)
 : RateHelper(price),
   convAdj_(Handle<Quote>(shared_ptr<Quote>(new SimpleQuote(convAdj))))
 {
     QL_REQUIRE(IMM::isIMMdate(immDate, false),
                immDate << "is not a valid IMM date");
     earliestDate_ = immDate;
     latestDate_ = calendar.advance(immDate, lengthInMonths*Months,
                                    convention, endOfMonth);
     yearFraction_ = dayCounter.yearFraction(earliestDate_, latestDate_);
 }
Exemplo n.º 11
0
    FuturesRateHelper::FuturesRateHelper(const Handle<Quote>& price,
                                         const Date& immDate,
                                         Natural lengthInMonths,
                                         const Calendar& calendar,
                                         BusinessDayConvention convention,
                                         bool endOfMonth,
                                         const DayCounter& dayCounter,
                                         const Handle<Quote>& convAdj)
    : RateHelper(price), convAdj_(convAdj) {
        QL_REQUIRE(IMM::isIMMdate(immDate, false),
                   immDate << " is not a valid IMM date");
        earliestDate_ = immDate;
        latestDate_ = calendar.advance(immDate, lengthInMonths*Months,
                                       convention, endOfMonth);
        yearFraction_ = dayCounter.yearFraction(earliestDate_, latestDate_);

        registerWith(convAdj_);
    }
Exemplo n.º 12
0
static bool test_bond_schedule_anotherday_cython()
{

  Date              last_month;
  Date              today;
  FixedRateBond*    bond;
  Calendar          calendar;
  Date              s_date;
  Date              b_date;
  Date              e_date;
  
  last_month = Date(30, August, 2011);

  today = Date::endOfMonth(last_month);

  bond = get_bond_for_evaluation_date(today);

  calendar = TARGET();

  s_date = calendar.advance(today, 3, Days, Following, 0);

  b_date = bond->settlementDate();

  e_date = QL::get_evaluation_date();

  if (s_date != b_date) {
      std::cout << "Dates are not equivalent " 
           << s_date 
           << " vs " 
           << b_date 
           << std::endl;
      return false;
   }
  
   if (today != e_date) {
      std::cout << "Evaluation dates are not equivalent " 
           << today 
           << " vs " 
           << e_date 
           << std::endl;
      return false;
  }
   return true;
} 
Exemplo n.º 13
0
	boost::shared_ptr<VanillaSwap> InstrumentFactory::make_vanillaSwap(Real notional,
																	const Date& ref_date,
																	const std::string& swap_index_cd,
																	Rate fixedRate,
																	VanillaSwap::Type fixedPayRecType,
																	Spread floatingLegSpread,
																	const Handle<YieldTermStructure>& evalYieldCurve,
																	const boost::shared_ptr<PricingEngine>& engine )
	{
		// 로드해

		boost::shared_ptr<SwapIndex> swapIndex = IndexFactory::swapIndex(swap_index_cd, evalYieldCurve.currentLink());

		Calendar calendar = SouthKorea();
		Period maturityTenor = swapIndex->tenor();
		Period couponTenor = swapIndex->fixedLegTenor();
		DayCounter dayCounter = swapIndex->dayCounter();
		BusinessDayConvention businessDayConvention = BusinessDayConvention::ModifiedFollowing;

		Schedule schedule = Schedule(ref_date,
			calendar.advance(ref_date, maturityTenor, businessDayConvention),
			couponTenor,
			calendar,
			businessDayConvention,
			businessDayConvention,
			DateGeneration::Rule::Forward,
			false);

		boost::shared_ptr<VanillaSwap> vanilla_swap
			= boost::shared_ptr<VanillaSwap>(new VanillaSwap(fixedPayRecType,
			notional,
			schedule,
			fixedRate, dayCounter,
			schedule,
			swapIndex->iborIndex()->clone(evalYieldCurve),
			floatingLegSpread,
			dayCounter));

		vanilla_swap->setPricingEngine(engine);

		return vanilla_swap;
	}
Exemplo n.º 14
0
    AverageBMACoupon::AverageBMACoupon(const Date& paymentDate,
                                       Real nominal,
                                       const Date& startDate,
                                       const Date& endDate,
                                       const boost::shared_ptr<BMAIndex>& index,
                                       Real gearing, Spread spread,
                                       const Date& refPeriodStart,
                                       const Date& refPeriodEnd,
                                       const DayCounter& dayCounter)
    : FloatingRateCoupon(paymentDate, nominal, startDate, endDate,
                         index->fixingDays(), index, gearing, spread,
                         refPeriodStart, refPeriodEnd, dayCounter, false)
    {
        Calendar cal = index->fixingCalendar();
        Integer fixingDays = Integer(index->fixingDays());
        fixingDays += bmaCutoffDays;
        Date fixingStart = cal.advance(startDate, -fixingDays*Days, Preceding);
        fixingSchedule_ = index->fixingSchedule(fixingStart, endDate);

        setPricer(boost::shared_ptr<FloatingRateCouponPricer>(
                                                 new AverageBMACouponPricer));
    }
Exemplo n.º 15
0
 Date BMAIndex::maturityDate(const Date& valueDate) const {
     Calendar cal = fixingCalendar();
     Date fixingDate = cal.advance(valueDate, -1, Days);
     Date nextWednesday = previousWednesday(fixingDate+7);
     return cal.advance(nextWednesday, 1, Days);
 }
void qlVariableValueFactory::setSerialClass(const boost::shared_ptr<FpmlSerialized::VariableValue>& serial_vv)
{
	const std::string& choiceStr_paraType = serial_vv->getChoiceStr_paraType();
	boost::shared_ptr<QuantLib::VariableValue> ql_vv;

	if( choiceStr_paraType == "indexRef")	{
		const boost::shared_ptr<FpmlSerialized::IndexRef>& serial_indexRef
				= serial_vv->getIndexRef();
		const Date& refDate = serial_indexRef->getEventDateRef()->getDateSingle()->dateValue();
		const std::string& fixingTypeChoiceStr = serial_indexRef->getFixingDays()->getChoiceStr_fixingType();

		Integer fixingDays = 0;

		if(fixingTypeChoiceStr == "days"){
			fixingDays = serial_indexRef->getFixingDays()->getDays()->IValue();
		}else
		{
			QL_FAIL("not implementation");
		}

		Calendar calendar = PathInformation::instance().getCalendar();

		const QuantLib::Period& dayUnit = QuantLib::Period(fixingDays,QuantLib::Days); 
		const Date& adjustedRefDate = calendar.advance(refDate,dayUnit);

		const boost::shared_ptr<FpmlSerialized::UnderlyingIndex>& serial_under 
						= serial_vv->getIndexRef()->getUnderlyingIndexRef();

		qlUnderlyingFactory ql_uf = qlUnderlyingFactory();
		ql_uf.setSerialClass(serial_under);

		boost::shared_ptr<QuantLib::Index> index = ql_uf.getIndex();

		ql_vv = boost::shared_ptr<QuantLib::SimpleVariableValue>(
								new QuantLib::SimpleVariableValue(index,adjustedRefDate));

	}
	else if(choiceStr_paraType == "indexTimeRef"){
		const boost::shared_ptr<FpmlSerialized::IndexTimeRef>& serial_indexItmeRef
				= serial_vv->getIndexTimeRef();
		const std::string& fixingTypeChoiceStr = serial_indexItmeRef->getFixingDays()->getChoiceStr_fixingType();

		Integer fixingDays = 0;

		if(fixingTypeChoiceStr == "days"){
			fixingDays = serial_indexItmeRef->getFixingDays()->getDays()->IValue();
		}else
		{
			QL_FAIL("not implementation");
		}

		Calendar calendar = PathInformation::instance().getCalendar();

		const boost::shared_ptr<FpmlSerialized::UnderlyingIndex>& serial_under 
						= serial_indexItmeRef->getUnderlyingIndexRef();

		qlUnderlyingFactory ql_uf = qlUnderlyingFactory();
		ql_uf.setSerialClass(serial_under);

		boost::shared_ptr<QuantLib::Index> index = ql_uf.getIndex();

		ql_vv = boost::shared_ptr<QuantLib::SimpleTimeVariableValue>(
								new QuantLib::SimpleTimeVariableValue(index,fixingDays));


	}
	else if(choiceStr_paraType == "symbolName"){
		const std::string& symbolName = serial_vv->getSymbolName()->SValue();

		ql_vv = boost::shared_ptr<QuantLib::ComplexVariableValue>(
											new QuantLib::ComplexVariableValue(symbolName));

	}
	else if(choiceStr_paraType == "constValue"){
		Real value = serial_vv->getConstValue()->DValue();
		ql_vv = boost::shared_ptr<QuantLib::ConstVariableValue>(new QuantLib::ConstVariableValue(value));
	}
	else
	{
		QL_FAIL("unknown type paraType");
	}

	ql_vv->registManager();

	this->variableValue_ = ql_vv;

}
Exemplo n.º 17
0
int main(int, char* []) {

    try {

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

        Date todaysDate(15, February, 2002);
        Calendar calendar = TARGET();
        Date settlementDate(19, February, 2002);
        Settings::instance().evaluationDate() = todaysDate;

        // flat yield term structure impling 1x5 swap at 5%
        boost::shared_ptr<Quote> flatRate(new SimpleQuote(0.04875825));
        Handle<YieldTermStructure> rhTermStructure(
            boost::shared_ptr<FlatForward>(
                      new FlatForward(settlementDate, Handle<Quote>(flatRate),
                                      Actual365Fixed())));

        // Define the ATM/OTM/ITM swaps
        Frequency fixedLegFrequency = Annual;
        BusinessDayConvention fixedLegConvention = Unadjusted;
        BusinessDayConvention floatingLegConvention = ModifiedFollowing;
        DayCounter fixedLegDayCounter = Thirty360(Thirty360::European);
        Frequency floatingLegFrequency = Semiannual;
        VanillaSwap::Type type = VanillaSwap::Payer;
        Rate dummyFixedRate = 0.03;
        boost::shared_ptr<IborIndex> indexSixMonths(new
            Euribor6M(rhTermStructure));

        Date startDate = calendar.advance(settlementDate,1,Years,
                                          floatingLegConvention);
        Date maturity = calendar.advance(startDate,5,Years,
                                         floatingLegConvention);
        Schedule fixedSchedule(startDate,maturity,Period(fixedLegFrequency),
                               calendar,fixedLegConvention,fixedLegConvention,
                               DateGeneration::Forward,false);
        Schedule floatSchedule(startDate,maturity,Period(floatingLegFrequency),
                               calendar,floatingLegConvention,floatingLegConvention,
                               DateGeneration::Forward,false);

        boost::shared_ptr<VanillaSwap> swap(new VanillaSwap(
            type, 1000.0,
            fixedSchedule, dummyFixedRate, fixedLegDayCounter,
            floatSchedule, indexSixMonths, 0.0,
            indexSixMonths->dayCounter()));
        swap->setPricingEngine(boost::shared_ptr<PricingEngine>(
                                 new DiscountingSwapEngine(rhTermStructure)));
        Rate fixedATMRate = swap->fairRate();
        Rate fixedOTMRate = fixedATMRate * 1.2;
        Rate fixedITMRate = fixedATMRate * 0.8;

        boost::shared_ptr<VanillaSwap> atmSwap(new VanillaSwap(
            type, 1000.0,
            fixedSchedule, fixedATMRate, fixedLegDayCounter,
            floatSchedule, indexSixMonths, 0.0,
            indexSixMonths->dayCounter()));
        boost::shared_ptr<VanillaSwap> otmSwap(new VanillaSwap(
            type, 1000.0,
            fixedSchedule, fixedOTMRate, fixedLegDayCounter,
            floatSchedule, indexSixMonths, 0.0,
            indexSixMonths->dayCounter()));
        boost::shared_ptr<VanillaSwap> itmSwap(new VanillaSwap(
            type, 1000.0,
            fixedSchedule, fixedITMRate, fixedLegDayCounter,
            floatSchedule, indexSixMonths, 0.0,
            indexSixMonths->dayCounter()));

        // defining the swaptions to be used in model calibration
        std::vector<Period> swaptionMaturities;
        swaptionMaturities.push_back(Period(1, Years));
        swaptionMaturities.push_back(Period(2, Years));
        swaptionMaturities.push_back(Period(3, Years));
        swaptionMaturities.push_back(Period(4, Years));
        swaptionMaturities.push_back(Period(5, Years));

        std::vector<boost::shared_ptr<CalibrationHelper> > swaptions;

        // List of times that have to be included in the timegrid
        std::list<Time> times;

        Size i;
        for (i=0; i<numRows; i++) {
            Size j = numCols - i -1; // 1x5, 2x4, 3x3, 4x2, 5x1
            Size k = i*numCols + j;
            boost::shared_ptr<Quote> vol(new SimpleQuote(swaptionVols[k]));
            swaptions.push_back(boost::shared_ptr<CalibrationHelper>(new
                SwaptionHelper(swaptionMaturities[i],
                               Period(swapLenghts[j], Years),
                               Handle<Quote>(vol),
                               indexSixMonths,
                               indexSixMonths->tenor(),
                               indexSixMonths->dayCounter(),
                               indexSixMonths->dayCounter(),
                               rhTermStructure)));
            swaptions.back()->addTimesTo(times);
        }

        // Building time-grid
        TimeGrid grid(times.begin(), times.end(), 30);


        // defining the models
        boost::shared_ptr<G2> modelG2(new G2(rhTermStructure));
        boost::shared_ptr<HullWhite> modelHW(new HullWhite(rhTermStructure));
        boost::shared_ptr<HullWhite> modelHW2(new HullWhite(rhTermStructure));
        boost::shared_ptr<BlackKarasinski> modelBK(
                                        new BlackKarasinski(rhTermStructure));


        // model calibrations

        std::cout << "G2 (analytic formulae) calibration" << std::endl;
        for (i=0; i<swaptions.size(); i++)
            swaptions[i]->setPricingEngine(boost::shared_ptr<PricingEngine>(
                new G2SwaptionEngine(modelG2, 6.0, 16)));

        calibrateModel(modelG2, swaptions);
        std::cout << "calibrated to:\n"
                  << "a     = " << modelG2->params()[0] << ", "
                  << "sigma = " << modelG2->params()[1] << "\n"
                  << "b     = " << modelG2->params()[2] << ", "
                  << "eta   = " << modelG2->params()[3] << "\n"
                  << "rho   = " << modelG2->params()[4]
                  << std::endl << std::endl;



        std::cout << "Hull-White (analytic formulae) calibration" << std::endl;
        for (i=0; i<swaptions.size(); i++)
            swaptions[i]->setPricingEngine(boost::shared_ptr<PricingEngine>(
                new JamshidianSwaptionEngine(modelHW)));

        calibrateModel(modelHW, swaptions);
        std::cout << "calibrated to:\n"
                  << "a = " << modelHW->params()[0] << ", "
                  << "sigma = " << modelHW->params()[1]
                  << std::endl << std::endl;

        std::cout << "Hull-White (numerical) calibration" << std::endl;
        for (i=0; i<swaptions.size(); i++)
            swaptions[i]->setPricingEngine(boost::shared_ptr<PricingEngine>(
                                     new TreeSwaptionEngine(modelHW2, grid)));

        calibrateModel(modelHW2, swaptions);
        std::cout << "calibrated to:\n"
                  << "a = " << modelHW2->params()[0] << ", "
                  << "sigma = " << modelHW2->params()[1]
                  << std::endl << std::endl;

        std::cout << "Black-Karasinski (numerical) calibration" << std::endl;
        for (i=0; i<swaptions.size(); i++)
            swaptions[i]->setPricingEngine(boost::shared_ptr<PricingEngine>(
                                      new TreeSwaptionEngine(modelBK, grid)));

        calibrateModel(modelBK, swaptions);
        std::cout << "calibrated to:\n"
                  << "a = " << modelBK->params()[0] << ", "
                  << "sigma = " << modelBK->params()[1]
                  << std::endl << std::endl;


        // ATM Bermudan swaption pricing

        std::cout << "Payer bermudan swaption "
                  << "struck at " << io::rate(fixedATMRate)
                  << " (ATM)" << std::endl;

        std::vector<Date> bermudanDates;
        const std::vector<boost::shared_ptr<CashFlow> >& leg =
            swap->fixedLeg();
        for (i=0; i<leg.size(); i++) {
            boost::shared_ptr<Coupon> coupon =
                boost::dynamic_pointer_cast<Coupon>(leg[i]);
            bermudanDates.push_back(coupon->accrualStartDate());
        }

        boost::shared_ptr<Exercise> bermudanExercise(
                                         new BermudanExercise(bermudanDates));

        Swaption bermudanSwaption(atmSwap, bermudanExercise);

        // Do the pricing for each model

        // G2 price the European swaption here, it should switch to bermudan
        bermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new TreeSwaptionEngine(modelG2, 50)));
        std::cout << "G2 (tree):      " << bermudanSwaption.NPV() << std::endl;
        bermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new FdG2SwaptionEngine(modelG2)));
        std::cout << "G2 (fdm) :      " << bermudanSwaption.NPV() << std::endl;

        bermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new TreeSwaptionEngine(modelHW, 50)));
        std::cout << "HW (tree):      " << bermudanSwaption.NPV() << std::endl;
        bermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new FdHullWhiteSwaptionEngine(modelHW)));
        std::cout << "HW (fdm) :      " << bermudanSwaption.NPV() << std::endl;

        bermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new TreeSwaptionEngine(modelHW2, 50)));
        std::cout << "HW (num, tree): " << bermudanSwaption.NPV() << std::endl;
        bermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new FdHullWhiteSwaptionEngine(modelHW2)));
        std::cout << "HW (num, fdm) : " << bermudanSwaption.NPV() << std::endl;

        bermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new TreeSwaptionEngine(modelBK, 50)));
        std::cout << "BK:             " << bermudanSwaption.NPV() << std::endl;


        // OTM Bermudan swaption pricing

        std::cout << "Payer bermudan swaption "
                  << "struck at " << io::rate(fixedOTMRate)
                  << " (OTM)" << std::endl;

        Swaption otmBermudanSwaption(otmSwap,bermudanExercise);

        // Do the pricing for each model
        otmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new TreeSwaptionEngine(modelG2, 300)));
        std::cout << "G2 (tree):       " << otmBermudanSwaption.NPV()
                  << std::endl;
        otmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new FdG2SwaptionEngine(modelG2)));
        std::cout << "G2 (fdm) :       " << otmBermudanSwaption.NPV()
                  << std::endl;

        otmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new TreeSwaptionEngine(modelHW, 50)));
        std::cout << "HW (tree):       " << otmBermudanSwaption.NPV()
                  << std::endl;
        otmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new FdHullWhiteSwaptionEngine(modelHW)));
        std::cout << "HW (fdm) :       " << otmBermudanSwaption.NPV()
                  << std::endl;

        otmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new TreeSwaptionEngine(modelHW2, 50)));
        std::cout << "HW (num, tree):  " << otmBermudanSwaption.NPV()
                  << std::endl;
        otmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new FdHullWhiteSwaptionEngine(modelHW2)));
        std::cout << "HW (num, fdm):   " << otmBermudanSwaption.NPV()
                  << std::endl;

        otmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new TreeSwaptionEngine(modelBK, 50)));
        std::cout << "BK:              " << otmBermudanSwaption.NPV()
                  << std::endl;


        // ITM Bermudan swaption pricing

        std::cout << "Payer bermudan swaption "
                  << "struck at " << io::rate(fixedITMRate)
                  << " (ITM)" << std::endl;

        Swaption itmBermudanSwaption(itmSwap,bermudanExercise);

        // Do the pricing for each model
        itmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new TreeSwaptionEngine(modelG2, 50)));
        std::cout << "G2 (tree):       " << itmBermudanSwaption.NPV()
                  << std::endl;
        itmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new FdG2SwaptionEngine(modelG2)));
        std::cout << "G2 (fdm) :       " << itmBermudanSwaption.NPV()
                  << std::endl;

        itmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new TreeSwaptionEngine(modelHW, 50)));
        std::cout << "HW (tree):       " << itmBermudanSwaption.NPV()
                  << std::endl;
        itmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new FdHullWhiteSwaptionEngine(modelHW)));
        std::cout << "HW (fdm) :       " << itmBermudanSwaption.NPV()
                  << std::endl;

        itmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new TreeSwaptionEngine(modelHW2, 50)));
        std::cout << "HW (num, tree):  " << itmBermudanSwaption.NPV()
                  << std::endl;
        itmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new FdHullWhiteSwaptionEngine(modelHW2)));
        std::cout << "HW (num, fdm) :  " << itmBermudanSwaption.NPV()
                  << std::endl;

        itmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
            new TreeSwaptionEngine(modelBK, 50)));
        std::cout << "BK:              " << itmBermudanSwaption.NPV()
                  << std::endl;

        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;
    }
}
Exemplo n.º 18
0
/* TODO: Instrument interface
 - swaps: euro swaps, usd
 - bonds:  UST, corp, tax-exempt munis
 */
int main () 
{
    cout << "QuantLib Version #: " << QL_VERSION << endl ;    
        
    Calendar calendar = TARGET();
//    Date todaysDate = TARGET().adjust( Date(20, September, 2004) );
    Date todaysDate = TARGET().adjust( Date(28, May, 2012) );
    
    Settings::instance().evaluationDate() = todaysDate;
    cout << "settings: " << &Settings::instance() << endl;
    cout << "\n\nToday: " << todaysDate << endl;
    
    string futtenors[] = {"ED1", "ED2", "ED3", "ED4", "ED5", "ED6", "ED7", "ED8"};
    double futspots[] = {96.2875, 96.7875, 96.9875, 96.6875, 96.4875, 96.3875, 96.2875, 96.0875};
    
    string depotenors[] = {"1W", "1M", "3M", "6M", "9M", "1y"};
    double depospots[] = {.0382, 0.0372, 0.0363, 0.0353, 0.0348, 0.0345};
    string swaptenors[] = {"2y", "3y", "5y", "10Y", "15Y"};
    double swapspots[] = {0.037125, 0.0398, 0.0443, 0.05165, 0.055175};
    
    cout << "test sc1" << endl;
    RateHelperCurve acurve = RateHelperCurve(EURiborCurve("6M"));
    acurve.update(depotenors, depospots, 6, 
                  swaptenors, swapspots, 5,
                  todaysDate);
    
    cout << "quote:  " << acurve.tenorquote("10Y") << endl;
    
    cout << "test tenors\n" << Period(6, Months) << " | " << Tenor("6M") << endl;
    cout << "fixing calendar: " << acurve.calendar() << endl;
    
    /*********************
     * SWAPS TO BE PRICED *
     **********************/

    RelinkableHandle<YieldTermStructure>forecastingTermStructure = acurve.forecastingTermStructure();
    
    // 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 settlementDate = acurve.referenceDate(); 
    Date maturity = acurve.referenceDate() + 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);
    
    cout << "swap." << endl;
    
    boost::shared_ptr<PricingEngine> swapEngine = createPriceEngine<DiscountingSwapEngine>(
                                                                                           acurve.discountingTermStructure()
                                                                                           );
    
    spot5YearSwap.setPricingEngine(swapEngine);
    oneYearForward5YearSwap.setPricingEngine(swapEngine);
    
    Real NPV;
    Rate fairRate;
    Spread fairSpread;
    
    cout << "spot " << endl;
    NPV = spot5YearSwap.NPV();
    fairSpread = spot5YearSwap.fairSpread();
    fairRate = spot5YearSwap.fairRate();
    
    cout << std::setprecision(2) << std::setw(12) << std::fixed <<
    "NPV : " << NPV << 
    "   | Fair Spread: " << io::rate(fairSpread) << 
    "   | Fair Rate: " << io::rate(fairRate) << endl;
    
    cout << std::setprecision(2) << std::setw(12) << std::fixed <<
    "fx NPV : " << spot5YearSwap.fixedLegNPV() << 
    "   | fx NPV : " << spot5YearSwap.floatingLegNPV() << endl; 
    
    cout << "forward " << endl;
    NPV = oneYearForward5YearSwap.NPV();
    fairSpread = oneYearForward5YearSwap.fairSpread();
    fairRate = oneYearForward5YearSwap.fairRate();
    
    cout << std::setprecision(2) << std::setw(12) << std::fixed <<
    "NPV : " << NPV << 
    "   | Fair Spread: " << io::rate(fairSpread) << 
    "   | Fair Rate: " << io::rate(fairRate) << endl;
    
    cout << std::setprecision(2) << std::setw(12) << std::fixed <<
    "fx NPV : " << oneYearForward5YearSwap.fixedLegNPV() << 
    "   | fx NPV : " << oneYearForward5YearSwap.floatingLegNPV() << endl; 
    
    cout << "test libor clone" << endl;
    RelinkableHandle<YieldTermStructure> indexTermStructure;
    boost::shared_ptr<IborIndex> libor3m(new USDLibor(Period(3, Months), 
                                                      indexTermStructure));
    
    Handle<YieldTermStructure>testTS = acurve.forecastingTermStructure();
    boost::shared_ptr<IborIndex> newlib = libor3m->clone(testTS);
    
    // If one wanted a USD Libor index....
    USDLiborBase testIndex;
    
    cout << "\n\nSwap to compare to first swap " << endl;
    cout << "Qswap" << endl;
    cout << "mty: " << maturity << " | cpn: " << io::rate(fixedRate) << endl;
    EuriborBase euribor(6, Months);
    
    FixedFloatSwap qswp(settlementDate,
                        maturity,
                        fixedRate,
                        euribor(acurve.yieldTermStructurePtr()),
                        FixedPayer,
                        0.0,
                        1000000.0,
                        Annual,
                        Thirty360(Thirty360::European),
                        Unadjusted,
                        Semiannual,
                        Actual360(),
                        ModifiedFollowing,
                        TARGET()
                        );
    
    qswp.setPricingEngine(swapEngine);
    
    cout << std::setprecision(2) << std::setw(12) << std::fixed <<
    "NPV : " << qswp.NPV() << 
    "   | Fair Spread: " << io::rate(qswp.fairSpread()) << 
    "   | Fair Rate: " << io::rate(qswp.fairRate()) << endl; 
    
    cout << std::setprecision(2) << std::setw(12) << std::fixed <<
    "fx NPV : " << qswp.fixedLegNPV() << 
    "   | fl NPV : " << qswp.floatingLegNPV() << endl; 
    
    cout << "Inspect Legs" << endl << endl;
    Leg fixedLeg = qswp.fixedLeg();
    Leg floatingLeg = qswp.floatingLeg();
    
    cout << "Fixed: " << endl;
    Leg::iterator fxIt;
    int cfCount =0;
    Date cfDate;
    double cfAmt;
    double cfDF;
    double cfNPV = 0.0;
    for (fxIt=fixedLeg.begin(); fxIt < fixedLeg.end(); fxIt++) {
        cfDate = (*fxIt)->date();
        cfAmt = (*fxIt)->amount();
        cfDF = acurve.discount((*fxIt)->date());
        cfNPV += cfAmt*cfDF;
        
        cout << cfCount++ << ") " 
        << std::setw(24) << cfDate << " | "  << std::setw(12) 
        << cfAmt << " | " 
        << std::setprecision(6) << cfDF << " | " 
        << std::setprecision(2) << cfNPV
        << endl;
    }

    cout << "Floating: " << endl;
    Leg::iterator flIt;
    cfCount =0;
    cfNPV = 0.0;
    for (flIt=floatingLeg.begin(); flIt < floatingLeg.end(); flIt++) {
        cfDate = (*flIt)->date();
        cfAmt = (*flIt)->amount();
        cfDF = acurve.discount((*flIt)->date());
        cfNPV += cfAmt*cfDF;
        
        cout << cfCount++ << ") " 
        << std::setw(24) << cfDate << " | "  << std::setw(12) 
        << cfAmt << " | " 
        << std::setprecision(6) << cfDF << " | " 
        << std::setprecision(2) << cfNPV
        << endl;
    }
    
    cout << "swp2 " << endl;
    
    SwapType<Euribor> euriborswaps(Annual,
                                   Thirty360(Thirty360::European),
                                   Unadjusted,
                                   Semiannual,
                                   Actual360(),
                                   ModifiedFollowing,
                                   TARGET()
                                   );
    
    cout << "create" << endl;
    boost::shared_ptr<FixedFloatSwap> qswp2 = euriborswaps.create(settlementDate,
                                                                  maturity,
                                                                  fixedRate);
    
    cout << "pricing" << endl;
    qswp2->setEngine(acurve);
    
    cout << "link" << endl;
    euriborswaps.linkIndex(acurve);
    
    cout << std::setprecision(2) << std::setw(12) << std::fixed <<
    "NPV : " << qswp2->NPV() << 
    "   | Fair Spread: " << io::rate(qswp2->fairSpread()) << 
    "   | Fair Rate: " << io::rate(qswp2->fairRate()) << endl; 
    
    cout << std::setprecision(2) << std::setw(12) << std::fixed <<
    "fx NPV : " << qswp2->fixedLegNPV() << 
    "   | fx NPV : " << qswp2->floatingLegNPV() << endl; 
    
    cout << "\nSwap 3: forward" << endl;
    boost::shared_ptr<FixedFloatSwap> qswp3 = euriborswaps.create(fwdStart,
                                                                  fwdMaturity,
                                                                  fixedRate);
    cout << "fixed rate: " << qswp3->fixedRate() << endl;
    qswp3->setPricingEngine(swapEngine);
    euriborswaps.linkIndexTo(acurve.yieldTermStructurePtr());
    
    cout << std::setprecision(2) << std::setw(12) << std::fixed <<
    "NPV : " << qswp3->NPV() << 
    "   | Fair Spread: " << io::rate(qswp3->fairSpread()) << 
    "   | Fair Rate: " << io::rate(qswp3->fairRate()) << endl; 
    
    cout << std::setprecision(2) << std::setw(12) << std::fixed <<
    "fx NPV : " << qswp3->fixedLegNPV() << 
    "   | fx NPV : " << qswp3->floatingLegNPV() << endl; 
    
    cout << "\n\nBonds" << endl;
    
    boost::shared_ptr<BulletBond> bond1(new BulletBond(.045, 
                                                       Date(15, May, 2017), 
                                                       Date(15, May, 2003))
                                        );
    
    cout << "mty: " << bond1->maturityDate() << endl;
    cout << "stl: " << bond1->settlementDate() << endl;
    
    cout << "test" << endl;
    bond1->setEngine(acurve);
    
    cout << "bondprice: " ;
    double prc = bond1->cleanPrice();
    cout << std::setprecision(3) << prc << endl;
    
    cout << "Yield: " ;
    double yld = bond1->yield(prc, bond1->dayCounter(), Compounded, bond1->frequency());
    cout << io::rate(yld) << endl;
    
    cout << "\n\nIMM Stuff\n";
    cout << "settle: " << settlementDate << endl;
    Date  imm = IMM::nextDate(settlementDate);
    string immcode = IMM::code(imm);
    
    Date imm2 = imm_nextDate(imm);
    string immcode2 = imm_nextCode(immcode);
    
    cout << "date: " << imm << " | code: " << immcode << endl; 
    cout << "date: " << imm2 << " | code: " << immcode2 << endl; 
    
    cout << "ED3: " << FuturesTenor("ED3") << endl;
    
    CurveMap depocurve;
    CurveMap futscurve;
    CurveMap swapcurve;
    RateHelperCurve rhcurve( EURiborCurve("6M", Annual) );
    
    if (futscurve.empty()) {
        cout << "futscurve empty " << endl;
    } else {
        cout << "futscurve not empty: " << endl;
    }

    
    for (int i=0; i<2; i++) 
        depocurve[depotenors[i]] = depospots[i];
    
    for (int i=0; i<6; i++) 
        futscurve[futtenors[i]] = futspots[i];
    
    for (int i=0; i<5; i++) 
        swapcurve[swaptenors[i]] = swapspots[i];
    
    rhcurve.update(depocurve, futscurve, swapcurve);
    
    cout << "\n10Y: " << io::rate(rhcurve.tenorquote("10Y")) << endl;
    cout << "discount: " << rhcurve.discount(10.0) << endl;
    return 0;
}
Exemplo n.º 19
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;
    }

}
Exemplo n.º 20
0
int main(int, char* []) {

    try {

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

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

        RelinkableHandle<YieldTermStructure> euriborTermStructure;
        boost::shared_ptr<IborIndex> euribor3m(
                                       new Euribor3M(euriborTermStructure));

        Date todaysDate = Date(23, May, 2006);
        Settings::instance().evaluationDate() = todaysDate;

        Calendar calendar = euribor3m->fixingCalendar();
        Integer fixingDays = euribor3m->fixingDays();
        Date settlementDate = calendar.advance(todaysDate, fixingDays, Days);

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

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


        // 3 month term FRA quotes (index refers to monthsToStart)
        Rate threeMonthFraQuote[10];

        threeMonthFraQuote[1]=0.030;
        threeMonthFraQuote[2]=0.031;
        threeMonthFraQuote[3]=0.032;
        threeMonthFraQuote[6]=0.033;
        threeMonthFraQuote[9]=0.034;

        /********************
         ***    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.


        // FRAs
        boost::shared_ptr<SimpleQuote> fra1x4Rate(
                                      new SimpleQuote(threeMonthFraQuote[1]));
        boost::shared_ptr<SimpleQuote> fra2x5Rate(
                                      new SimpleQuote(threeMonthFraQuote[2]));
        boost::shared_ptr<SimpleQuote> fra3x6Rate(
                                      new SimpleQuote(threeMonthFraQuote[3]));
        boost::shared_ptr<SimpleQuote> fra6x9Rate(
                                      new SimpleQuote(threeMonthFraQuote[6]));
        boost::shared_ptr<SimpleQuote> fra9x12Rate(
                                      new SimpleQuote(threeMonthFraQuote[9]));

        RelinkableHandle<Quote> h1x4;  h1x4.linkTo(fra1x4Rate);
        RelinkableHandle<Quote> h2x5;  h2x5.linkTo(fra2x5Rate);
        RelinkableHandle<Quote> h3x6;  h3x6.linkTo(fra3x6Rate);
        RelinkableHandle<Quote> h6x9;  h6x9.linkTo(fra6x9Rate);
        RelinkableHandle<Quote> h9x12; h9x12.linkTo(fra9x12Rate);

        /*********************
         ***  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.

        DayCounter fraDayCounter = euribor3m->dayCounter();
        BusinessDayConvention convention = euribor3m->businessDayConvention();
        bool endOfMonth = euribor3m->endOfMonth();

        boost::shared_ptr<RateHelper> fra1x4(
                           new FraRateHelper(h1x4, 1, 4,
                                             fixingDays, calendar, convention,
                                             endOfMonth, fraDayCounter));

        boost::shared_ptr<RateHelper> fra2x5(
                           new FraRateHelper(h2x5, 2, 5,
                                             fixingDays, calendar, convention,
                                             endOfMonth, fraDayCounter));

        boost::shared_ptr<RateHelper> fra3x6(
                           new FraRateHelper(h3x6, 3, 6,
                                             fixingDays, calendar, convention,
                                             endOfMonth, fraDayCounter));

        boost::shared_ptr<RateHelper> fra6x9(
                           new FraRateHelper(h6x9, 6, 9,
                                             fixingDays, calendar, convention,
                                             endOfMonth, fraDayCounter));

        boost::shared_ptr<RateHelper> fra9x12(
                           new FraRateHelper(h9x12, 9, 12,
                                             fixingDays, calendar, convention,
                                             endOfMonth, fraDayCounter));


        /*********************
         **  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 FRA curve
        std::vector<boost::shared_ptr<RateHelper> > fraInstruments;

        fraInstruments.push_back(fra1x4);
        fraInstruments.push_back(fra2x5);
        fraInstruments.push_back(fra3x6);
        fraInstruments.push_back(fra6x9);
        fraInstruments.push_back(fra9x12);

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


        // Term structures used for pricing/discounting

        RelinkableHandle<YieldTermStructure> discountingTermStructure;
        discountingTermStructure.linkTo(fraTermStructure);


        /***********************
         ***  construct FRA's ***
         ***********************/

        Calendar fraCalendar = euribor3m->fixingCalendar();
        BusinessDayConvention fraBusinessDayConvention =
            euribor3m->businessDayConvention();
        Position::Type fraFwdType = Position::Long;
        Real fraNotional = 100.0;
        const Integer FraTermMonths = 3;
        Integer monthsToStart[] = { 1, 2, 3, 6, 9 };

        euriborTermStructure.linkTo(fraTermStructure);

        cout << endl;
        cout << "Test FRA construction, NPV calculation, and FRA purchase"
             << endl
             << endl;

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

            Date fraValueDate = fraCalendar.advance(
                                       settlementDate,monthsToStart[i],Months,
                                       fraBusinessDayConvention);

            Date fraMaturityDate = fraCalendar.advance(
                                            fraValueDate,FraTermMonths,Months,
                                            fraBusinessDayConvention);

            Rate fraStrikeRate = threeMonthFraQuote[monthsToStart[i]];

            ForwardRateAgreement myFRA(fraValueDate, fraMaturityDate,
                                       fraFwdType,fraStrikeRate,
                                       fraNotional, euribor3m,
                                       discountingTermStructure);

            cout << "3m Term FRA, Months to Start: "
                 << monthsToStart[i]
                 << endl;
            cout << "strike FRA rate: "
                 << io::rate(fraStrikeRate)
                 << endl;
            cout << "FRA 3m forward rate: "
                 << myFRA.forwardRate()
                 << endl;
            cout << "FRA market quote: "
                 << io::rate(threeMonthFraQuote[monthsToStart[i]])
                 << endl;
            cout << "FRA spot value: "
                 << myFRA.spotValue()
                 << endl;
            cout << "FRA forward value: "
                 << myFRA.forwardValue()
                 << endl;
            cout << "FRA implied Yield: "
                 << myFRA.impliedYield(myFRA.spotValue(),
                                       myFRA.forwardValue(),
                                       settlementDate,
                                       Simple,
                                       fraDayCounter)
                 << endl;
            cout << "market Zero Rate: "
                 << discountingTermStructure->zeroRate(fraMaturityDate,
                                                       fraDayCounter,
                                                       Simple)
                 << endl;
            cout << "FRA NPV [should be zero]: "
                 << myFRA.NPV()
                 << endl
                 << endl;

        }




        cout << endl << endl;
        cout << "Now take a 100 basis-point upward shift in FRA quotes "
             << "and examine NPV"
             << endl
             << endl;

        const Real BpsShift = 0.01;

        threeMonthFraQuote[1]=0.030+BpsShift;
        threeMonthFraQuote[2]=0.031+BpsShift;
        threeMonthFraQuote[3]=0.032+BpsShift;
        threeMonthFraQuote[6]=0.033+BpsShift;
        threeMonthFraQuote[9]=0.034+BpsShift;

        fra1x4Rate->setValue(threeMonthFraQuote[1]);
        fra2x5Rate->setValue(threeMonthFraQuote[2]);
        fra3x6Rate->setValue(threeMonthFraQuote[3]);
        fra6x9Rate->setValue(threeMonthFraQuote[6]);
        fra9x12Rate->setValue(threeMonthFraQuote[9]);


        for (i=0; i<LENGTH(monthsToStart); i++) {

            Date fraValueDate = fraCalendar.advance(
                                       settlementDate,monthsToStart[i],Months,
                                       fraBusinessDayConvention);

            Date fraMaturityDate = fraCalendar.advance(
                                            fraValueDate,FraTermMonths,Months,
                                            fraBusinessDayConvention);

            Rate fraStrikeRate =
                threeMonthFraQuote[monthsToStart[i]] - BpsShift;

            ForwardRateAgreement myFRA(fraValueDate, fraMaturityDate,
                                       fraFwdType, fraStrikeRate,
                                       fraNotional, euribor3m,
                                       discountingTermStructure);

            cout << "3m Term FRA, 100 notional, Months to Start = "
                 << monthsToStart[i]
                 << endl;
            cout << "strike FRA rate: "
                 << io::rate(fraStrikeRate)
                 << endl;
            cout << "FRA 3m forward rate: "
                 << myFRA.forwardRate()
                 << endl;
            cout << "FRA market quote: "
                 << io::rate(threeMonthFraQuote[monthsToStart[i]])
                 << endl;
            cout << "FRA spot value: "
                 << myFRA.spotValue()
                 << endl;
            cout << "FRA forward value: "
                 << myFRA.forwardValue()
                 << endl;
            cout << "FRA implied Yield: "
                 << myFRA.impliedYield(myFRA.spotValue(),
                                       myFRA.forwardValue(),
                                       settlementDate,
                                       Simple,
                                       fraDayCounter)
                 << endl;
            cout << "market Zero Rate: "
                 << discountingTermStructure->zeroRate(fraMaturityDate,
                                                       fraDayCounter,
                                                       Simple)
                 << endl;
            cout << "FRA NPV [should be positive]: "
                 << myFRA.NPV()
                 << endl
                 << endl;
        }

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

        return 0;

    } catch (exception& e) {
        cerr << e.what() << endl;
        return 1;
    } catch (...) {
        cerr << "unknown error" << endl;
        return 1;
    }
}
/*Market Data ->  FRA Quote -> FRA rate helper -> Curve Building -> Construct FRA*/
int main(int, char* []) {

    try {

        boost::timer timer;
        std::cout << std::endl;
        std::ifstream       file("data.csv");
        CSVRow data_row;
        file >> data_row;
        const size_t num_data = data_row.size()/2;



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

        RelinkableHandle<YieldTermStructure> euriborTermStructure;
        boost::shared_ptr<IborIndex> euribor3m(
                                       new Euribor3M(euriborTermStructure));

        Date todaysDate = Date(23, May, 2006);
        Settings::instance().evaluationDate() = todaysDate;

        Calendar calendar = euribor3m->fixingCalendar();
        Integer fixingDays = euribor3m->fixingDays();
        Date settlementDate = calendar.advance(todaysDate, fixingDays, Days);

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

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


        // 3 month term FRA quotes (index refers to monthsToStart)
        vector <stFRAMarketData> vecMarketData;

        for(size_t i = 0 ; i < num_data; i++) {
          stFRAMarketData element_data;
          convertFromString(element_data.iMonthToStart, data_row[i]);
          element_data.iTermDuration = 3; //3 month term
          convertFromString(element_data.rateFraQuote, data_row[i + num_data]);
          vecMarketData.push_back(element_data);
        }



        /********************
         ***    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.


        // FRAs
        std::vector <boost::shared_ptr<SimpleQuote> > vecFRAQuote;

        for(size_t i = 0 ; i < num_data; i++) {
          boost::shared_ptr<SimpleQuote> fraRate(new SimpleQuote(vecMarketData[i].rateFraQuote));
          vecFRAQuote.push_back(fraRate);
        }
        std::vector <RelinkableHandle<Quote> > vecQuoteHandle;

        for(size_t i = 0 ; i < num_data; i++) { 
          RelinkableHandle<Quote> hQuote;
          hQuote.linkTo(vecFRAQuote[i]);
          vecQuoteHandle.push_back(hQuote);
        }

        /*********************
         ***  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.

        DayCounter fraDayCounter = euribor3m->dayCounter();
        BusinessDayConvention convention = euribor3m->businessDayConvention();
        bool endOfMonth = euribor3m->endOfMonth();
        std::vector < boost::shared_ptr<RateHelper> > vecRateHelper;

        for(size_t i = 0 ; i < num_data; i++) {
          boost::shared_ptr<RateHelper> fra_helper(
                           new FraRateHelper(vecQuoteHandle[i],vecMarketData[i].iMonthToStart, 
                                             vecMarketData[i].iMonthToStart + vecMarketData[i].iTermDuration,
                                             fixingDays, calendar, convention,
                                             endOfMonth, fraDayCounter));

          vecRateHelper.push_back(fra_helper);
        }

        /*********************
         **  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 FRA curve
        boost::shared_ptr<YieldTermStructure> fraTermStructure(
                     new PiecewiseYieldCurve<Discount,LogLinear>(
                                         settlementDate, vecRateHelper,
                                         termStructureDayCounter,
                                         tolerance));

        // Term structures used for pricing/discounting

        RelinkableHandle<YieldTermStructure> discountingTermStructure;
        discountingTermStructure.linkTo(fraTermStructure);


        /***********************
         ***  construct FRA's ***
         ***********************/

        Calendar fraCalendar = euribor3m->fixingCalendar();
        BusinessDayConvention fraBusinessDayConvention =
            euribor3m->businessDayConvention();
        Position::Type fraFwdType = Position::Long;
        Real fraNotional = 100.0;
        //const Integer FraTermMonths = 3;
        //Integer monthsToStart[] = { 1, 2, 3, 6, 9 };

        euriborTermStructure.linkTo(fraTermStructure);

        cout << endl;
        cout << "Test FRA construction, NPV calculation, and FRA purchase"
             << endl
             << endl;

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

            Date fraValueDate = fraCalendar.advance(
                                       settlementDate,vecMarketData[i].iMonthToStart, Months,
                                       fraBusinessDayConvention);

            Date fraMaturityDate = fraCalendar.advance(
                                            fraValueDate,vecMarketData[i].iTermDuration,Months,
                                            fraBusinessDayConvention);

            Rate fraStrikeRate = vecMarketData[i].rateFraQuote;

            ForwardRateAgreement myFRA(fraValueDate, fraMaturityDate,
                                       fraFwdType,fraStrikeRate,
                                       fraNotional, euribor3m,
                                       discountingTermStructure);

            cout << vecMarketData[i].iTermDuration<<"m Term FRA, Months to Start: "
                 << vecMarketData[i].iMonthToStart
                 << endl;
            cout << "strike FRA rate: "
                 << io::rate(fraStrikeRate)
                 << endl;
            cout << "FRA 3m forward rate: "
                 << myFRA.forwardRate()
                 << endl;
            cout << "FRA market quote: "
                 << io::rate(vecMarketData[i].rateFraQuote)
                 << endl;
            cout << "FRA spot value: "
                 << myFRA.spotValue()
                 << endl;
            cout << "FRA forward value: "
                 << myFRA.forwardValue()
                 << endl;
            cout << "FRA implied Yield: "
                 << myFRA.impliedYield(myFRA.spotValue(),
                                       myFRA.forwardValue(),
                                       settlementDate,
                                       Simple,
                                       fraDayCounter)
                 << endl;
            cout << "market Zero Rate: "
                 << discountingTermStructure->zeroRate(fraMaturityDate,
                                                       fraDayCounter,
                                                       Simple)
                 << endl;
            cout << "FRA NPV [should be zero]: "
                 << myFRA.NPV()
                 << endl
                 << endl;

        }




        cout << endl << endl;
        cout << "Now take a 100 basis-point upward shift in FRA quotes "
             << "and examine NPV"
             << endl
             << endl;

        const Real BpsShift = 0.01;

        for(size_t i = 0; i< num_data; i++ ) {
          vecMarketData[i].rateFraQuote += BpsShift;
          vecFRAQuote[i]->setValue(vecMarketData[i].rateFraQuote);
        }

        for (i=0; i<num_data; i++) {

            Date fraValueDate = fraCalendar.advance(
                                       settlementDate,vecMarketData[i].iMonthToStart,Months,
                                       fraBusinessDayConvention);

            Date fraMaturityDate = fraCalendar.advance(
                                            fraValueDate,vecMarketData[i].iTermDuration,Months,
                                            fraBusinessDayConvention);

            Rate fraStrikeRate =
                vecMarketData[i].rateFraQuote - BpsShift;

            ForwardRateAgreement myFRA(fraValueDate, fraMaturityDate,
                                       fraFwdType, fraStrikeRate,
                                       fraNotional, euribor3m,
                                       discountingTermStructure);

            cout << vecMarketData[i].iTermDuration <<"m Term FRA, 100 notional, Months to Start = "
                 << vecMarketData[i].iMonthToStart
                 << endl;
            cout << "strike FRA rate: "
                 << io::rate(fraStrikeRate)
                 << endl;
            cout << "FRA 3m forward rate: "
                 << myFRA.forwardRate()
                 << endl;
            cout << "FRA market quote: "
                 << io::rate(vecMarketData[i].rateFraQuote)
                 << endl;
            cout << "FRA spot value: "
                 << myFRA.spotValue()
                 << endl;
            cout << "FRA forward value: "
                 << myFRA.forwardValue()
                 << endl;
            cout << "FRA implied Yield: "
                 << myFRA.impliedYield(myFRA.spotValue(),
                                       myFRA.forwardValue(),
                                       settlementDate,
                                       Simple,
                                       fraDayCounter)
                 << endl;
            cout << "market Zero Rate: "
                 << discountingTermStructure->zeroRate(fraMaturityDate,
                                                       fraDayCounter,
                                                       Simple)
                 << endl;
            cout << "FRA NPV [should be positive]: "
                 << myFRA.NPV()
                 << endl
                 << endl;
        }

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

        return 0;

    } catch (exception& e) {
        cerr << e.what() << endl;
        return 1;
    } catch (...) {
        cerr << "unknown error" << endl;
        return 1;
    }
}
Exemplo n.º 22
0
    Schedule::Schedule(Date effectiveDate,
                       const Date& terminationDate,
                       const Period& tenor,
                       const Calendar& cal,
                       BusinessDayConvention convention,
                       BusinessDayConvention terminationDateConvention,
                       DateGeneration::Rule rule,
                       bool endOfMonth,
                       const Date& first,
                       const Date& nextToLast)
    : tenor_(tenor), calendar_(cal), convention_(convention),
      terminationDateConvention_(terminationDateConvention), rule_(rule),
      endOfMonth_(allowsEndOfMonth(tenor) ? endOfMonth : false),
      firstDate_(first==effectiveDate ? Date() : first),
      nextToLastDate_(nextToLast==terminationDate ? Date() : nextToLast)
    {
        // sanity checks
        QL_REQUIRE(terminationDate != Date(), "null termination date");

        // in many cases (e.g. non-expired bonds) the effective date is not
        // really necessary. In these cases a decent placeholder is enough
        if (effectiveDate==Date() && first==Date()
                                  && rule==DateGeneration::Backward) {
            Date evalDate = Settings::instance().evaluationDate();
            QL_REQUIRE(evalDate < terminationDate, "null effective date");
            Natural y;
            if (nextToLast != Date()) {
                y = (nextToLast - evalDate)/366 + 1;
                effectiveDate = nextToLast - y*Years;
            } else {
                y = (terminationDate - evalDate)/366 + 1;
                effectiveDate = terminationDate - y*Years;
            }
        } else
            QL_REQUIRE(effectiveDate != Date(), "null effective date");

        QL_REQUIRE(effectiveDate < terminationDate,
                   "effective date (" << effectiveDate
                   << ") later than or equal to termination date ("
                   << terminationDate << ")");

        if (tenor.length()==0)
            rule_ = DateGeneration::Zero;
        else
            QL_REQUIRE(tenor.length()>0,
                       "non positive tenor (" << tenor << ") not allowed");

        if (firstDate_ != Date()) {
            switch (*rule_) {
              case DateGeneration::Backward:
              case DateGeneration::Forward:
                QL_REQUIRE(firstDate_ > effectiveDate &&
                           firstDate_ < terminationDate,
                           "first date (" << firstDate_ <<
                           ") out of effective-termination date range [" <<
                           effectiveDate << ", " << terminationDate << ")");
                // we should ensure that the above condition is still
                // verified after adjustment
                break;
              case DateGeneration::ThirdWednesday:
                  QL_REQUIRE(IMM::isIMMdate(firstDate_, false),
                             "first date (" << firstDate_ <<
                             ") is not an IMM date");
                break;
              case DateGeneration::Zero:
              case DateGeneration::Twentieth:
              case DateGeneration::TwentiethIMM:
              case DateGeneration::OldCDS:
              case DateGeneration::CDS:
                QL_FAIL("first date incompatible with " << *rule_ <<
                        " date generation rule");
              default:
                QL_FAIL("unknown rule (" << Integer(*rule_) << ")");
            }
        }
        if (nextToLastDate_ != Date()) {
            switch (*rule_) {
              case DateGeneration::Backward:
              case DateGeneration::Forward:
                QL_REQUIRE(nextToLastDate_ > effectiveDate &&
                           nextToLastDate_ < terminationDate,
                           "next to last date (" << nextToLastDate_ <<
                           ") out of effective-termination date range (" <<
                           effectiveDate << ", " << terminationDate << "]");
                // we should ensure that the above condition is still
                // verified after adjustment
                break;
              case DateGeneration::ThirdWednesday:
                QL_REQUIRE(IMM::isIMMdate(nextToLastDate_, false),
                           "next-to-last date (" << nextToLastDate_ <<
                           ") is not an IMM date");
                break;
              case DateGeneration::Zero:
              case DateGeneration::Twentieth:
              case DateGeneration::TwentiethIMM:
              case DateGeneration::OldCDS:
              case DateGeneration::CDS:
                QL_FAIL("next to last date incompatible with " << *rule_ <<
                        " date generation rule");
              default:
                QL_FAIL("unknown rule (" << Integer(*rule_) << ")");
            }
        }


        // calendar needed for endOfMonth adjustment
        Calendar nullCalendar = NullCalendar();
        Integer periods = 1;
        Date seed, exitDate;
        switch (*rule_) {

          case DateGeneration::Zero:
            tenor_ = 0*Years;
            dates_.push_back(effectiveDate);
            dates_.push_back(terminationDate);
            isRegular_.push_back(true);
            break;

          case DateGeneration::Backward:

            dates_.push_back(terminationDate);

            seed = terminationDate;
            if (nextToLastDate_ != Date()) {
                dates_.insert(dates_.begin(), nextToLastDate_);
                Date temp = nullCalendar.advance(seed,
                    -periods*(*tenor_), convention, *endOfMonth_);
                if (temp!=nextToLastDate_)
                    isRegular_.insert(isRegular_.begin(), false);
                else
                    isRegular_.insert(isRegular_.begin(), true);
                seed = nextToLastDate_;
            }

            exitDate = effectiveDate;
            if (firstDate_ != Date())
                exitDate = firstDate_;

            for (;;) {
                Date temp = nullCalendar.advance(seed,
                    -periods*(*tenor_), convention, *endOfMonth_);
                if (temp < exitDate) {
                    if (firstDate_ != Date() &&
                        (calendar_.adjust(dates_.front(),convention)!=
                         calendar_.adjust(firstDate_,convention))) {
                        dates_.insert(dates_.begin(), firstDate_);
                        isRegular_.insert(isRegular_.begin(), false);
                    }
                    break;
                } else {
                    // skip dates that would result in duplicates
                    // after adjustment
                    if (calendar_.adjust(dates_.front(),convention)!=
                        calendar_.adjust(temp,convention)) {
                        dates_.insert(dates_.begin(), temp);
                        isRegular_.insert(isRegular_.begin(), true);
                    }
                    ++periods;
                }
            }

            if (calendar_.adjust(dates_.front(),convention)!=
                calendar_.adjust(effectiveDate,convention)) {
                dates_.insert(dates_.begin(), effectiveDate);
                isRegular_.insert(isRegular_.begin(), false);
            }
            break;

          case DateGeneration::Twentieth:
          case DateGeneration::TwentiethIMM:
          case DateGeneration::ThirdWednesday:
          case DateGeneration::OldCDS:
          case DateGeneration::CDS:
            QL_REQUIRE(!*endOfMonth_,
                       "endOfMonth convention incompatible with " << *rule_ <<
                       " date generation rule");
          // fall through
          case DateGeneration::Forward:

            if (*rule_ == DateGeneration::CDS) {
                dates_.push_back(previousTwentieth(effectiveDate,
                                                   DateGeneration::CDS));
            } else {
                dates_.push_back(effectiveDate);
            }

            seed = dates_.back();

            if (firstDate_!=Date()) {
                dates_.push_back(firstDate_);
                Date temp = nullCalendar.advance(seed, periods*(*tenor_),
                                                 convention, *endOfMonth_);
                if (temp!=firstDate_)
                    isRegular_.push_back(false);
                else
                    isRegular_.push_back(true);
                seed = firstDate_;
            } else if (*rule_ == DateGeneration::Twentieth ||
                       *rule_ == DateGeneration::TwentiethIMM ||
                       *rule_ == DateGeneration::OldCDS ||
                       *rule_ == DateGeneration::CDS) {
                Date next20th = nextTwentieth(effectiveDate, *rule_);
                if (*rule_ == DateGeneration::OldCDS) {
                    // distance rule inforced in natural days
                    static const BigInteger stubDays = 30;
                    if (next20th - effectiveDate < stubDays) {
                        // +1 will skip this one and get the next
                        next20th = nextTwentieth(next20th + 1, *rule_);
                    }
                }
                if (next20th != effectiveDate) {
                    dates_.push_back(next20th);
                    isRegular_.push_back(false);
                    seed = next20th;
                }
            }

            exitDate = terminationDate;
            if (nextToLastDate_ != Date())
                exitDate = nextToLastDate_;

            for (;;) {
                Date temp = nullCalendar.advance(seed, periods*(*tenor_),
                                                 convention, *endOfMonth_);
                if (temp > exitDate) {
                    if (nextToLastDate_ != Date() &&
                        (calendar_.adjust(dates_.back(),convention)!=
                         calendar_.adjust(nextToLastDate_,convention))) {
                        dates_.push_back(nextToLastDate_);
                        isRegular_.push_back(false);
                    }
                    break;
                } else {
                    // skip dates that would result in duplicates
                    // after adjustment
                    if (calendar_.adjust(dates_.back(),convention)!=
                        calendar_.adjust(temp,convention)) {
                        dates_.push_back(temp);
                        isRegular_.push_back(true);
                    }
                    ++periods;
                }
            }

            if (calendar_.adjust(dates_.back(),terminationDateConvention)!=
                calendar_.adjust(terminationDate,terminationDateConvention)) {
                if (*rule_ == DateGeneration::Twentieth ||
                    *rule_ == DateGeneration::TwentiethIMM ||
                    *rule_ == DateGeneration::OldCDS ||
                    *rule_ == DateGeneration::CDS) {
                    dates_.push_back(nextTwentieth(terminationDate, *rule_));
                    isRegular_.push_back(true);
                } else {
                    dates_.push_back(terminationDate);
                    isRegular_.push_back(false);
                }
            }

            break;

          default:
            QL_FAIL("unknown rule (" << Integer(*rule_) << ")");
        }

        // adjustments
        if (*rule_==DateGeneration::ThirdWednesday)
            for (Size i=1; i<dates_.size()-1; ++i)
                dates_[i] = Date::nthWeekday(3, Wednesday,
                                             dates_[i].month(),
                                             dates_[i].year());

        if (*endOfMonth_ && calendar_.isEndOfMonth(seed)) {
            // adjust to end of month
            if (convention == Unadjusted) {
                for (Size i=1; i<dates_.size()-1; ++i)
                    dates_[i] = Date::endOfMonth(dates_[i]);
            } else {
                for (Size i=1; i<dates_.size()-1; ++i)
                    dates_[i] = calendar_.endOfMonth(dates_[i]);
            }
            if (terminationDateConvention != Unadjusted) {
                dates_.front() = calendar_.endOfMonth(dates_.front());
                dates_.back() = calendar_.endOfMonth(dates_.back());
            } else {
                // the termination date is the first if going backwards,
                // the last otherwise.
                if (*rule_ == DateGeneration::Backward)
                    dates_.back() = Date::endOfMonth(dates_.back());
                else
                    dates_.front() = Date::endOfMonth(dates_.front());
            }
        } else {
            // first date not adjusted for CDS schedules
            if (*rule_ != DateGeneration::OldCDS)
                dates_[0] = calendar_.adjust(dates_[0], convention);
            for (Size i=1; i<dates_.size()-1; ++i)
                dates_[i] = calendar_.adjust(dates_[i], convention);

            // termination date is NOT adjusted as per ISDA
            // specifications, unless otherwise specified in the
            // confirmation of the deal or unless we're creating a CDS
            // schedule
            if (terminationDateConvention != Unadjusted
                || *rule_ == DateGeneration::Twentieth
                || *rule_ == DateGeneration::TwentiethIMM
                || *rule_ == DateGeneration::OldCDS
                || *rule_ == DateGeneration::CDS) {
                dates_.back() = calendar_.adjust(dates_.back(),
                                                terminationDateConvention);
            }
        }

        // Final safety checks to remove extra next-to-last date, if
        // necessary.  It can happen to be equal or later than the end
        // date due to EOM adjustments (see the Schedule test suite
        // for an example).
        if (dates_.size() >= 2 && dates_[dates_.size()-2] >= dates_.back()) {
            isRegular_[dates_.size()-2] =
                (dates_[dates_.size()-2] == dates_.back());
            dates_[dates_.size()-2] = dates_.back();
            dates_.pop_back();
            isRegular_.pop_back();
        }
        if (dates_.size() >= 2 && dates_[1] <= dates_.front()) {
            isRegular_[1] =
                (dates_[1] == dates_.front());
            dates_[1] = dates_.front();
            dates_.erase(dates_.begin());
            isRegular_.erase(isRegular_.begin());
        }

        QL_ENSURE(dates_.size()>1,
            "degenerate single date (" << dates_[0] << ") schedule" <<
            "\n seed date: " << seed <<
            "\n exit date: " << exitDate <<
            "\n effective date: " << effectiveDate <<
            "\n first date: " << first <<
            "\n next to last date: " << nextToLast <<
            "\n termination date: " << terminationDate <<
            "\n generation rule: " << *rule_ <<
            "\n end of month: " << *endOfMonth_);

    }
Exemplo n.º 23
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;
    }
}
void DefaultProbabilityCurveTest::testDefaultProbability() {

    BOOST_TEST_MESSAGE("Testing default-probability structure...");

    Real hazardRate = 0.0100;
    Handle<Quote> hazardRateQuote = Handle<Quote>(
                boost::shared_ptr<Quote>(new SimpleQuote(hazardRate)));
    DayCounter dayCounter = Actual360();
    Calendar calendar = TARGET();
    Size n = 20;

    double tolerance = 1.0e-10;
    Date today = Settings::instance().evaluationDate();
    Date startDate = today;
    Date endDate = startDate;

    FlatHazardRate flatHazardRate(startDate, hazardRateQuote, dayCounter);

    for(Size i=0; i<n; i++){
        startDate = endDate;
        endDate = calendar.advance(endDate, 1, Years);

        Probability pStart = flatHazardRate.defaultProbability(startDate);
        Probability pEnd = flatHazardRate.defaultProbability(endDate);

        Probability pBetweenComputed =
            flatHazardRate.defaultProbability(startDate, endDate);

        Probability pBetween = pEnd - pStart;

        if (std::fabs(pBetween - pBetweenComputed) > tolerance)
            BOOST_ERROR(
                "Failed to reproduce probability(d1, d2) "
                << "for default probability structure\n"
                << std::setprecision(12)
                << "    calculated probability: " << pBetweenComputed << "\n"
                << "    expected probability:   " << pBetween);

        Time t2 = dayCounter.yearFraction(today, endDate);
        Probability timeProbability = flatHazardRate.defaultProbability(t2);
        Probability dateProbability =
            flatHazardRate.defaultProbability(endDate);

        if (std::fabs(timeProbability - dateProbability) > tolerance)
            BOOST_ERROR(
                "single-time probability and single-date probability do not match\n"
                << std::setprecision(10)
                << "    time probability: " << timeProbability << "\n"
                << "    date probability: " << dateProbability);

        Time t1 = dayCounter.yearFraction(today, startDate);
        timeProbability = flatHazardRate.defaultProbability(t1, t2);
        dateProbability = flatHazardRate.defaultProbability(startDate, endDate);

        if (std::fabs(timeProbability - dateProbability) > tolerance)
            BOOST_ERROR(
                "double-time probability and double-date probability do not match\n"
                << std::setprecision(10)
                << "    time probability: " << timeProbability << "\n"
                << "    date probability: " << dateProbability);
    }
}
Exemplo n.º 25
0
void QuoteTest::testForwardValueQuoteAndImpliedStdevQuote() {
    BOOST_MESSAGE(
        "Testing forward-value and implied-standard-deviation quotes...");
    Real forwardRate = .05;
    DayCounter dc = ActualActual();
    Calendar calendar = TARGET();
    boost::shared_ptr<SimpleQuote> forwardQuote(new SimpleQuote(forwardRate));
    Handle<Quote> forwardHandle(forwardQuote);
    Date evaluationDate = Settings::instance().evaluationDate();
    boost::shared_ptr<YieldTermStructure>yc (new FlatForward(
                evaluationDate, forwardHandle, dc));
    Handle<YieldTermStructure> ycHandle(yc);
    Period euriborTenor(1,Years);
    boost::shared_ptr<Index> euribor(new Euribor(euriborTenor, ycHandle));
    Date fixingDate = calendar.advance(evaluationDate, euriborTenor);
    boost::shared_ptr<ForwardValueQuote> forwardValueQuote( new
            ForwardValueQuote(euribor, fixingDate));
    Rate forwardValue =  forwardValueQuote->value();
    Rate expectedForwardValue = euribor->fixing(fixingDate, true);
    // we test if the forward value given by the quote is consistent
    // with the one directly given by the index
    if (std::fabs(forwardValue-expectedForwardValue) > 1.0e-15)
        BOOST_FAIL("Foward Value Quote quote yields " << forwardValue << "\n"
                   << "expected result is " << expectedForwardValue);
    // then we test the observer/observable chain
    Flag f;
    f.registerWith(forwardValueQuote);
    forwardQuote->setValue(0.04);
    if (!f.isUp())
        BOOST_FAIL("Observer was not notified of quote change");

    // and we retest if the values are still matching
    forwardValue =  forwardValueQuote->value();
    expectedForwardValue = euribor->fixing(fixingDate, true);
    if (std::fabs(forwardValue-expectedForwardValue) > 1.0e-15)
        BOOST_FAIL("Foward Value Quote quote yields " << forwardValue << "\n"
                   << "expected result is " << expectedForwardValue);
    // we test the ImpliedStdevQuote class
    f.unregisterWith(forwardValueQuote);
    f.lower();
    Real price = 0.02;
    Rate strike = 0.04;
    Volatility guess = .15;
    Real accuracy = 1.0e-6;
    Option::Type optionType = Option::Call;
    boost::shared_ptr<SimpleQuote> priceQuote(new SimpleQuote(price));
    Handle<Quote> priceHandle(priceQuote);
    boost::shared_ptr<ImpliedStdDevQuote> impliedStdevQuote(new
            ImpliedStdDevQuote(optionType, forwardHandle, priceHandle,
                               strike, guess, accuracy));
    Real impliedStdev = impliedStdevQuote->value();
    Real expectedImpliedStdev =
        blackFormulaImpliedStdDev(optionType, strike,
                                  forwardQuote->value(), price,
                                  1.0, 0.0, guess, 1.0e-6);
    if (std::fabs(impliedStdev-expectedImpliedStdev) > 1.0e-15)
        BOOST_FAIL("\nimpliedStdevQuote yields :" << impliedStdev <<
                   "\nexpected result is       :" << expectedImpliedStdev);
    // then we test the observer/observable chain
    boost::shared_ptr<Quote> quote = impliedStdevQuote;
    f.registerWith(quote);
    forwardQuote->setValue(0.05);
    if (!f.isUp())
        BOOST_FAIL("Observer was not notified of quote change");
    quote->value();
    f.lower();
    quote->value();
    priceQuote->setValue(0.11);
    if (!f.isUp())
        BOOST_FAIL("Observer was not notified of quote change");

}
Exemplo n.º 26
0
// evaluate fitting error on benchmark with parameter set
Real HestonPriceBenchmark(Handle<Quote> &s0, std::vector<CALIB> &c, std::vector<RD> &rd,
                          std::vector<double> p, double sdCutOff) {

    Date settlementDate(24, January, 2011);
    SavedSettings backup;
    Settings::instance().evaluationDate() = settlementDate;

    Real theta = p[0];
    Real kappa = p[1];
    Real sigma = p[2];
    Real rho = p[3];
    Real v0 = p[4];

    std::cout << "Theta: " << theta <<
    "\nKappa: " << kappa <<
    "\nsigma: " << sigma <<
    "\nrho: " << rho <<
    "\nv0: " << v0 << std::endl;

    DayCounter dayCounter = Actual365Fixed();
    Calendar calendar = TARGET();

    std::vector<Date> dates;
    std::vector<Rate> rates;
    std::vector<Rate> div;

    // this is indispensable: expiry in Heston helper is computed from YC settlement date

    dates.push_back(settlementDate);
    rates.push_back(rd[0].R);
    div.push_back(rd[0].D);
    for (Size i = 0; i < rd.size(); ++i) {
        Integer days = 365*rd[i].T;
        dates.push_back(settlementDate + days);

        rates.push_back(rd[i].R);
        div.push_back(rd[i].D);
    }

    Date dtLast = settlementDate + ((int) 365*rd[rd.size()-1].T);

    std::cout << "Last curve date: " << dtLast << std::endl;

    Integer days = (rd[rd.size()-1].T+1)*365;
    dates.push_back(settlementDate + days);
    rates.push_back(rd[rd.size()-1].R);
    div.push_back(rd[rd.size()-1].D);


    std::cout << "Heston model Benchmark Pricing: TS..." << std::endl;

    Handle<YieldTermStructure> riskFreeTS(
        boost::shared_ptr<YieldTermStructure>(
            new ZeroCurve(dates, rates, dayCounter)));

    Handle<YieldTermStructure> dividendTS(
        boost::shared_ptr<YieldTermStructure>(
            new ZeroCurve(dates, div, dayCounter)));

    Volatility vol = 2.0;

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


    boost::shared_ptr<BlackScholesMertonProcess> BSprocess(
        new BlackScholesMertonProcess(s0, dividendTS, riskFreeTS, volTS));
//    boost::shared_ptr<PricingEngine> BSengine(
//        new AnalyticEuropeanEngine(BSprocess));

    boost::shared_ptr<HestonProcess> process(new HestonProcess(
                riskFreeTS, dividendTS, s0, v0, kappa, theta, sigma, rho));

    boost::shared_ptr<PricingEngine> engine(new AnalyticHestonEngine(
                                                boost::shared_ptr<HestonModel>(new HestonModel(process)), 64));

    std::cout << "Heston model Benchmark Pricing: engine set ..." << std::endl;

    IncrementalStatistics errorStat;
    vector<Real> error;

    ofstream myfile;
    Volatility ivol;

    Real errorBid;
    Real errorAsk;


//        myfile.open ("dump.csv", ios::out|ios::trunc); // this is the default
//        myfile << "T, dm, y, CP, PB, Calc, PA, Vega, iVol, ErrorBid, ErrorAsk" << std::endl;

    for (Size i = 0; i < c.size(); ++i) {
        Integer days = 365*c[i].T;
        //std::cout << "Expiry dates: " << dtExpiry << std::endl;
        Period maturity((int)((days+3)/7.), Weeks); // round to weeks
        Date dtExpiry = calendar.advance(riskFreeTS->referenceDate(),
                                         maturity);

        if (i==0)
            std::cout << dtExpiry << std::endl;

        // Time tau = riskFreeTS->dayCounter().yearFraction(
        //                       riskFreeTS->referenceDate(), dtExpiry);

        boost::shared_ptr<StrikedTypePayoff> payoff(
            new PlainVanillaPayoff(Option::Call, c[i].K));

        boost::shared_ptr<Exercise> exercise(new EuropeanExercise(dtExpiry));

        VanillaOption option(payoff, exercise);
        option.setPricingEngine(engine);
        Real calculated = option.NPV();

        // option.setPricingEngine(BSengine);

        if (calculated >0) {
            try {
                ivol = option.impliedVolatility(calculated, BSprocess, 1.e-6, 1000, .1, 10);
                errorBid  = std::max((c[i].VB-ivol), 0.0)*100;
                errorAsk =  std::max((ivol-c[i].VA), 0.0)*100;
            } catch (...) {
                errorBid  = 0.0;
                errorAsk =  0.0;
            };
        } else {
            vol = 0.0;
            errorAsk = 0.0;
            errorBid = 0.0;
        };

        error.push_back(errorBid+errorAsk);
//            myfile << c[i].T << "," << dtExpiry << "," << c[i].CP << "," << c[i].PB << "," << calculated << "," << c[i].PA << "," << c[i].Vega << "," << ivol << "," << errorBid << "," << errorAsk << std::endl;
    }

    // remove outliers and calculate sse

    errorStat.addSequence(error.begin(), error.end());
    Real sse = errorStat.standardDeviation();

    for (Size i=0; i<error.size(); ++i)
        if (abs(error[i]) > sdCutOff*sse) error[i] = 0.0;

    errorStat.reset();
    errorStat.addSequence(error.begin(), error.end());
    sse = errorStat.standardDeviation();
    return sse;
}
Exemplo n.º 27
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);
                }
            }
        }
    }
}
Exemplo n.º 28
0
int main(int, char* [])
{
    try {

        boost::timer timer;

        Date today = Date(16,October,2007);
        Settings::instance().evaluationDate() = today;

        cout <<  endl;
        cout << "Pricing a callable fixed rate bond using" << endl;
        cout << "Hull White model w/ reversion parameter = 0.03" << endl;
        cout << "BAC4.65 09/15/12  ISIN: US06060WBJ36" << endl;
        cout << "roughly five year tenor, ";
        cout << "quarterly coupon and call dates" << endl;
        cout << "reference date is : " << today << endl << endl;

        /* Bloomberg OAS1: "N" model (Hull White)
           varying volatility parameter

           The curve entered into Bloomberg OAS1 is a flat curve,
           at constant yield = 5.5%, semiannual compounding.
           Assume here OAS1 curve uses an ACT/ACT day counter,
           as documented in PFC1 as a "default" in the latter case.
        */

        // set up a flat curve corresponding to Bloomberg flat curve

        Rate bbCurveRate = 0.055;
        DayCounter bbDayCounter = ActualActual(ActualActual::Bond);
        InterestRate bbIR(bbCurveRate,bbDayCounter,Compounded,Semiannual);

        Handle<YieldTermStructure> termStructure(flatRate(today,
                                                          bbIR.rate(),
                                                          bbIR.dayCounter(),
                                                          bbIR.compounding(),
                                                          bbIR.frequency()));

        // set up the call schedule

        CallabilitySchedule callSchedule;
        Real callPrice = 100.;
        Size numberOfCallDates = 24;
        Date callDate = Date(15,September,2006);

        for (Size i=0; i< numberOfCallDates; i++) {
            Calendar nullCalendar = NullCalendar();

            Callability::Price myPrice(callPrice,
                                       Callability::Price::Clean);
            callSchedule.push_back(
                boost::shared_ptr<Callability>(
                    new Callability(myPrice,
                                    Callability::Call,
                                    callDate )));
            callDate = nullCalendar.advance(callDate, 3, Months);
        }


        // set up the callable bond

        Date dated = Date(16,September,2004);
        Date issue = dated;
        Date maturity = Date(15,September,2012);
        Natural settlementDays = 3;  // Bloomberg OAS1 settle is Oct 19, 2007
        Calendar bondCalendar = UnitedStates(UnitedStates::GovernmentBond);
        Real coupon = .0465;
        Frequency frequency = Quarterly;
        Real redemption = 100.0;
        Real faceAmount = 100.0;

        /* The 30/360 day counter Bloomberg uses for this bond cannot
           reproduce the US Bond/ISMA (constant) cashflows used in PFC1.
           Therefore use ActAct(Bond)
        */
        DayCounter bondDayCounter = ActualActual(ActualActual::Bond);

        // PFC1 shows no indication dates are being adjusted
        // for weekends/holidays for vanilla bonds
        BusinessDayConvention accrualConvention = Unadjusted;
        BusinessDayConvention paymentConvention = Unadjusted;

        Schedule sch(dated, maturity, Period(frequency), bondCalendar,
                     accrualConvention, accrualConvention,
                     DateGeneration::Backward, false);

        Size maxIterations = 1000;
        Real accuracy = 1e-8;
        Integer gridIntervals = 40;
        Real reversionParameter = .03;

        // output price/yield results for varying volatility parameter

        Real sigma = QL_EPSILON; // core dumps if zero on Cygwin

        boost::shared_ptr<ShortRateModel> hw0(
                       new HullWhite(termStructure,reversionParameter,sigma));

        boost::shared_ptr<PricingEngine> engine0(
                      new TreeCallableFixedRateBondEngine(hw0,gridIntervals));

        CallableFixedRateBond callableBond(settlementDays, faceAmount, sch,
                                           vector<Rate>(1, coupon),
                                           bondDayCounter, paymentConvention,
                                           redemption, issue, callSchedule);
        callableBond.setPricingEngine(engine0);

        cout << setprecision(2)
             << showpoint
             << fixed
             << "sigma/vol (%) = "
             << 100.*sigma
             << endl;

        cout << "QuantLib price/yld (%)  ";
        cout << callableBond.cleanPrice() << " / "
             << 100. * callableBond.yield(bondDayCounter,
                                          Compounded,
                                          frequency,
                                          accuracy,
                                          maxIterations)
             << endl;

        cout << "Bloomberg price/yld (%) ";
        cout << "96.50 / 5.47"
             << endl
             << endl;

        sigma = .01;

        cout << "sigma/vol (%) = " << 100.*sigma << endl;

        boost::shared_ptr<ShortRateModel> hw1(
                       new HullWhite(termStructure,reversionParameter,sigma));

        boost::shared_ptr<PricingEngine> engine1(
                      new TreeCallableFixedRateBondEngine(hw1,gridIntervals));

        callableBond.setPricingEngine(engine1);

        cout << "QuantLib price/yld (%)  ";
        cout << callableBond.cleanPrice() << " / "
             << 100.* callableBond.yield(bondDayCounter,
                                         Compounded,
                                         frequency,
                                         accuracy,
                                         maxIterations)
             << endl;

        cout << "Bloomberg price/yld (%) ";
        cout << "95.68 / 5.66"
             << endl
             << endl;

        ////////////////////

        sigma = .03;

        boost::shared_ptr<ShortRateModel> hw2(
                     new HullWhite(termStructure, reversionParameter, sigma));

        boost::shared_ptr<PricingEngine> engine2(
                      new TreeCallableFixedRateBondEngine(hw2,gridIntervals));

        callableBond.setPricingEngine(engine2);

        cout << "sigma/vol (%) = "
             << 100.*sigma
             << endl;

        cout << "QuantLib price/yld (%)  ";
        cout << callableBond.cleanPrice() << " / "
             << 100. * callableBond.yield(bondDayCounter,
                                          Compounded,
                                          frequency,
                                          accuracy,
                                          maxIterations)
             << endl;

        cout << "Bloomberg price/yld (%) ";
        cout << "92.34 / 6.49"
             << endl
             << endl;

        ////////////////////////////

        sigma = .06;

        boost::shared_ptr<ShortRateModel> hw3(
                     new HullWhite(termStructure, reversionParameter, sigma));

        boost::shared_ptr<PricingEngine> engine3(
                      new TreeCallableFixedRateBondEngine(hw3,gridIntervals));

        callableBond.setPricingEngine(engine3);

        cout << "sigma/vol (%) = "
             << 100.*sigma
             << endl;

        cout << "QuantLib price/yld (%)  ";
        cout << callableBond.cleanPrice() << " / "
             << 100. * callableBond.yield(bondDayCounter,
                                          Compounded,
                                          frequency,
                                          accuracy,
                                          maxIterations)
             << endl;

        cout << "Bloomberg price/yld (%) ";
        cout << "87.16 / 7.83"
             << endl
             << endl;

        /////////////////////////

        sigma = .12;

        boost::shared_ptr<ShortRateModel> hw4(
                     new HullWhite(termStructure, reversionParameter, sigma));

        boost::shared_ptr<PricingEngine> engine4(
                      new TreeCallableFixedRateBondEngine(hw4,gridIntervals));

        callableBond.setPricingEngine(engine4);

        cout << "sigma/vol (%) = "
             << 100.*sigma
             << endl;

        cout << "QuantLib price/yld (%)  ";
        cout << callableBond.cleanPrice() << " / "
             << 100.* callableBond.yield(bondDayCounter,
                                         Compounded,
                                         frequency,
                                         accuracy,
                                         maxIterations)
             << endl;

        cout << "Bloomberg price/yld (%) ";
        cout << "77.31 / 10.65"
             << endl
             << endl;

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

        return 0;

    } catch (std::exception& e) {
        std::cerr << e.what() << std::endl;
        return 1;
    } catch (...) {
        std::cerr << "unknown error" << std::endl;
        return 1;
    }
}
Exemplo n.º 29
0
boost::shared_ptr<IborIndex> curveCreation(				// creates the libor index (the "curve")
	utilities::csvBuilder & file) {

	const Real convexity_     = 0.009;					// convexity adjustment for future prices
	const Real meanReverting_ = 0.09 ;					// mean reversion for future prices

	const Calendar calendar								// pricing calendar
		= JointCalendar(
		UnitedStates(UnitedStates::Settlement),
		UnitedKingdom(UnitedKingdom::Settlement));

	const Date pricingDate								// set global evaluation date
		= Settings::instance().evaluationDate();

	boost::shared_ptr<RelinkableHandle<YieldTermStructure> > ts(
		new RelinkableHandle<YieldTermStructure>());	// create the yield term structure

	boost::shared_ptr<IborIndex> libor(					// libor index associated
		new USDLibor(
		Period(3, Months),
		*ts));

	libor->addFixing(Date(16, April, 2014), .0022785);	// add a few fixings
	libor->addFixing(Date(15, April, 2014), .0022635);
	libor->addFixing(Date(14, April, 2014), .0022865);
	libor->addFixing(Date(11, April, 2014), .0022645);

	// the rate helpers
	std::vector<boost::shared_ptr<RateHelper> > rateHelpers;

	std::vector<depositData> depositRates				// deposit data
		= std::vector<depositData>
	{

		{ .0009070, 0, Period(1, Days  ) },
		{ .0014250, 1, Period(2, Days  ) },
		{ .0012150, 2, Period(1, Weeks ) },
		{ .0015200, 2, Period(1, Months) },
		{ .0019300, 2, Period(2, Months) }

	};

	std::vector<futureData> futureRates					// future data
		= std::vector<futureData>
	{

		{ 99.7700, "EDM4" },
		{ 99.7600, "EDU4" },
		{ 99.7250, "EDZ4" },
		{ 99.6300, "EDH5" },
		{ 99.4550, "EDM5" },
		{ 99.2250, "EDU5" },
		{ 98.9450, "EDZ5" },
		{ 98.6450, "EDH6" },
		{ 98.3400, "EDM6" },
		{ 98.0500, "EDU6" },
		{ 97.7850, "EDZ6" }

	};

	std::vector<swapData> swapRates					// future data
		= std::vector<swapData>
	{

		{ .0139980, Period(4 , Years) },
		{ .0176100, Period(5 , Years) },
		{ .0205300, Period(6 , Years) },
		{ .0228500, Period(7 , Years) },
		{ .0247290, Period(8 , Years) },
		{ .0262750, Period(9 , Years) },
		{ .0275070, Period(10, Years) },
		{ .0286800, Period(11, Years) },
		{ .0296100, Period(12, Years) }

	};

	for (std::vector<depositData>::const_iterator It = depositRates.cbegin();
		It != depositRates.cend(); It++)
	{

		// settlement and maturity dates
		Date settlement = calendar.advance(
			pricingDate, Period(It->settlementDays_, Days));

		Date maturity = calendar.advance(
			settlement, It->maturity_);

		// creating the deposit
		boost::shared_ptr<QuantLib::deposit> myDepositPtr(
			new deposit(
			pricingDate,
			maturity,
			calendar,
			It->settlementDays_));

		Handle<Quote> quoteHandler(						// quote handle
			boost::shared_ptr<Quote>(
			new SimpleQuote(
			myDepositPtr->cleanPrice(
			It->quote_,
			Actual360(),
			Simple,
			Once,
			Unadjusted,
			settlement))));


		rateHelpers.push_back(							// insert RateHelper
			boost::shared_ptr<RateHelper>(
			new	depositBootstrapHelper(
			quoteHandler,
			myDepositPtr)));

	}

	for (std::vector<futureData>::const_iterator It = futureRates.cbegin();
		It != futureRates.cend(); It++)
	{

		Handle<Quote> convexityHandle(					// convexity adjustment
			boost::shared_ptr<Quote>(
			new SimpleQuote(convexity_)));

		Handle<Quote> meanRevertingHandle(				// mean reverting
			boost::shared_ptr<Quote>(
			new SimpleQuote(meanReverting_)));

		Handle<Quote> futurePriceHandle(				// price
			boost::shared_ptr<Quote>(
			new SimpleQuote(It->price_)));

		Date futureDate = IMM::date(					// IMM date
			It->futureCode_.substr(2, 2),
			pricingDate);

		Handle<Quote> convexityAdjustedQuoteHendle(		// convexity adjustement
			boost::shared_ptr<Quote>(
			new futuresConvexityAdjustmentQuote2(
			libor,
			futureDate,
			futurePriceHandle,
			convexityHandle,
			meanRevertingHandle,
			pricingDate)));

		rateHelpers.push_back(							// helper
			boost::shared_ptr<FuturesRateHelper>(
			new FuturesRateHelper(
			futurePriceHandle,
			futureDate,
			libor,
			convexityAdjustedQuoteHendle)));

	}

	for (std::vector<swapData>::const_iterator It = swapRates.cbegin();
		It != swapRates.cend(); It++)
	{


		QuantLib::Handle<QuantLib::Quote> myHandle(		// creates the rate handle
			boost::shared_ptr<QuantLib::Quote>(
			new QuantLib::SimpleQuote(It->fairRate_)));


		rateHelpers.push_back(
			boost::shared_ptr<QuantLib::RateHelper>(new
			QuantLib::SwapRateHelper(
			myHandle,
			It->maturity_,
			calendar,
			Semiannual,
			ModifiedFollowing,
			ActualActual(),
			libor)));

	}

	boost::shared_ptr<swapCurve> curve(					// building the curve object
		new swapCurve(rateHelpers, calendar, 10e-12));

	ts->linkTo(curve);									// finally relink the index

	Size size_ = 20;
	Array times(size_, 0.0);							// saves yield curve data
	Array rates(size_, 0.0);	
	Array fwd  (size_, 0.0);

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

		times[i] = .5 * i;								// the fixing times from model
		rates[i] = libor->forwardingTermStructure()->zeroRate(
			times[i], Continuous);
		fwd[i] = libor->forwardingTermStructure()->forwardRate(
			times[i], times[i] + .02, Continuous);

	}

	file.add("times"  , 1, 1);							// adds the yield curve data
	file.add(times    , 2, 1); 
	file.add("rates"  , 1, 2);
	file.add(rates    , 2, 2);
	file.add("forward", 1, 3);
	file.add(fwd      , 2, 3);

	return libor;

}
    void historicalForwardRatesAnalysis(
                SequenceStatistics& statistics,
                std::vector<Date>& skippedDates,
                std::vector<std::string>& skippedDatesErrorMessage,
                std::vector<Date>& failedDates,
                std::vector<std::string>& failedDatesErrorMessage,
                std::vector<Period>& fixingPeriods,
                const Date& startDate,
                const Date& endDate,
                const Period& step,
                const boost::shared_ptr<InterestRateIndex>& fwdIndex,
                const Period& initialGap,
                const Period& horizon,
                const std::vector<boost::shared_ptr<IborIndex> >& iborIndexes,
                const std::vector<boost::shared_ptr<SwapIndex> >& swapIndexes,
                const DayCounter& yieldCurveDayCounter,
                Real yieldCurveAccuracy = 1.0e-12,
                const Interpolator& i = Interpolator()) {


        statistics.reset();
        skippedDates.clear();
        skippedDatesErrorMessage.clear();
        failedDates.clear();
        failedDatesErrorMessage.clear();
        fixingPeriods.clear();

        SavedSettings backup;
        Settings::instance().enforcesTodaysHistoricFixings() = true;

        std::vector<boost::shared_ptr<RateHelper> > rateHelpers;

        // Create DepositRateHelper
        std::vector<boost::shared_ptr<SimpleQuote> > iborQuotes;
        std::vector<boost::shared_ptr<IborIndex> >::const_iterator ibor;
        for (ibor=iborIndexes.begin(); ibor!=iborIndexes.end(); ++ibor) {
            boost::shared_ptr<SimpleQuote> quote(new SimpleQuote);
            iborQuotes.push_back(quote);
            Handle<Quote> quoteHandle(quote);
            rateHelpers.push_back(boost::shared_ptr<RateHelper> (new
                DepositRateHelper(quoteHandle,
                                  (*ibor)->tenor(),
                                  (*ibor)->fixingDays(),
                                  (*ibor)->fixingCalendar(),
                                  (*ibor)->businessDayConvention(),
                                  (*ibor)->endOfMonth(),
                                  (*ibor)->dayCounter())));
        }

        // Create SwapRateHelper
        std::vector<boost::shared_ptr<SimpleQuote> > swapQuotes;
        std::vector<boost::shared_ptr<SwapIndex> >::const_iterator swap;
        for (swap=swapIndexes.begin(); swap!=swapIndexes.end(); ++swap) {
            boost::shared_ptr<SimpleQuote> quote(new SimpleQuote);
            swapQuotes.push_back(quote);
            Handle<Quote> quoteHandle(quote);
            rateHelpers.push_back(boost::shared_ptr<RateHelper> (new
                SwapRateHelper(quoteHandle,
                               (*swap)->tenor(),
                               (*swap)->fixingCalendar(),
                               (*swap)->fixedLegTenor().frequency(),
                               (*swap)->fixedLegConvention(),
                               (*swap)->dayCounter(),
                               (*swap)->iborIndex())));
        }

        // Set up the forward rates time grid
        Period indexTenor = fwdIndex->tenor();
        Period fixingPeriod = initialGap;
        while (fixingPeriod<=horizon) {
            fixingPeriods.push_back(fixingPeriod);
            fixingPeriod += indexTenor;
        }

        Size nRates = fixingPeriods.size();
        statistics.reset(nRates);
        std::vector<Rate> fwdRates(nRates);
        std::vector<Rate> prevFwdRates(nRates);
        std::vector<Rate> fwdRatesDiff(nRates);
        DayCounter indexDayCounter = fwdIndex->dayCounter();
        Calendar cal = fwdIndex->fixingCalendar();

        // Bootstrap the yield curve at the currentDate
        Natural settlementDays = 0;
        PiecewiseYieldCurve<Traits, Interpolator> yc(settlementDays,
                                                     cal,
                                                     rateHelpers,
                                                     yieldCurveDayCounter,
                                                     std::vector<Handle<Quote> >(),
                                                     std::vector<Date>(),
                                                     yieldCurveAccuracy,
                                                     i);

        // start with a valid business date
        Date currentDate = cal.advance(startDate, 1*Days, Following);
        bool isFirst = true;
        // Loop over the historical dataset
        for (; currentDate<=endDate;
            currentDate = cal.advance(currentDate, step, Following)) {

            // move the evaluationDate to currentDate
            // and update ratehelpers dates...
            Settings::instance().evaluationDate() = currentDate;

            try {
                // update the quotes...
                for (Size i=0; i<iborIndexes.size(); ++i) {
                    Rate fixing = iborIndexes[i]->fixing(currentDate, false);
                    iborQuotes[i]->setValue(fixing);
                }
                for (Size i=0; i<swapIndexes.size(); ++i) {
                    Rate fixing = swapIndexes[i]->fixing(currentDate, false);
                    swapQuotes[i]->setValue(fixing);
                }
            } catch (std::exception& e) {
                skippedDates.push_back(currentDate);
                skippedDatesErrorMessage.push_back(e.what());
                continue;
            }

            try {
                for (Size i=0; i<nRates; ++i) {
                    // Time-to-go forwards
                    Date d = currentDate + fixingPeriods[i];
                    fwdRates[i] = yc.forwardRate(d,
                                                 indexTenor,
                                                 indexDayCounter,
                                                 Simple);
                }
            } catch (std::exception& e) {
                failedDates.push_back(currentDate);
                failedDatesErrorMessage.push_back(e.what());
                continue;
            }

            // From 2nd step onwards, calculate forward rate
            // relative differences
            if (!isFirst){
                for (Size i=0; i<nRates; ++i)
                    fwdRatesDiff[i] = fwdRates[i]/prevFwdRates[i] -1.0;
                // add observation
                statistics.add(fwdRatesDiff.begin(), fwdRatesDiff.end());
            }
            else
                isFirst = false;

            // Store last calculated forward rates
            std::swap(prevFwdRates, fwdRates);

        }
    }