[R-SIG-Finance] American option sensitivities
Enrico Schumann
enricoschumann at yahoo.de
Fri Feb 10 18:05:04 CET 2012
Am 10.02.2012 15:24, schrieb J Toll:
> On Fri, Feb 10, 2012 at 3:18 AM, Enrico Schumann
> <enricoschumann at yahoo.de> wrote:
>>
>> Hi all,
>>
>> (comments below)
>>
>> Am 10.02.2012 01:02, schrieb J Toll:
>>
>>> On Thu, Feb 9, 2012 at 5:17 PM, Dirk Eddelbuettel<edd at debian.org> wrote:
>>>>
>>>>
>>>> On 9 February 2012 at 17:06, J Toll wrote:
>>>> | Hi,
>>>> |
>>>> | I'd like to calculate sensitivities on American options. I was hoping
>>>> | somebody might be able to summarize of the current state of that
>>>> | functionality within the various R packages. It's my understanding
>>>> | that the fOptions package can calculate greeks for European options
>>>> | but not American. RQuantLib appears to have had the ability to
>>>> | calculate greeks for American options at one point, but it appears
>>>> | that functionality was removed in Release 0.1.8 sometime around
>>>> | 2003-11-28.
>>>>
>>>> ... because that functionality was removed upstream by QuantLib.
>>>>
>>>> |
>>>> |
>>>> http://lists.r-forge.r-project.org/pipermail/rquantlib-commits/2010-August/000117.html
>>>> |
>>>> | Additionally, from RQuantLib ?AmericanOptions says,
>>>> |
>>>> | "Note that under the new pricing framework used in QuantLib, binary
>>>> | pricers do not provide analytics for 'Greeks'. This is expected to be
>>>> | addressed in future releases of QuantLib."
>>>> |
>>>> | I haven't found any other packages for calculating option
>>>> | sensitivities. Are there any other packages?
>>>> |
>>>> | Regarding RQuantLib, is the issue that that functionality hasn't been
>>>> | implemented in R yet, or is it QuantLib that's broken?
>>>>
>>>> There is a third door behind which you find the price: "numerical
>>>> shocks".
>>>>
>>>> Evaluate your american option, then shift the various parameters (spot,
>>>> vol,
>>>> int.rate, time to mat, ...) each by a small amount and calculate the
>>>> change
>>>> in option price -- voila for the approximate change in option value for
>>>> change input. You can also compute twice at 'x - eps' and 'x + eps'
>>>> etc.
>>>>
>>>> Dirk
>>>
>>>
>>> Dirk,
>>>
>>> Thank you for your response. I was hoping you might reply.
>>>
>>> I understand the concept of your suggestion, although I don't have any
>>> practical experience implementing it. I'm guessing this is what's
>>> generally referred to as finite difference methods. In theory, the
>>> first order greeks should be simple enough, although my impression is
>>> the second or third order greeks may be a bit more challenging.
>>>
>>> I hate to trouble you for more information, but I'm curious why? Is
>>> this the "standard" method of calculating greeks for American options?
>>> Has QuantLib decided not to implement this calculation? Just curious.
>>>
>>> Thanks again,
>>>
>>
>> A simple forward difference is
>>
>> [f(x + h) - f(x)] / h
>>
>> 'f' is the option pricing formula; 'x' are the arguments to the formula, and
>> 'h' is a small offset.
>>
>> Numerically, 'h' should not be made too small:
>>
>> (1) Even for smooth functions, we trade off truncation error (which is large
>> when 'h' is large) against roundoff-error (in the extreme, 'x + h' may still
>> be 'x' for a very small 'h').
>>
>> (2) American options are typically valued via finite-difference or tree
>> methods, and hence 'f' is not smooth and any 'bumps' in the function will be
>> magnified by dividing by a very small 'h'. So when 'h' is too small, the
>> results will become nonsensical.
>>
>> Here is an example. As a first test, I use a European option.
>>
>> require("RQuantLib")
>> h<- 1e-4
>> S<- 100
>> K<- 100
>> tau<- 0.5
>> vol<- 0.3
>> C0<- EuropeanOption(type = "call",
>> underlying = S, strike = K,
>> dividendYield = 0.0,
>> riskFreeRate = 0.03, maturity = tau,
>> volatility = 0.3)
>> Cplus<- EuropeanOption(type="call",
>> underlying = S + h, strike = K,
>> dividendYield = 0.0,
>> riskFreeRate=0.03, maturity=tau,
>> volatility=0.3)
>> Cminus<- EuropeanOption(type="call",
>> underlying = S - h, strike=K,
>> dividendYield=0.0,
>> riskFreeRate=0.03, maturity=tau,
>> volatility=0.3)
>>
>> ## a first-order difference: delta
>> (Cplus$value-C0$value)/h
>> ## [1] 0.570159
>> C0$delta
>> ## [1] 0.5701581
>>
>>
>> ## a second-order difference
>> (Cplus$delta-C0$delta)/h
>> ## [1] 0.01851474
>> C0$gamma
>> ## [1] 0.01851475
>>
>>
>>
>>
>> Now for an American option. Here we don't have the delta, so we first need
>> to compute it as well.
>>
>> C0<- AmericanOption(type="put",
>> underlying = S, strike=K,
>> dividendYield=0.0,
>> riskFreeRate=0.03, maturity=tau,
>> volatility=vol)
>> Cplus<- AmericanOption(type="put",
>> underlying = S + h, strike=K,
>> dividendYield=0.0,
>> riskFreeRate=0.03, maturity=tau,
>> volatility=vol)
>> Cminus<- AmericanOption(type="put",
>> underlying = S - h, strike=K,
>> dividendYield=0.0,
>> riskFreeRate=0.03, maturity=tau,
>> volatility=vol)
>>
>> ## a first-order difference: delta
>> (dplus<- (Cplus$value - C0$value)/h)
>> (dminus<-(C0$value - Cminus$value)/h)
>>
>> ## a second-order difference
>> (dplus - dminus)/h
>> ## [1] 0.01905605
>>
>> I ran a little a experiment with different levels of 'h', where you can
>> clearly see when the gamma diverges.
>>
>> | h | gamma |
>> | 1 | 0.01905385 |
>> | 0.01 | 0.01905612 |
>> | 1e-4 | 0.01905605 |
>> | 1e-5 | 0.01915801 |
>> | 1e-6 | 0.03463896 |
>> | 1e-8 | 8.881784 |
>>
>>
>> In the literatur, you find a number of tricks to smooth the function, but in
>> my experience, you are fine if you make 'h' small with respect to 'x' --
>> small, not tiny. So if the stock price is 100, a change of 1 or 0.1 is
>> small. (And think of it: even if we found that a change of one-thousandth of
>> a cent led to a meaningful numerical difference; if the stock price never
>> moves by such an amount, such a computation would not be empirically
>> meaningful.)
>>
>>
>> Regards,
>> Enrico
>>
>
> Enrico,
>
> Thank you so much for such a detailed and helpful example. I had
> found an article on Wikipedia mentioning many of the issues you write
> about regarding selection of h. In that article, the author/s
> suggest:
>
> "A choice for h which is small without producing a large rounding
> error is sqrt(ε x) where the machine epsilon ε is typically of the
> order 2.2×10-16."
>
> http://en.wikipedia.org/wiki/Numerical_differentiation
>
> So for R, I suppose that would equate to:
>
> h<- sqrt(.Machine$double.eps * x)
>
> Thanks again for your really helpful example.
>
> Best,
>
I am glad if it helped. The value for 'h' that the Wikipedia article
cites is very likely for a forward difference; this is not generally
appropriate for other differences (eg, central or higher-order
differences) -- it will be too small then.
Here is again the example I gave, slightly modified to directly compute
the second-order derivative.
require("RQuantLib")
h <- 10^(-(0:10)) ## a vector of values
S <- 100
K <- 100
tau <- 0.5
vol <- 0.3
C0 <- EuropeanOption(type = "call",
underlying = S, strike = K,
dividendYield = 0.0,
riskFreeRate = 0.03, maturity = tau,
volatility = vol)
gammaVec <- numeric(length(h))
for (i in seq(along.with = h)) {
Cplus <- EuropeanOption(type="call",
underlying = S + h[i], strike = K,
dividendYield = 0.0,
riskFreeRate = 0.03,
maturity = tau,
volatility = vol)
Cminus <- EuropeanOption(type="call",
underlying = S - h[i], strike = K,
dividendYield = 0.0,
riskFreeRate = 0.03, maturity = tau,
volatility = vol)
## a central difference
gammaVec[i] <- (Cplus$value + Cminus$value - 2*C0$value)/h[i]^2
}
## the analytic solution
C0$gamma
## [1] 0.01851475
data.frame(h = h, gamma = gammaVec)
h gamma
1 1e+00 1.851213e-02
2 1e-01 1.851473e-02
3 1e-02 1.851475e-02
4 1e-03 1.851475e-02
5 1e-04 1.851461e-02
6 1e-05 1.861622e-02
7 1e-06 1.421085e-02
8 1e-07 0.000000e+00
9 1e-08 7.105427e+01
10 1e-09 -1.421085e+04
11 1e-10 -7.105427e+05
The goal in choosing 'h' is to find the 'sweet spot' where the
approximation error (which is a combination of truncation and roundoff
error) is smallest. My suggestion is that, if in doubt, to use a larger
value for 'h' than prescribed on Wikipedia or the literature. (Or, even
better, to run experiments to determine a good value for 'h' for your
implementation.)
Regards,
Enrico
>
> James
>
>
--
Enrico Schumann
Lucerne, Switzerland
http://nmof.net/
More information about the R-SIG-Finance
mailing list