QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
americanpayoffatexpiry.cpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2004 Ferdinando Ametrano
5
6 This file is part of QuantLib, a free-software/open-source library
7 for financial quantitative analysts and developers - http://quantlib.org/
8
9 QuantLib is free software: you can redistribute it and/or modify it
10 under the terms of the QuantLib license. You should have received a
11 copy of the license along with this program; if not, please email
12 <quantlib-dev@lists.sf.net>. The license is also available online at
13 <http://quantlib.org/license.shtml>.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
20#include <ql/pricingengines/americanpayoffatexpiry.hpp>
21#include <ql/math/distributions/normaldistribution.hpp>
22
23namespace QuantLib {
24
26 Real spot, DiscountFactor discount, DiscountFactor dividendDiscount,
27 Real variance, const ext::shared_ptr<StrikedTypePayoff>& payoff,
28 bool knock_in)
29 : spot_(spot), discount_(discount), dividendDiscount_(dividendDiscount),
30 variance_(variance), knock_in_(knock_in) {
31
32 QL_REQUIRE(spot_>0.0,
33 "positive spot value required");
34
35 QL_REQUIRE(discount_>0.0,
36 "positive discount required");
37
38 QL_REQUIRE(dividendDiscount_>0.0,
39 "positive dividend discount required");
40
41 QL_REQUIRE(variance_>=0.0,
42 "negative variance not allowed");
43
44 stdDev_ = std::sqrt(variance_);
45
46 Option::Type type = payoff->optionType();
47 strike_ = payoff->strike();
49
50 mu_ = std::log(dividendDiscount_/discount_)/variance_ - 0.5;
51
52 // binary cash-or-nothing payoff?
53 ext::shared_ptr<CashOrNothingPayoff> coo =
54 ext::dynamic_pointer_cast<CashOrNothingPayoff>(payoff);
55 if (coo != nullptr) {
56 K_ = coo->cashPayoff();
57 }
58
59 // binary asset-or-nothing payoff?
60 ext::shared_ptr<AssetOrNothingPayoff> aoo =
61 ext::dynamic_pointer_cast<AssetOrNothingPayoff>(payoff);
62 if (aoo != nullptr) {
63 K_ = forward_;
64 mu_ += 1.0;
65 }
66
67
68 log_H_S_ = std::log(strike_/spot_);
69 Real log_S_H_ = std::log(spot_/strike_);
70
71 double eta;
72 double phi;
73 switch (type) {
74 case Option::Call:
75 if (knock_in_) {
76 // up-and-in cash-(at-expiry)-or-nothing option
77 // a.k.a. american call with cash-or-nothing payoff
78 eta = -1.0;
79 phi = 1.0;
80 } else {
81 // up-and-out cash-(at-expiry)-or-nothing option
82 eta = -1.0;
83 phi = -1.0;
84 }
85 break;
86 case Option::Put:
87 if (knock_in_) {
88 // down-and-in cash-(at-expiry)-or-nothing option
89 // a.k.a. american put with cash-or-nothing payoff
90 eta = 1.0;
91 phi = -1.0;
92 } else {
93 // down-and-out cash-(at-expiry)-or-nothing option
94 eta = 1.0;
95 phi = 1.0;
96 }
97 break;
98 default:
99 QL_FAIL("invalid option type");
100 }
101
102
103 if (variance_>=QL_EPSILON) {
104 D1_ = phi*(log_S_H_/stdDev_ + mu_*stdDev_);
105 D2_ = eta*(log_H_S_/stdDev_ + mu_*stdDev_);
106
108 cum_d1_ = f(D1_);
109 cum_d2_ = f(D2_);
110 n_d1_ = f.derivative(D1_);
111 n_d2_ = f.derivative(D2_);
112 } else {
113 if (log_S_H_ * phi >0)
114 cum_d1_= 1.0;
115 else
116 cum_d1_= 0.0;
117 if (log_H_S_ * eta >0)
118 cum_d2_= 1.0;
119 else
120 cum_d2_= 0.0;
121 n_d1_ = 0.0;
122 n_d2_ = 0.0;
123 }
124
125
126 switch (type) {
127 case Option::Call:
128 if (strike_<=spot_) {
129 if (knock_in_) {
130 // up-and-in cash-(at-expiry)-or-nothing option
131 // a.k.a. american call with cash-or-nothing payoff
132 cum_d1_ = 0.5;
133 cum_d2_ = 0.5;
134 } else {
135 // up-and-out cash-(at-expiry)-or-nothing option
136 // already knocked out
137 cum_d1_ = 0.0;
138 cum_d2_ = 0.0;
139 }
140 n_d1_ = 0.0;
141 n_d2_ = 0.0;
142 }
143 break;
144 case Option::Put:
145 if (strike_>=spot_) {
146 if (knock_in_) {
147 // down-and-in cash-(at-expiry)-or-nothing option
148 // a.k.a. american put with cash-or-nothing payoff
149 cum_d1_ = 0.5;
150 cum_d2_ = 0.5;
151 } else {
152 // down-and-out cash-(at-expiry)-or-nothing option
153 // already knocked out
154 cum_d1_ = 0.0;
155 cum_d2_ = 0.0;
156 }
157 n_d1_ = 0.0;
158 n_d2_ = 0.0;
159 }
160 break;
161 default:
162 QL_FAIL("invalid option type");
163 }
164
165
166 inTheMoney_ = (type==Option::Call && strike_<spot_) ||
167 (type==Option::Put && strike_>spot_);
168 if (inTheMoney_) {
169 X_ = 1.0;
170 Y_ = 1.0;
171 } else {
172 X_ = 1.0;
173 if (cum_d2_ == 0.0)
174 Y_ = 0.0; // check needed on some extreme cases
175 else
176 Y_ = std::pow(Real(strike_/spot_), Real(2.0*mu_));
177 }
178 if (!knock_in_)
179 Y_ *= -1.0;
180 }
181
182}
183
AmericanPayoffAtExpiry(Real spot, DiscountFactor discount, DiscountFactor dividendDiscount, Real variance, const ext::shared_ptr< StrikedTypePayoff > &payoff, bool knock_in=true)
Cumulative normal distribution function.
#define QL_EPSILON
Definition: qldefines.hpp:178
QL_REAL Real
real number
Definition: types.hpp:50
Real DiscountFactor
discount factor between dates
Definition: types.hpp:66
Definition: any.hpp:35