R:使用Black-Scholes和二分法计算IV,循环拒绝工作

时间:2016-09-27 03:11:16

标签: r loops quantitative-finance bisection volatility

我有Black-Scholes函数和我的二分模型,用于来自CSV的数据的调用选项。它似乎陷入内循环,因为它保持在容差之上。我的Black-Scholes确实准确计算,我使用的是平均出价并要求市场价格而不是期权的实际价格。经过几个小时的努力,也许我只是遗漏了一些明显的东西。

CSV的链接位于: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
}

2 个答案:

答案 0 :(得分: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循环,条件是,如果为true,则始终为true。这是一个无限循环。在您的第一行数据上遇到此问题。

如何修复此错误特定于您的使用案例,但如果您只是将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, ...))
}

答案 1 :(得分:0)

Jeez,这是我到目前为止的第三次编辑......

让我们在while时重建i=1循环并打印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
经过不到30次迭代后,

volMid收敛到1,从那里开始,它就被卡住了。