Python与MATLAB计算无穷大的积分与不同的结果,替代(即将高斯 - 勒让德正交扩展到-x->无穷大)?

时间:2016-05-21 03:07:40

标签: python matlab cython numerical-integration quad

我在MATLAB的quadgk和Python的quad例程之间得到不一致的结果,来自(-x或0)的积分 - >无穷。我相信MATLAB版本是正确的(基于将flag参数从1切换到-1的检测),而Python版本给出了错误的结果,在这种情况下为0. MATLAB产生0.1022。 integrands是相同的,我已经将每一步都绑定了,甚至将MATLAB的x生成的quadgk值插入到Python中(这导致Python版本生成与MATLAB,只是将它们传递给integrand函数。此时我正在寻找使用另一个例程而不是SciPy,例如Gauss-Legendre正交https://sourceforge.net/projects/fastgausslegendrequadrature/,但我不知道如何将它从a / b范围扩展到-a>无穷大(I已经看到这些方法只有有限的数字:

https://upload.wikimedia.org/math/a/7/f/ Different intervals for Gauss-Legendre quadrature in numpyb=np.Inf会产生NaN。也不确定如何设置从返回的节点和权重的集成,虽然我一直在阅读转换但仅适用于a和b有限范围:https://pomax.github.io/bezierinfo/legendre-gauss.html要么或者如果有人知道可以处理这个的Python库 - 我真的不喜欢quad没有矢量化的事实,并且可能会在Cython中编写代码,因为我必须快速集成600,000个函数(即链接到上面的C ++库链接)。真正奇怪的是,我已经设法通过在任何地方{= 1}输入任何地方> = 0.39来获得相同的结果,低于Python的结果在0处崩溃。非常令人困惑。任何帮助都表示赞赏,自从微积分以来已有多年......这里是Python代码:

vol

这是MATLAB代码(必须将from scipy.stats import norm, lognorm from scipy.integrate import quad import numpy as np def integrand(x, flag, F, K, vol, T2, T1): d1 = (np.log(x / (x+K)) + 0.5 * (vol**2) * (T2-T1)) / (vol * np.sqrt(T2 - T1)) d2 = d1 - vol*np.sqrt(T2 - T1) mu = np.log(F) - 0.5 *vol **2 * T1 sigma = vol * np.sqrt(T1) value = lognorm.pdf(x, scale=np.exp(mu), s=sigma) * (flag * x*norm.cdf(flag * d1) - flag * (x+K)*norm.cdf(flag * d2)) return value if __name__ == '__main__': flag = 1 F = 54.31 K = 1.1967 vol = 0.1328 T2 = 0.0411 T1 = 0.0137 quad(integrand, 0, np.Inf, args=(flag, F, K, vol, T2, T1), epsabs=1e-12)[0] 保存为.M然后才能在命令窗口中输入脚本):

integrand

%脚本部分

function value = integrand(x, flag, F,K,vol,T2,T1)
d1 = (log(x ./ (x+K)) + 0.5 .* (vol.^2) .* (T2-T1)) ./ (vol .* sqrt(T2 - T1));
d2 = d1 - vol.*sqrt(T2 - T1);
mu = log(F) - 0.5 .*vol .^2 .* T1;
sigma = vol .* sqrt(T1);
value = lognpdf(x, mu, sigma) .* (flag .* x.*normcdf(flag .* d1) - flag .* (x+K).*normcdf(flag .* d2));
end

我应该注意到MATLAB和Python在传递这些输入时使用quad生成相同的结果(在变量上方转换):

flag = 1
F = 54.31
K = 1.1967
vol = 0.1328
T2 = 0.0411
T1 = 0.0137
quadgk(@(x) integrand(x,flag, F, K, vol, T2, T1), 0, Inf, 'AbsTol',1e-12)

1 个答案:

答案 0 :(得分:0)

好的,这很有趣。除非epsabs变量设置得非常高,否则整合就会崩溃。我已经设法使用epsabs=-1e1000在MATLAB和Python之间复制结果。可能很慢,但至少它可以工作。