26 class AnalyticDiscreteGeometricAveragePriceAsianHestonEngine::Integrand {
30 const std::vector<Time> t_n_, tauK_;
31 const AnalyticDiscreteGeometricAveragePriceAsianHestonEngine*
const parent_;
33 std::complex<Real> i_;
39 std::vector<Time> t_n,
40 std::vector<Time> tauK,
42 const AnalyticDiscreteGeometricAveragePriceAsianHestonEngine*
const parent,
44 :
t_(
t),
T_(
T), K_(K), logK_(
std::log(K)), kStar_(kStar), t_n_(
std::move(t_n)),
45 tauK_(
std::move(tauK)), parent_(parent), xiRightLimit_(xiRightLimit),
46 i_(
std::complex<
Real>(0.0, 1.0)) {}
49 Real xiDash = (0.5+1e-8+0.5*xi) * xiRightLimit_;
51 std::complex<Real> inner1 = parent_->Phi(1.0 + xiDash*i_, 0, t_, T_, kStar_, t_n_, tauK_);
52 std::complex<Real> inner2 = -K_*parent_->Phi(xiDash*i_, 0, t_, T_, kStar_, t_n_, tauK_);
54 return 0.5*xiRightLimit_*std::real((inner1 + inner2) * std::exp(-xiDash*logK_*i_) / (xiDash*i_));
61 ext::shared_ptr<HestonProcess> process,
Real xiRightLimit)
62 : process_(
std::move(process)), xiRightLimit_(xiRightLimit), integrator_(128) {
78 const std::complex<Real>& z1,
79 const std::complex<Real>& z2,
90 const std::complex<Real>& z1,
91 const std::complex<Real>& z2,
94 return 0.5*temp*sinh(0.5*tau*temp) + 0.5*(
kappa_ - z2*
sigma_*
sigma_)*cosh(0.5*tau*temp);
98 const std::complex<Real>&
s,
const std::complex<Real>& w,
Size k,
Size n)
const {
102 std::complex<Real> term2 = (1-
rho_*
rho_)*pow(((n_-
k_+1)*
s + n_*w), 2)/(2*n_*n_);
104 return term1 + term2;
108 const std::complex<Real>&
s,
const std::complex<Real>& w,
Size k,
Size kStar,
Size n)
const {
119 const std::complex<Real>&
s,
120 const std::complex<Real>& w,
122 const std::vector<Time>& t_n)
const {
123 auto kStar_ =
Real(kStar);
124 auto n_ =
Real(t_n.size());
127 Time summation = 0.0;
128 Real summation2 = 0.0;
129 for (
Size i=kStar+1; i<=t_n.size(); i++) {
130 summation += t_n[i-1];
135 std::complex<Real> term2 = temp*(
s*summation/n_ + w*
T) + w*
Tr_T_ + summation2*
s/n_;
137 return term1 + term2;
141 const std::complex<Real>&
s,
142 const std::complex<Real>& w,
144 const std::vector<Time>& tauK)
const {
145 std::complex<Real> omega_k =
omega(
s, w, k, kStar,
n);
149 Time dTauk = tauK[k+1] - tauK[k];
150 std::complex<Real> z_kp1 =
z(
s, w, k+1,
n);
153 std::complex<Real> omega_kp1 = 0.0;
158 std::complex<Real> value = position->second;
164 std::complex<Real> ratio =
F_tilde(z_kp1,omega_kp1,dTauk)/
F(z_kp1,omega_kp1,dTauk);
175 const std::complex<Real>
s,
176 const std::complex<Real> w,
178 const std::vector<Time>& t_n,
179 const std::vector<Time>& tauK)
const {
185 std::complex<Real> aTerm =
a(
s, w,
t,
T, kStar, t_n);
186 std::complex<Real> omegaTerm =
v0_*
omega_tilde(
s, w, kStar, kStar,
n, tauK);
189 std::complex<Real> summation = 0.0;
190 for (
Size i=kStar+1; i<=
n+1; i++) {
191 Real dTau = tauK[i] - tauK[i-1];
192 std::complex<Real> z_k =
z(
s, w, i,
n);
193 std::complex<Real> omega_tilde_k =
omega_tilde(
s, w, i, kStar,
n, tauK);
195 summation += std::log(
F(z_k, omega_tilde_k, dTau));
199 return std::exp(aTerm + omegaTerm + term3 - term4);
209 "not an European Option");
215 "positive running product required: "
224 ext::shared_ptr<PlainVanillaPayoff>
payoff =
225 ext::dynamic_pointer_cast<PlainVanillaPayoff>(
arguments_.payoff);
232 QL_REQUIRE(expiryTime >= 0.0,
"Expiry Date cannot be in the past");
236 Time startTime = 0.0;
237 std::vector<Time> fixingTimes, tauK;
239 fixingTimes.push_back(this->
process_->time(fixingDate));
241 std::sort(fixingTimes.begin(), fixingTimes.end());
246 tauK.insert(tauK.begin(), startTime);
247 tauK.push_back(expiryTime);
252 for (
Size i=0; i<pastFixings; i++) {
253 fixingTimes.insert(fixingTimes.begin(), -1.0);
254 tauK.insert(tauK.begin(), -1.0);
257 Size kStar = pastFixings;
265 for (
Real fixingTime : fixingTimes) {
266 if (fixingTime < 0) {
275 Real prefactor = std::exp(runningLog / fixingTimes.size());
276 Real adjustedStrike = strike / prefactor;
279 Real term1 = 0.5 * (std::real(
Phi(1,0, startTime, expiryTime, kStar, fixingTimes, tauK)) - adjustedStrike);
281 Integrand integrand(startTime, expiryTime, kStar, fixingTimes, tauK, adjustedStrike,
this,
xiRightLimit_);
286 switch (
payoff->optionType()){
288 value = expiryDcf * prefactor * (term1 + term2);
291 value = expiryDcf * prefactor * (-term1 + term2);
294 QL_FAIL(
"unknown option type");
Analytic engine for discrete geometric average price Asian in the Heston model.
ext::shared_ptr< HestonProcess > process_
std::complex< Real > F_tilde(const std::complex< Real > &z1, const std::complex< Real > &z2, Time tau) const
std::complex< Real > omega(const std::complex< Real > &s, const std::complex< Real > &w, Size k, Size kStar, Size n) const
std::map< Size, std::complex< Real > > omegaTildeLookupTable_
std::complex< Real > z(const std::complex< Real > &s, const std::complex< Real > &w, Size k, Size n) const
std::vector< Real > tkr_tk_
AnalyticDiscreteGeometricAveragePriceAsianHestonEngine(ext::shared_ptr< HestonProcess > process, Real xiRightLimit=100.0)
void calculate() const override
std::complex< Real > Phi(std::complex< Real > s, std::complex< Real > w, Time t, Time T, Size kStar, const std::vector< Time > &t_n, const std::vector< Time > &tauK) const
GaussLegendreIntegration integrator_
std::complex< Real > a(const std::complex< Real > &s, const std::complex< Real > &w, Time t, Time T, Size kStar, const std::vector< Time > &t_n) const
std::complex< Real > F(const std::complex< Real > &z1, const std::complex< Real > &z2, Time tau) const
Handle< YieldTermStructure > dividendYield_
std::complex< Real > omega_tilde(const std::complex< Real > &s, const std::complex< Real > &w, Size k, Size kStar, Size n, const std::vector< Time > &tauK) const
Handle< YieldTermStructure > riskFreeRate_
Average::Type averageType
std::vector< Date > fixingDates
DiscreteAveragingAsianOption::results results_
DiscreteAveragingAsianOption::arguments arguments_
std::map< std::string, ext::any > additionalResults
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
#define QL_FAIL(message)
throw an error (possibly with file and line information)
Real Time
continuous quantity with 1-year units
std::size_t Size
size of a container
ext::shared_ptr< QuantLib::Payoff > payoff