Spread CallableBond::OAS(Real cleanPrice, const Handle<YieldTermStructure>& engineTS, const DayCounter& dayCounter, Compounding compounding, Frequency frequency, Date settlement, Real accuracy, Size maxIterations, Spread guess) { if (settlement == Date()) settlement = settlementDate(); Real dirtyPrice = cleanPrice + accruedAmount(settlement); boost::function<Real(Real)> f = NPVSpreadHelper(*this); OASHelper obj(f, dirtyPrice); Brent solver; solver.setMaxEvaluations(maxIterations); Real step = 0.001; Spread oas=solver.solve(obj, accuracy, guess, step); return continuousToConv(oas, *this, engineTS, dayCounter, compounding, frequency); }
Volatility CalibrationHelper::impliedVolatility(Real targetValue, Real accuracy, Size maxEvaluations, Volatility minVol, Volatility maxVol) const { ImpliedVolatilityHelper f(*this,targetValue); Brent solver; solver.setMaxEvaluations(maxEvaluations); return solver.solve(f,accuracy,volatility_->value(),minVol,maxVol); }
std::vector<Volatility> OptionletStripper2::spreadsVolImplied() const { Brent solver; std::vector<Volatility> result(nOptionExpiries_); Volatility guess = 0.0001, minSpread = -0.1, maxSpread = 0.1; for (Size j=0; j<nOptionExpiries_; ++j) { ObjectiveFunction f(stripper1_, caps_[j], atmCapFloorPrices_[j]); solver.setMaxEvaluations(maxEvaluations_); Volatility root = solver.solve(f, accuracy_, guess, minSpread, maxSpread); result[j] = root; } return result; }
Volatility CallableBond::impliedVolatility( Real targetValue, const Handle<YieldTermStructure>& discountCurve, Real accuracy, Size maxEvaluations, Volatility minVol, Volatility maxVol) const { calculate(); QL_REQUIRE(!isExpired(), "instrument expired"); Volatility guess = 0.5*(minVol + maxVol); blackDiscountCurve_.linkTo(*discountCurve, false); ImpliedVolHelper f(*this,targetValue); Brent solver; solver.setMaxEvaluations(maxEvaluations); return solver.solve(f, accuracy, guess, minVol, maxVol); }
Volatility HestonBlackVolSurface::blackVolImpl(Time t, Real strike) const { const boost::shared_ptr<HestonProcess> process = hestonModel_->process(); const DiscountFactor df = process->riskFreeRate()->discount(t, true); const DiscountFactor div = process->dividendYield()->discount(t, true); const Real spotPrice = process->s0()->value(); const Real fwd = spotPrice * process->dividendYield()->discount(t, true) / process->riskFreeRate()->discount(t, true); const PlainVanillaPayoff payoff( fwd > strike ? Option::Put : Option::Call, strike); const Real kappa = hestonModel_->kappa(); const Real theta = hestonModel_->theta(); const Real rho = hestonModel_->rho(); const Real sigma = hestonModel_->sigma(); const Real v0 = hestonModel_->v0(); const AnalyticHestonEngine::ComplexLogFormula cpxLogFormula = AnalyticHestonEngine::Gatheral; const AnalyticHestonEngine* const hestonEnginePtr = 0; Real npv; Size evaluations; AnalyticHestonEngine::doCalculation( df, div, spotPrice, strike, t, kappa, theta, sigma, v0, rho, payoff, integration_, cpxLogFormula, hestonEnginePtr, npv, evaluations); if (npv <= 0.0) return std::sqrt(theta); Brent solver; solver.setMaxEvaluations(10000); const Volatility guess = std::sqrt(theta); const Real accuracy = std::numeric_limits<Real>::epsilon(); const boost::function<Real(Real)> f = boost::bind( &blackValue, payoff.optionType(), strike, fwd, t, _1, df, npv); return solver.solve(f, accuracy, guess, 0.01); }
Real InverseNonCentralChiSquareDistribution::operator()(Real x) const { // first find the right side of the interval Real upper = guess_; Size evaluations = maxEvaluations_; while (nonCentralDist_(upper) < x && evaluations > 0) { upper*=2.0; --evaluations; } // use a brent solver for the rest Brent solver; solver.setMaxEvaluations(evaluations); return solver.solve(compose(std::bind2nd(std::minus<Real>(),x), nonCentralDist_), accuracy_, 0.75*upper, (evaluations == maxEvaluations_)? 0.0: 0.5*upper, upper); }
Volatility CdsOption::impliedVolatility( Real targetValue, const Handle<YieldTermStructure>& termStructure, const Handle<DefaultProbabilityTermStructure>& probability, Real recoveryRate, Real accuracy, Size maxEvaluations, Volatility minVol, Volatility maxVol) const { calculate(); QL_REQUIRE(!isExpired(), "instrument expired"); Volatility guess = 0.10; ImpliedVolHelper f(*this, probability, recoveryRate, termStructure, targetValue); Brent solver; solver.setMaxEvaluations(maxEvaluations); return solver.solve(f, accuracy, guess, minVol, maxVol); }
Volatility ImpliedVolatilityHelper::calculate( const Instrument& instrument, const PricingEngine& engine, SimpleQuote& volQuote, Real targetValue, Real accuracy, Natural maxEvaluations, Volatility minVol, Volatility maxVol) { instrument.setupArguments(engine.getArguments()); engine.getArguments()->validate(); PriceError f(engine, volQuote, targetValue); Brent solver; solver.setMaxEvaluations(maxEvaluations); Volatility guess = (minVol+maxVol)/2.0; Volatility result = solver.solve(f, accuracy, guess, minVol, maxVol); return result; }
CapPseudoDerivative::CapPseudoDerivative(boost::shared_ptr<MarketModel> inputModel, Real strike, Size startIndex, Size endIndex, Real firstDF) : firstDF_(firstDF) { QL_REQUIRE(startIndex < endIndex, "for a cap pseudo derivative the start of the cap must be before the end"); QL_REQUIRE( endIndex <= inputModel->numberOfRates(), "for a cap pseudo derivative the end of the cap must before the end of the rates"); Size numberCaplets = endIndex-startIndex; Size numberRates = inputModel->numberOfRates(); Size factors = inputModel->numberOfFactors(); LMMCurveState curve(inputModel->evolution().rateTimes()); curve.setOnForwardRates(inputModel->initialRates()); const Matrix& totalCovariance(inputModel->totalCovariance(inputModel->numberOfSteps()-1)); std::vector<Real> displacedImpliedVols(numberCaplets); std::vector<Real> annuities(numberCaplets); std::vector<Real> initialRates(numberCaplets); std::vector<Real> expiries(numberCaplets); Real capPrice =0.0; Real guess=0.0; Real minVol = 1e10; Real maxVol =0.0; for (Size j = startIndex; j < endIndex; ++j) { Size capletIndex = j - startIndex; Time resetTime = inputModel->evolution().rateTimes()[j]; expiries[capletIndex] = resetTime; Real sd = std::sqrt(totalCovariance[j][j]); displacedImpliedVols[capletIndex] = std::sqrt(totalCovariance[j][j]/resetTime); Real forward = inputModel->initialRates()[j]; initialRates[capletIndex] = forward; Real annuity = curve.discountRatio(j+1,0)* inputModel->evolution().rateTaus()[j]*firstDF_; annuities[capletIndex] = annuity; Real displacement = inputModel->displacements()[j]; guess+= displacedImpliedVols[capletIndex]*(forward+displacement)/forward; minVol =std::min(minVol, displacedImpliedVols[capletIndex]); maxVol =std::max(maxVol, displacedImpliedVols[capletIndex]*(forward+displacement)/forward); Real capletPrice = blackFormula(Option::Call, strike, forward, sd, annuity, displacement ); capPrice += capletPrice; } guess/=numberCaplets; for (Size step =0; step < inputModel->evolution().numberOfSteps(); ++step) { Matrix thisDerivative(numberRates,factors,0.0); for (Size rate =std::max(inputModel->evolution().firstAliveRate()[step],startIndex); rate < endIndex; ++rate) { for (Size f=0; f < factors; ++f) { Real expiry = inputModel->evolution().rateTimes()[rate]; Real volDerivative = inputModel->pseudoRoot(step)[rate][f] /(displacedImpliedVols[rate-startIndex]*expiry); Real capletVega = blackFormulaVolDerivative(strike,inputModel->initialRates()[rate], displacedImpliedVols[rate-startIndex]*std::sqrt(expiry), expiry, annuities[rate-startIndex], inputModel->displacements()[rate]); // note that the cap derivative is equal to one of the caplet ones so we lose a loop thisDerivative[rate][f] = volDerivative*capletVega; } } priceDerivatives_.push_back(thisDerivative); } QuickCap capPricer(strike, annuities, initialRates, expiries,capPrice); Size maxEvaluations = 1000; Real accuracy = 1E-6; Brent solver; solver.setMaxEvaluations(maxEvaluations); impliedVolatility_ = solver.solve(capPricer,accuracy,guess,minVol*0.99,maxVol*1.01); vega_ = capPricer.vega(impliedVolatility_); for (Size step =0; step < inputModel->evolution().numberOfSteps(); ++step) { Matrix thisDerivative(numberRates,factors,0.0); for (Size rate =std::max(inputModel->evolution().firstAliveRate()[step],startIndex); rate < endIndex; ++rate) { for (Size f=0; f < factors; ++f) { thisDerivative[rate][f] = priceDerivatives_[step][rate][f]/vega_; } } volatilityDerivatives_.push_back(thisDerivative); } }
void AnalyticCompoundOptionEngine::calculate() const { QL_REQUIRE(strikeDaughter()>0.0, "Daughter strike must be positive"); QL_REQUIRE(strikeMother()>0.0, "Mother strike must be positive"); QL_REQUIRE(spot() >= 0.0, "negative or null underlying given"); /* Solver Setup ***************************************************/ Date helpDate(process_->riskFreeRate()->referenceDate()); Date helpMaturity=helpDate+(maturityDaughter()-maturityMother())*Days; Real vol =process_->blackVolatility()->blackVol(helpMaturity, strikeDaughter()); Time helpTimeToMat=process_->time(helpMaturity); vol=vol*std::sqrt(helpTimeToMat); DiscountFactor dividendDiscount = process_->dividendYield()->discount(helpMaturity); DiscountFactor riskFreeDiscount = process_->riskFreeRate()->discount(helpMaturity); boost::shared_ptr<ImpliedSpotHelper> f( new ImpliedSpotHelper(dividendDiscount, riskFreeDiscount, vol, payoffDaughter(), strikeMother())); Brent solver; solver.setMaxEvaluations(1000); Real accuracy = 1.0e-6; Real X=0.0; Real sSolved=0.0; sSolved=solver.solve(*f, accuracy, strikeDaughter(), 1.0e-6, strikeDaughter()*1000.0); X=transformX(sSolved); // transform stock to return as in Wystup's book /* Solver Setup Finished*****************************************/ Real phi=typeDaughter(); // -1 or 1 Real w=typeMother(); // -1 or 1 Real rho=std::sqrt(residualTimeMother()/residualTimeDaughter()); BivariateCumulativeNormalDistributionDr78 N2(w*rho) ; DiscountFactor ddD=dividendDiscountDaughter(); DiscountFactor rdD=riskFreeDiscountDaughter(); //DiscountFactor ddM=dividendDiscountMother(); DiscountFactor rdM=riskFreeDiscountMother(); Real XmSM=X-stdDeviationMother(); Real S=spot(); Real dP=dPlus(); Real dPT12=dPlusTau12(sSolved); Real vD=volatilityDaughter(); Real dM=dMinus(); Real strD=strikeDaughter(); Real strM=strikeMother(); Real rTM=residualTimeMother(); Real rTD=residualTimeDaughter(); Real rD=riskFreeRateDaughter(); Real dD=dividendRateDaughter(); Real tempRes=0.0; Real tempDelta=0.0; Real tempGamma=0.0; Real tempVega=0.0; Real tempTheta=0.0; Real N2XmSM=N2(-phi*w*XmSM,phi*dP); Real N2X=N2(-phi*w*X,phi*dM); Real NeX=N_(-phi*w*e(X)); Real NX=N_(-phi*w*X); Real NT12=N_(phi*dPT12); Real ndP=n_(dP); Real nXm=n_(XmSM); Real invMTime=1/std::sqrt(rTM); Real invDTime=1/std::sqrt(rTD); tempRes=phi*w*S*ddD*N2XmSM-phi*w*strD*rdD*N2X-w*strM*rdM*NX; tempDelta=phi*w*ddD*N2XmSM; tempGamma=(ddD/(vD*S))*(invMTime*nXm*NT12+w*invDTime*ndP*NeX); tempVega=ddD*S*((1/invMTime)*nXm*NT12+w*(1/invDTime)*ndP*NeX); tempTheta+=phi*w*dD*S*ddD*N2XmSM-phi*w*rD*strD*rdD*N2X-w*rD*strM*rdM*NX; tempTheta-=0.5*vD*S*ddD*(invMTime*nXm*NT12+w*invDTime*ndP*NeX); results_.value=tempRes; results_.delta=tempDelta; results_.gamma=tempGamma; results_.vega=tempVega; results_.theta=tempTheta; }