如何将最初使用sympy.statistics编写的Normal / cdf()计算转换为sympy.stats?

时间:2019-04-26 15:03:16

标签: python sympy

我没有跟上SymPy的变化。我在查看以下Black Scholes公式:https://aaronschlegel.me/black-scholes-formula-python.html。似乎在SymPy中完成了一些重构,因此这不再起作用。我将如何更改以下内容使其再次起作用:

import sympy as sy
import sympy.statistics as systats

def euro_put_sym(S, K, T, r, sigma):        
    #S: spot price
    #K: strike price
    #T: time to maturity
    #r: interest rate
    #sigma: volatility of underlying asset

    N = systats.Normal(0.0, 1.0)

    d1 = (sy.ln(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * sy.sqrt(T))
    d2 = (sy.ln(S / K) + (r - 0.5 * sigma ** 2) * T) / (sigma * sy.sqrt(T))

    put = (K * sy.exp(-r * T) * N.cdf(-d2) - S * N.cdf(-d1))

    return put
  

我得到的错误是:

     

模块'sympy'中没有名称'statistics'

     

无法导入“ sympy.statistics”

特别是现在如何Normalcdf完成?

2 个答案:

答案 0 :(得分:1)

Sympy中的统计模块名为stats。  另外,Normal采用3个参数。一个简单的用法示例如下所示:

>>> from sympy import symbols

>>> from sympy.stats import Normal, density, cdf

>>> x, mu, sigma = symbols("x mu sigma")

>>> N = Normal("N", mu, sigma)

>>> density(N)(x)

sqrt(2)*exp(-(-mu + x)**2/(2*sigma**2))/(2*sqrt(pi)*sigma)

>>> cdf(N)(x)

erf(sqrt(2)*(-mu + x)/(2*sigma))/2 + 1/2

有关更多参考,请参见Sympy Stats docsNormal Distribution docs

现在就您的情况,让我解释一下您应该怎么做。

import sympy as sy
import sympy.stats as systats

def euro_put_sym(S, K, T, r, sigma):        
    #S: spot price
    #K: strike price
    #T: time to maturity
    #r: interest rate
    #sigma: volatility of underlying asset

    N = systats.Normal('N', 0.0, 1.0)

    d1 = (sy.ln(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * sy.sqrt(T))
    d2 = (sy.ln(S / K) + (r - 0.5 * sigma ** 2) * T) / (sigma * sy.sqrt(T))

    put = (K * sy.exp(-r * T) * systats.cdf(N)(-d2) - S * systats.cdf(N)(-d1))

    return put

现在

S, K, T, r, sigma = sy.symbols("S K T r sigma")
sy.pprint(euro_put_sym(S, K, T, r, sigma), use_unicode=False)

将输出显示为

  /       /      ___ /  /             2\      /S\\\\           /       /      
  |       |0.5*\/ 2 *|T*\r - 0.5*sigma / + log|-||||           |       |0.5*\/
  |       |          \                        \K//||           |       |      
  |    erf|---------------------------------------||           |    erf|------
  |       |                ___                    ||           |       |      
  |1      \              \/ T *sigma              /|  -T*r     |1      \      
K*|- - --------------------------------------------|*e     - S*|- - ----------
  \2                        2                      /           \2             

___ /  /             2\      /S\\\\
 2 *|T*\r + 0.5*sigma / + log|-||||
    \                        \K//||
---------------------------------||
          ___                    ||
        \/ T *sigma              /|
----------------------------------|
           2                      /

这是预期的输出吗?

我通过您提供的链接中的示例进行了测试,结果匹配。

>>> euro_put_sym(50, 100, 1, 0.05, 0.25)
-25*erf(1.22379436111989*sqrt(2)) + 22.5614712250357 + 47.5614712250357*erf(1.34879436111989*sqrt(2))

答案 1 :(得分:0)

我认为这是从旧的统计信息包到新的统计信息包的正确转换。你们怎么看?

import sympy as sy
import sympy.stats as systats

def euro_put_sym(S, K, T, r, sigma):        
    #S: spot price
    #K: strike price
    #T: time to maturity
    #r: interest rate
    #sigma: volatility of underlying asset

    N = systats.Normal('x', 0.0, 1.0)

    d1 = (sy.ln(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * sy.sqrt(T))
    d2 = (sy.ln(S / K) + (r - 0.5 * sigma ** 2) * T) / (sigma * sy.sqrt(T))

    put = (K * sy.exp(-r * T) * systats.cdf(N)(-d2) - S * systats.cdf(N)(-d1))

    return put