RcppExport SEXP yearFraction(SEXP startDates, SEXP endDates, SEXP dayCounter){ try { Rcpp::DateVector s = Rcpp::DateVector(startDates); Rcpp::DateVector e = Rcpp::DateVector(endDates); Rcpp::NumericVector dc(dayCounter); int n = dc.size(); std::vector<double> result(n); for (int i=0; i< n; i++){ QuantLib::Date d1( dateFromR(s[i]) ); QuantLib::Date d2( dateFromR(e[i]) ); QuantLib::DayCounter counter = getDayCounter(dc[i]); result[i] = (double)counter.yearFraction(d1, d2); } return Rcpp::wrap(result); } catch(std::exception &ex) { forward_exception_to_r(ex); } catch(...) { ::Rf_error("c++ exception (unknown reason)"); } return R_NilValue; }
RcppExport SEXP cfamounts(SEXP params){ SEXP rl=R_NilValue; char* exceptionMesg=NULL; try{ RcppParams rparam(params); QuantLib::Date maturity(dateFromR(rparam.getDateValue("Maturity"))); QuantLib::Date settle(dateFromR(rparam.getDateValue("Settle"))); QuantLib::Date issue(dateFromR(rparam.getDateValue("IssueDate"))); double rate = rparam.getDoubleValue("CouponRate"); std::vector<double> rateVec(1, rate); double faceAmount = rparam.getDoubleValue("Face"); double period = rparam.getDoubleValue("Period"); double basis = rparam.getDoubleValue("Basis"); DayCounter dayCounter = getDayCounter(basis); Frequency freq = getFrequency(period); Period p(freq); double EMR = rparam.getDoubleValue("EMR"); Calendar calendar=UnitedStates(UnitedStates::GovernmentBond); Schedule sch(settle, maturity, p, calendar, Unadjusted, Unadjusted, DateGeneration::Backward, (EMR == 1)? true : false); FixedRateBond bond(1, faceAmount, sch, rateVec, dayCounter, Following, 100, issue); //cashflow int numCol = 2; std::vector<std::string> colNames(numCol); colNames[0] = "Date"; colNames[1] = "Amount"; RcppFrame frame(colNames); Leg bondCashFlow = bond.cashflows(); for (unsigned int i = 0; i< bondCashFlow.size(); i++){ std::vector<ColDatum> row(numCol); Date d = bondCashFlow[i]->date(); row[0].setDateValue(RcppDate(d.month(), d.dayOfMonth(), d.year())); row[1].setDoubleValue(bondCashFlow[i]->amount()); frame.addRow(row); } RcppResultSet rs; rs.add("cashFlow", frame); rl = rs.getReturnList(); } catch(std::exception& ex) { exceptionMesg = copyMessageToR(ex.what()); } catch(...) { exceptionMesg = copyMessageToR("unknown reason"); } if(exceptionMesg != NULL) Rf_error(exceptionMesg); return rl; }
RcppExport SEXP cfdates(SEXP params){ SEXP rl = R_NilValue; char* exceptionMesg = NULL; try { RcppParams rparam(params); double basis = rparam.getDoubleValue("dayCounter"); DayCounter dayCounter = getDayCounter(basis); double p = rparam.getDoubleValue("period"); Frequency freq = getFrequency(p); Period period(freq); double emr = rparam.getDoubleValue("emr"); bool endOfMonth = false; if (emr == 1) endOfMonth = true; QuantLib::Date d1(dateFromR(rparam.getDateValue("settle"))); QuantLib::Date d2(dateFromR(rparam.getDateValue("maturity"))); Calendar calendar=UnitedStates(UnitedStates::GovernmentBond); Schedule sch(d1, d2, period, calendar, Unadjusted, Unadjusted, DateGeneration::Backward, endOfMonth); //cfdates int numCol = 1; std::vector<std::string> colNames(numCol); colNames[0] = "Date"; RcppFrame frame(colNames); std::vector<QuantLib::Date> dates = sch.dates(); for (unsigned int i = 0; i< dates.size(); i++){ std::vector<ColDatum> row(numCol); Date d = dates[i]; row[0].setDateValue(RcppDate(d.month(), d.dayOfMonth(), d.year())); frame.addRow(row); } RcppResultSet rs; rs.add("", frame); rl = rs.getReturnList(); } catch(std::exception& ex) { exceptionMesg = copyMessageToR(ex.what()); } catch(...) { exceptionMesg = copyMessageToR("unknown reason"); } if(exceptionMesg != NULL) Rf_error(exceptionMesg); return rl; }
// [[Rcpp::export]] Rcpp::List calibrateHullWhiteUsingSwapsEngine(SEXP termStrcDateVec, SEXP termStrcZeroVec, SEXP swapDataDF, SEXP iborDateVec, SEXP iborZeroVec, std::string iborType, QuantLib::Date evalDate) { QuantLib::Settings::instance().evaluationDate() = evalDate; //set up the HullWhite model QuantLib::Handle<QuantLib::YieldTermStructure> term(rebuildCurveFromZeroRates(termStrcDateVec, termStrcZeroVec)); boost::shared_ptr<QuantLib::HullWhite> model(new QuantLib::HullWhite(term)); //set up ibor index QuantLib::Handle<QuantLib::YieldTermStructure> indexStrc(rebuildCurveFromZeroRates(iborDateVec, iborZeroVec)); boost::shared_ptr<QuantLib::IborIndex> index = buildIborIndex(iborType, indexStrc); //process capDataDF boost::shared_ptr<QuantLib::PricingEngine> engine(new QuantLib::JamshidianSwaptionEngine(model)); std::vector<boost::shared_ptr <QuantLib::CalibrationHelper> > swaps; Rcpp::DataFrame swapDF(swapDataDF); Rcpp::NumericVector i0v = swapDF[0]; Rcpp::CharacterVector s1v = swapDF[1]; Rcpp::NumericVector i2v = swapDF[2]; Rcpp::CharacterVector s3v = swapDF[3]; Rcpp::NumericVector d4v = swapDF[4]; Rcpp::NumericVector i5v = swapDF[5]; Rcpp::CharacterVector s6v = swapDF[6]; Rcpp::NumericVector i7v = swapDF[7]; Rcpp::NumericVector i8v = swapDF[8]; //std::vector<std::vector<ColDatum> > table = swapDF.getTableData(); //int nrow = table.size(); int nrow = i0v.size(); for (int row=0; row<nrow;row++) { QuantLib::Period maturity = periodByTimeUnit(i0v[row], Rcpp::as<std::string>(s1v[row])); QuantLib::Period length = periodByTimeUnit(i0v[row], Rcpp::as<std::string>(s3v[row])); boost::shared_ptr<QuantLib::Quote> vol(new QuantLib::SimpleQuote(d4v[row])); QuantLib::Period fixedLegTenor = periodByTimeUnit(i5v[row], Rcpp::as<std::string>(s6v[row])); QuantLib::DayCounter fixedLegDayCounter = getDayCounter(i7v[row]); QuantLib::DayCounter floatingLegDayCounter = getDayCounter(i8v[row]); boost::shared_ptr<QuantLib::CalibrationHelper> helper(new QuantLib::SwaptionHelper(maturity, length, QuantLib::Handle<QuantLib::Quote>(vol), index, fixedLegTenor, fixedLegDayCounter, floatingLegDayCounter, term)); helper->setPricingEngine(engine); swaps.push_back(helper); } //calibrate the data QuantLib::LevenbergMarquardt optimizationMethod(1.0e-8,1.0e-8,1.0e-8); QuantLib::EndCriteria endCriteria(10000, 100, 1e-6, 1e-8, 1e-8); model->calibrate(swaps, optimizationMethod, endCriteria); //EndCriteria::Type ecType = model->endCriteria(); //return the result QuantLib::Array xMinCalculated = model->params(); return Rcpp::List::create(Rcpp::Named("alpha") = xMinCalculated[0], Rcpp::Named("sigma") = xMinCalculated[1]); }
// [[Rcpp::export]] Rcpp::List calibrateHullWhiteUsingCapsEngine(SEXP termStrcDateVec, SEXP termStrcZeroVec, SEXP capDataDF, SEXP iborDateVec, SEXP iborZeroVec, std::string iborType, QuantLib::Date evalDate) { QuantLib::Settings::instance().evaluationDate() = evalDate; QuantLib::Handle<QuantLib::YieldTermStructure> term(rebuildCurveFromZeroRates(termStrcDateVec, termStrcZeroVec)); //set up ibor index QuantLib::Handle<QuantLib::YieldTermStructure> indexStrc(rebuildCurveFromZeroRates(iborDateVec, iborZeroVec)); boost::shared_ptr<QuantLib::IborIndex> index = buildIborIndex(iborType, indexStrc); //process capDataDF std::vector<boost::shared_ptr <QuantLib::CalibrationHelper> > caps; Rcpp::DataFrame capDF(capDataDF); Rcpp::NumericVector i0v = capDF[0]; Rcpp::CharacterVector s1v = capDF[1]; Rcpp::NumericVector d2v = capDF[2]; Rcpp::NumericVector i3v = capDF[3]; Rcpp::NumericVector i4v = capDF[4]; Rcpp::NumericVector i5v = capDF[5]; //std::vector<std::vector<ColDatum> > table = capDF.getTableData(); //int nrow = table.size(); int nrow = i0v.size(); for (int row=0; row<nrow;row++) { QuantLib::Period p = periodByTimeUnit(i0v[row], Rcpp::as<std::string>(s1v[row])); boost::shared_ptr<QuantLib::Quote> vol(new QuantLib::SimpleQuote(d2v[row])); QuantLib::DayCounter dc = getDayCounter(i4v[row]); boost::shared_ptr<QuantLib::CalibrationHelper> helper(new QuantLib::CapHelper(p, QuantLib::Handle<QuantLib::Quote>(vol), index, getFrequency(i3v[row]), dc, (i5v[row]==1) ? true : false, term)); boost::shared_ptr<QuantLib::BlackCapFloorEngine> engine(new QuantLib::BlackCapFloorEngine(term, d2v[row])); helper->setPricingEngine(engine); caps.push_back(helper); } //set up the HullWhite model boost::shared_ptr<QuantLib::HullWhite> model(new QuantLib::HullWhite(term)); //calibrate the data QuantLib::LevenbergMarquardt optimizationMethod(1.0e-8,1.0e-8,1.0e-8); QuantLib::EndCriteria endCriteria(10000, 100, 1e-6, 1e-8, 1e-8); model->calibrate(caps, optimizationMethod, endCriteria); //EndCriteria::Type ecType = model->endCriteria(); //return the result QuantLib::Array xMinCalculated = model->params(); return Rcpp::List::create(Rcpp::Named("alpha") = xMinCalculated[0], Rcpp::Named("sigma") = xMinCalculated[1]); }
// [[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"); } }