19#include <ql/event.hpp>
20#include <ql/exercise.hpp>
26using QuantLib::DiscountFactor;
27using QuantLib::GeneralizedBlackScholesProcess;
28using QuantLib::Handle;
30using QuantLib::PricingEngine;
32using QuantLib::Settings;
33using QuantLib::StrikedTypePayoff;
35using QuantLib::VanillaOption;
36using QuantLib::YieldTermStructure;
37using QuantLib::detail::simple_event;
42 const QuantLib::ext::shared_ptr<GeneralizedBlackScholesProcess>& bsp)
43 : underlyingEngine_(bsp), bsp_(bsp) {
47AnalyticCashSettledEuropeanEngine::AnalyticCashSettledEuropeanEngine(
48 const QuantLib::ext::shared_ptr<GeneralizedBlackScholesProcess>& bsp,
const Handle<YieldTermStructure>& discountCurve)
49 : underlyingEngine_(bsp, discountCurve), bsp_(bsp), discountCurve_(discountCurve) {
51 registerWith(discountCurve_);
54void AnalyticCashSettledEuropeanEngine::calculate()
const {
57 QuantLib::ext::shared_ptr<YieldTermStructure> dts =
58 discountCurve_.empty() ? bsp_->riskFreeRate().currentLink() : discountCurve_.currentLink();
61 Date expiryDate =
arguments_.exercise->lastDate();
63 Date today = Settings::instance().evaluationDate();
64 if (expiryDate <= today) {
66 Real payoffAmount = 0.0;
67 Real priceAtExercise = 0.0;
68 bool deterministicPayoff =
true;
71 QL_REQUIRE(
arguments_.underlying,
"Expect a valid underlying index when exercise is automatic.");
72 priceAtExercise =
arguments_.underlying->fixing(expiryDate);
73 payoffAmount = (*
arguments_.payoff)(priceAtExercise);
76 QL_REQUIRE(
arguments_.priceAtExercise != Null<Real>(),
"Expect a valid price at exercise when option "
77 <<
"has been manually exercised.");
79 payoffAmount = (*
arguments_.payoff)(priceAtExercise);
80 }
else if (expiryDate == today) {
82 priceAtExercise = bsp_->x0();
83 payoffAmount = (*
arguments_.payoff)(priceAtExercise);
84 deterministicPayoff =
false;
87 if(deterministicPayoff) {
97 DiscountFactor df_tp = dts->discount(
arguments_.paymentDate);
98 Time delta_tp = dts->timeFromReference(
arguments_.paymentDate);
101 results_.value = df_tp * payoffAmount;
104 if (delta_tp > 0.0 && !close(delta_tp, 0.0)) {
110 results_.additionalResults[
"spot"] = bsp_->x0();
111 auto payoff = QuantLib::ext::dynamic_pointer_cast<StrikedTypePayoff>(
arguments_.payoff);
113 results_.additionalResults[
"strike"] = payoff->strike();
114 results_.additionalResults[
"priceAtExercise"] = priceAtExercise;
115 results_.additionalResults[
"payoffAmount"] = payoffAmount;
116 results_.additionalResults[
"discountFactor"] = df_tp;
117 results_.additionalResults[
"timeToExpiry"] = delta_tp;
125 underlyingEngine_.reset();
128 QL_REQUIRE(underlyingArgs,
"Underlying engine expected to have vanilla option arguments.");
129 underlyingArgs->exercise =
arguments_.exercise;
134 if (
auto cfi = QuantLib::ext::dynamic_pointer_cast<CommodityFuturesIndex>(
arguments_.underlying)) {
139 underlyingEngine_.calculate();
142 DiscountFactor df_te_tp = dts->discount(
arguments_.paymentDate) / dts->discount(expiryDate);
143 Time delta_te_tp = dts->timeFromReference(
arguments_.paymentDate) - dts->timeFromReference(expiryDate);
146 const CashSettledEuropeanOption::results* underlyingResults =
147 dynamic_cast<const CashSettledEuropeanOption::results*
>(underlyingEngine_.getResults());
148 QL_REQUIRE(underlyingResults,
"Underlying engine expected to have compatible results.");
150 results_.value = df_te_tp * underlyingResults->value;
151 results_.delta = df_te_tp * underlyingResults->delta;
152 results_.deltaForward = df_te_tp * underlyingResults->deltaForward;
153 results_.elasticity = underlyingResults->elasticity;
154 results_.gamma = df_te_tp * underlyingResults->gamma;
155 results_.rho = df_te_tp * (underlyingResults->rho - delta_te_tp * underlyingResults->value);
156 results_.dividendRho = df_te_tp * underlyingResults->dividendRho;
157 results_.vega = df_te_tp * underlyingResults->vega;
158 if (underlyingResults->theta != Null<Real>())
159 results_.theta = df_te_tp * underlyingResults->theta;
160 if (underlyingResults->thetaPerDay != Null<Real>())
161 results_.thetaPerDay = df_te_tp * underlyingResults->thetaPerDay;
162 results_.strikeSensitivity = df_te_tp * underlyingResults->strikeSensitivity;
163 results_.itmCashProbability = underlyingResults->itmCashProbability;
166 results_.additionalResults = underlyingResults->additionalResults;
167 results_.additionalResults[
"discountFactorTeTp"] = df_te_tp;
pricing engine for cash settled European vanilla options.
const Instrument::results * results_
AnalyticCashSettledEuropeanEngine(const QuantLib::ext::shared_ptr< QuantLib::GeneralizedBlackScholesProcess > &bsp)
Arguments for Vanilla Forward Option calculation
QuantLib::Date forwardDate
commodity index class for holding commodity spot and futures price histories and forwarding.
Swap::arguments * arguments_