54 {
55
56
57 QuantLib::ext::shared_ptr<YieldTermStructure> dts =
59
60
61 Date expiryDate =
arguments_.exercise->lastDate();
62
63 Date today = Settings::instance().evaluationDate();
64 if (expiryDate <= today) {
65
66 Real payoffAmount = 0.0;
67 Real priceAtExercise = 0.0;
68 bool deterministicPayoff = true;
70
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);
75
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) {
81
82 priceAtExercise =
bsp_->x0();
83 payoffAmount = (*
arguments_.payoff)(priceAtExercise);
84 deterministicPayoff = false;
85 }
86
87 if(deterministicPayoff) {
94 }
95
96
97 DiscountFactor df_tp = dts->discount(
arguments_.paymentDate);
98 Time delta_tp = dts->timeFromReference(
arguments_.paymentDate);
99
100
101 results_.value = df_tp * payoffAmount;
104 if (delta_tp > 0.0 && !close(delta_tp, 0.0)) {
106 }
108
109
111 auto payoff = QuantLib::ext::dynamic_pointer_cast<StrikedTypePayoff>(
arguments_.payoff);
112 if (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;
118
119 } else {
120
121
122
123
124
126 VanillaForwardOption::arguments* underlyingArgs =
127 dynamic_cast<VanillaForwardOption::arguments*
>(
underlyingEngine_.getArguments());
128 QL_REQUIRE(underlyingArgs, "Underlying engine expected to have vanilla option arguments.");
129 underlyingArgs->exercise =
arguments_.exercise;
131
132
133
134 if (
auto cfi = QuantLib::ext::dynamic_pointer_cast<CommodityFuturesIndex>(
arguments_.underlying)) {
135 underlyingArgs->forwardDate = cfi->expiryDate();
136 } else {
137 underlyingArgs->forwardDate = expiryDate;
138 }
140
141
142 DiscountFactor df_te_tp = dts->discount(
arguments_.paymentDate) / dts->discount(expiryDate);
143 Time delta_te_tp = dts->timeFromReference(
arguments_.paymentDate) - dts->timeFromReference(expiryDate);
144
145
146 const CashSettledEuropeanOption::results* underlyingResults =
147 dynamic_cast<const CashSettledEuropeanOption::results*
>(
underlyingEngine_.getResults());
148 QL_REQUIRE(underlyingResults, "Underlying engine expected to have compatible results.");
149
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;
164
165
166 results_.additionalResults = underlyingResults->additionalResults;
167 results_.additionalResults[
"discountFactorTeTp"] = df_te_tp;
168 }
169
170}
const Instrument::results * results_
QuantLib::Handle< QuantLib::YieldTermStructure > discountCurve_
Curve for discounting cashflows.
QuantExt::AnalyticEuropeanForwardEngine underlyingEngine_
Underlying engine that does the work.
QuantLib::ext::shared_ptr< QuantLib::GeneralizedBlackScholesProcess > bsp_
Underlying process.
void calculate() const override
Swap::arguments * arguments_