Пример #1
0
    Spread CallableBond::OAS(Real cleanPrice,
                             const Handle<YieldTermStructure>& engineTS,
                             const DayCounter& dayCounter,
                             Compounding compounding,
                             Frequency frequency,
                             Date settlement,
                             Real accuracy,
                             Size maxIterations,
                             Spread guess)
    {
        if (settlement == Date())
            settlement = settlementDate();

        Real dirtyPrice = cleanPrice + accruedAmount(settlement);

        boost::function<Real(Real)> f = NPVSpreadHelper(*this);
        OASHelper obj(f, dirtyPrice);

        Brent solver;
        solver.setMaxEvaluations(maxIterations);

        Real step = 0.001;
        Spread oas=solver.solve(obj, accuracy, guess, step);

        return continuousToConv(oas,
                                *this,
                                engineTS,
                                dayCounter,
                                compounding,
                                frequency);
    }
Пример #2
0
    Real CallableFixedRateBond::accrued(Date settlement) const {

        if (settlement == Date()) settlement = settlementDate();

        const bool IncludeToday = false;
        for (Size i = 0; i<cashflows_.size(); ++i) {
            // the first coupon paying after d is the one we're after
            if (!cashflows_[i]->hasOccurred(settlement,IncludeToday)) {
                boost::shared_ptr<Coupon> coupon =
                    boost::dynamic_pointer_cast<Coupon>(cashflows_[i]);
                if (coupon)
                    // !!!
                    return coupon->accruedAmount(settlement) /
                           notional(settlement) * 100.0;
                else
                    return 0.0;
            }
        }
        return 0.0;
    }
Пример #3
0
    Real CallableBond::cleanPriceOAS(Real oas,
                                     const Handle<YieldTermStructure>& engineTS,
                                     const DayCounter& dayCounter,
                                     Compounding compounding,
                                     Frequency frequency,
                                     Date settlement)
    {
        if (settlement == Date())
            settlement = settlementDate();

        oas=convToContinuous(oas,
                             *this,
                             engineTS,
                             dayCounter,
                             compounding,
                             frequency);

        boost::function<Real(Real)> f = NPVSpreadHelper(*this);

        Real P = f(oas) - accruedAmount(settlement);

        return P;
    }
        /* Fonction de calcul du nombre de flux restant */
DLLEXPORT xloper * xlInstrumentFlowCount (const char * instrumentId_,
                                          xloper * settlementDate_,
                                          xloper * trigger_) {

         boost::shared_ptr<ObjectHandler::FunctionCall> functionCall(
            new ObjectHandler::FunctionCall("xlInstrumentFlowCount")) ;

         try {

            QL_ENSURE(! functionCall->calledByFunctionWizard(), "") ;

                    /* recherche de code erreur */
            ObjectHandler::validateRange(trigger_, "trigger") ;
            ObjectHandler::validateRange(settlementDate_, "settlement Date") ;

                /* on récupère l'instrument */
            OH_GET_UNDERLYING(myBond, 
                              instrumentId_, 
                              QuantLibAddin::Bond,
                              QuantLib::Bond)

                /* les XLOPER des date */
            ObjectHandler::ConvertOper myOper(* settlementDate_) ;

            QuantLib::Date settlementDate(
                    myOper.missing() ? 
                    QuantLib::Date() : 
                    QuantLib::Date(static_cast<QuantLib::BigInteger>(myOper))) ;

			QuantLib::Natural returnValue = 0;

				// increments
			for (std::vector<boost::shared_ptr<QuantLib::CashFlow> >::const_reverse_iterator It = myBond.cashflows().crbegin();
				It != myBond.cashflows().crend(); It++)
			
				It->get()->date() > settlementDate ? returnValue++ : 0;

            static XLOPER returnOper ;
            ObjectHandler::scalarToOper(static_cast<double>(returnValue), returnOper) ;

            return & returnOper ;

        } catch (std::exception & e) {

            #ifdef _DEBUG

				OutputDebugString(e.what()) ;

            #endif

            ObjectHandler::RepositoryXL::instance().logError(e.what(), functionCall) ;
            static XLOPER returnOper ;
            returnOper.xltype = xltypeErr ;
            returnOper.val.err = xlerrValue ;

            return & returnOper ;


        }


    } ;
Пример #5
0
// [[Rcpp::export]]
Rcpp::List affineWithRebuiltCurveEngine(Rcpp::List rparam,
                                        Rcpp::List legparams,
                                        std::vector<QuantLib::Date> dateVec, 
                                        std::vector<double> zeroVec,
                                        Rcpp::NumericVector swaptionMat,
                                        Rcpp::NumericVector swapLengths,
                                        Rcpp::NumericVector swaptionVols) {
    
    // std::vector<std::string> tsnames = tslist.names();

    
    QuantLib::Size i;
    //int *swaptionMat=0, *swapLengths=0;
    //double **swaptionVols=0;

    double notional = 10000; // prices in basis points

    QuantLib::Date todaysDate(Rcpp::as<QuantLib::Date>(rparam["tradeDate"])); 
    QuantLib::Date settlementDate(Rcpp::as<QuantLib::Date>(rparam["settleDate"])); 
    QuantLib::Date startDate(Rcpp::as<QuantLib::Date>(rparam["startDate"])); 
    QuantLib::Date maturity(Rcpp::as<QuantLib::Date>(rparam["maturity"])); 
    bool payfix = Rcpp::as<bool>(rparam["payFixed"]);
    bool european = Rcpp::as<bool>(rparam["european"]);
    
    
    //cout << "TradeDate: " << todaysDate << endl << "Settle: " << settlementDate << endl;
    
    RQLContext::instance().settleDate = settlementDate;
    QuantLib::Settings::instance().evaluationDate() = todaysDate;
    
    // initialise from the singleton instance
    QuantLib::Calendar calendar = RQLContext::instance().calendar;
    //Integer fixingDays = RQLContext::instance().fixingDays;
    
    double strike = Rcpp::as<double>(rparam["strike"]);
    std::string method = Rcpp::as<std::string>(rparam["method"]);

    QuantLib::Handle<QuantLib::YieldTermStructure> 
        rhTermStructure(rebuildCurveFromZeroRates(dateVec, zeroVec));
    
    // Get swaption maturities
    //Rcpp::NumericVector swaptionMat(maturities);
    int numRows = swaptionMat.size(); 

    // Create dummy swap to get schedules.
    QuantLib::Frequency fixedLegFrequency = getFrequency(Rcpp::as<double>(legparams["fixFreq"]));
    QuantLib::BusinessDayConvention fixedLegConvention = QuantLib::Unadjusted;
    QuantLib::BusinessDayConvention floatingLegConvention = QuantLib::ModifiedFollowing;
    QuantLib::DayCounter swFixedLegDayCounter = getDayCounter(Rcpp::as<double>(legparams["dayCounter"]));
    boost::shared_ptr<QuantLib::IborIndex> swFloatingLegIndex(new QuantLib::Euribor(QuantLib::Period(Rcpp::as<int>(legparams["floatFreq"]),QuantLib::Months),rhTermStructure));


    QuantLib::Rate dummyFixedRate = 0.03;

    QuantLib::Schedule fixedSchedule(startDate,maturity,
                                     QuantLib::Period(fixedLegFrequency),calendar,
                                     fixedLegConvention,fixedLegConvention,
                                     QuantLib::DateGeneration::Forward,false);
    QuantLib::Schedule floatSchedule(startDate,maturity,QuantLib::Period(Rcpp::as<int>(legparams["floatFreq"]),QuantLib::Months),
                                     calendar,
                                     floatingLegConvention,floatingLegConvention,
                                     QuantLib::DateGeneration::Forward,false);
    
    QuantLib::VanillaSwap::Type type;
    
    if(payfix){
        type = QuantLib::VanillaSwap::Payer;} 
    else{
        type = QuantLib::VanillaSwap::Receiver;    
    }
    boost::shared_ptr<QuantLib::VanillaSwap> 
        swap(new QuantLib::VanillaSwap(type, notional,
                                       fixedSchedule, dummyFixedRate, swFixedLegDayCounter,
                                       floatSchedule, swFloatingLegIndex, 0.0,
                                       swFloatingLegIndex->dayCounter()));
    swap->setPricingEngine(boost::shared_ptr<QuantLib::PricingEngine>(new QuantLib::DiscountingSwapEngine(rhTermStructure)));

    // Find the ATM or break-even rate
    QuantLib::Rate fixedATMRate = swap->fairRate();

    QuantLib::Rate fixedRate;
    if(strike < 0) // factor instead of real strike
        fixedRate = fixedATMRate * (-strike);
    else
        fixedRate = strike;

    // The swap underlying the Affine swaption.
    boost::shared_ptr<QuantLib::VanillaSwap> 
        mySwap(new QuantLib::VanillaSwap(type, notional,
                                         fixedSchedule, fixedRate,swFixedLegDayCounter,
                                         floatSchedule, swFloatingLegIndex, 0.0,
                                         swFloatingLegIndex->dayCounter()));
    swap->setPricingEngine(boost::shared_ptr<QuantLib::PricingEngine>(new QuantLib::DiscountingSwapEngine(rhTermStructure)));

    
    // Build swaptions that will be used to calibrate model to
    // the volatility matrix.
    std::vector<QuantLib::Period> swaptionMaturities;
    for(i = 0; i < (QuantLib::Size)numRows; i++)
        swaptionMaturities.push_back(QuantLib::Period(swaptionMat[i], QuantLib::Years));
    
    // Swaptions used for calibration
    std::vector<boost::shared_ptr<QuantLib::BlackCalibrationHelper> > swaptions;

    // List of times that have to be included in the timegrid
    std::list<QuantLib::Time> times;
    for (i=0; i<(QuantLib::Size)numRows; i++) {
        //boost::shared_ptr<QuantLib::Quote> vol(new QuantLib::SimpleQuote(swaptionVols[i][numCols-i-1]));
        boost::shared_ptr<QuantLib::Quote> vol(new QuantLib::SimpleQuote(swaptionVols(i)));
        swaptions.push_back(boost::shared_ptr<QuantLib::BlackCalibrationHelper>(new QuantLib::SwaptionHelper(swaptionMaturities[i],
                                                                                                             QuantLib::Period(swapLengths[i], QuantLib::Years),
                                                                                                             QuantLib::Handle<QuantLib::Quote>(vol),
                                                                                                             swFloatingLegIndex,
                                                                                                             swFloatingLegIndex->tenor(),
                                                                                                             swFloatingLegIndex->dayCounter(),
                                                                                                             swFloatingLegIndex->dayCounter(),
                                                                                                             rhTermStructure)));
        swaptions.back()->addTimesTo(times);
    }
    
    // Building time-grid
    QuantLib::TimeGrid grid(times.begin(), times.end(), 30);

    
    // Get Affine swaption exercise dates, single date if europen, coupon dates if bermudan
    std::vector<QuantLib::Date> affineDates;
    const std::vector<boost::shared_ptr<QuantLib::CashFlow> >& leg = swap->fixedLeg();
    if(european){
        boost::shared_ptr<QuantLib::Coupon> coupon = boost::dynamic_pointer_cast<QuantLib::Coupon>(leg[0]);
        affineDates.push_back(coupon->accrualStartDate());
    } else{
        for (i=0; i<leg.size(); i++) {
            boost::shared_ptr<QuantLib::Coupon> coupon = boost::dynamic_pointer_cast<QuantLib::Coupon>(leg[i]);
            affineDates.push_back(coupon->accrualStartDate());
        }

    }
    
    boost::shared_ptr<QuantLib::Exercise> affineExercise(new QuantLib::BermudanExercise(affineDates));
    
    // Price based on method selected.
    if (method.compare("G2Analytic") == 0) {
        boost::shared_ptr<QuantLib::G2> modelG2(new QuantLib::G2(rhTermStructure));
        Rprintf((char*)"G2/Jamshidian (analytic) calibration\n");
        for(i = 0; i < swaptions.size(); i++)
            swaptions[i]->setPricingEngine(boost::shared_ptr<QuantLib::PricingEngine>(new QuantLib::G2SwaptionEngine(modelG2, 6.0, 16)));
        calibrateModel2(modelG2, swaptions, 0.05, swaptionMat, swapLengths, swaptionVols); 
        boost::shared_ptr<QuantLib::PricingEngine> engine(new QuantLib::TreeSwaptionEngine(modelG2, 50));
        QuantLib::Swaption affineSwaption(mySwap, affineExercise); 
        affineSwaption.setPricingEngine(engine);
        return Rcpp::List::create(Rcpp::Named("a")         = modelG2->params()[0],
                                  Rcpp::Named("sigma")     = modelG2->params()[1],
                                  Rcpp::Named("b")         = modelG2->params()[2],
                                  Rcpp::Named("eta")       = modelG2->params()[3],
                                  Rcpp::Named("rho")       = modelG2->params()[4],
                                  Rcpp::Named("NPV")       = affineSwaption.NPV(),
                                  Rcpp::Named("ATMStrike") = fixedATMRate);
        //Rcpp::Named("params")    = params);
        
    } else if (method.compare("HWAnalytic") == 0) {
        boost::shared_ptr<QuantLib::HullWhite> modelHW(new QuantLib::HullWhite(rhTermStructure));
        Rprintf((char*)"Hull-White (analytic) calibration\n");
        for (i=0; i<swaptions.size(); i++)
            swaptions[i]->setPricingEngine(boost::shared_ptr<QuantLib::PricingEngine>(new QuantLib::JamshidianSwaptionEngine(modelHW)));
        calibrateModel2(modelHW, swaptions, 0.05, swaptionMat, swapLengths, swaptionVols);
        boost::shared_ptr<QuantLib::PricingEngine> engine(new QuantLib::TreeSwaptionEngine(modelHW, 50));
        QuantLib::Swaption affineSwaption(mySwap, affineExercise);
        affineSwaption.setPricingEngine(engine);
        return Rcpp::List::create(Rcpp::Named("a") = modelHW->params()[0],
                                  Rcpp::Named("sigma") = modelHW->params()[1],
                                  Rcpp::Named("NPV") = affineSwaption.NPV(),
                                  Rcpp::Named("ATMStrike") = fixedATMRate);
        //Rcpp::Named("params") = params);
        
    } else if (method.compare("HWTree") == 0) {
        boost::shared_ptr<QuantLib::HullWhite> modelHW2(new QuantLib::HullWhite(rhTermStructure));
        Rprintf((char*)"Hull-White (tree) calibration\n");
        for (i=0; i<swaptions.size(); i++)
            swaptions[i]->setPricingEngine(boost::shared_ptr<QuantLib::PricingEngine>(new QuantLib::TreeSwaptionEngine(modelHW2,grid)));

        calibrateModel2(modelHW2, swaptions, 0.05, swaptionMat, swapLengths, swaptionVols);
        boost::shared_ptr<QuantLib::PricingEngine> engine(new QuantLib::TreeSwaptionEngine(modelHW2, 50));
        QuantLib::Swaption affineSwaption(mySwap, affineExercise);
        affineSwaption.setPricingEngine(engine);
        return Rcpp::List::create(Rcpp::Named("a") = modelHW2->params()[0],
                                  Rcpp::Named("sigma") = modelHW2->params()[1],
                                  Rcpp::Named("NPV") = affineSwaption.NPV(),
                                  Rcpp::Named("ATMStrike") = fixedATMRate);
        //Rcpp::Named("params") = params);
        
            
    } else if (method.compare("BKTree") == 0) {
        boost::shared_ptr<QuantLib::BlackKarasinski> modelBK(new QuantLib::BlackKarasinski(rhTermStructure));
        Rprintf((char*)"Black-Karasinski (tree) calibration\n");
        for (i=0; i<swaptions.size(); i++)
            swaptions[i]->setPricingEngine(boost::shared_ptr<QuantLib::PricingEngine>(new QuantLib::TreeSwaptionEngine(modelBK,grid)));
        calibrateModel2(modelBK, swaptions, 0.05, swaptionMat, swapLengths, swaptionVols);
            
        boost::shared_ptr<QuantLib::PricingEngine> engine(new QuantLib::TreeSwaptionEngine(modelBK, 50));
        QuantLib::Swaption affineSwaption(mySwap, affineExercise);
        affineSwaption.setPricingEngine(engine);
        return Rcpp::List::create(Rcpp::Named("a") = modelBK->params()[0],
                                  Rcpp::Named("sigma") = modelBK->params()[1],
                                  Rcpp::Named("price") = affineSwaption.NPV(),
                                  Rcpp::Named("ATMStrike") = fixedATMRate);
        //Rcpp::Named("params") = params);
            
    } else {
        throw std::range_error("Unknown method in AffineSwaption\n");
    }
    
}
Пример #6
0
int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
{
  DDS::DomainParticipantFactory_var dpf = DDS::DomainParticipantFactory::_nil();
  DDS::DomainParticipant_var participant = DDS::DomainParticipant::_nil();

  try
  {
     QuantLibAddinCpp::initializeAddin();

     QuantLib::Calendar calendar = QuantLib::TARGET();

     QuantLib::Date settlementDate(22, QuantLib::September, 2004);

     settlementDate = calendar.adjust(settlementDate);

     QuantLib::Integer fixingDays = 2;

     QuantLib::Date todaysDate = calendar.advance(settlementDate, -fixingDays, QuantLib::Days);

     QuantLibAddinCpp::qlSettingsSetEvaluationDate( todaysDate.serialNumber(), OH_NULL );
     std::cout << "Today: " << todaysDate.weekday() << ", " << todaysDate << std::endl;
     std::cout << "Settlement date: " << settlementDate.weekday() << ", " << settlementDate << std::endl;

     // Initialize, and create a DomainParticipant
     dpf = TheParticipantFactoryWithArgs(argc, argv);


     qldds_utils::BasicDomainParticipant irs_participant( dpf, IRS_DOMAIN_ID );
     irs_participant.createPublisher();
     irs_participant.createSubscriber();

     std::string term_structure;

     std::vector<std::string> rate_helpers;

     ACE_Get_Opt cmd_opts( argc, argv, ":c:n:i:" );

     int option;

     while ( (option = cmd_opts()) != EOF )
     {
       switch( option )
       {
         case 'c' :
         { 
           std::istringstream f( cmd_opts.opt_arg() );
           std::string s;

           while (std::getline(f, s, '|')) {
             rate_helpers.push_back(s);
           }
           break;
         }
         case 'n' :
         {
           term_structure = cmd_opts.opt_arg();
           break;
         }
       }
     }

     QuantLibAddinCpp::qlLibor("Libor", "USD", "6M", "", false, false, true);
     
     // Topics for Swap Components
     // Setting up schedule topic
     DDS::Topic_var schedule_topic =
         irs_participant.createTopicAndRegisterType
         < schedule::qlScheduleTypeSupport_var, schedule::qlScheduleTypeSupportImpl >
         ( SCHEDULE_TOPIC_NAME );

     // setting up vanilla swap topic 
     DDS::Topic_var vanilla_swap_topic =
         irs_participant.createTopicAndRegisterType
         < vanillaswap::qlVanillaSwapTypeSupport_var, vanillaswap::qlVanillaSwapTypeSupportImpl >
         ( VANILLA_SWAP_TOPIC_NAME );

 
     // Topics for curve components
     // setting up deposit rate helper
     DDS::Topic_var deposit_rate_helper2_topic = irs_participant.createTopicAndRegisterType
         < ratehelpers::qlDepositRateHelper2TypeSupport_var, ratehelpers::qlDepositRateHelper2TypeSupportImpl >
          ( DEPOSIT_RATE_HELPER2_TOPIC_NAME );

     // setting up FRA Rate helper
     DDS::Topic_var fra_rate_helper2_topic = irs_participant.createTopicAndRegisterType
         < ratehelpers::qlFraRateHelper2TypeSupport_var, ratehelpers::qlFraRateHelper2TypeSupportImpl >
          ( FRA_RATE_HELPER2_TOPIC_NAME );

     // setting up Swap Rate helper
     DDS::Topic_var swap_rate_helper2_topic = irs_participant.createTopicAndRegisterType
       < ratehelpers::qlSwapRateHelper2TypeSupport_var, ratehelpers::qlSwapRateHelper2TypeSupportImpl >
        (  SWAP_RATE_HELPER2_TOPIC_NAME );


    irs_participant.createDataReaderListener< schedule::qlScheduleDataReaderListenerImpl> ( qldds_lock, schedule_topic );
    irs_participant.createDataReaderListener< VanillaSwapDataReaderListenerImpl > ( qldds_lock, vanilla_swap_topic );

    irs_participant.createDataReaderListener< DepositRateHelper2DataReaderListenerImpl > ( qldds_lock,deposit_rate_helper2_topic );
    irs_participant.createDataReaderListener< FraRateHelper2DataReaderListenerImpl > ( qldds_lock, fra_rate_helper2_topic );
    irs_participant.createDataReaderListener< SwapRateHelper2DataReaderListenerImpl > ( qldds_lock, swap_rate_helper2_topic );

    // setting up IRS Portfolio. Priced portfolios will be published on this topic
    DDS::Topic_var irs_portfolio_topic = irs_participant.createTopicAndRegisterType
       < IRS::PortfolioTypeSupport_var, IRS::PortfolioTypeSupportImpl >
        (  IRS_PORTFOLIO_TOPIC_NAME  );

    IRS::PortfolioDataWriter_var irs_portfolio_dw = irs_participant.createDataWriter
      < IRS::PortfolioDataWriter_var, IRS::PortfolioDataWriter >
       ( irs_portfolio_topic );

    curves.insert( std::pair < std::string, std::vector< std::string > > ( term_structure, rate_helpers ) );

    int calculation_performed = 0;

    while ( calculation_performed < 30 )
    {
      IRS::Portfolio irs_portfolio_out;

      if ( computeNPVs( term_structure,  irs_portfolio_out ) == false )
      {
        ACE_Time_Value sleep_100ms( 0, 100000 );
        ACE_OS::sleep( sleep_100ms );

        continue;
      } else {
        calculation_performed++;
        ACE_OS::sleep(1);
      } 

      std::cout << "Calculator ["<< term_structure << "] publishing NPVs for "<< irs_portfolio_out.swaps.length() << " interest rate swaps."<< std::endl; 

      int ret = irs_portfolio_dw->write( irs_portfolio_out, DDS::HANDLE_NIL );
      if (ret != DDS::RETCODE_OK) {
         ACE_ERROR ((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: IRS Portfolio write returned %d.\n"), ret));
      }

    }

  } catch (CORBA::Exception& e)
  {
    cerr << "Exception caught in main.cpp:" << endl << e << endl;
    ACE_OS::exit(1);
  }

  TheServiceParticipant->shutdown();

  return 0;
}
 bool ForwardRateAgreement::isExpired() const {
     return detail::simple_event(valueDate_).hasOccurred(settlementDate());
 }
Пример #8
0
int TestFromQuantLib() {

	try {

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

		// set up dates
		Calendar calendar = TARGET();
		Date todaysDate(15, May, 1998);
		Date settlementDate(17, May, 1998);
		Settings::instance().evaluationDate() = todaysDate;

		// our options
		Option::Type type(Option::Put);
		Real underlying = 36;
		Real strike = 40;
		Spread dividendYield = 0.00;
		Rate riskFreeRate = 0.06;
		Volatility volatility = 0.20;
		Date maturity(17, May, 1999);
		DayCounter dayCounter = Actual365Fixed();

		std::cout << "Option type = " << type << std::endl;
		std::cout << "Maturity = " << maturity << std::endl;
		std::cout << "Underlying price = " << underlying << std::endl;
		std::cout << "Strike = " << strike << 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, 14 };
		std::cout << std::setw(widths[0]) << std::left << "Method"
			<< std::setw(widths[1]) << std::left << "European"
			<< std::setw(widths[2]) << std::left << "Bermudan"
			<< std::setw(widths[3]) << std::left << "American"
			<< std::endl;

		std::vector<Date> exerciseDates;
		for (Integer i = 1; i <= 4; i++)
			exerciseDates.push_back(settlementDate + 3 * i*Months);

		boost::shared_ptr<Exercise> europeanExercise(
			new EuropeanExercise(maturity));

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

		boost::shared_ptr<Exercise> americanExercise(
			new AmericanExercise(settlementDate,
				maturity));

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

		// bootstrap the yield/dividend/vol curves
		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<StrikedTypePayoff> payoff(
			new PlainVanillaPayoff(type, strike));
		boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(
			new BlackScholesMertonProcess(underlyingH, flatDividendTS,
				flatTermStructure, flatVolTS));

		// options
		VanillaOption europeanOption(payoff, europeanExercise);
		VanillaOption bermudanOption(payoff, bermudanExercise);
		VanillaOption americanOption(payoff, americanExercise);

		// Analytic formulas:

		// Black-Scholes for European
		method = "Black-Scholes";
		europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new AnalyticEuropeanEngine(bsmProcess)));
		std::cout << std::setw(widths[0]) << std::left << method
			<< std::fixed
			<< std::setw(widths[1]) << std::left << europeanOption.NPV()
			<< std::setw(widths[2]) << std::left << "N/A"
			<< std::setw(widths[3]) << std::left << "N/A"
			<< std::endl;

		// semi-analytic Heston for European
		method = "Heston semi-analytic";
		boost::shared_ptr<HestonProcess> hestonProcess(
			new HestonProcess(flatTermStructure, flatDividendTS,
				underlyingH, volatility*volatility,
				1.0, volatility*volatility, 0.001, 0.0));
		boost::shared_ptr<HestonModel> hestonModel(
			new HestonModel(hestonProcess));
		europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new AnalyticHestonEngine(hestonModel)));
		std::cout << std::setw(widths[0]) << std::left << method
			<< std::fixed
			<< std::setw(widths[1]) << std::left << europeanOption.NPV()
			<< std::setw(widths[2]) << std::left << "N/A"
			<< std::setw(widths[3]) << std::left << "N/A"
			<< std::endl;

		// semi-analytic Bates for European
		method = "Bates semi-analytic";
		boost::shared_ptr<BatesProcess> batesProcess(
			new BatesProcess(flatTermStructure, flatDividendTS,
				underlyingH, volatility*volatility,
				1.0, volatility*volatility, 0.001, 0.0,
				1e-14, 1e-14, 1e-14));
		boost::shared_ptr<BatesModel> batesModel(new BatesModel(batesProcess));
		europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BatesEngine(batesModel)));
		std::cout << std::setw(widths[0]) << std::left << method
			<< std::fixed
			<< std::setw(widths[1]) << std::left << europeanOption.NPV()
			<< std::setw(widths[2]) << std::left << "N/A"
			<< std::setw(widths[3]) << std::left << "N/A"
			<< std::endl;

		// Barone-Adesi and Whaley approximation for American
		method = "Barone-Adesi/Whaley";
		americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BaroneAdesiWhaleyApproximationEngine(bsmProcess)));
		std::cout << std::setw(widths[0]) << std::left << method
			<< std::fixed
			<< std::setw(widths[1]) << std::left << "N/A"
			<< std::setw(widths[2]) << std::left << "N/A"
			<< std::setw(widths[3]) << std::left << americanOption.NPV()
			<< std::endl;

		// Bjerksund and Stensland approximation for American
		method = "Bjerksund/Stensland";
		americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BjerksundStenslandApproximationEngine(bsmProcess)));
		std::cout << std::setw(widths[0]) << std::left << method
			<< std::fixed
			<< std::setw(widths[1]) << std::left << "N/A"
			<< std::setw(widths[2]) << std::left << "N/A"
			<< std::setw(widths[3]) << std::left << americanOption.NPV()
			<< std::endl;

		// Integral
		method = "Integral";
		europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new IntegralEngine(bsmProcess)));
		std::cout << std::setw(widths[0]) << std::left << method
			<< std::fixed
			<< std::setw(widths[1]) << std::left << europeanOption.NPV()
			<< std::setw(widths[2]) << std::left << "N/A"
			<< std::setw(widths[3]) << std::left << "N/A"
			<< std::endl;

		// Finite differences
		Size timeSteps = 801;
		method = "Finite differences";
		europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new FDEuropeanEngine<CrankNicolson>(bsmProcess,
				timeSteps, timeSteps - 1)));
		bermudanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new FDBermudanEngine<CrankNicolson>(bsmProcess,
				timeSteps, timeSteps - 1)));
		americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new FDAmericanEngine<CrankNicolson>(bsmProcess,
				timeSteps, timeSteps - 1)));
		std::cout << std::setw(widths[0]) << std::left << method
			<< std::fixed
			<< std::setw(widths[1]) << std::left << europeanOption.NPV()
			<< std::setw(widths[2]) << std::left << bermudanOption.NPV()
			<< std::setw(widths[3]) << std::left << americanOption.NPV()
			<< std::endl;

		// Binomial method: Jarrow-Rudd
		method = "Binomial Jarrow-Rudd";
		europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<JarrowRudd>(bsmProcess, timeSteps)));
		bermudanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<JarrowRudd>(bsmProcess, timeSteps)));
		americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<JarrowRudd>(bsmProcess, timeSteps)));
		std::cout << std::setw(widths[0]) << std::left << method
			<< std::fixed
			<< std::setw(widths[1]) << std::left << europeanOption.NPV()
			<< std::setw(widths[2]) << std::left << bermudanOption.NPV()
			<< std::setw(widths[3]) << std::left << americanOption.NPV()
			<< std::endl;
		method = "Binomial Cox-Ross-Rubinstein";
		europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<CoxRossRubinstein>(bsmProcess,
				timeSteps)));
		bermudanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<CoxRossRubinstein>(bsmProcess,
				timeSteps)));
		americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<CoxRossRubinstein>(bsmProcess,
				timeSteps)));
		std::cout << std::setw(widths[0]) << std::left << method
			<< std::fixed
			<< std::setw(widths[1]) << std::left << europeanOption.NPV()
			<< std::setw(widths[2]) << std::left << bermudanOption.NPV()
			<< std::setw(widths[3]) << std::left << americanOption.NPV()
			<< std::endl;

		// Binomial method: Additive equiprobabilities
		method = "Additive equiprobabilities";
		europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<AdditiveEQPBinomialTree>(bsmProcess,
				timeSteps)));
		bermudanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<AdditiveEQPBinomialTree>(bsmProcess,
				timeSteps)));
		americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<AdditiveEQPBinomialTree>(bsmProcess,
				timeSteps)));
		std::cout << std::setw(widths[0]) << std::left << method
			<< std::fixed
			<< std::setw(widths[1]) << std::left << europeanOption.NPV()
			<< std::setw(widths[2]) << std::left << bermudanOption.NPV()
			<< std::setw(widths[3]) << std::left << americanOption.NPV()
			<< std::endl;

		// Binomial method: Binomial Trigeorgis
		method = "Binomial Trigeorgis";
		europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<Trigeorgis>(bsmProcess, timeSteps)));
		bermudanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<Trigeorgis>(bsmProcess, timeSteps)));
		americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<Trigeorgis>(bsmProcess, timeSteps)));
		std::cout << std::setw(widths[0]) << std::left << method
			<< std::fixed
			<< std::setw(widths[1]) << std::left << europeanOption.NPV()
			<< std::setw(widths[2]) << std::left << bermudanOption.NPV()
			<< std::setw(widths[3]) << std::left << americanOption.NPV()
			<< std::endl;

		// Binomial method: Binomial Tian
		method = "Binomial Tian";
		europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<Tian>(bsmProcess, timeSteps)));
		bermudanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<Tian>(bsmProcess, timeSteps)));
		americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<Tian>(bsmProcess, timeSteps)));
		std::cout << std::setw(widths[0]) << std::left << method
			<< std::fixed
			<< std::setw(widths[1]) << std::left << europeanOption.NPV()
			<< std::setw(widths[2]) << std::left << bermudanOption.NPV()
			<< std::setw(widths[3]) << std::left << americanOption.NPV()
			<< std::endl;

		// Binomial method: Binomial Leisen-Reimer
		method = "Binomial Leisen-Reimer";
		europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<LeisenReimer>(bsmProcess, timeSteps)));
		bermudanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<LeisenReimer>(bsmProcess, timeSteps)));
		americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<LeisenReimer>(bsmProcess, timeSteps)));
		std::cout << std::setw(widths[0]) << std::left << method
			<< std::fixed
			<< std::setw(widths[1]) << std::left << europeanOption.NPV()
			<< std::setw(widths[2]) << std::left << bermudanOption.NPV()
			<< std::setw(widths[3]) << std::left << americanOption.NPV()
			<< std::endl;

		// Binomial method: Binomial Joshi
		method = "Binomial Joshi";
		europeanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<Joshi4>(bsmProcess, timeSteps)));
		bermudanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<Joshi4>(bsmProcess, timeSteps)));
		americanOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
			new BinomialVanillaEngine<Joshi4>(bsmProcess, timeSteps)));
		std::cout << std::setw(widths[0]) << std::left << method
			<< std::fixed
			<< std::setw(widths[1]) << std::left << europeanOption.NPV()
			<< std::setw(widths[2]) << std::left << bermudanOption.NPV()
			<< std::setw(widths[3]) << std::left << americanOption.NPV()
			<< std::endl;

		// Monte Carlo Method: MC (crude)
		timeSteps = 1;
		method = "MC (crude)";
		Size mcSeed = 42;
		boost::shared_ptr<PricingEngine> mcengine1;
		mcengine1 = MakeMCEuropeanEngine<PseudoRandom>(bsmProcess)
			.withSteps(timeSteps)
			.withAbsoluteTolerance(0.02)
			.withSeed(mcSeed);
		europeanOption.setPricingEngine(mcengine1);
		// Real errorEstimate = europeanOption.errorEstimate();
		std::cout << std::setw(widths[0]) << std::left << method
			<< std::fixed
			<< std::setw(widths[1]) << std::left << europeanOption.NPV()
			<< std::setw(widths[2]) << std::left << "N/A"
			<< std::setw(widths[3]) << std::left << "N/A"
			<< std::endl;

		// Monte Carlo Method: QMC (Sobol)
		method = "QMC (Sobol)";
		Size nSamples = 32768;  // 2^15

		boost::shared_ptr<PricingEngine> mcengine2;
		mcengine2 = MakeMCEuropeanEngine<LowDiscrepancy>(bsmProcess)
			.withSteps(timeSteps)
			.withSamples(nSamples);
		europeanOption.setPricingEngine(mcengine2);
		std::cout << std::setw(widths[0]) << std::left << method
			<< std::fixed
			<< std::setw(widths[1]) << std::left << europeanOption.NPV()
			<< std::setw(widths[2]) << std::left << "N/A"
			<< std::setw(widths[3]) << std::left << "N/A"
			<< std::endl;

		// Monte Carlo Method: MC (Longstaff Schwartz)
		method = "MC (Longstaff Schwartz)";
		boost::shared_ptr<PricingEngine> mcengine3;
		mcengine3 = MakeMCAmericanEngine<PseudoRandom>(bsmProcess)
			.withSteps(100)
			.withAntitheticVariate()
			.withCalibrationSamples(4096)
			.withAbsoluteTolerance(0.02)
			.withSeed(mcSeed);
		americanOption.setPricingEngine(mcengine3);
		std::cout << std::setw(widths[0]) << std::left << method
			<< std::fixed
			<< std::setw(widths[1]) << std::left << "N/A"
			<< std::setw(widths[2]) << std::left << "N/A"
			<< std::setw(widths[3]) << std::left << americanOption.NPV()
			<< std::endl;

		// End test
		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;
	}
}
// parametric fitted curve
DLLEXPORT char * xlInitiateFittedBondDiscountCurve (const char   * objectID_         ,
        const xloper * evaluationDate_   ,
        const xloper * settlementDate_   ,
        const xloper * instruments_      ,
        const xloper * quote_            ,
        const char   * calendarID_       ,
        const char   * fittingMethodID_  ,
        const xloper * bondSelectionRule_,
        const xloper * trigger_) {

    boost::shared_ptr<ObjectHandler::FunctionCall> functionCall(
        new ObjectHandler::FunctionCall("xlInitiateFittedBondDiscountCurve"));

    try {

        QL_ENSURE(! functionCall->calledByFunctionWizard(), "");						// called by wizard ?

        ObjectHandler::validateRange(trigger_,           "trigger"            );	// validate range
        ObjectHandler::validateRange(settlementDate_,    "settlement Date"    );
        ObjectHandler::validateRange(instruments_,       "instruments"        );
        ObjectHandler::validateRange(quote_,             "quotes"             );
        ObjectHandler::validateRange(bondSelectionRule_, "bond selection rule");

        ObjectHandler::ConvertOper myOper1(* bondSelectionRule_);					// bond selection rule oper

        QuantLib::bondSelectionRule myRule =										// the rule
            (myOper1.missing() ?
             QuantLib::activeRule() :
             ObjectHandler::bondSelectionRuleFactory()(
                 static_cast<std::string>(myOper1)));

        QuantLib::Calendar curveCalendar											// calendar
            = ObjectHandler::calendarFactory()(calendarID_);

        ObjectHandler::ConvertOper oper1(* evaluationDate_);						// evaluation date

        QuantLib::Date evaluationDate(oper1.missing() ?
                                      QuantLib::Date() :
                                      static_cast<QuantLib::Date>(oper1));

        std::vector<std::string> instruments =										// instrument ids
            ObjectHandler::operToVector<std::string>(
                * instruments_, "instruments");

        std::vector<QuantLib::Real> quote =											// quotes
            ObjectHandler::operToVector<double>(
                * quote_, "quote");

        std::vector<boost::shared_ptr<QuantLib::BondHelper> > instrumentsObject;	// helpers

        for (unsigned int i = 0 ; i < instruments.size() ; i++) {					// capture individual bonds

            try {

                OH_GET_REFERENCE(instrumentPtr,										// get a reference
                                 instruments[i],
                                 QuantLibAddin::Bond,
                                 QuantLib::Bond)

                if (quote[i] != 0.0 && instrumentPtr->isTradable()) {				// valid quote ?

                    QuantLib::RelinkableHandle<QuantLib::Quote> quoteHandle;	// the handler

                    quoteHandle.linkTo(boost::shared_ptr<QuantLib::Quote>(		// link to the quote
                                           new QuantLib::SimpleQuote(quote[i])));

                    boost::shared_ptr<QuantLib::BondHelper> noteHelper(			// the helper
                        new QuantLib::BondHelper(quoteHandle, instrumentPtr));

                    instrumentsObject.push_back(noteHelper);					// helper storage

                }

            } catch (...) {}													// nothing on exception

        }

        ObjectHandler::ConvertOper oper2(* settlementDate_);						// settlement date

        QuantLib::Date settlementDate(oper2.missing() ?
                                      instrumentsObject[0]->bond()->settlementDate(evaluationDate) :
                                      static_cast<QuantLib::Date>(oper2));

        OH_GET_OBJECT(fittingMethodTemp,											// fitting method selection
                      fittingMethodID_,
                      ObjectHandler::Object)

        std::string returnValue;

        if (fittingMethodTemp->properties()->className()								// svensson ?
                == "stochasticFittingValueObject") {

            OH_GET_REFERENCE(fittingMethodPtr,
                             fittingMethodID_,
                             QuantLibAddin::stochasticFittingObject,
                             QuantLib::stochasticFittingHelper)

            // build the value object
            boost::shared_ptr<QuantLibAddin::ValueObjects::fittedBondDiscountCurveValueObject> curveValueObject(
                new QuantLibAddin::ValueObjects::fittedBondDiscountCurveValueObject(
                    objectID_,
                    settlementDate.serialNumber(),
                    true));

            boost::shared_ptr<ObjectHandler::Object> myCurve(				// instanciating the curve
                new QuantLibAddin::fittedBondDiscountCurveObject(
                    curveValueObject,
                    settlementDate,
                    myRule.select(instrumentsObject, settlementDate),
                    * fittingMethodPtr->fittingMethod(),
                    fittingMethodPtr->initialVector(),
                    fittingMethodPtr->randomMatrix(),
                    fittingMethodPtr->accuracy(),
                    fittingMethodPtr->maxEvaluationPercycle(),
                    fittingMethodPtr->cyclesPerThread(),
                    fittingMethodPtr->cycles(),
                    1.000,													// simplex lambda
                    true)) ;

            returnValue =													// the value to return
                ObjectHandler::RepositoryXL::instance().storeObject(objectID_,
                        myCurve  ,
                        true      );

        }

        static char ret[XL_MAX_STR_LEN];
        ObjectHandler::stringToChar(returnValue, ret);
        return ret;

    } catch (std::exception & e) {

        static char ret[XL_MAX_STR_LEN];
        ObjectHandler::RepositoryXL::instance().logError(e.what(), functionCall);
        ObjectHandler::stringToChar(std::string(e.what()), ret);
        return ret;

    }

};