正态分布最佳方法



我正试图构建一个简单的程序,使用black-scholes公式对看涨期权进行定价http://en.wikipedia.org/wiki/Black%E2%80%93Scholes.我正试图找出从正态分布中得到概率的最佳方法。例如,如果我用手做这件事,我得到的值为d1=0.43,那么我会在这个表中查找0.43http://www.math.unb.ca/~knight/putility/NormTble.htm,并获得值0.6664。

我相信c或objective-c中没有函数可以找到正态分布。我也在考虑创建一个二维数组,然后循环直到找到所需的值。或者,我可以用相应的值定义300个double,并循环使用这些值,直到得到合适的结果。对最佳方法有什么想法吗?

您需要更清楚地定义您要查找的内容。根据你发布的内容,你似乎在寻找累积分布函数或P(d<d1),其中d1是以标准偏差测量的,d是正态分布:根据你的例子,如果d1=0.43,那么P(d<d1)=0.6664。

你想要的函数被称为误差函数erf(x),有一些很好的近似值

显然,erf(x)是C中标准math.h的一部分(不确定objective-C,但我认为它可能也包含它)。

但是erf(x)并不是您所需要的功能。一般形式P(d<d1)可以由erf(x)通过以下公式计算:

P(d<d1) = f(d1,sigma) = (erf(x/sigma/sqrt(2))+1)/2

其中西格玛是标准偏差。(在您的情况下,您可以使用西格玛=1。)

您可以在WolframAlpha上测试这一点,例如:f(0.43,1)=(erf(0.43/sqrt(2))+1)/2=0.666402,这与您的表相匹配。

还有两件事很重要:

  1. 如果你正在寻找p(d<d1),其中d1很大(绝对值大于大约3.0*sigma),那么你真的应该使用互补误差函数erfc(x) = 1-erf(x),它告诉你p(d<d1)与0或1有多接近,而不会遇到数值误差。对于d1&lt-3*sigma,P(d<d1)=(erf(d1/sigma/sqrt(2))+1)/2=erfc(-d1/sigma/sqrt(2);而是将其保留为1-K,其中K=erfc(d1/sigma/sqrt(2))/2。例如,如果d1=5*sigma,则P(d<d1)=1-2.866516*10-7

  2. 例如,如果您的编程环境没有在可用的库中内置erf(x),则需要一个良好的近似值。(我以为我有一个很容易使用的,但我找不到它,我认为它实际上是用于逆误差函数的)。我发现了W.J.Cody 1969年的这篇文章,它给出了erf(x)的一个很好的近似,如果|x|<0.5,并且当|x|>0.5时,最好使用erf(x)=1-erfc(x)。例如,假设您想要erf(0.2)&大约;来自Wolfram Alpha的0.2227025892105;Cody说用x*R(x2)求值,其中R是一个有理函数,你可以从他的表中得到。

如果我在Javascript中尝试这个(Cody论文表II中的系数):

 // use only for |x| <= 0.5
 function erf1(x)
 {
    var y = x*x;
    return x*(3.6767877 - 9.7970565e-2*y)/(3.2584593 + y);
 }

然后我得到erf1(0.2) = 0.22270208866303123,它非常接近,对于一阶有理函数。Cody给出了4次有理函数的系数表;这是学位2:

 // use only for |x| <= 0.5
 function erf2(x)
 {
    var y = x*x;
    return x*(21.3853322378 + 1.72227577039*y + 0.316652890658*y*y)
      / (18.9522572415 + 7.8437457083*y + y*y);
 }

它给出了精确到小数点后10位的CCD_ 9。Cody论文还为您提供了类似的erfc(x)公式,其中|x|在0.5和4.0之间,以及第三个erfc(x)公式,这里|x|>4.0,如果您愿意,您可以使用Wolfram-Alpha或已知的erfc表检查结果的准确性。

希望这能有所帮助!

最新更新