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); }
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; }
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 ; } } ;
// [[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"); } }
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()); }
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; } };