使用Numpy数组,收到错误

时间:2015-10-12 20:16:13

标签: python arrays numpy numpy-broadcasting

我正在尝试编写为B-S模型计算financial greeks的函数 我从这样的事情开始:

def greeks_vanilla(S, K, r, q, t, T, sigma):
    import numpy as np
    from scipy.stats import norm

    tau = np.linspace(t, T, num = T)
    d1 = ( np.log(S/K) + (r - q + sigma**2 /2)*tau ) / (sigma * np.sqrt(tau))
    d2 = d1 - sigma*np.sqrt(tau)

    delta_call = np.exp(-q*tau) * norm.cdf(d1)
    delta_put = -np.exp(-q*tau) * norm.cdf(-d1)
    ...

    return {'d1':d1, 'd2': d2, 'delta_call': delta_call, 'delta_put': delta_put, ...}

' ...'意味着,有更多的希腊人在计算,但在这里并不重要 它工作正常,我有合理的价值观,漂亮的情节等等;然而,我的老师告诉我,他希望看到的不仅是时间(x轴上的tau),还有S(S - 股票价格,x轴)。换句话说,我必须为tau和S改变计算希腊语。

我试过以下:

def greeks_vanilla(S, K, r, q, t, T, sigma):
    import numpy as np
    from scipy.stats import norm

    S = np.linspace(1, S, num = S)

    tau = np.linspace(t, T, num = T)
    d1 = ( np.log(S/K) + (r - q + sigma**2 /2)*tau ) / (sigma * np.sqrt(tau))
    d2 = d1 - sigma*np.sqrt(tau)

    delta_call = np.exp(-q*tau) * norm.cdf(d1)
    delta_put = -np.exp(-q*tau) * norm.cdf(-d1)
    ...

对于这两个版本,我在params和run(a-variable)之后初始化:

S = 30.0 #Stock price
K = 50.0 #Strike price
r = 0.05 #Risk-free rate
q = 0.01 #also called delta, annual dividend yield
t = 1.0
T = 100.0
sigma = 0.15
a = greeks_vanilla(S, K, r, q, t, T, sigma)

在第一种情况下它工作正常,但是当我想改变S(第二功能)时,我得到以下错误:

     File "greeks.py", line 11, in greeks_vanilla
    d1 = ( np.log(S/K) + (r - q + sigma**2 /2)*tau ) / (sigma * np.sqrt(tau))
ValueError: operands could not be broadcast together with shapes (30,) (100,) 

我google了一下,看起来Numpy库和它的数据类型(数组)有些东西。我不是很熟练或经验丰富的程序员(还在学习),所以我自己无法想象。
看起来现在只能使用S == 100(S = T),但这不是理想的解决方案。
我试过了:

S = list(S)

但它只输出:

File "greeks.py", line 11, in greeks_vanilla
    d1 = ( np.log(S/K) + (r - q + sigma**2 /2)*tau ) / (sigma * np.sqrt(tau))
TypeError: unsupported operand type(s) for /: 'list' and 'float'

请帮我找到解决方法。我不知道我是否应该尝试循环S(我尝试过但失败了......),做一些数据类型技巧,以其他方式计算(如何?)或其他任何东西。

1 个答案:

答案 0 :(得分:1)

根据我的理解,您可以使用1D案例,在np.linspace中评估每个值的函数。现在,您正试图让它在2D中工作,并且仍在使用np.linspace

Numpy想要在元素方面做事。因此,当你给它两个不同大小的linspace时,它不知道如何将元素从一个linspace映射到另一个(s, t)中的元素。但是如果你想想你想要什么,你应该意识到你想要评估s in S t in tau#................... #................... #................... #................... #................... #################### 所有对组合的函数,所有这些对都是2D上的点网格。因此,您要使用的工具是np.meshgrid

以图形方式,你编写它的方式,你只是试图在#s评估你的表达。

tau

这就是numpy抱怨的原因 - 它说我不确定S中的哪个值与tau的值相对应。我想要做的是将S的一个值与len(tau)==len(S)的所有值匹配,或将它们配对,但只有np.meshgrid才能看到。你真正想要的是在网格上的所有点评估你的表达,这就是linspaces允许你做的事情。

Numpy的meshgrid起初可能很难理解如何使用。如果你给它喂两个向量(例如你的def greeks_vanilla(S, K, r, q, t, T, sigma): import numpy as np from scipy.stats import norm v1 = np.linspace(1, S, num = S) v2 = np.linspace(t, T, num = T) S, TAU = np.meshgrid(v1, v2) d1 = ( np.log(S/K) + (r - q + sigma**2 /2)*TAU ) / (sigma * np.sqrt(TAU)) d2 = d1 - sigma*np.sqrt(TAU) delta_call = np.exp(-q*TAU) * norm.cdf(d1) delta_put = -np.exp(-q*TAU) * norm.cdf(-d1) ... ),它将返回两个2D数组,指定这两个向量所跨越的每个网格点的坐标。我想你可能会喜欢这样的事情:

N = 300; % length of the the array
in = [1:1:N]; % index array

delta = 0.5; 
M = 70;
R = N/M;

t(1:M-1) = 1./(in(1:M-1)*M);
t(M) = log(R/delta)/M;
t(M+1:N) = 0;

不再引发错误。