sympy符号简化Norm CDF PDF?

问题描述 投票:0回答:2

寻找一种方法来简化以下内容。计算一些涉及正常 cdf 的导数。

当尝试简化时,我希望它们以范数 pdf [0,1] 和范数 cdf [0,1] 表示。如何在没有 erf 的情况下获得规范 cdf 规范 pdf 的符号答案。

例如,Delta 计算应简化为 Norm.cdf(d1) 见下图;

Delta Simp in Terms of CDF

对于另一个例子,theta 函数应该简化为范数 pdf 和 cdf 的函数,请参见下图。

Theta Simp in Terms of CDF and PDF

下面附有代码,请告知如何获得所需的简化。

import sympy as sp
from sympy.stats import Normal, cdf


#spot, strike, volatility, time, interest rate, time at expiry, d1, and d2
S, K, sigma, t, r, T, d1, d2 = sp.symbols('S_t,K,sigma,t,r,T,d_1,d_2')

#define a symbol to represent the normal CDF
N = sp.Function('N')

#Black and Scholes price
C = S * N(d1) - N(d2) * K * sp.exp(-r * (T-t))




#expanded d1 and d2 for substitution:
d1_sub = (sp.ln(S / K) + (r + sp.Rational(1,2) * sigma ** 2) * (T-t)) / (sigma * sp.sqrt(T-t))
d2_sub = d1 - sigma * sp.sqrt(T-t)

#instance a standard normal distribution:
Norm = Normal('N',0.0, 1.0)

#define the long form b-s equation with all substitutions:
bs = C.subs(N, cdf(Norm)).subs(d2, d2_sub).subs(d1, d1_sub)

#Callable function for black and scholes price:
#example usage: bs_calc(100, 98, 0.15, 0, 0.03, 0.5)
bs_calc = sp.lambdify((S, K, sigma, t, r, T), bs)


print("Delta -> Mess")
print(sp.diff(bs,S))

print('Delta -> mess unresolved')
print(sp.simplify(sp.diff(bs,S)))

print("Theta -> Even worse Mess")
print(sp.diff(bs,T))

print('Theta -> Even Worse unresolved')
print(sp.simplify(sp.diff(bs,T)))

解决方案集将其打印到控制台:

运行文件('我的文件')

Delta -> 混乱 -0.5sqrt(2)Kexp(-r(T - t))exp(-0.5(-sigmasqrt(T - t) + ((T - t)(r + sigma) 2/2) + log(S_t/K))/(sigmasqrt(T - t)))**2)/(sqrt(pi)S_tsigmasqrt(T - t)) + erf(0.5 sqrt(2)((T - t)*(r + sigma2/2) + log(S_t/K))/(sigmasqrt(T - t)))/2 + 1/2 + 0.5 sqrt(2)exp(-0.5((T - t)(r + sigma**2/2) + log(S_t/K))2/(sigma2(T - t)) )/(sqrt(pi)sigmasqrt(T - t))

Delta -> 混乱尚未解决 -0.5sqrt(2)Kexp(-r(T - t))exp(-0.5(sigmasqrt(T - t)) - ((T - t)(r + sigma2) /2) + log(S_t/K))/(sigmasqrt(T - t)))**2)/(sqrt(pi)S_tsigmasqrt(T - t)) + erf(0.5 sqrt(2)((T - t)*(r + sigma2/2) + log(S_t/K))/(sigmasqrt(T - t)))/2 + 1/2 + 0.5 sqrt(2)exp(-0.5((T - t)(r + sigma**2/2) + log(S_t/K))2/(sigma2(T - t))) /(sqrt(pi)sigmasqrt(T - t))

Theta -> 更糟糕的混乱 Kr(erf(0.5sqrt(2)(-sigmasqrt(T - t) + ((T - t)(r + sigma2/2) + log(S_t/K))/ (sigmasqrt(T - t))))/2 + 1/2)exp(-r(T - t)) - 0.5sqrt(2)K(-sigma/(2*sqrt( T - t)) + (r + sigma2/2)/(sigmasqrt(T - t)) - ((T - t)(r + sigma2/2) + log(S_t/K) )/(2sigma(T - t)(3/2)))exp(-r(T - t))exp(-0.5(-sigmasqrt(T - t) + ( (T - t)(r + sigma2/2) + log(S_t/K))/(sigmasqrt(T - t)))2)/sqrt(pi) + S_t(0.5) sqrt(2)(r + sigma2/2)/(sigmasqrt(T - t)) - 0.25sqrt(2)((T - t)(r + sigma2/2) + log(S_t/K))/(sigma*(T - t)(3/2)))exp(-0.5((T - t)(r + sigma**2/2) + log( S_t/K))2/(sigma2(T - t)))/sqrt(pi)

Theta -> 更糟糕的是尚未解决 (-piKrsigma(T - t)(9/2)(erf(sqrt(2)(0.5*sigma2*(T - t) - 0.25*(T - t)) (2r + sigma2) - 0.5log(S_t/K))/(sigmasqrt(T - t))) - 1)exp((rsigma2*(T - t)) 2 + 0.125((T - t)(2r + 西格玛**2) + 2log(S_t/K))2 + 0.125(2sigma2*(T - t) ) - (T - t)(2r + sigma2) - 2log(S_t/K))2)/(sigma2(T - t))) + 0.25sqrt(2) sqrt(pi)K(T - t)3(2sigma**2(T - t) - (T - t)(2r + sigma**2) + 2 log(S_t/K))exp((rsigma2*(T - t)2 + 0.125((T - t)(2*r + sigma2) + 2log(S_t) /K))2)/(sigma2(T - t))) + 2sqrt(2)sqrt(pi)S_t(T - t)3(0.125(T - t)(2r + sigma2) - 0.25log(S_t/K))exp((2rsigma2*(T - t)2 + 0.125(2sigma) 2*(T - t) - (T - t)(2r + sigma2) - 2log(S_t/K))2)/(sigma2(T - t)))) exp(-(2rsigma**2(T - t)2 + 0.125((T - t)(2r + sigma**2) + 2log(S_t/K ))2 + 0.125(2sigma2*(T - t) - (T - t)(2r + sigma2) - 2log(S_t/K))2)/ (西格玛2(T - t)))/(2pi西格玛*(T - t)**(9/2))

python-3.x statistics sympy symbolic-math normal-distribution
2个回答
1
投票

尽可能避免使用浮点数,因此最好使用

Normal('N', 0, 1)
,就像我对下面的输出所做的那样。

sympy 中没有用于正态分布 cdf 的 Phi 函数,因为它是用 erf 表示的。不过,您可以定义自己的 Phi 函数:

In [108]: phi = Function('phi')                                                                                                   

In [109]: class Phi(Function): 
     ...:     def _eval_derivative(self, x): 
     ...:         return phi(self.args[0]) * self.args[0].diff(x) 
     ...:                                                                                                                         

In [110]: bs.subs(erf, Lambda(x, 2*Phi(x*sqrt(2))-1))                                                                             
Out[110]: 
     ⎛                        ⎛     2⎞          ⎞                   ⎛        ⎛     2⎞          ⎞
     ⎜                        ⎜    σ ⎟      ⎛Sₜ⎞⎟                   ⎜        ⎜    σ ⎟      ⎛Sₜ⎞⎟
     ⎜                (T - t)⋅⎜r + ──⎟ + log⎜──⎟⎟                   ⎜(T - t)⋅⎜r + ──⎟ + log⎜──⎟⎟
     ⎜      _______           ⎝    2 ⎠      ⎝K ⎠⎟  -r⋅(T - t)       ⎜        ⎝    2 ⎠      ⎝K ⎠⎟
- K⋅Φ⎜- σ⋅╲╱ T - t  + ──────────────────────────⎟⋅ℯ           + Sₜ⋅Φ⎜──────────────────────────⎟
     ⎜                           _______        ⎟                   ⎜           _______        ⎟
     ⎝                       σ⋅╲╱ T - t         ⎠                   ⎝       σ⋅╲╱ T - t         ⎠

In [111]: bs.subs(erf, Lambda(x, 2*Phi(x*sqrt(2))-1)).diff(S)                                                                     
Out[111]: 
     ⎛                        ⎛     2⎞          ⎞                                                ⎛        ⎛     2⎞          ⎞
     ⎜                        ⎜    σ ⎟      ⎛Sₜ⎞⎟                                                ⎜        ⎜    σ ⎟      ⎛Sₜ⎞⎟
     ⎜                (T - t)⋅⎜r + ──⎟ + log⎜──⎟⎟                                                ⎜(T - t)⋅⎜r + ──⎟ + log⎜──⎟⎟
     ⎜      _______           ⎝    2 ⎠      ⎝K ⎠⎟  -r⋅(T - t)    ⎛        ⎛     2⎞          ⎞    ⎜        ⎝    2 ⎠      ⎝K ⎠⎟
  K⋅φ⎜- σ⋅╲╱ T - t  + ──────────────────────────⎟⋅ℯ              ⎜        ⎜    σ ⎟      ⎛Sₜ⎞⎟   φ⎜──────────────────────────⎟
     ⎜                           _______        ⎟                ⎜(T - t)⋅⎜r + ──⎟ + log⎜──⎟⎟    ⎜           _______        ⎟
     ⎝                       σ⋅╲╱ T - t         ⎠                ⎜        ⎝    2 ⎠      ⎝K ⎠⎟    ⎝       σ⋅╲╱ T - t         ⎠
- ─────────────────────────────────────────────────────────── + Φ⎜──────────────────────────⎟ + ─────────────────────────────
                                _______                          ⎜           _______        ⎟                _______         
                         Sₜ⋅σ⋅╲╱ T - t                           ⎝       σ⋅╲╱ T - t         ⎠            σ⋅╲╱ T - t  

0
投票

扩展上述解决方案,对于那些希望进行进一步导数或数值评估的人:

from sympy import diff, Function, sqrt, exp, pi
from sympy.stats import P, Normal, density

class Phi(Function):
    def _eval_derivative(self, x):
        return phi(self.args[0]) * self.args[0].diff(x)
    @classmethod
    def eval(cls, x):
        Z = Normal('Z', 0, 1)
        return P(Z<x)

class phi(Function):
    def _eval_derivative(self, x):
        return diff(
            density(Normal("x", 0, 1))(x),
            x
        )
        # for printing out derivatives without 'erf':
        # comment the one above and uncomment this one
        # return -0.5*sqrt(2)*x*exp(-0.5*x**2)/sqrt(pi)
    @classmethod
    def eval(cls, x):
        return density(Normal("x", 0, 1))(x)
© www.soinside.com 2019 - 2024. All rights reserved.