R:使用 Black-Scholes 和二分法计算 IV,循环拒绝工作
R: Calculating IV using Black-Scholes and bisection method, loop refusing to work
我有我的 Black-Scholes 函数和我的看涨期权二分模型,数据来自 CSV。它似乎卡在了内部循环中,因为它保持在公差之上。我的 Black-Scholes 确实计算准确,我使用的是出价和要价的平均值,而不是期权的实际价格。在为此工作了几个小时之后,也许我只是遗漏了一些明显的东西。
CSV 的 link 在这里:http://s000.tinyupload.com/?file_id=06213890949979926112
########################################################################
#Black-Scholes-Merton Call
bsmCall <- function(S, K, M, sig, r) {
yrTime=(M/252)
d1 <- (log(S/K)+(r+(sig^2/2))*(yrTime))/(sig*(sqrt(yrTime)))
d2 <- d1-sig*(sqrt(yrTime))
C <- (S*(pnorm(d1)))-((pnorm(d2))*K*(exp(-r*yrTime)))
return(C)
}
########################################################################
myData = read.csv("09-26-16.csv", stringsAsFactors=FALSE) #DATA
myData <- myData[,2:24] #omit first column
####### start bisection method of CALLS and put IV in database #######
i <- 1 # reset counter
tol <- 0.000001 #tolerance
while(i <= nrow(myData)) {
if((myData[i,5] != 0) & (myData[i,6] != 0)) {
volLower <- .0001 #will need to reset with each iteration
volUpper <- 1 #will need to reset with each iteration
volMid <- (volLower + volUpper) / 2 #will need to reset with each iteration
while(abs(bsmCall(as.numeric(as.character(myData[i,17])),as.numeric(as.character(myData[i,1])),as.numeric(as.character(myData[i,22])),volMid,as.numeric(as.character(myData[i,23])))-(as.numeric(as.character(myData[i,5])))) >= tol) {
if((bsmCall(as.numeric(as.character(myData[i,17])),as.numeric(as.character(myData[i,1])),as.numeric(as.character(myData[i,22])),volMid,as.numeric(as.character(myData[i,23])))-(as.numeric(as.character(myData[i,5])))) < 0) {
volLower <- volMid
volMid <- (volUpper + volMid)/2
} else {
volUpper <- volMid
volMid <- (volLower + volMid)/2
}
}
myData[i,8] <- volMid
} else { myData[i,8] <- 0 }
i=i+1
}
问题出在这里:
while(abs(bsmCall(as.numeric(as.character(myData[i,17])),
as.numeric(as.character(myData[i,1])),
as.numeric(as.character(myData[i,22])),
volMid,
as.numeric(as.character(myData[i,23])))-(as.numeric(as.character(myData[i,5])))) >= tol)
您正在使用 while
循环,条件是如果为真,则始终为真。这是一个无限循环。在您的第一行数据上遇到了这个问题。
如何修复此错误特定于您的用例,但如果您只是将 while
更改为 if
,您会立即看到循环完成。
你问的是二分法。包中有一些,这是 here:
中的另一个
bisect <- function(fn, lower, upper, tol=1.e-07, ...) {
f.lo <- fn(lower, ...)
f.hi <- fn(upper, ...)
feval <- 2
if (f.lo * f.hi > 0) stop("Root is not bracketed in the specified interval
\n")
chg <- upper - lower
while (abs(chg) > tol) {
x.new <- (lower + upper) / 2
f.new <- fn(x.new, ...)
if (abs(f.new) <= tol) break
if (f.lo * f.new < 0) upper <- x.new
if (f.hi * f.new < 0) lower <- x.new
chg <- upper - lower
feval <- feval + 1
}
list(x = x.new, value = f.new, fevals=feval)
}
# An example
fn1 <- function(x, a) {
exp(-x) - a*x
}
bisect(fn1, 0, 2, a=1)
bisect(fn1, 0, 2, a=2)
递归版本:
bisectMatt <- function(fn, lo, hi, tol = 1e-7, ...) {
flo <- fn(lo, ...)
fhi <- fn(hi, ...)
if(flo * fhi > 0)
stop("root is not bracketed by lo and hi")
mid <- (lo + hi) / 2
fmid <- fn(mid, ...)
if(abs(fmid) <= tol || abs(hi-lo) <= tol)
return(mid)
if(fmid * fhi > 0)
return(bisectMatt(fn, lo, mid, tol, ...))
return(bisectMatt(fn, mid, hi, tol, ...))
}
哎呀,这是我迄今为止的第 3 次编辑...
让我们在 i=1
时重建 while
循环并打印 volMid
- while
条件的唯一部分在每次迭代后更新
i <- 1
volLower <- .0001 #will need to reset with each iteration
volUpper <- 1 #will need to reset with each iteration
volMid <- (volLower + volUpper) / 2 #will need to reset with each iteration
j <- 1
while(abs(bsmCall(myData[i,17], myData[i,1], myData[i,22],volMid,myData[i,23])-myData[i,5]) >= tol & j < 30) {
if(bsmCall(myData[i,17], myData[i,1], myData[i,22],volMid,myData[i,23])-myData[i,5] < 0) {
volLower <- volMid
volMid <- (volUpper + volMid)/2
} else {
print("pos")
volUpper <- volMid
volMid <- (volLower + volMid)/2
}
j <- j + 1
print(volMid)
}
结果:
#[1] 0.750025
#[1] 0.8750125
#[1] 0.9375062
#[1] 0.9687531
#[1] 0.9843766
#[1] 0.9921883
#[1] 0.9960941
#[1] 0.9980471
#[1] 0.9990235
#[1] 0.9995118
#[1] 0.9997559
#[1] 0.9998779
#[1] 0.999939
#[1] 0.9999695
#[1] 0.9999847
#[1] 0.9999924
#[1] 0.9999962
#[1] 0.9999981
#[1] 0.999999
#[1] 0.9999995
#[1] 0.9999998
#[1] 0.9999999
#[1] 0.9999999
#[1] 1
#[1] 1
#[1] 1
#[1] 1
#[1] 1
#[1] 1
volMid
在不到 30 次迭代后收敛到 1
,从那以后,它被卡住了。
我有我的 Black-Scholes 函数和我的看涨期权二分模型,数据来自 CSV。它似乎卡在了内部循环中,因为它保持在公差之上。我的 Black-Scholes 确实计算准确,我使用的是出价和要价的平均值,而不是期权的实际价格。在为此工作了几个小时之后,也许我只是遗漏了一些明显的东西。
CSV 的 link 在这里:http://s000.tinyupload.com/?file_id=06213890949979926112
########################################################################
#Black-Scholes-Merton Call
bsmCall <- function(S, K, M, sig, r) {
yrTime=(M/252)
d1 <- (log(S/K)+(r+(sig^2/2))*(yrTime))/(sig*(sqrt(yrTime)))
d2 <- d1-sig*(sqrt(yrTime))
C <- (S*(pnorm(d1)))-((pnorm(d2))*K*(exp(-r*yrTime)))
return(C)
}
########################################################################
myData = read.csv("09-26-16.csv", stringsAsFactors=FALSE) #DATA
myData <- myData[,2:24] #omit first column
####### start bisection method of CALLS and put IV in database #######
i <- 1 # reset counter
tol <- 0.000001 #tolerance
while(i <= nrow(myData)) {
if((myData[i,5] != 0) & (myData[i,6] != 0)) {
volLower <- .0001 #will need to reset with each iteration
volUpper <- 1 #will need to reset with each iteration
volMid <- (volLower + volUpper) / 2 #will need to reset with each iteration
while(abs(bsmCall(as.numeric(as.character(myData[i,17])),as.numeric(as.character(myData[i,1])),as.numeric(as.character(myData[i,22])),volMid,as.numeric(as.character(myData[i,23])))-(as.numeric(as.character(myData[i,5])))) >= tol) {
if((bsmCall(as.numeric(as.character(myData[i,17])),as.numeric(as.character(myData[i,1])),as.numeric(as.character(myData[i,22])),volMid,as.numeric(as.character(myData[i,23])))-(as.numeric(as.character(myData[i,5])))) < 0) {
volLower <- volMid
volMid <- (volUpper + volMid)/2
} else {
volUpper <- volMid
volMid <- (volLower + volMid)/2
}
}
myData[i,8] <- volMid
} else { myData[i,8] <- 0 }
i=i+1
}
问题出在这里:
while(abs(bsmCall(as.numeric(as.character(myData[i,17])),
as.numeric(as.character(myData[i,1])),
as.numeric(as.character(myData[i,22])),
volMid,
as.numeric(as.character(myData[i,23])))-(as.numeric(as.character(myData[i,5])))) >= tol)
您正在使用 while
循环,条件是如果为真,则始终为真。这是一个无限循环。在您的第一行数据上遇到了这个问题。
如何修复此错误特定于您的用例,但如果您只是将 while
更改为 if
,您会立即看到循环完成。
你问的是二分法。包中有一些,这是 here:
中的另一个bisect <- function(fn, lower, upper, tol=1.e-07, ...) {
f.lo <- fn(lower, ...)
f.hi <- fn(upper, ...)
feval <- 2
if (f.lo * f.hi > 0) stop("Root is not bracketed in the specified interval
\n")
chg <- upper - lower
while (abs(chg) > tol) {
x.new <- (lower + upper) / 2
f.new <- fn(x.new, ...)
if (abs(f.new) <= tol) break
if (f.lo * f.new < 0) upper <- x.new
if (f.hi * f.new < 0) lower <- x.new
chg <- upper - lower
feval <- feval + 1
}
list(x = x.new, value = f.new, fevals=feval)
}
# An example
fn1 <- function(x, a) {
exp(-x) - a*x
}
bisect(fn1, 0, 2, a=1)
bisect(fn1, 0, 2, a=2)
递归版本:
bisectMatt <- function(fn, lo, hi, tol = 1e-7, ...) {
flo <- fn(lo, ...)
fhi <- fn(hi, ...)
if(flo * fhi > 0)
stop("root is not bracketed by lo and hi")
mid <- (lo + hi) / 2
fmid <- fn(mid, ...)
if(abs(fmid) <= tol || abs(hi-lo) <= tol)
return(mid)
if(fmid * fhi > 0)
return(bisectMatt(fn, lo, mid, tol, ...))
return(bisectMatt(fn, mid, hi, tol, ...))
}
哎呀,这是我迄今为止的第 3 次编辑...
让我们在 i=1
时重建 while
循环并打印 volMid
- while
条件的唯一部分在每次迭代后更新
i <- 1
volLower <- .0001 #will need to reset with each iteration
volUpper <- 1 #will need to reset with each iteration
volMid <- (volLower + volUpper) / 2 #will need to reset with each iteration
j <- 1
while(abs(bsmCall(myData[i,17], myData[i,1], myData[i,22],volMid,myData[i,23])-myData[i,5]) >= tol & j < 30) {
if(bsmCall(myData[i,17], myData[i,1], myData[i,22],volMid,myData[i,23])-myData[i,5] < 0) {
volLower <- volMid
volMid <- (volUpper + volMid)/2
} else {
print("pos")
volUpper <- volMid
volMid <- (volLower + volMid)/2
}
j <- j + 1
print(volMid)
}
结果:
#[1] 0.750025
#[1] 0.8750125
#[1] 0.9375062
#[1] 0.9687531
#[1] 0.9843766
#[1] 0.9921883
#[1] 0.9960941
#[1] 0.9980471
#[1] 0.9990235
#[1] 0.9995118
#[1] 0.9997559
#[1] 0.9998779
#[1] 0.999939
#[1] 0.9999695
#[1] 0.9999847
#[1] 0.9999924
#[1] 0.9999962
#[1] 0.9999981
#[1] 0.999999
#[1] 0.9999995
#[1] 0.9999998
#[1] 0.9999999
#[1] 0.9999999
#[1] 1
#[1] 1
#[1] 1
#[1] 1
#[1] 1
#[1] 1
volMid
在不到 30 次迭代后收敛到 1
,从那以后,它被卡住了。