boost::shared_ptr<Lattice> HullWhite::tree(const TimeGrid& grid) const { TermStructureFittingParameter phi(termStructure()); boost::shared_ptr<ShortRateDynamics> numericDynamics( new Dynamics(phi, a(), sigma())); boost::shared_ptr<TrinomialTree> trinomial( new TrinomialTree(numericDynamics->process(), grid)); boost::shared_ptr<ShortRateTree> numericTree( new ShortRateTree(trinomial, numericDynamics, grid)); typedef TermStructureFittingParameter::NumericalImpl NumericalImpl; boost::shared_ptr<NumericalImpl> impl = boost::dynamic_pointer_cast<NumericalImpl>(phi.implementation()); impl->reset(); for (Size i=0; i<(grid.size() - 1); i++) { Real discountBond = termStructure()->discount(grid[i+1]); const Array& statePrices = numericTree->statePrices(i); Size size = numericTree->size(i); Time dt = numericTree->timeGrid().dt(i); Real dx = trinomial->dx(i); Real x = trinomial->underlying(i,0); Real value = 0.0; for (Size j=0; j<size; j++) { value += statePrices[j]*std::exp(-x*dt); x += dx; } value = std::log(value/discountBond)/dt; impl->set(grid[i], value); } return numericTree; }
boost::shared_ptr<Lattice> BlackKarasinski::tree(const TimeGrid& grid) const { TermStructureFittingParameter phi(termStructure()); boost::shared_ptr<ShortRateDynamics> numericDynamics( new Dynamics(phi, a(), sigma())); boost::shared_ptr<TrinomialTree> trinomial( new TrinomialTree(numericDynamics->process(), grid)); boost::shared_ptr<ShortRateTree> numericTree( new ShortRateTree(trinomial, numericDynamics, grid)); typedef TermStructureFittingParameter::NumericalImpl NumericalImpl; boost::shared_ptr<NumericalImpl> impl = boost::dynamic_pointer_cast<NumericalImpl>(phi.implementation()); impl->reset(); Real value = 1.0; Real vMin = -50.0; Real vMax = 50.0; for (Size i=0; i<(grid.size() - 1); i++) { Real discountBond = termStructure()->discount(grid[i+1]); Real xMin = trinomial->underlying(i, 0); Real dx = trinomial->dx(i); Helper finder(i, xMin, dx, discountBond, numericTree); Brent s1d; s1d.setMaxEvaluations(1000); value = s1d.solve(finder, 1e-7, value, vMin, vMax); impl->set(grid[i], value); // vMin = value - 10.0; // vMax = value + 10.0; } return numericTree; }
Real Generalized_HullWhite::A(Time t, Time T) const { DiscountFactor discount1 = termStructure()->discount(t); DiscountFactor discount2 = termStructure()->discount(T); Rate forward = termStructure()->forwardRate(t, t, Continuous, NoFrequency); Real temp = B(t,T); Real value = B(t,T)*forward - 0.5*temp*temp*Vr(0, t); return std::exp(value)*discount2/discount1; }
Real Qg1dLocalVolModel::zerobond(const Date &maturity, const Date &referenceDate, const Real x, const Real y, const Handle<YieldTermStructure> &yts) { return zerobond(termStructure()->timeFromReference(maturity), termStructure()->timeFromReference(referenceDate), x, y, yts); }
Real HullWhite::A(Time t, Time T) const { DiscountFactor discount1 = termStructure()->discount(t); DiscountFactor discount2 = termStructure()->discount(T); Rate forward = termStructure()->forwardRate(t, t, Continuous, NoFrequency); Real temp = sigma()*B(t,T); Real value = B(t,T)*forward - 0.25*temp*temp*B(0.0,2.0*t); return std::exp(value)*discount2/discount1; }
Real Generalized_HullWhite::discountBondOption(Option::Type type, Real strike, Time maturity, Time bondMaturity) const { Real _a = a(); Real v; v = std::sqrt(Vp(0, maturity, bondMaturity)); Real f = termStructure()->discount(bondMaturity); Real k = termStructure()->discount(maturity)*strike; return blackFormula(type, k, f, v); }
Real Qg1dLocalVolModel::d2SwapRateDx2(const Date &startDate, const Date &referenceDate, const boost::shared_ptr<SwapIndex> &index, const Period &tenor, const Real x, const Real y) const { Real T0; std::vector<Real> taus, times; timesAndTaus(startDate, index, tenor, T0, times, taus); return d2SwapRateDx2(termStructure()->timeFromReference(startDate), termStructure()->timeFromReference(referenceDate), times, taus, x, y, index->forwardingTermStructure()); }
void Qg1dLocalVolModel::timesAndTaus(const Date &startDate, const boost::shared_ptr<SwapIndex> &index, const Period &tenor, Real &T0, std::vector<Real> ×, std::vector<Real> &taus) const { T0 = termStructure()->timeFromReference(startDate); std::vector<Date> dates = index->underlyingSwap(index->clone(tenor)->fixingDate(startDate)) ->fixedSchedule() .dates(); times.resize(dates.size() - 1); taus.resize(dates.size() - 1); for (Size i = 1; i < dates.size(); ++i) { times[i - 1] = termStructure()->timeFromReference(dates[i]); taus[i - 1] = index->dayCounter().yearFraction(dates[i - 1], dates[i]); } }
Real HullWhite::discountBondOption(Option::Type type, Real strike, Time maturity, Time bondMaturity) const { Real _a = a(); Real v; if (_a < std::sqrt(QL_EPSILON)) { v = sigma()*B(maturity, bondMaturity)* std::sqrt(maturity); } else { v = sigma()*B(maturity, bondMaturity)* std::sqrt(0.5*(1.0 - std::exp(-2.0*_a*maturity))/_a); } Real f = termStructure()->discount(bondMaturity); Real k = termStructure()->discount(maturity)*strike; return blackFormula(type, k, f, v); }
Real Qg1dLocalVolModel::zerobond(const Real T, const Real t, const Real x, const Real y, const Handle<YieldTermStructure> &yts) const { Real tmp = G(t, T); const Handle<YieldTermStructure> &ytsTmp = yts.empty() ? termStructure() : yts; return ytsTmp->discount(T) / ytsTmp->discount(t) * std::exp(-G(t, T) * x - 0.5 * tmp * tmp * y); }
Real HullWhite::discountBondOption(Option::Type type, Real strike, Time maturity, Time bondStart, Time bondMaturity) const { Real _a = a(); Real v; if (_a < std::sqrt(QL_EPSILON)) { v = sigma()*B(bondStart, bondMaturity)* std::sqrt(maturity); } else { v = sigma()/(_a*sqrt(2.0*_a)) * sqrt ( exp(-2.0*_a*(bondStart-maturity))-exp(-2.0*_a*bondStart) -2.0*(exp(-_a*(bondStart+bondMaturity-2.0*maturity))-exp(-_a*(bondStart+bondMaturity))) +exp(-2.0*_a*(bondMaturity-maturity))-exp(-2.0*_a*bondMaturity)); } Real f = termStructure()->discount(bondMaturity); Real k = termStructure()->discount(bondStart)*strike; return blackFormula(type, k, f, v); }
const Real Gsr::zerobondImpl(const Time T, const Time t, const Real y, const Handle<YieldTermStructure> &yts) const { calculate(); if (t == 0.0) return yts.empty() ? this->termStructure()->discount(T, true) : yts->discount(T, true); boost::shared_ptr<GsrProcess> p = boost::dynamic_pointer_cast<GsrProcess>(stateProcess_); Real x = y * p->stdDeviation(0.0, 0.0, t) + stateProcess_->expectation(0.0, 0.0, t); Real gtT = p->G(t, T, x); Real d = yts.empty() ? termStructure()->discount(T, true) / termStructure()->discount(t, true) : yts->discount(T, true) / yts->discount(t, true); return d * exp(-x * gtT - 0.5 * p->y(t) * gtT * gtT); }
void Gsr::initialize(Real T) { volsteptimesArray_ = Array(volstepdates_.size()); updateTimes(); QL_REQUIRE(volatilities_.size() == volsteptimes_.size() + 1, "there must be n+1 volatilities (" << volatilities_.size() << ") for n volatility step times (" << volsteptimes_.size() << ")"); // sigma_ = // PiecewiseConstantParameter(volsteptimes_,PositiveConstraint()); sigma_ = PiecewiseConstantParameter(volsteptimes_, NoConstraint()); QL_REQUIRE(reversions_.size() == 1 || reversions_.size() == volsteptimes_.size() + 1, "there must be 1 or n+1 reversions (" << reversions_.size() << ") for n volatility step times (" << volsteptimes_.size() << ")"); if (reversions_.size() == 1) { reversion_ = ConstantParameter(reversions_[0]->value(), NoConstraint()); } else { reversion_ = PiecewiseConstantParameter(volsteptimes_, NoConstraint()); } for (Size i = 0; i < sigma_.size(); i++) { sigma_.setParam(i, volatilities_[i]->value()); } for (Size i = 0; i < reversion_.size(); i++) { reversion_.setParam(i, reversions_[i]->value()); } stateProcess_ = boost::shared_ptr<GsrProcess>(new GsrProcess( volsteptimesArray_, sigma_.params(), reversion_.params(), T)); registerWith(termStructure()); registerWith(stateProcess_); for(Size i=0;i<reversions_.size();++i) registerWith(reversions_[i]); for(Size i=0;i<volatilities_.size();++i) registerWith(volatilities_[i]); }
void Gsr::updateTimes() const { volsteptimes_.clear(); int j = 0; for (std::vector<Date>::const_iterator i = volstepdates_.begin(); i != volstepdates_.end(); ++i, ++j) { volsteptimes_.push_back(termStructure()->timeFromReference(*i)); volsteptimesArray_[j] = volsteptimes_[j]; if (j == 0) QL_REQUIRE(volsteptimes_[0] > 0.0, "volsteptimes must be positive (" << volsteptimes_[0] << ")"); else QL_REQUIRE(volsteptimes_[j] > volsteptimes_[j - 1], "volsteptimes must be strictly increasing (" << volsteptimes_[j - 1] << "@" << (j - 1) << ", " << volsteptimes_[j] << "@" << j << ")"); } if (stateProcess_ != NULL) boost::static_pointer_cast<GsrProcess>(stateProcess_)->flushCache(); }
void HullWhite::generateArguments() { phi_ = FittingParameter(termStructure(), a(), sigma()); }
const Real Gaussian1dModel::zerobondOption( const Option::Type &type, const Date &expiry, const Date &valueDate, const Date &maturity, const Rate strike, const Date &referenceDate, const Real y, const Handle<YieldTermStructure> &yts, const Real yStdDevs, const Size yGridPoints, const bool extrapolatePayoff, const bool flatPayoffExtrapolation) const { calculate(); Time fixingTime = termStructure()->timeFromReference(expiry); Time referenceTime = referenceDate == Null<Date>() ? 0.0 : termStructure()->timeFromReference(referenceDate); Array yg = yGrid(yStdDevs, yGridPoints, fixingTime, referenceTime, y); Array z = yGrid(yStdDevs, yGridPoints); Array p(yg.size()); for (Size i = 0; i < yg.size(); i++) { Real expValDsc = zerobond(valueDate, expiry, yg[i], yts); Real discount = zerobond(maturity, expiry, yg[i], yts) / expValDsc; p[i] = std::max((type == Option::Call ? 1.0 : -1.0) * (discount - strike), 0.0) / numeraire(fixingTime, yg[i], yts) * expValDsc; } CubicInterpolation payoff( z.begin(), z.end(), p.begin(), CubicInterpolation::Spline, true, CubicInterpolation::Lagrange, 0.0, CubicInterpolation::Lagrange, 0.0); Real price = 0.0; for (Size i = 0; i < z.size() - 1; i++) { price += gaussianShiftedPolynomialIntegral( 0.0, payoff.cCoefficients()[i], payoff.bCoefficients()[i], payoff.aCoefficients()[i], p[i], z[i], z[i], z[i + 1]); } if (extrapolatePayoff) { if (flatPayoffExtrapolation) { price += gaussianShiftedPolynomialIntegral( 0.0, 0.0, 0.0, 0.0, p[z.size() - 2], z[z.size() - 2], z[z.size() - 1], 100.0); price += gaussianShiftedPolynomialIntegral(0.0, 0.0, 0.0, 0.0, p[0], z[0], -100.0, z[0]); } else { if (type == Option::Call) price += gaussianShiftedPolynomialIntegral( 0.0, payoff.cCoefficients()[z.size() - 2], payoff.bCoefficients()[z.size() - 2], payoff.aCoefficients()[z.size() - 2], p[z.size() - 2], z[z.size() - 2], z[z.size() - 1], 100.0); if (type == Option::Put) price += gaussianShiftedPolynomialIntegral( 0.0, payoff.cCoefficients()[0], payoff.bCoefficients()[0], payoff.aCoefficients()[0], p[0], z[0], -100.0, z[0]); } } return numeraire(referenceTime, y, yts) * price; }
DiscountFactor discount(Time t) const { return termStructure()->discount(t); }
inline void ExtendedCoxIngersollRoss::generateArguments() { phi_ = FittingParameter(termStructure(), theta(), k(), sigma(), x0()); }
void Generalized_HullWhite::generateArguments() { phi_ = FittingParameter(termStructure(), a0_, sigma_, volperiods_); }