44
45 const Real S = process->x0();
46 QL_REQUIRE(S > 0.0, "negative or null underlying given");
47
48 std::vector<std::pair<Time, Real>> intermediateSteps;
49 for (Size i = 0; i < dividendSchedule.size(); ++i) {
50 const Time t = process->time(dividendSchedule[i]->date());
51 if (t <= maturity && t >= 0.0)
52 intermediateSteps.push_back(
53 std::make_pair(process->time(dividendSchedule[i]->date()), dividendSchedule[i]->amount()));
54 }
55
56 const Size intermediateTimeSteps = std::max<Size>(2, Size(24.0 * maturity));
57 for (Size i = 0; i < intermediateTimeSteps; ++i)
58 intermediateSteps.push_back(std::make_pair((i + 1) * (maturity / intermediateTimeSteps), 0.0));
59
60 std::sort(intermediateSteps.begin(), intermediateSteps.end());
61
62 const Handle<YieldTermStructure> rTS = process->riskFreeRate();
63
64 const Handle<YieldTermStructure> qTS =
65 (fdmQuantoHelper)
66 ? Handle<YieldTermStructure>(ext::make_shared<QuantoTermStructure>(
67 process->dividendYield(), process->riskFreeRate(), Handle<YieldTermStructure>(fdmQuantoHelper->fTS_),
68 process->blackVolatility(), strike, Handle<BlackVolTermStructure>(fdmQuantoHelper->fxVolTS_),
69 fdmQuantoHelper->exchRateATMlevel_, fdmQuantoHelper->equityFxCorrelation_))
70 : process->dividendYield();
71
72 Time lastDivTime = 0.0;
73 Real fwd = S + spotAdjustment;
74 Real mi = fwd, ma = fwd;
75
76 for (Size i = 0; i < intermediateSteps.size(); ++i) {
77 const Time divTime = intermediateSteps[i].first;
78 const Real divAmount = intermediateSteps[i].second;
79
80 fwd = fwd / rTS->discount(divTime) * rTS->discount(lastDivTime) * qTS->discount(divTime) /
81 qTS->discount(lastDivTime);
82
83 mi = std::min(mi, fwd);
84 ma = std::max(ma, fwd);
85
86 fwd -= divAmount;
87
88 mi = std::min(mi, fwd);
89 ma = std::max(ma, fwd);
90
91 lastDivTime = divTime;
92 }
93
94
95 const Real normInvEps = InverseCumulativeNormal()(1 - eps);
96 const Real sigmaSqrtT =
97 std::max(1.0E-2, process->blackVolatility()->blackVol(maturity, strike) * std::sqrt(maturity));
98
99 Real xMin = std::log(mi) - sigmaSqrtT * normInvEps * scaleFactor;
100 Real xMax = std::log(ma) + sigmaSqrtT * normInvEps * scaleFactor;
101
102 if (xMinConstraint != Null<Real>()) {
103 xMin = xMinConstraint;
104 }
105 if (xMaxConstraint != Null<Real>()) {
106 xMax = xMaxConstraint;
107 }
108
109
110 std::vector<QuantLib::ext::tuple<Real, Real, bool>> cPointsEff;
111 for (auto const& c : cPoints) {
112 if (QuantLib::ext::get<0>(c) == Null<Real>() || QuantLib::ext::get<0>(c) < xMin || QuantLib::ext::get<0>(c) > xMax)
113 continue;
114 cPointsEff.push_back(c);
115 }
116
117 ext::shared_ptr<Fdm1dMesher>
helper;
118 if (cPointsEff.empty()) {
119 helper = ext::shared_ptr<Fdm1dMesher>(
new Uniform1dMesher(xMin, xMax, size));
120 } else if (cPointsEff.size() == 1) {
121 helper = ext::shared_ptr<Fdm1dMesher>(
new Concentrating1dMesher(
122 xMin, xMax, size, std::make_pair(QuantLib::ext::get<0>(cPointsEff[0]), QuantLib::ext::get<1>(cPointsEff[0])),
123 QuantLib::ext::get<2>(cPointsEff[0])));
124 } else {
125 helper = ext::shared_ptr<Fdm1dMesher>(
new Concentrating1dMesher(xMin, xMax, size, cPointsEff));
126 }
127
128 locations_ =
helper->locations();
129 for (Size i = 0; i < locations_.size(); ++i) {
130 dplus_[i] =
helper->dplus(i);
131 dminus_[i] =
helper->dminus(i);
132 }
133}
QuantLib::BootstrapHelper< QuantLib::OptionletVolatilityStructure > helper