22#include <ql/exercise.hpp>
23#include <ql/math/distributions/normaldistribution.hpp>
24#include <ql/pricingengines/blackformula.hpp>
29 const QuantLib::ext::shared_ptr<GeneralizedBlackScholesProcess>& process,
const std::vector<Time>& bucketTimesDeltaGamma,
30 const std::vector<Time>& bucketTimesVega,
const bool computeDeltaVega,
const bool computeGamma,
bool linearInZero)
31 : process_(process), bucketTimesDeltaGamma_(bucketTimesDeltaGamma), bucketTimesVega_(bucketTimesVega),
32 computeDeltaVega_(computeDeltaVega), computeGamma_(computeGamma), linearInZero_(linearInZero) {
35 "bucket times are empty, although sensitivities have to be calculated");
40 QL_REQUIRE(
arguments_.exercise->type() == Exercise::European,
"not an European option");
42 QuantLib::ext::shared_ptr<StrikedTypePayoff> payoff = QuantLib::ext::dynamic_pointer_cast<StrikedTypePayoff>(
arguments_.payoff);
43 QL_REQUIRE(payoff,
"non-striked payoff given");
46 DiscountFactor dividendDiscount =
process_->dividendYield()->discount(
arguments_.exercise->lastDate());
47 DiscountFactor riskFreeDiscount =
process_->riskFreeRate()->discount(
arguments_.exercise->lastDate());
48 Real spot =
process_->stateVariable()->value();
49 QL_REQUIRE(spot > 0.0,
"negative or null underlying given");
50 Real forwardPrice = spot * dividendDiscount / riskFreeDiscount;
52 Option::Type type = payoff->optionType();
53 Real w = type == Option::Call ? 1.0 : -1.0;
54 Real strike = payoff->strike();
57 Real npv = riskFreeDiscount * blackFormula(type, strike, forwardPrice, std::sqrt(
variance), 1.0, 0.0);
60 Date referenceDate =
process_->riskFreeRate()->referenceDate();
61 Date exerciseDate =
arguments_.exercise->lastDate();
64 DayCounter dc =
process_->blackVolatility()->dayCounter();
65 Time t = dc.yearFraction(referenceDate, exerciseDate);
67 CumulativeNormalDistribution cnd;
68 Real d1 = std::log(forwardPrice / strike) / stdDev + 0.5 * stdDev;
70 Real npvr = 0.0, npvq = 0.0, npvs = 0.0;
72 npvs = w * cnd(w * d1) * dividendDiscount;
73 results_.additionalResults[
"deltaSpot"] = npvs;
75 std::sqrt(t) * blackFormulaStdDevDerivative(strike, forwardPrice, stdDev, 1.0, 0.0) * riskFreeDiscount;
76 std::map<Date, Real> vegaRaw;
77 vegaRaw[exerciseDate] = singleVega;
79 results_.additionalResults[
"vega"] = resVega;
80 std::map<Date, Real> deltaRateRaw, deltaDividendRaw;
81 Real tmp = dividendDiscount * w * cnd(w * d1);
82 npvr = t * (-npv + spot * tmp);
83 deltaRateRaw[exerciseDate] = npvr;
84 npvq = -t * spot * tmp;
85 deltaDividendRaw[exerciseDate] = npvq;
86 std::vector<Real> resDeltaRate =
88 results_.additionalResults[
"deltaRate"] = resDeltaRate;
89 std::vector<Real> resDeltaDividend =
91 results_.additionalResults[
"deltaDividend"] = resDeltaDividend;
95 Real tmp = cnd.derivative(d1) / (forwardPrice * stdDev);
96 results_.additionalResults[
"gammaSpot"] = tmp * dividendDiscount * dividendDiscount / riskFreeDiscount;
97 std::map<Date, Real> gammaRateRaw;
98 std::map<std::pair<Date, Date>, Real> gammaDivRaw, gammaRateDivRaw;
99 gammaRateRaw[exerciseDate] =
100 t * (-npvr + t * spot * spot * dividendDiscount * dividendDiscount / riskFreeDiscount * tmp);
101 gammaDivRaw[std::make_pair(exerciseDate, exerciseDate)] =
102 -t * (npvq - t * spot * spot * dividendDiscount * dividendDiscount / riskFreeDiscount * tmp);
103 gammaRateDivRaw[std::make_pair(exerciseDate, exerciseDate)] =
104 t * (-npvq - t * spot * dividendDiscount * w * cnd(w * d1) -
105 t * spot * spot * dividendDiscount * dividendDiscount / riskFreeDiscount * tmp);
108 results_.additionalResults[
"gamma"] = resGamma;
109 std::map<Date, Real> gammaSpotRateRaw, gammaSpotDivRaw;
110 gammaSpotRateRaw[exerciseDate] = t * (-npvs + dividendDiscount * w * cnd(w * d1) +
111 spot * dividendDiscount * dividendDiscount / riskFreeDiscount * tmp);
112 gammaSpotDivRaw[exerciseDate] = -t * (dividendDiscount * w * cnd(w * d1) +
113 spot * dividendDiscount * dividendDiscount / riskFreeDiscount * tmp);
114 std::vector<Real> resGammaSpotRate =
117 results_.additionalResults[
"gammaSpotRate"] = resGammaSpotRate;
118 std::vector<Real> resGammaSpotDiv =
121 results_.additionalResults[
"gammaSpotDiv"] = resGammaSpotDiv;
Analytic European engine providing sensitivities.
const Instrument::results * results_
const bool computeDeltaVega_
AnalyticEuropeanEngineDeltaGamma(const QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > &process, const std::vector< Time > &bucketTimeDeltaGamma=std::vector< Time >(), const std::vector< Time > &bucketTimesVega=std::vector< Time >(), const bool computeDeltaVega=false, const bool computeGamma=false, const bool linearInZero=true)
void calculate() const override
QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > process_
const std::vector< Time > bucketTimesDeltaGamma_
const std::vector< Time > bucketTimesVega_
Swap engine providing analytical deltas and gammas for vanilla swaps.
Matrix rebucketGammas(const std::vector< Time > &gammaTimes, const std::map< Date, Real > &gammaDscRaw, std::map< std::pair< Date, Date >, Real > &gammaForward, std::map< std::pair< Date, Date >, Real > &gammaDscFwd, const bool forceFullMatrix, const Date &referenceDate, const DayCounter &dc, const bool linearInZero)
std::vector< Real > rebucketDeltas(const std::vector< Time > &deltaTimes, const std::map< Date, Real > &deltaRaw, const Date &referenceDate, const DayCounter &dc, const bool linearInZero)
RandomVariable variance(const RandomVariable &r)
Swap::arguments * arguments_