boost::shared_ptr<BlackVolTermStructure> flatVol(const Date& today, const boost::shared_ptr<Quote>& vol, const DayCounter& dc) { return boost::shared_ptr<BlackVolTermStructure>(new BlackConstantVol(today, NullCalendar(), Handle<Quote>(vol), dc)); }
ScenarioGenerator(const Calendar &calendar = NullCalendar(), const DayCounter &dc = Actual365Fixed()) : calendar_(calendar), dc_(dc), pathNumber_(0), validPath_(true), validHorizonDate_(true) { resetHorizonDate(); baseDate_ = horizonDate_; }
FixedLocalVolSurface::FixedLocalVolSurface( const Date& referenceDate, const std::vector<Date>& dates, const std::vector<Real>& strikes, const boost::shared_ptr<Matrix>& localVolMatrix, const DayCounter& dayCounter, Extrapolation lowerExtrapolation, Extrapolation upperExtrapolation) : LocalVolTermStructure( referenceDate, NullCalendar(), Following, dayCounter), maxDate_(dates.back()), localVolMatrix_(localVolMatrix), strikes_(dates.size(),boost::make_shared<std::vector<Real> >(strikes)), localVolInterpol_(dates.size()), lowerExtrapolation_(lowerExtrapolation), upperExtrapolation_(upperExtrapolation) { QL_REQUIRE(dates[0]>=referenceDate, "cannot have dates[0] < referenceDate"); times_ = std::vector<Time>(dates.size()); for (Size j=0; j<times_.size(); j++) times_[j] = timeFromReference(dates[j]); checkSurface(); setInterpolation<Linear>(); }
Real RiskyAssetSwap::recoveryValue() const { Real recoveryValue = 0; // simple Euler integral to evaluate the recovery value for (Size i = 1; i < fixedSchedule_.size(); i++) { TimeUnit stepSize = Days; Date d; if (fixedSchedule_[i-1] >= defaultTS_->referenceDate()) d = fixedSchedule_[i-1]; else d = defaultTS_->referenceDate(); Date d0 = d; do { Real disc = yieldTS_->discount (d); Real dd = defaultTS_->defaultDensity (d, true); Real dcf = defaultTS_->dayCounter().yearFraction (d0, d); recoveryValue += disc * dd * dcf; d0 = d; d = NullCalendar().advance (d0, 1, stepSize, Unadjusted); } while (d < fixedSchedule_[i]); } recoveryValue *= recoveryRate_; return recoveryValue; }
Real HestonRNDCalculator::invcdf(Real p, Time t) const { const Real v0 = hestonProcess_->v0(); const Real kappa = hestonProcess_->kappa(); const Real theta = hestonProcess_->theta(); const Volatility expVol = std::sqrt(theta + (v0-theta)*(1-std::exp(-kappa*t))/(t*kappa)); const ext::shared_ptr<BlackScholesMertonProcess> bsmProcess( ext::make_shared<BlackScholesMertonProcess>( hestonProcess_->s0(), hestonProcess_->dividendYield(), hestonProcess_->riskFreeRate(), Handle<BlackVolTermStructure>( ext::make_shared<BlackConstantVol>( hestonProcess_->riskFreeRate()->referenceDate(), NullCalendar(), expVol, hestonProcess_->riskFreeRate()->dayCounter())))); const Real guess = BSMRNDCalculator(bsmProcess).invcdf(p, t); return RiskNeutralDensityCalculator::InvCDFHelper( this, guess, 0.1*integrationEps_, maxIntegrationIterations_) .inverseCDF(p, t); }
SABRVolTermStructure(Real alpha, Real beta, Real gamma, Real rho, Real s0, Real r, const Date& referenceDate, const DayCounter dc) : BlackVolatilityTermStructure( referenceDate, NullCalendar(), Following, dc), alpha_(alpha), beta_(beta), gamma_(gamma), rho_(rho), s0_(s0), r_(r) { }
BlackStyleSwaptionEngine<Spec>::BlackStyleSwaptionEngine( const Handle<YieldTermStructure> &discountCurve, Volatility vol, const DayCounter &dc, Real displacement) : discountCurve_(discountCurve), vol_(boost::shared_ptr<SwaptionVolatilityStructure>( new ConstantSwaptionVolatility(0, NullCalendar(), Following, vol, dc, Spec().type, displacement))), displacement_(displacement) { registerWith(discountCurve_); }
HestonBlackVolSurface::HestonBlackVolSurface( const Handle<HestonModel>& hestonModel) : BlackVolTermStructure( hestonModel->process()->riskFreeRate()->referenceDate(), NullCalendar(), Following, hestonModel->process()->riskFreeRate()->dayCounter()), hestonModel_(hestonModel), integration_(AnalyticHestonEngine::Integration::gaussLaguerre(164)) { registerWith(hestonModel_); }
BlackCapFloorEngine::BlackCapFloorEngine( const Handle<YieldTermStructure>& discountCurve, Volatility v, const DayCounter& dc, Real displacement) : discountCurve_(discountCurve), vol_(boost::shared_ptr<OptionletVolatilityStructure>(new ConstantOptionletVolatility(0, NullCalendar(), Following, v, dc))), displacement_(displacement) { registerWith(discountCurve_); }
boost::shared_ptr<BlackVolTermStructure> ProcessInfo::ProcessParser_Impl:: make_vol_ts(const std::string& keyName, std::map<std::string, std::string>& variable_map, std::map<std::string, std::vector<std::string>>& variable_array_map, std::map<std::string, Matrix>& variable_matrix_map) { boost::shared_ptr<BlackVolTermStructure> vol_ts; Date refDate = Settings::instance().evaluationDate(); const std::string& vol_type = "TYPE"; if (variable_map.find(keyName) != variable_map.end()) { double value = std::stod(variable_map[keyName]); vol_ts = boost::shared_ptr<BlackConstantVol>( new BlackConstantVol(refDate, NullCalendar(), value, Actual365Fixed())); return vol_ts; } vol_ts = boost::shared_ptr<BlackConstantVol>( new BlackConstantVol(refDate, NullCalendar(), 0.3, Actual365Fixed())); //if (vol_type == "CONSTANT") //{ // vol_ts = boost::shared_ptr<BlackConstantVol>( // new BlackConstantVol(refDate, NullCalendar(), 0.3, Actual365Fixed())); //} //else if (vol_type == "CURVE") //{ //} //else if (vol_type == "SURFACE") //{ //} //else //{ //} return vol_ts; }
QuantLib::Calendar calendar(const std::string& typeStr) { QuantLib::Calendar calendar; std::string upperStr = boost::to_upper_copy(typeStr); if(upperStr=="KOR") { calendar = SouthKorea(); } else if(upperStr=="NULL") { calendar = NullCalendar(); } else if(upperStr=="NULLCALENDAR") { calendar = NullCalendar(); } else { QL_FAIL("unknown type calendar"); } return calendar; }
BlackScholesProcess::BlackScholesProcess( const Handle<Quote>& x0, const Handle<YieldTermStructure>& riskFreeTS, const Handle<BlackVolTermStructure>& blackVolTS, const boost::shared_ptr<discretization>& d) : GeneralizedBlackScholesProcess( x0, // no dividend yield Handle<YieldTermStructure>(boost::shared_ptr<YieldTermStructure>( new FlatForward(0, NullCalendar(), 0.0, Actual365Fixed()))), riskFreeTS, blackVolTS, d) {}
boost::shared_ptr<EarlySeePricer> pricer() { // 잡다한거 받아서 여기서 세팅...? // 머 차수별 , 구조별 , this->calendar_ = NullCalendar(); boost::shared_ptr<EarlySeePricer> pricer = boost::shared_ptr<EarlySeePricer>( new EarlySeePricer(this->productInfo_, this->expense_leg(), this->premium_leg(), this->annuity_leg(), this->claim_leg())); return pricer; }
SubPeriodsCoupon::SubPeriodsCoupon( const Date& paymentDate, Real nominal, const boost::shared_ptr<IborIndex>& index, const Date& startDate, const Date& endDate, Natural fixingDays, const DayCounter& dayCounter, Real gearing, Rate couponSpread, Rate rateSpread, const Date& refPeriodStart, const Date& refPeriodEnd) : FloatingRateCoupon(paymentDate, nominal, startDate, endDate, fixingDays, index, gearing, couponSpread, refPeriodStart, refPeriodEnd, dayCounter), rateSpread_(rateSpread) { const Handle<YieldTermStructure>& rateCurve = index->forwardingTermStructure(); const Date& referenceDate = rateCurve->referenceDate(); observationsSchedule_ = boost::shared_ptr<Schedule>(new Schedule(startDate, endDate, index->tenor(), NullCalendar(), Unadjusted, Unadjusted, DateGeneration::Forward, false)); observationDates_ = observationsSchedule_->dates(); observationDates_.pop_back(); //remove end date observations_ = observationDates_.size(); startTime_ = dayCounter.yearFraction(referenceDate, startDate); endTime_ = dayCounter.yearFraction(referenceDate, endDate); for (Size i=0; i<observations_; ++i) { observationTimes_.push_back( dayCounter.yearFraction(referenceDate, observationDates_[i])); } }
MakeSchedule::operator Schedule() const { // check for mandatory arguments QL_REQUIRE(effectiveDate_ != Date(), "effective date not provided"); QL_REQUIRE(terminationDate_ != Date(), "termination date not provided"); QL_REQUIRE(tenor_, "tenor/frequency not provided"); // set dynamic defaults: BusinessDayConvention convention; // if a convention was set, we use it. if (convention_) { convention = *convention_; } else { if (!calendar_.empty()) { // ...if we set a calendar, we probably want it to be used; convention = Following; } else { // if not, we don't care. convention = Unadjusted; } } BusinessDayConvention terminationDateConvention; // if set explicitly, we use it; if (terminationDateConvention_) { terminationDateConvention = *terminationDateConvention_; } else { // Unadjusted as per ISDA specification terminationDateConvention = convention; } Calendar calendar = calendar_; // if no calendar was set... if (calendar.empty()) { // ...we use a null one. calendar = NullCalendar(); } return Schedule(effectiveDate_, terminationDate_, *tenor_, calendar, convention, terminationDateConvention, rule_, endOfMonth_, firstDate_, nextToLastDate_); }
FixedLocalVolSurface::FixedLocalVolSurface( const Date& referenceDate, const std::vector<Time>& times, const std::vector<Real>& strikes, const boost::shared_ptr<Matrix>& localVolMatrix, const DayCounter& dayCounter, Extrapolation lowerExtrapolation, Extrapolation upperExtrapolation) : LocalVolTermStructure( referenceDate, NullCalendar(), Following, dayCounter), maxDate_(time2Date(referenceDate, dayCounter, times.back())), times_(times), localVolMatrix_(localVolMatrix), strikes_(times.size(),boost::make_shared<std::vector<Real> >(strikes)), localVolInterpol_(times.size()), lowerExtrapolation_(lowerExtrapolation), upperExtrapolation_(upperExtrapolation) { QL_REQUIRE(times_[0]>=0, "cannot have times[0] < 0"); checkSurface(); setInterpolation<Linear>(); }
void VannaVolgaDoubleBarrierEngine::calculate() const { const Real sigmaShift_vega = 0.001; const Real sigmaShift_volga = 0.0001; const Real spotShift_delta = 0.0001 * spotFX_->value(); const Real sigmaShift_vanna = 0.0001; Handle<Quote> x0Quote( //used for shift boost::make_shared<SimpleQuote>(spotFX_->value())); Handle<Quote> atmVolQuote( //used for shift boost::make_shared<SimpleQuote>(atmVol_->value())); boost::shared_ptr<BlackVolTermStructure> blackVolTS = boost::make_shared<BlackConstantVol>( Settings::instance().evaluationDate(), NullCalendar(), atmVolQuote, Actual365Fixed()); boost::shared_ptr<BlackScholesMertonProcess> stochProcess = boost::make_shared<BlackScholesMertonProcess>( x0Quote, foreignTS_, domesticTS_, Handle<BlackVolTermStructure>(blackVolTS)); boost::shared_ptr<PricingEngine> engineBS = boost::make_shared<AnalyticDoubleBarrierEngine>(stochProcess, series_); BlackDeltaCalculator blackDeltaCalculatorAtm( Option::Call, atmVol_->deltaType(), x0Quote->value(), domesticTS_->discount(T_), foreignTS_->discount(T_), atmVol_->value() * sqrt(T_)); Real atmStrike = blackDeltaCalculatorAtm.atmStrike(atmVol_->atmType()); Real call25Vol = vol25Call_->value(); Real put25Vol = vol25Put_->value(); BlackDeltaCalculator blackDeltaCalculatorPut25( Option::Put, vol25Put_->deltaType(), x0Quote->value(), domesticTS_->discount(T_), foreignTS_->discount(T_), put25Vol * sqrt(T_)); Real put25Strike = blackDeltaCalculatorPut25.strikeFromDelta(-0.25); BlackDeltaCalculator blackDeltaCalculatorCall25( Option::Call, vol25Call_->deltaType(), x0Quote->value(), domesticTS_->discount(T_), foreignTS_->discount(T_), call25Vol * sqrt(T_)); Real call25Strike = blackDeltaCalculatorCall25.strikeFromDelta(0.25); //here use vanna volga interpolated smile to price vanilla std::vector<Real> strikes; std::vector<Real> vols; strikes.push_back(put25Strike); vols.push_back(put25Vol); strikes.push_back(atmStrike); vols.push_back(atmVol_->value()); strikes.push_back(call25Strike); vols.push_back(call25Vol); VannaVolga vannaVolga(x0Quote->value(), foreignTS_->discount(T_), foreignTS_->discount(T_), T_); Interpolation interpolation = vannaVolga.interpolate(strikes.begin(), strikes.end(), vols.begin()); interpolation.enableExtrapolation(); const boost::shared_ptr<StrikedTypePayoff> payoff = boost::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff); Real strikeVol = interpolation(payoff->strike()); //vannila option price Real vanillaOption = blackFormula(payoff->optionType(), payoff->strike(), x0Quote->value()* foreignTS_->discount(T_)/ domesticTS_->discount(T_), strikeVol * sqrt(T_), domesticTS_->discount(T_)); //already out if((x0Quote->value() > arguments_.barrier[1] || x0Quote->value() < arguments_.barrier[0]) && arguments_.barrierType[0] == Barrier::DownOut) { results_.value = 0.0; results_.additionalResults["VanillaPrice"] = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption; results_.additionalResults["BarrierInPrice"] = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption; results_.additionalResults["BarrierOutPrice"] = 0.0; } //already in else if((x0Quote->value() > arguments_.barrier[1] || x0Quote->value() < arguments_.barrier[0]) && arguments_.barrierType[0] == Barrier::DownIn) { results_.value = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption; results_.additionalResults["VanillaPrice"] = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption; results_.additionalResults["BarrierInPrice"] = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption; results_.additionalResults["BarrierOutPrice"] = 0.0; } else { //set up BS barrier option pricing //only calculate out barrier option price // in barrier price = vanilla - out barrier boost::shared_ptr<StrikedTypePayoff> payoff = boost::static_pointer_cast<StrikedTypePayoff> (arguments_.payoff); DoubleBarrierOption doubleBarrierOption(arguments_.barrierType, arguments_.barrier, arguments_.rebate, payoff, arguments_.exercise); doubleBarrierOption.setPricingEngine(engineBS); //BS price Real priceBS = doubleBarrierOption.NPV(); Real priceAtmCallBS = blackFormula(Option::Call,atmStrike, x0Quote->value()* foreignTS_->discount(T_)/ domesticTS_->discount(T_), atmVol_->value() * sqrt(T_), domesticTS_->discount(T_)); Real price25CallBS = blackFormula(Option::Call,call25Strike, x0Quote->value()* foreignTS_->discount(T_)/ domesticTS_->discount(T_), atmVol_->value() * sqrt(T_), domesticTS_->discount(T_)); Real price25PutBS = blackFormula(Option::Put,put25Strike, x0Quote->value()* foreignTS_->discount(T_)/ domesticTS_->discount(T_), atmVol_->value() * sqrt(T_), domesticTS_->discount(T_)); //market price Real priceAtmCallMkt = blackFormula(Option::Call,atmStrike, x0Quote->value()* foreignTS_->discount(T_)/ domesticTS_->discount(T_), atmVol_->value() * sqrt(T_), domesticTS_->discount(T_)); Real price25CallMkt = blackFormula(Option::Call,call25Strike, x0Quote->value()* foreignTS_->discount(T_)/ domesticTS_->discount(T_), call25Vol * sqrt(T_), domesticTS_->discount(T_)); Real price25PutMkt = blackFormula(Option::Put,put25Strike, x0Quote->value()* foreignTS_->discount(T_)/ domesticTS_->discount(T_), put25Vol * sqrt(T_), domesticTS_->discount(T_)); //Analytical Black Scholes formula NormalDistribution norm; Real d1atm = (std::log(x0Quote->value()* foreignTS_->discount(T_)/ domesticTS_->discount(T_)/atmStrike) + 0.5*std::pow(atmVolQuote->value(),2.0) * T_)/(atmVolQuote->value() * sqrt(T_)); Real vegaAtm_Analytical = x0Quote->value() * norm(d1atm) * sqrt(T_) * foreignTS_->discount(T_); Real vannaAtm_Analytical = vegaAtm_Analytical/x0Quote->value() *(1.0 - d1atm/(atmVolQuote->value()*sqrt(T_))); Real volgaAtm_Analytical = vegaAtm_Analytical * d1atm * (d1atm - atmVolQuote->value() * sqrt(T_))/atmVolQuote->value(); Real d125call = (std::log(x0Quote->value()* foreignTS_->discount(T_)/ domesticTS_->discount(T_)/call25Strike) + 0.5*std::pow(atmVolQuote->value(),2.0) * T_)/(atmVolQuote->value() * sqrt(T_)); Real vega25Call_Analytical = x0Quote->value() * norm(d125call) * sqrt(T_) * foreignTS_->discount(T_); Real vanna25Call_Analytical = vega25Call_Analytical/x0Quote->value() *(1.0 - d125call/(atmVolQuote->value()*sqrt(T_))); Real volga25Call_Analytical = vega25Call_Analytical * d125call * (d125call - atmVolQuote->value() * sqrt(T_))/atmVolQuote->value(); Real d125Put = (std::log(x0Quote->value()* foreignTS_->discount(T_)/ domesticTS_->discount(T_)/put25Strike) + 0.5*std::pow(atmVolQuote->value(),2.0) * T_)/(atmVolQuote->value() * sqrt(T_)); Real vega25Put_Analytical = x0Quote->value() * norm(d125Put) * sqrt(T_) * foreignTS_->discount(T_); Real vanna25Put_Analytical = vega25Put_Analytical/x0Quote->value() *(1.0 - d125Put/(atmVolQuote->value()*sqrt(T_))); Real volga25Put_Analytical = vega25Put_Analytical * d125Put * (d125Put - atmVolQuote->value() * sqrt(T_))/atmVolQuote->value(); //BS vega boost::static_pointer_cast<SimpleQuote> (atmVolQuote.currentLink())->setValue(atmVolQuote->value() + sigmaShift_vega); doubleBarrierOption.recalculate(); Real vegaBarBS = (doubleBarrierOption.NPV() - priceBS)/sigmaShift_vega; boost::static_pointer_cast<SimpleQuote> (atmVolQuote.currentLink())->setValue(atmVolQuote->value() - sigmaShift_vega);//setback //BS volga //vegaBar2 //base NPV boost::static_pointer_cast<SimpleQuote> (atmVolQuote.currentLink())->setValue(atmVolQuote->value() + sigmaShift_volga); doubleBarrierOption.recalculate(); Real priceBS2 = doubleBarrierOption.NPV(); //shifted npv boost::static_pointer_cast<SimpleQuote> (atmVolQuote.currentLink())->setValue(atmVolQuote->value() + sigmaShift_vega); doubleBarrierOption.recalculate(); Real vegaBarBS2 = (doubleBarrierOption.NPV() - priceBS2)/sigmaShift_vega; Real volgaBarBS = (vegaBarBS2 - vegaBarBS)/sigmaShift_volga; boost::static_pointer_cast<SimpleQuote> (atmVolQuote.currentLink())->setValue(atmVolQuote->value() - sigmaShift_volga - sigmaShift_vega);//setback //BS Delta //base delta boost::static_pointer_cast<SimpleQuote> (x0Quote.currentLink())->setValue(x0Quote->value() + spotShift_delta);//shift forth doubleBarrierOption.recalculate(); Real priceBS_delta1 = doubleBarrierOption.NPV(); boost::static_pointer_cast<SimpleQuote> (x0Quote.currentLink())->setValue(x0Quote->value() - 2 * spotShift_delta);//shift back doubleBarrierOption.recalculate(); Real priceBS_delta2 = doubleBarrierOption.NPV(); boost::static_pointer_cast<SimpleQuote> (x0Quote.currentLink())->setValue(x0Quote->value() + spotShift_delta);//set back Real deltaBar1 = (priceBS_delta1 - priceBS_delta2)/(2.0*spotShift_delta); //shifted vanna boost::static_pointer_cast<SimpleQuote> (atmVolQuote.currentLink())->setValue(atmVolQuote->value() + sigmaShift_vanna);//shift sigma //shifted delta boost::static_pointer_cast<SimpleQuote> (x0Quote.currentLink())->setValue(x0Quote->value() + spotShift_delta);//shift forth doubleBarrierOption.recalculate(); priceBS_delta1 = doubleBarrierOption.NPV(); boost::static_pointer_cast<SimpleQuote> (x0Quote.currentLink())->setValue(x0Quote->value() - 2 * spotShift_delta);//shift back doubleBarrierOption.recalculate(); priceBS_delta2 = doubleBarrierOption.NPV(); boost::static_pointer_cast<SimpleQuote> (x0Quote.currentLink())->setValue(x0Quote->value() + spotShift_delta);//set back Real deltaBar2 = (priceBS_delta1 - priceBS_delta2)/(2.0*spotShift_delta); Real vannaBarBS = (deltaBar2 - deltaBar1)/sigmaShift_vanna; boost::static_pointer_cast<SimpleQuote> (atmVolQuote.currentLink())->setValue(atmVolQuote->value() - sigmaShift_vanna);//set back //Matrix Matrix A(3,3,0.0); //analytical A[0][0] = vegaAtm_Analytical; A[0][1] = vega25Call_Analytical; A[0][2] = vega25Put_Analytical; A[1][0] = vannaAtm_Analytical; A[1][1] = vanna25Call_Analytical; A[1][2] = vanna25Put_Analytical; A[2][0] = volgaAtm_Analytical; A[2][1] = volga25Call_Analytical; A[2][2] = volga25Put_Analytical; Array b(3,0.0); b[0] = vegaBarBS; b[1] = vannaBarBS; b[2] = volgaBarBS; Array q = inverse(A) * b; Real H = arguments_.barrier[1]; Real L = arguments_.barrier[0]; Real theta_tilt_minus = ((domesticTS_->zeroRate(T_, Continuous) - foreignTS_->zeroRate(T_, Continuous))/atmVol_->value() - atmVol_->value()/2.0)*std::sqrt(T_); Real h = 1.0/atmVol_->value() * std::log(H/x0Quote->value())/std::sqrt(T_); Real l = 1.0/atmVol_->value() * std::log(L/x0Quote->value())/std::sqrt(T_); CumulativeNormalDistribution cnd; Real doubleNoTouch = 0.0; for(int j = -series_; j< series_; j++ ) { Real e_minus = 2*j*(h-l) - theta_tilt_minus; doubleNoTouch += std::exp(-2.0*j*theta_tilt_minus*(h-l))*(cnd(h+e_minus) - cnd(l+e_minus)) - std::exp(-2.0*j*theta_tilt_minus*(h-l)+2.0*theta_tilt_minus*h)*(cnd(h-2.0*h+e_minus) - cnd(l-2.0*h+e_minus)); } Real p_survival = doubleNoTouch; Real lambda = p_survival ; Real adjust = q[0]*(priceAtmCallMkt - priceAtmCallBS) + q[1]*(price25CallMkt - price25CallBS) + q[2]*(price25PutMkt - price25PutBS); Real outPrice = priceBS + lambda*adjust;// Real inPrice; //adapt Vanilla delta if(adaptVanDelta_ == true) { outPrice += lambda*(bsPriceWithSmile_ - vanillaOption); //capfloored by (0, vanilla) outPrice = std::max(0.0, std::min(bsPriceWithSmile_, outPrice)); inPrice = bsPriceWithSmile_ - outPrice; } else { //capfloored by (0, vanilla) outPrice = std::max(0.0, std::min(vanillaOption , outPrice)); inPrice = vanillaOption - outPrice; } if(arguments_.barrierType[0] == Barrier::DownOut) results_.value = outPrice; else results_.value = inPrice; results_.additionalResults["VanillaPrice"] = vanillaOption; results_.additionalResults["BarrierInPrice"] = inPrice; results_.additionalResults["BarrierOutPrice"] = outPrice; results_.additionalResults["lambda"] = lambda; } }
Rate YoYInflationIndex::fixing(const Date& fixingDate, bool /*forecastTodaysFixing*/) const { Date today = Settings::instance().evaluationDate(); Date todayMinusLag = today - availabilityLag_; std::pair<Date,Date> lim = inflationPeriod(todayMinusLag, frequency_); Date lastFix = lim.first-1; Date flatMustForecastOn = lastFix+1; Date interpMustForecastOn = lastFix+1 - Period(frequency_); if (interpolated() && fixingDate >= interpMustForecastOn) { return forecastFixing(fixingDate); } if (!interpolated() && fixingDate >= flatMustForecastOn) { return forecastFixing(fixingDate); } // four cases with ratio() and interpolated() const TimeSeries<Real>& ts = timeSeries(); if (ratio()) { if(interpolated()){ // IS ratio, IS interpolated std::pair<Date,Date> lim = inflationPeriod(fixingDate, frequency_); Date fixMinus1Y=NullCalendar().advance(fixingDate, -1*Years, ModifiedFollowing); std::pair<Date,Date> limBef = inflationPeriod(fixMinus1Y, frequency_); Real dp= lim.second + 1 - lim.first; Real dpBef=limBef.second + 1 - limBef.first; Real dl = fixingDate-lim.first; // potentially does not work on 29th Feb Real dlBef = fixMinus1Y - limBef.first; // get the four relevant fixings // recall that they are stored flat for every day Rate limFirstFix = ts[lim.first]; QL_REQUIRE(limFirstFix != Null<Rate>(), "Missing " << name() << " fixing for " << lim.first ); Rate limSecondFix = ts[lim.second+1]; QL_REQUIRE(limSecondFix != Null<Rate>(), "Missing " << name() << " fixing for " << lim.second+1 ); Rate limBefFirstFix = ts[limBef.first]; QL_REQUIRE(limBefFirstFix != Null<Rate>(), "Missing " << name() << " fixing for " << limBef.first ); Rate limBefSecondFix = IndexManager::instance().getHistory(name())[limBef.second+1]; QL_REQUIRE(limBefSecondFix != Null<Rate>(), "Missing " << name() << " fixing for " << limBef.second+1 ); Real linearNow = limFirstFix + (limSecondFix-limFirstFix)*dl/dp; Real linearBef = limBefFirstFix + (limBefSecondFix-limBefFirstFix)*dlBef/dpBef; Rate wasYES = linearNow / linearBef - 1.0; return wasYES; } else { // IS ratio, NOT interpolated Rate pastFixing = ts[fixingDate]; QL_REQUIRE(pastFixing != Null<Rate>(), "Missing " << name() << " fixing for " << fixingDate); Date previousDate = fixingDate - 1*Years; Rate previousFixing = ts[previousDate]; QL_REQUIRE(previousFixing != Null<Rate>(), "Missing " << name() << " fixing for " << previousDate ); return pastFixing/previousFixing - 1.0; } } else { // NOT ratio if (interpolated()) { // NOT ratio, IS interpolated std::pair<Date,Date> lim = inflationPeriod(fixingDate, frequency_); Real dp= lim.second + 1 - lim.first; Real dl = fixingDate-lim.first; Rate limFirstFix = ts[lim.first]; QL_REQUIRE(limFirstFix != Null<Rate>(), "Missing " << name() << " fixing for " << lim.first ); Rate limSecondFix = ts[lim.second+1]; QL_REQUIRE(limSecondFix != Null<Rate>(), "Missing " << name() << " fixing for " << lim.second+1 ); Real linearNow = limFirstFix + (limSecondFix-limFirstFix)*dl/dp; return linearNow; } else { // NOT ratio, NOT interpolated // so just flat Rate pastFixing = ts[fixingDate]; QL_REQUIRE(pastFixing != Null<Rate>(), "Missing " << name() << " fixing for " << fixingDate); return pastFixing; } } // QL_FAIL("YoYInflationIndex::fixing, should never get here"); }
void IntegralCDOEngine::calculate() const { Date today = Settings::instance().evaluationDate(); results_.protectionValue = 0.0; results_.premiumValue = 0.0; results_.upfrontPremiumValue = 0.0; results_.error = 0; results_.expectedTrancheLoss.clear(); // todo Should be remaining when considering realized loses results_.xMin = arguments_.basket->attachmentAmount(); results_.xMax = arguments_.basket->detachmentAmount(); results_.remainingNotional = results_.xMax - results_.xMin; const Real inceptionTrancheNotional = arguments_.basket->trancheNotional(); // compute expected loss at the beginning of first relevant period Real e1 = 0; // todo add includeSettlement date flows variable to engine. if (!arguments_.normalizedLeg[0]->hasOccurred(today)) // cast to fixed rate coupon? e1 = arguments_.basket->expectedTrancheLoss( boost::dynamic_pointer_cast<Coupon>( arguments_.normalizedLeg[0])->accrualStartDate()); results_.expectedTrancheLoss.push_back(e1);// zero or realized losses? for (Size i = 0; i < arguments_.normalizedLeg.size(); i++) { if(arguments_.normalizedLeg[i]->hasOccurred(today)) { // add includeSettlement date flows variable to engine. results_.expectedTrancheLoss.push_back(0.); continue; } const boost::shared_ptr<Coupon> coupon = boost::dynamic_pointer_cast<Coupon>( arguments_.normalizedLeg[i]); Date d1 = coupon->accrualStartDate(); Date d2 = coupon->date(); Date d, d0 = d1; Real e2; do { d = NullCalendar().advance(d0 > today ? d0 : today, stepSize_); if (d > d2) d = d2; e2 = arguments_.basket->expectedTrancheLoss(d); results_.premiumValue // ..check for e2 including past/realized losses += (inceptionTrancheNotional - e2) * arguments_.runningRate * arguments_.dayCounter.yearFraction(d0, d) * discountCurve_->discount(d); // TO DO: Addd default coupon accrual value here----- if (e2 < e1) results_.error ++; results_.protectionValue += (e2 - e1) * discountCurve_->discount(d); d0 = d; e1 = e2; } while (d < d2); results_.expectedTrancheLoss.push_back(e2); } // add includeSettlement date flows variable to engine. if (!arguments_.normalizedLeg[0]->hasOccurred(today)) results_.upfrontPremiumValue = inceptionTrancheNotional * arguments_.upfrontRate * discountCurve_->discount( boost::dynamic_pointer_cast<Coupon>( arguments_.normalizedLeg[0])->accrualStartDate()); if (arguments_.side == Protection::Buyer) { results_.protectionValue *= -1; results_.premiumValue *= -1; results_.upfrontPremiumValue *= -1; } results_.value = results_.premiumValue - results_.protectionValue + results_.upfrontPremiumValue; results_.errorEstimate = Null<Real>(); // Fair spread GIVEN the upfront Real fairSpread = 0.; if (results_.premiumValue != 0.0) { fairSpread = -(results_.protectionValue + results_.upfrontPremiumValue) *arguments_.runningRate/results_.premiumValue; } results_.additionalResults["fairPremium"] = fairSpread; results_.additionalResults["premiumLegNPV"] = results_.premiumValue + results_.upfrontPremiumValue; results_.additionalResults["protectionLegNPV"] = results_.protectionValue; }
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void IntegralCDOEngine::calculate() const { Date today = Settings::instance().evaluationDate(); const vector<Date>& dates = arguments_.schedule.dates(); results_.protectionValue = 0.0; results_.premiumValue = 0.0; results_.upfrontPremiumValue = 0.0; results_.error = 0; results_.expectedTrancheLoss.clear(); results_.expectedTrancheLoss.resize(dates.size(), 0.0); // set remainingBasket_, results_.remainingNotional, // vector results_.expectedTrancheLoss for all schedule dates initialize(); Real e1 = 0; if (arguments_.schedule.dates().front() > today) e1 = expectedTrancheLoss (arguments_.schedule.dates()[0]); for (Size i = 1; i < arguments_.schedule.size(); i++) { Date d2 = arguments_.schedule.dates()[i]; if (d2 < today) continue; Date d1 = arguments_.schedule.dates()[i-1]; Date d, d0 = d1; do { d = NullCalendar().advance (d0 > today ? d0 : today, stepSize_); if (d > d2) d = d2; Real e2 = expectedTrancheLoss (d); results_.premiumValue += (results_.remainingNotional - e2) * arguments_.runningRate * arguments_.dayCounter.yearFraction (d0, d) * arguments_.yieldTS->discount (d); if (e2 < e1) results_.error ++; results_.protectionValue += (e2 - e1) * arguments_.yieldTS->discount (d); d0 = d; e1 = e2; } while (d < d2); } if (arguments_.schedule.dates().front() >= today) results_.upfrontPremiumValue = results_.remainingNotional * arguments_.upfrontRate * arguments_.yieldTS->discount(arguments_.schedule.dates()[0]); if (arguments_.side == Protection::Buyer) { results_.protectionValue *= -1; results_.premiumValue *= -1; results_.upfrontPremiumValue *= -1; } results_.value = results_.premiumValue - results_.protectionValue + results_.upfrontPremiumValue; results_.errorEstimate = Null<Real>(); }
boost::shared_ptr<YieldTermStructure> flatRate(const boost::shared_ptr<Quote>& forward, const DayCounter& dc) { return boost::shared_ptr<YieldTermStructure>( new FlatForward(0, NullCalendar(), Handle<Quote>(forward), dc)); }
Schedule::Schedule(Date effectiveDate, const Date& terminationDate, const Period& tenor, const Calendar& cal, BusinessDayConvention convention, BusinessDayConvention terminationDateConvention, DateGeneration::Rule rule, bool endOfMonth, const Date& first, const Date& nextToLast) : tenor_(tenor), calendar_(cal), convention_(convention), terminationDateConvention_(terminationDateConvention), rule_(rule), endOfMonth_(allowsEndOfMonth(tenor) ? endOfMonth : false), firstDate_(first==effectiveDate ? Date() : first), nextToLastDate_(nextToLast==terminationDate ? Date() : nextToLast) { // sanity checks QL_REQUIRE(terminationDate != Date(), "null termination date"); // in many cases (e.g. non-expired bonds) the effective date is not // really necessary. In these cases a decent placeholder is enough if (effectiveDate==Date() && first==Date() && rule==DateGeneration::Backward) { Date evalDate = Settings::instance().evaluationDate(); QL_REQUIRE(evalDate < terminationDate, "null effective date"); Natural y; if (nextToLast != Date()) { y = (nextToLast - evalDate)/366 + 1; effectiveDate = nextToLast - y*Years; } else { y = (terminationDate - evalDate)/366 + 1; effectiveDate = terminationDate - y*Years; } } else QL_REQUIRE(effectiveDate != Date(), "null effective date"); QL_REQUIRE(effectiveDate < terminationDate, "effective date (" << effectiveDate << ") later than or equal to termination date (" << terminationDate << ")"); if (tenor.length()==0) rule_ = DateGeneration::Zero; else QL_REQUIRE(tenor.length()>0, "non positive tenor (" << tenor << ") not allowed"); if (firstDate_ != Date()) { switch (*rule_) { case DateGeneration::Backward: case DateGeneration::Forward: QL_REQUIRE(firstDate_ > effectiveDate && firstDate_ < terminationDate, "first date (" << firstDate_ << ") out of effective-termination date range [" << effectiveDate << ", " << terminationDate << ")"); // we should ensure that the above condition is still // verified after adjustment break; case DateGeneration::ThirdWednesday: QL_REQUIRE(IMM::isIMMdate(firstDate_, false), "first date (" << firstDate_ << ") is not an IMM date"); break; case DateGeneration::Zero: case DateGeneration::Twentieth: case DateGeneration::TwentiethIMM: case DateGeneration::OldCDS: case DateGeneration::CDS: QL_FAIL("first date incompatible with " << *rule_ << " date generation rule"); default: QL_FAIL("unknown rule (" << Integer(*rule_) << ")"); } } if (nextToLastDate_ != Date()) { switch (*rule_) { case DateGeneration::Backward: case DateGeneration::Forward: QL_REQUIRE(nextToLastDate_ > effectiveDate && nextToLastDate_ < terminationDate, "next to last date (" << nextToLastDate_ << ") out of effective-termination date range (" << effectiveDate << ", " << terminationDate << "]"); // we should ensure that the above condition is still // verified after adjustment break; case DateGeneration::ThirdWednesday: QL_REQUIRE(IMM::isIMMdate(nextToLastDate_, false), "next-to-last date (" << nextToLastDate_ << ") is not an IMM date"); break; case DateGeneration::Zero: case DateGeneration::Twentieth: case DateGeneration::TwentiethIMM: case DateGeneration::OldCDS: case DateGeneration::CDS: QL_FAIL("next to last date incompatible with " << *rule_ << " date generation rule"); default: QL_FAIL("unknown rule (" << Integer(*rule_) << ")"); } } // calendar needed for endOfMonth adjustment Calendar nullCalendar = NullCalendar(); Integer periods = 1; Date seed, exitDate; switch (*rule_) { case DateGeneration::Zero: tenor_ = 0*Years; dates_.push_back(effectiveDate); dates_.push_back(terminationDate); isRegular_.push_back(true); break; case DateGeneration::Backward: dates_.push_back(terminationDate); seed = terminationDate; if (nextToLastDate_ != Date()) { dates_.insert(dates_.begin(), nextToLastDate_); Date temp = nullCalendar.advance(seed, -periods*(*tenor_), convention, *endOfMonth_); if (temp!=nextToLastDate_) isRegular_.insert(isRegular_.begin(), false); else isRegular_.insert(isRegular_.begin(), true); seed = nextToLastDate_; } exitDate = effectiveDate; if (firstDate_ != Date()) exitDate = firstDate_; for (;;) { Date temp = nullCalendar.advance(seed, -periods*(*tenor_), convention, *endOfMonth_); if (temp < exitDate) { if (firstDate_ != Date() && (calendar_.adjust(dates_.front(),convention)!= calendar_.adjust(firstDate_,convention))) { dates_.insert(dates_.begin(), firstDate_); isRegular_.insert(isRegular_.begin(), false); } break; } else { // skip dates that would result in duplicates // after adjustment if (calendar_.adjust(dates_.front(),convention)!= calendar_.adjust(temp,convention)) { dates_.insert(dates_.begin(), temp); isRegular_.insert(isRegular_.begin(), true); } ++periods; } } if (calendar_.adjust(dates_.front(),convention)!= calendar_.adjust(effectiveDate,convention)) { dates_.insert(dates_.begin(), effectiveDate); isRegular_.insert(isRegular_.begin(), false); } break; case DateGeneration::Twentieth: case DateGeneration::TwentiethIMM: case DateGeneration::ThirdWednesday: case DateGeneration::OldCDS: case DateGeneration::CDS: QL_REQUIRE(!*endOfMonth_, "endOfMonth convention incompatible with " << *rule_ << " date generation rule"); // fall through case DateGeneration::Forward: if (*rule_ == DateGeneration::CDS) { dates_.push_back(previousTwentieth(effectiveDate, DateGeneration::CDS)); } else { dates_.push_back(effectiveDate); } seed = dates_.back(); if (firstDate_!=Date()) { dates_.push_back(firstDate_); Date temp = nullCalendar.advance(seed, periods*(*tenor_), convention, *endOfMonth_); if (temp!=firstDate_) isRegular_.push_back(false); else isRegular_.push_back(true); seed = firstDate_; } else if (*rule_ == DateGeneration::Twentieth || *rule_ == DateGeneration::TwentiethIMM || *rule_ == DateGeneration::OldCDS || *rule_ == DateGeneration::CDS) { Date next20th = nextTwentieth(effectiveDate, *rule_); if (*rule_ == DateGeneration::OldCDS) { // distance rule inforced in natural days static const BigInteger stubDays = 30; if (next20th - effectiveDate < stubDays) { // +1 will skip this one and get the next next20th = nextTwentieth(next20th + 1, *rule_); } } if (next20th != effectiveDate) { dates_.push_back(next20th); isRegular_.push_back(false); seed = next20th; } } exitDate = terminationDate; if (nextToLastDate_ != Date()) exitDate = nextToLastDate_; for (;;) { Date temp = nullCalendar.advance(seed, periods*(*tenor_), convention, *endOfMonth_); if (temp > exitDate) { if (nextToLastDate_ != Date() && (calendar_.adjust(dates_.back(),convention)!= calendar_.adjust(nextToLastDate_,convention))) { dates_.push_back(nextToLastDate_); isRegular_.push_back(false); } break; } else { // skip dates that would result in duplicates // after adjustment if (calendar_.adjust(dates_.back(),convention)!= calendar_.adjust(temp,convention)) { dates_.push_back(temp); isRegular_.push_back(true); } ++periods; } } if (calendar_.adjust(dates_.back(),terminationDateConvention)!= calendar_.adjust(terminationDate,terminationDateConvention)) { if (*rule_ == DateGeneration::Twentieth || *rule_ == DateGeneration::TwentiethIMM || *rule_ == DateGeneration::OldCDS || *rule_ == DateGeneration::CDS) { dates_.push_back(nextTwentieth(terminationDate, *rule_)); isRegular_.push_back(true); } else { dates_.push_back(terminationDate); isRegular_.push_back(false); } } break; default: QL_FAIL("unknown rule (" << Integer(*rule_) << ")"); } // adjustments if (*rule_==DateGeneration::ThirdWednesday) for (Size i=1; i<dates_.size()-1; ++i) dates_[i] = Date::nthWeekday(3, Wednesday, dates_[i].month(), dates_[i].year()); if (*endOfMonth_ && calendar_.isEndOfMonth(seed)) { // adjust to end of month if (convention == Unadjusted) { for (Size i=1; i<dates_.size()-1; ++i) dates_[i] = Date::endOfMonth(dates_[i]); } else { for (Size i=1; i<dates_.size()-1; ++i) dates_[i] = calendar_.endOfMonth(dates_[i]); } if (terminationDateConvention != Unadjusted) { dates_.front() = calendar_.endOfMonth(dates_.front()); dates_.back() = calendar_.endOfMonth(dates_.back()); } else { // the termination date is the first if going backwards, // the last otherwise. if (*rule_ == DateGeneration::Backward) dates_.back() = Date::endOfMonth(dates_.back()); else dates_.front() = Date::endOfMonth(dates_.front()); } } else { // first date not adjusted for CDS schedules if (*rule_ != DateGeneration::OldCDS) dates_[0] = calendar_.adjust(dates_[0], convention); for (Size i=1; i<dates_.size()-1; ++i) dates_[i] = calendar_.adjust(dates_[i], convention); // termination date is NOT adjusted as per ISDA // specifications, unless otherwise specified in the // confirmation of the deal or unless we're creating a CDS // schedule if (terminationDateConvention != Unadjusted || *rule_ == DateGeneration::Twentieth || *rule_ == DateGeneration::TwentiethIMM || *rule_ == DateGeneration::OldCDS || *rule_ == DateGeneration::CDS) { dates_.back() = calendar_.adjust(dates_.back(), terminationDateConvention); } } // Final safety checks to remove extra next-to-last date, if // necessary. It can happen to be equal or later than the end // date due to EOM adjustments (see the Schedule test suite // for an example). if (dates_.size() >= 2 && dates_[dates_.size()-2] >= dates_.back()) { isRegular_[dates_.size()-2] = (dates_[dates_.size()-2] == dates_.back()); dates_[dates_.size()-2] = dates_.back(); dates_.pop_back(); isRegular_.pop_back(); } if (dates_.size() >= 2 && dates_[1] <= dates_.front()) { isRegular_[1] = (dates_[1] == dates_.front()); dates_[1] = dates_.front(); dates_.erase(dates_.begin()); isRegular_.erase(isRegular_.begin()); } QL_ENSURE(dates_.size()>1, "degenerate single date (" << dates_[0] << ") schedule" << "\n seed date: " << seed << "\n exit date: " << exitDate << "\n effective date: " << effectiveDate << "\n first date: " << first << "\n next to last date: " << nextToLast << "\n termination date: " << terminationDate << "\n generation rule: " << *rule_ << "\n end of month: " << *endOfMonth_); }
boost::shared_ptr<CapFloorTermVolatilityStructure> ProcessInfo::ProcessParser_Impl:: make_capfloor_vol_ts(std::map<std::string, std::string>& variable_map, std::map<std::string, std::vector<std::string>>& variable_array_map, std::map<std::string, Matrix>& variable_matrix_map) { boost::shared_ptr<CapFloorTermVolatilityStructure> capfloor_vol_ts; Date refDate = Settings::instance().evaluationDate(); const Calendar& calendar = NullCalendar(); BusinessDayConvention bdc = BusinessDayConvention::ModifiedFollowing; DayCounter daycounter = Actual365Fixed(); std::string type_key = "CAPFLOOR_TYPE"; if (variable_map.find(type_key) == variable_map.end()) QL_FAIL(type_key << " does not exist."); std::string vol_type = variable_map[type_key]; if (vol_type == "CONSTANT") { std::string cap_flat_vol_key = "CAP_VOL_CONSTANT"; if (variable_array_map.find(cap_flat_vol_key) == variable_array_map.end()) QL_FAIL(cap_flat_vol_key << " does not exist."); Real flatVol = 0.0; capfloor_vol_ts = boost::shared_ptr<CapFloorTermVolatilityStructure>( new ConstantCapFloorTermVolatility(refDate, calendar, bdc, flatVol, daycounter)); } else if (vol_type == "CURVE") { std::string optionTenor_key = "CAP_VOL_CURVE_TENOR"; std::string value_key = "CAP_VOL_SURFACE_VALUE"; if (variable_array_map.find(optionTenor_key) == variable_array_map.end()) QL_FAIL(optionTenor_key << " does not exist."); if (variable_array_map.find(value_key) == variable_array_map.end()) QL_FAIL(value_key << " does not exist."); std::vector<std::string> optionTenors = variable_array_map[optionTenor_key]; std::vector<std::string> values = variable_array_map[value_key]; std::vector<Period> optionPeriod_data; std::vector<Real> data; // converting for (Size i = 0; i < optionTenors.size(); i++) optionPeriod_data.push_back(PeriodParser::parse(optionTenors[i])); for (Size i = 0; i < values.size(); i++) data.push_back(std::stod(values[i])); QL_REQUIRE(optionTenors.size() == data.size(), "tenor size must be same to value size"); //std::string interpolatedID = "LINEAR"; //if (variable_map.find(interpolation_key) != variable_map.end()) // interpolatedID = variable_map[interpolation_key]; //QL_DEBUG(tenor_key << " does not exist. Linear interpolation is used"); capfloor_vol_ts = boost::shared_ptr<CapFloorTermVolatilityStructure>( new CapFloorTermVolCurve(refDate, calendar, bdc, optionPeriod_data, data, daycounter)); } else if (vol_type == "SURFACE") { std::string optionTenor_key = "CAP_VOL_SURFACE_OPTIONTENOR"; std::string strikeTenor_key = "CAP_VOL_SURFACE_STRIKE"; std::string value_key = "CAP_VOL_SURFACE_VALUE"; // default bilinear //std::string interpolation_key = "CAP_VOL_CURVE_INTERPOLATION"; if (variable_array_map.find(optionTenor_key) == variable_array_map.end()) QL_FAIL(optionTenor_key << " does not exist."); if (variable_array_map.find(strikeTenor_key) == variable_array_map.end()) QL_FAIL(strikeTenor_key << " does not exist."); if (variable_matrix_map.find(value_key) == variable_matrix_map.end()) QL_FAIL(value_key << " does not exist."); std::vector<std::string> optionTenors = variable_array_map[optionTenor_key]; std::vector<std::string> strikes = variable_array_map[strikeTenor_key]; Matrix value_matrix = variable_matrix_map[value_key]; std::vector<Period> optionPeriod_data; std::vector<Real> strike_data; for (Size i = 0; i < optionTenors.size(); i++) optionPeriod_data.push_back(PeriodParser::parse(optionTenors[i])); for (Size i = 0; i < optionTenors.size(); i++) strike_data.push_back(std::stod(strikes[i])); // converting QL_REQUIRE(optionTenors.size() * strikes.size() == value_matrix.rows() * value_matrix.columns(), "tenor * strike must be same to value matrix size"); //std::string interpolatedID = "LINEAR"; //if (variable_map.find(interpolation_key) != variable_map.end()) // interpolatedID = variable_map[interpolation_key]; //QL_DEBUG(tenor_key << " does not exist. Linear interpolation is used"); capfloor_vol_ts = boost::shared_ptr<CapFloorTermVolatilityStructure>( new CapFloorTermVolSurface(refDate, calendar, bdc, optionPeriod_data, strike_data, value_matrix, daycounter)); } else { } return capfloor_vol_ts; }
boost::shared_ptr<SwaptionVolatilityStructure> ProcessInfo::ProcessParser_Impl:: make_swaption_vol_ts(std::map<std::string, std::string>& variable_map, std::map<std::string, std::vector<std::string>>& variable_array_map, std::map<std::string, Matrix>& variable_matrix_map) { boost::shared_ptr<SwaptionVolatilityStructure> swaption_vol_ts; Date refDate = Settings::instance().evaluationDate(); const Calendar& calendar = NullCalendar(); BusinessDayConvention bdc = BusinessDayConvention::ModifiedFollowing; DayCounter daycounter = Actual365Fixed(); std::string type_key = "SWAPTION_TYPE"; if (variable_map.find(type_key) == variable_map.end()) QL_FAIL(type_key << " does not exist."); std::string vol_type = variable_map[type_key]; if (vol_type == "CONSTANT") { std::string swaption_flat_vol_key = "SWAP_VOL_CONSTANT"; if (variable_array_map.find(swaption_flat_vol_key) == variable_array_map.end()) QL_FAIL(swaption_flat_vol_key << " does not exist."); Real flatVol = 0.0; swaption_vol_ts = boost::shared_ptr<SwaptionVolatilityStructure>( new ConstantSwaptionVolatility(refDate, calendar, bdc, flatVol, daycounter)); } else if (vol_type == "SURFACE") { std::string optionTenor_key = "SWAPTION_VOL_SURFACE_OPTIONTENOR"; std::string swapTenor_key = "SWAPTION_VOL_SURFACE_SWAPTENOR"; std::string value_key = "SWAPTION_VOL_SURFACE_VALUE"; if (variable_array_map.find(optionTenor_key) == variable_array_map.end()) QL_FAIL(optionTenor_key << " does not exist."); if (variable_array_map.find(swapTenor_key) == variable_array_map.end()) QL_FAIL(swapTenor_key << " does not exist."); if (variable_matrix_map.find(value_key) == variable_matrix_map.end()) QL_FAIL(value_key << " does not exist."); std::vector<std::string> optionTenors = variable_array_map[optionTenor_key]; std::vector<std::string> swapTenors = variable_array_map[swapTenor_key]; Matrix value_matrix = variable_matrix_map[value_key]; std::vector<Period> optionPeriod_data; std::vector<Period> swapPeriod_data; for (Size i = 0; i < optionTenors.size(); i++) optionPeriod_data.push_back(PeriodParser::parse(optionTenors[i])); for (Size i = 0; i < swapTenors.size(); i++) swapPeriod_data.push_back(PeriodParser::parse(swapTenors[i])); // converting QL_REQUIRE(optionTenors.size() * swapTenors.size() == value_matrix.rows() * value_matrix.columns(), "tenor * strike must be same to value matrix size"); //std::string interpolatedID = "LINEAR"; //if (variable_map.find(interpolation_key) != variable_map.end()) // interpolatedID = variable_map[interpolation_key]; //QL_DEBUG(tenor_key << " does not exist. Linear interpolation is used"); swaption_vol_ts = boost::shared_ptr<SwaptionVolatilityStructure>( new SwaptionVolatilityMatrix(refDate, calendar, bdc, optionPeriod_data, swapPeriod_data, value_matrix, daycounter)); } else if (vol_type == "CUBE") { QL_FAIL("not implemeted"); } else { } return swaption_vol_ts; }