https://github.com/cran/fOptions
Raw File
Tip revision: 429a9b1805024ce58873e3229048371980a535a2 authored by Diethelm Wuertz on 08 August 1977, 00:00:00 UTC
version 221.10065
Tip revision: 429a9b1
xmpDWChapter084.R
#
# Examples from the forthcoming Monograph:
# 	Rmetrics - Financial Engineering and Computational Finance
#   A Practitioner's Guide for R and SPlus Programmers
#   written by Diethelm Wuertz
#   ISBN to be published
#
# Details:
#   Examples from Chapter 7.4
#   Heston-Nandi Option Pricing
#
# List of Examples, Exercises and Code Snippets
#
#   * Example: Computing the Price of Heston-Nandi Options
#   * Example: Computing the Greeks of Heston-Nandi Options
#   * Example: HN Options Pricing - GARCH(1,1) Simulation 
#   * Example: HN Options Pricing - Max LogLikelihood Estimation
#   * Example: HN Options Pricing - Scaling of Prices   
#   * Example: Investigate the Smile Effect
#
#   *** This list is not yet complete ***
#
# Author:
#	(C) 2002-2005, Diethelm Wuertz, GPL
# 	  www.rmetrics.org
# 	  www.itp.phys.ethz.ch
# 	  www.finance.ch
#


################################################################################


### Example: Computing the Price of Heston-Nandi Options

	# Calculate the price of Heston-Nandi Garch(1,1)
	# call and put options. 	
	###

	# Set the Model Parameters for the HN Garch(1,1) Option:
	model = list(lambda = -0.5, omega = 5e-6, alpha = 1e-8, 
		beta = 0.7, gamma = 10)
	S = X = 100
   	Time.inDays = 250
   	r.daily = 0.05/250
   	###
   	
	# List the R Function:
	HNGOption
	###
	
	# Compute the Option Price:
	# Call:
	HNGOption(TypeFlag = "c", model, S, X, Time.inDays, r.daily)
	# Put:
	HNGOption(TypeFlag = "p", model, S, X, Time.inDays, r.daily)
	###
	
	# Compare with the Black-Scholes Formula:
	# Unconditional Variance:
	sigma2.daily = (model$alpha + model$omega) /
		(1-model$beta-model$alpha*model$gamma^2)	
	# Call:
	GBSOption("c", S = 100, X = 100, Time = 1, r = 0.05,
		b = 0.05, sigma = sqrt(sigma2.daily*250))	
	# Put:
	GBSOption("p", S = 100, X = 100, Time = 1, r = 0.05,
		b = 0.05, sigma = sqrt(sigma2.daily*250))
	###
		
# ------------------------------------------------------------------------------


### Example: Computing the Greeks of Heston-Nandi Options
	
	# Calculate the sensitiviteis delta and gamma of 
	# Heston-Nandi Garch(1,1) call and put options. 	
	###
	
	# Option Parameters:
	S = X = 100
	Time.inDays = 125
	r.daily = 0.05/250
	model = list(lambda = -0.5, omega = 2.3e-6, alpha = 2.9e-6, 
		beta = 0.85, gamma = 184.25)
	sigma.daily = sqrt((model$alpha + model$omega) /
		(1 - model$beta - model$alpha*model$gamma^2))		
	# Print:
	S; X; Time.inDays; r.daily; sigma.daily
	model
	###

	# Compute the Delta 
	# and compare the result with the finite dfference approaximation:
	Summary = NULL
	# Call:
	Greek = HNGGreeks("Delta", "c", model, S, X, Time.inDays, r.daily)
	C1 = HNGOption("c", model, S*0.9999, X, Time.inDays, r.daily)$price
	C2 = HNGOption("c", model, S*1.0001, X, Time.inDays, r.daily)$price
	numGreek = (C2-C1)/(0.0002*S)
	Diff = 100*(Greek-numGreek)/Greek
	Summary = rbind(Summary, c(Greek, numGreek, Diff))
	# Put:
	Greek = HNGGreeks("Delta", "p", model, S, X, Time.inDays, r.daily)
	C1 = HNGOption("p", model, S*0.9999, X, Time.inDays, r.daily)$price
	C2 = HNGOption("p", model, S*1.0001, X, Time.inDays, r.daily)$price
	numGreek = (C2-C1)/(0.0002*S)
	Diff = 100*(Greek-numGreek)/Greek
	Summary = rbind(Summary, c(Greek, numGreek, Diff))
	# Print:
	dimnames(Summary) <- 
		list(c("Call", "Put"), c("Greek", "numGreek", "Diff"))
	Summary
	###
	
	# Do the same for the Gamma Sensitivity ...
	Summary = NULL
	# Call:
	Greek = HNGGreeks("Gamma", "c", model, S, X, Time.inDays, r.daily)
	C0 = HNGOption("c", model, S, X, Time.inDays, r.daily)$price
	C1 = HNGOption("c", model, S*0.9999, X, Time.inDays, r.daily)$price 
	C2 = HNGOption("c", model, S*1.0001, X, Time.inDays, r.daily)$price 	
	numGreek = (C2 - 2*C0 + C1)/(0.0002*S/2)^2
	Diff = 100*(Greek-numGreek)/Greek	
	Summary = rbind(Summary, c(Greek, numGreek, Diff))
	# Put:
	Greek = HNGGreeks("Gamma", "p", model, S, X, Time.inDays, r.daily)
	C0 = HNGOption("p", model, S, X, Time.inDays, r.daily)$price
	C1 = HNGOption("p", model, S*0.9999, X, Time.inDays, r.daily)$price 
	C2 = HNGOption("p", model, S*1.0001, X, Time.inDays, r.daily)$price 
	numGreek = (C2 - 2*C0 + C1)/(0.0002*S/2)^2
	Diff = 100*(Greek-numGreek)/Greek	
	Summary = rbind(Summary, c(Greek, numGreek, Diff))
	# Print:
	dimnames(Summary) <- 
		list(c("Call", "Put"), c("Greek", "numGreek", "Diff"))
	Summary
	###
	
	
# ------------------------------------------------------------------------------


### Example: HN Options Pricing - GARCH(1,1) Simulation

	# Description:
	#	Simulate time series with the same parameters as those
	#	fitted by Heston and nandi to the SP500 data ranging
	#	the three years from 01/08/1992 to 12/30/1994.
	#   DATA:
	#     Index Value at 2:30 PM
	#     No. of observations 755
	#     r - TBill rate (3.7%)
	#   RESULT:
	#           lambda   omega   alpha  beta  gamma  THETA   PERS  MLLH
	#     Sym:     0.7  1.6e-6  1.0e-6  0.92    ---   9.2%   0.92  3492
	#     Asym:    0.2  5.0e-6  1.0e-6  0.59    421   8.0%   0.77  3504 
	# Reference:
	# 	S. Heston and S. Nandi, 1997
	# 	A Closed-Form GARCH Option Pricing Model
	###
	
	# Fit a Symmetric HN-GARCH(1,1) Process:
 	set.seed(4711)
 	model = list(lambda = 0.7, omega = 1.6e-6, alpha = 1e-6, 
 		beta = 0.92, gamma = 0, rf = 0.037/252)
 	ts.sym = hngarchSim(model, n = 755, n.start = 100)
 	par(mfcol = c(3, 2), cex = 0.5)
 	ts.plot(ts.sym, main = "Symmetric Data")
	###
		
	# Fit an Asymmetric HN-GARCH(1,1) Process:
 	set.seed(4711)
 	model = list(lambda = 0.2, omega = 5.0e-6, alpha = 1e-6, 
 		beta = 0.59, gamma = 421, rf = 0.037/252)
 	ts.asym = hngarchSim(model, n = 755, n.start = 100)
 	ts.plot(ts.asym, main = "Asymmetric Data")
 	# Plot Both:
 	ts.plot(ts.asym, main = "Both Data Sets")
 	lines(ts.sym, col = "red")
	###
	
	# ACF Plots:
	result = acf(abs(ts.sym), main = "ACF: Symmetric Data")
	result = acf(abs(ts.asym), main = "ACF: Asymmetric Data")
	###
	
	
# ------------------------------------------------------------------------------


### Example: HN Options Pricing - Max LogLikelihood Estimation

	# Simulate time series with the same parameters as those
	# fitted by Heston and nandi to the SP500 data ranging
	# from 2/8/1992 to 30/12/1994, finally re-fit the parameters.
	#   DATA:
	#     Index Value at 2:30 PM
	#     No. of observations 755
	#     r - TBill rate (3.5%)
	#   RESULT:
	#           lambda   omega   alpha  beta  gamma  THETA   PERS  MLLH
	#     Sym:     0.7  1.6e-6  1.0e-6  0.92    ---   9.2%   0.92  3492
	#     Asym:    0.2  5.0e-6  1.0e-6  0.59    421   8.0%   0.77  3504 
	# Reference:
	# 	S. Heston and S. Nandi, 1997
	# 	A Closed-Form GARCH Option Pricing Model
	###

	# SP500 Data from MASS Package:
	require(MASS)
	data(SP500)
	returns = SP500[505:(505+755)]/100
	model.sym = list(lambda = 0.2, omega = 1.6e-6, alpha = 1e-6, 
		beta = 0.92, gamma = 0, rf = 0.035/252)
	model.asym = list(lambda = 0.7, omega = 5e-6, alpha = 1e-6,
		beta = 0.59, gamma = 421, rf = 0.035/252)
	###
	
	# Estimate the Symmetric HN-GARCH(1,1) Parameters: 
  	fit.sym = hngarchFit(x = returns, model = model.sym, 
  		symmetric = TRUE)
  	fit.sym
  	###	
  
	# Estimate the Asymmetric HN-GARCH(1,1):
  	fit.asym = hngarchFit(x = returns, model = model.asym, 
  		symmetric = FALSE)
	fit.asym
	###
	
	# Summarize Results:	
	data.frame(cbind(
		SYM = unlist(model.sym), 
		SYM.FIT = unlist(fit.sym$model),
		ASYM = unlist(model.asym),
		ASYM.FIT = unlist(fit.asym$model)
		))
	###
	
	# Diagnostic Analysis:
	par(mfcol = c(3,2), cex=0.5)
	summary(fit.sym)
	summary(fit.asym)
	###
	
	# Moment Statistics:
	unlist(hngarchStats(model.sym))
	unlist(hngarchStats(model.asym))
	unlist(hngarchStats(fit.sym$model))
	unlist(hngarchStats(fit.asym$model))
	###
	
	
# ------------------------------------------------------------------------------


### Example: HN Options Pricing - Scaling of Prices

	# The example shows for the HN Garch(1,1) model 
	# the scaling in price/strike and volatility*time.
	###
	
	# Initial Parameter Setting:
   	scales = c(1/2, 1, 2)
   	Model = list(lambda=-0.5, omega=1e-6, alpha=1e-6, beta=0.5, gamma=0)
 	par (mfrow = c(2, 2), cex = 0.7)
	###
	
	# Price/Strike Variation:
	S  = seq(75, 125, by = 5); X = 100
	Time = 126 
	###
	
 	# HNG:	
	plot(x = c(0.75, 1.25), y = c(0, 28), type = "n", 
		xlab = "S/X", ylab = "Call Price", 
		main = "HN: Volatility*Time fixed")
 	for (j in 1:length(scales)) {
	 	model = Model
		model$omega = Model$omega*scales[j]
		model$alpha = Model$alpha*scales[j]
      	for (i in 1:length(S)) {
	      	x = S[i]/X
   			y = HNGOption("c", model, S[i], X, Time/scales[j], 0)$price
        	points(x, y, col = j, pch = (j+2)) } }
    legend(0.8, 26, legend = c("scale = 1/2", "scale = 1", "scale = 2"), 
		pch = "\3\4", bty = "n", col = 1:3)
    ###
     	
	# BS:
	plot(x = c(0.75, 1.25), y = c(0, 28), type = "n", 
		xlab = "S/X", ylab = "Call Price", 
		main = "BS: Volatility*Time fixed")
 	for (j in 1:length(scales)) {
	 	model = Model
		model$omega = Model$omega/scales[j]
		model$alpha = Model$alpha/scales[j]
		sigma = sqrt((model$alpha+model$omega)/(1-model$beta))
		print(sigma^2 * Time*scales[j])
      	for (i in 1:length(S)) {
	      	x = S[i]/X
   			y = GBSOption("c", S[i], X, Time*scales[j], r=0, b=0, 
   				sigma=sigma)$price
        	points(x, y, col = j, pch = (j+2)) } }	
	legend(0.8, 26, legend = c("scale = 1/2", "scale = 1", "scale = 2"), 
		pch = "\3\4", bty = "n", col = 1:3)
	###	

	# Volatility*Time Variation:
	S = 100; X = 100
	Time = c((12:1)*21, 5, 1) 
	sigma = sqrt((Model$alpha+Model$omega)/(1-Model$beta)); 252*sigma
	###
	
 	# HNG:		
	plot(x = c(-252, 0) , y = c(1.5, 0), type = "n", xlab = "Days", 
		ylab = "Put Price / scale", main = "HN: S/X fixed")
 	for ( j in 1:length(scales) ) {
	 	S.scaled = S*scales[j]; X.scaled = X*scales[j]	
   		for (i in 1:length(Time)) {
   			x = -Time[i]
   			y = HNGOption("c", Model, S.scaled, X.scaled, Time[i], 0)$price /
   				scales[j]
   			points(x, y, col = j, pch = (j+2)) } }
	legend(-240, 0.6, legend = c("scale = 0.5", "scale = 1", "scale = 2"), 
		pch = "\3\4", bty = "n", col = 1:3)
	###	
			
	# BS:
	plot(x = c(-252, 0) , y = c(1.5, 0), type = "n", xlab = "Days", 
		ylab = "Put Price / scale ", main = "BS: S/X fixed")
	for (j in 1:length(scales) ) {
	 	S.scaled = S*scales[j]; X.scaled = X*scales[j]	
   		for (i in 1:length(Time)) {
   			x = -Time[i]
   			y = GBSOption("c", S.scaled, X.scaled, Time[i], 0, 0, sigma)$price /
   				scales[j]
   			points(x, y, col = j, pch = (j+2)) } }
	legend(-240, 0.6, legend = c("scale = 0.5", "scale = 1", "scale = 2"), 
		pch = "\3\4", bty = "n", col = 1:3)
	###
			
		
# ------------------------------------------------------------------------------


### Example: Investigate the Smile Effect

	# This program calculates for the estimated symmetric and asymmetric
	# Garch(1,1) the implied volatility from the Black and Scholes Option
	# Pricing formula assuming that the real market follows ideally the
	# Heston Nandi Option Garch(1,1) model
	###	
	 	
	# Show the GBSVolatility function:
    GBSVolatility
    ###

	# Compute Smile - Parameters:
	S  = 85:115; X = 100
	Time.inDays = 126 
	model = list(lambda=-0.5, omega=6e-6, alpha=4e-6, beta=0.8, gamma=0)
	sigma = sqrt(252*(model$alpha+model$omega)/(1-model$beta))
	sigma	
	###
	
	# Pricing the Put:
	Put <- impVola <- NULL
	for (i in 1:length(S)) {
		Price = HNGOption("p", model, S[i], X, Time.inDays, 0)$price
		Put = c(Put, Price) 
		Volatility = GBSVolatility(Price, "p", S[i], X, Time.inDays/252, 0, 0)
		impVola = c(impVola, Volatility)
		cat("\n\t", i, "\t", S[i], "\t", Price, "\t", Volatility) }
	###
		
	# Plot:
	par(mfrow = c(2, 2), cex = 0.7)
	plot(S/X, Put, 
		xlab = "S/X", ylab = "Price", main = "HN Put Price")
	plot(S/X, impVola, 
		xlab = "S/X", ylab = "Volatility", main = "BS Implied Volatility")
	###	
	
		
################################################################################


back to top