void AssetSwapHelper::initializeDates() { evaluationDate_ = Settings::instance().evaluationDate(); earliestDate_ = calendar_.advance (evaluationDate_, settlementDays_, Days); Date maturity = earliestDate_ + tenor_; latestDate_ = calendar_.adjust (maturity, fixedConvention_); Schedule fixedSchedule(earliestDate_, maturity, fixedPeriod_, calendar_, fixedConvention_, fixedConvention_, DateGeneration::Forward, false); Schedule floatSchedule(earliestDate_, maturity, floatPeriod_, calendar_, floatConvention_, floatConvention_, DateGeneration::Forward, false); asw_ = boost::shared_ptr<RiskyAssetSwap>( new RiskyAssetSwap(true, 100.0, fixedSchedule, floatSchedule, fixedDayCount_, floatDayCount_, 0.01, recoveryRate_, yieldTS_, probability_)); }
void SwaptionHelper::performCalculations() const { Calendar calendar = index_->fixingCalendar(); Natural fixingDays = index_->fixingDays(); Date exerciseDate = exerciseDate_; if (exerciseDate == Null<Date>()) exerciseDate = calendar.advance(termStructure_->referenceDate(), maturity_, index_->businessDayConvention()); Date startDate = calendar.advance(exerciseDate, fixingDays, Days, index_->businessDayConvention()); Date endDate = endDate_; if (endDate == Null<Date>()) endDate = calendar.advance(startDate, length_, index_->businessDayConvention()); Schedule fixedSchedule(startDate, endDate, fixedLegTenor_, calendar, index_->businessDayConvention(), index_->businessDayConvention(), DateGeneration::Forward, false); Schedule floatSchedule(startDate, endDate, index_->tenor(), calendar, index_->businessDayConvention(), index_->businessDayConvention(), DateGeneration::Forward, false); boost::shared_ptr<PricingEngine> swapEngine( new DiscountingSwapEngine(termStructure_, false)); VanillaSwap::Type type = VanillaSwap::Receiver; VanillaSwap temp(VanillaSwap::Receiver, nominal_, fixedSchedule, 0.0, fixedLegDayCounter_, floatSchedule, index_, 0.0, floatingLegDayCounter_); temp.setPricingEngine(swapEngine); Real forward = temp.fairRate(); if(strike_ == Null<Real>()) { exerciseRate_ = forward; } else { exerciseRate_ = strike_; type = strike_ <= forward ? VanillaSwap::Receiver : VanillaSwap::Payer; // ensure that calibration instrument is out of the money } swap_ = boost::shared_ptr<VanillaSwap>( new VanillaSwap(type, nominal_, fixedSchedule, exerciseRate_, fixedLegDayCounter_, floatSchedule, index_, 0.0, floatingLegDayCounter_)); swap_->setPricingEngine(swapEngine); boost::shared_ptr<Exercise> exercise(new EuropeanExercise(exerciseDate)); swaption_ = boost::shared_ptr<Swaption>(new Swaption(swap_, exercise)); CalibrationHelper::performCalculations(); }
MakeCms::operator boost::shared_ptr<Swap>() const { Date startDate; if (effectiveDate_ != Date()) startDate = effectiveDate_; else { Natural fixingDays = iborIndex_->fixingDays(); Date refDate = Settings::instance().evaluationDate(); // if the evaluation date is not a business day // then move to the next business day refDate = floatCalendar_.adjust(refDate); Date spotDate = floatCalendar_.advance(refDate, fixingDays*Days); startDate = spotDate+forwardStart_; } Date terminationDate = startDate+swapTenor_; Schedule cmsSchedule(startDate, terminationDate, cmsTenor_, cmsCalendar_, cmsConvention_, cmsTerminationDateConvention_, cmsRule_, cmsEndOfMonth_, cmsFirstDate_, cmsNextToLastDate_); Schedule floatSchedule(startDate, terminationDate, floatTenor_, floatCalendar_, floatConvention_, floatTerminationDateConvention_, floatRule_ , floatEndOfMonth_, floatFirstDate_, floatNextToLastDate_); Leg cmsLeg = CmsLeg(cmsSchedule, swapIndex_) .withNotionals(nominal_) .withPaymentDayCounter(cmsDayCount_) .withPaymentAdjustment(cmsConvention_) .withFixingDays(swapIndex_->fixingDays()) .withGearings(cmsGearing_) .withSpreads(cmsSpread_) .withCaps(cmsCap_) .withFloors(cmsFloor_); if (couponPricer_) setCouponPricer(cmsLeg, couponPricer_); Rate usedSpread = iborSpread_; if (useAtmSpread_) { QL_REQUIRE(!iborIndex_->forwardingTermStructure().empty(), "null term structure set to this instance of " << iborIndex_->name()); QL_REQUIRE(!swapIndex_->forwardingTermStructure().empty(), "null term structure set to this instance of " << swapIndex_->name()); QL_REQUIRE(couponPricer_, "no CmsCouponPricer set (yet)"); Leg floatLeg = IborLeg(floatSchedule, iborIndex_) .withNotionals(nominal_) .withPaymentDayCounter(floatDayCount_) .withPaymentAdjustment(floatConvention_) .withFixingDays(iborIndex_->fixingDays()); Swap temp(cmsLeg, floatLeg); temp.setPricingEngine(engine_); Real npv = temp.legNPV(0)+temp.legNPV(1); usedSpread = -npv/temp.legBPS(1)*1e-4; } else { QL_REQUIRE(usedSpread != Null<Spread>(), "null spread set"); } Leg floatLeg = IborLeg(floatSchedule, iborIndex_) .withNotionals(nominal_) .withPaymentDayCounter(floatDayCount_) .withPaymentAdjustment(floatConvention_) .withFixingDays(iborIndex_->fixingDays()) .withSpreads(usedSpread); boost::shared_ptr<Swap> swap; if (payCms_) swap = boost::shared_ptr<Swap>(new Swap(cmsLeg, floatLeg)); else swap = boost::shared_ptr<Swap>(new Swap(floatLeg, cmsLeg)); swap->setPricingEngine(engine_); return swap; }
// [[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"); } }
MakeVanillaSwap::operator ext::shared_ptr<VanillaSwap>() const { Date startDate; if (effectiveDate_ != Date()) startDate = effectiveDate_; else { Date refDate = Settings::instance().evaluationDate(); // if the evaluation date is not a business day // then move to the next business day refDate = floatCalendar_.adjust(refDate); Date spotDate = floatCalendar_.advance(refDate, settlementDays_*Days); startDate = spotDate+forwardStart_; if (forwardStart_.length()<0) startDate = floatCalendar_.adjust(startDate, Preceding); else startDate = floatCalendar_.adjust(startDate, Following); } Date endDate = terminationDate_; if (endDate == Date()) { if (floatEndOfMonth_) endDate = floatCalendar_.advance(startDate, swapTenor_, ModifiedFollowing, floatEndOfMonth_); else endDate = startDate + swapTenor_; } const Currency& curr = iborIndex_->currency(); Period fixedTenor; if (fixedTenor_ != Period()) fixedTenor = fixedTenor_; else { if ((curr == EURCurrency()) || (curr == USDCurrency()) || (curr == CHFCurrency()) || (curr == SEKCurrency()) || (curr == GBPCurrency() && swapTenor_ <= 1 * Years)) fixedTenor = Period(1, Years); else if ((curr == GBPCurrency() && swapTenor_ > 1 * Years) || (curr == JPYCurrency()) || (curr == AUDCurrency() && swapTenor_ >= 4 * Years)) fixedTenor = Period(6, Months); else if ((curr == HKDCurrency() || (curr == AUDCurrency() && swapTenor_ < 4 * Years))) fixedTenor = Period(3, Months); else QL_FAIL("unknown fixed leg default tenor for " << curr); } Schedule fixedSchedule(startDate, endDate, fixedTenor, fixedCalendar_, fixedConvention_, fixedTerminationDateConvention_, fixedRule_, fixedEndOfMonth_, fixedFirstDate_, fixedNextToLastDate_); Schedule floatSchedule(startDate, endDate, floatTenor_, floatCalendar_, floatConvention_, floatTerminationDateConvention_, floatRule_, floatEndOfMonth_, floatFirstDate_, floatNextToLastDate_); DayCounter fixedDayCount; if (fixedDayCount_ != DayCounter()) fixedDayCount = fixedDayCount_; else { if (curr == USDCurrency()) fixedDayCount = Actual360(); else if (curr == EURCurrency() || curr == CHFCurrency() || curr == SEKCurrency()) fixedDayCount = Thirty360(Thirty360::BondBasis); else if (curr == GBPCurrency() || curr == JPYCurrency() || curr == AUDCurrency() || curr == HKDCurrency()) fixedDayCount = Actual365Fixed(); else QL_FAIL("unknown fixed leg day counter for " << curr); } Rate usedFixedRate = fixedRate_; if (fixedRate_ == Null<Rate>()) { VanillaSwap temp(type_, nominal_, fixedSchedule, 0.0, // fixed rate fixedDayCount, floatSchedule, iborIndex_, floatSpread_, floatDayCount_); if (engine_ == 0) { Handle<YieldTermStructure> disc = iborIndex_->forwardingTermStructure(); QL_REQUIRE(!disc.empty(), "null term structure set to this instance of " << iborIndex_->name()); bool includeSettlementDateFlows = false; ext::shared_ptr<PricingEngine> engine(new DiscountingSwapEngine(disc, includeSettlementDateFlows)); temp.setPricingEngine(engine); } else temp.setPricingEngine(engine_); usedFixedRate = temp.fairRate(); } ext::shared_ptr<VanillaSwap> swap(new VanillaSwap(type_, nominal_, fixedSchedule, usedFixedRate, fixedDayCount, floatSchedule, iborIndex_, floatSpread_, floatDayCount_)); if (engine_ == 0) { Handle<YieldTermStructure> disc = iborIndex_->forwardingTermStructure(); bool includeSettlementDateFlows = false; ext::shared_ptr<PricingEngine> engine(new DiscountingSwapEngine(disc, includeSettlementDateFlows)); swap->setPricingEngine(engine); } else swap->setPricingEngine(engine_); return swap; }