【问题标题】:calling function with dataframe data gives error (cannot convert the series to <class 'float'>)使用数据帧数据调用函数会出错(无法将系列转换为 <class 'float'>)
【发布时间】:2015-06-14 11:18:11
【问题描述】:

我有一个期权定价模型(非常简单的 Black Scholes),可以很好地以这种方式处理数据:

In [18]:
BS2(100.,100.,1.,.001,.3)

Out[18]:
11.96762435837207

函数在这里:

Black Sholes Function

def BS2(S,X,T,r,v):
    d1 = (log(S/X)+(.001+v*v/2)*T)/(v*sqrt(T))
    d2 = d1-v*sqrt(T)
    return (S*CND(d1)-X*exp(-.001*T)*CND(d2))

我认为这个问题并不重要,但 BS2 称之为:

Cumulative normal distribution function

def CND(X):
    (a1,a2,a3,a4,a5) = (0.31938153, -0.356563782, 1.781477937, 
     -1.821255978, 1.330274429)
    L = abs(X)
    K = 1.0 / (1.0 + 0.2316419 * L)
    w = 1.0 - 1.0 / sqrt(2*pi)*exp(-L*L/2.) * (a1*K + a2*K*K + a3*pow(K,3) +
    a4*pow(K,4) + a5*pow(K,5))
    if X<0:
        w = 1.0-w
    return w

我试图修改有效的 BS 函数以接受来自 df 的数据,但似乎做错了什么:

def BS(df):
    d1 = (log(S/X)+(.001+v*v/2)*T)/(v*sqrt(T))
    d2 = d1-v*sqrt(T)
    return pd.Series((S*CND(d1)-X*exp(-.001*T)*CND(d2)))

我的数据非常简单:

In [13]:
df

Out[13]:
    S    X   T    r    v
0  100  100  1  0.001  0.3
1   50   50  1  0.001  0.3

都是float64

In [14]:

df.dtypes
Out[14]:
S    float64
X    float64
T    float64
r    float64
v    float64
dtype: object

我还尝试在发送到 BS2 之前将 df 变量分配给一个名称(我这样做了,但没有这个分配:

S=df['S']
X=df['X']
T=df['T']
r=df['r']
v=df['v']

冒着发送过多信息的风险,这里是错误消息:

In [18]:

BS(df)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-18-745e7dd0eb2c> in <module>()
----> 1 BS(df)

<ipython-input-17-b666a39cd530> in BS(df)
  3 def BS(df):
  4     CallPutFlag='c'
----> 5     d1 = (log(S/X)+(.001+v*v/2)*T)/(v*sqrt(T))
  6     d2 = d1-v*sqrt(T)
  7     cp = ((S*CND(d1)-X*exp(-.001*T)*CND(d2)))

C:\Users\camcompco\AppData\Roaming\Python\Python34\site-   packages\pandas\core\series.py in wrapper(self)
 74             return converter(self.iloc[0])
 75         raise TypeError(
---> 76             "cannot convert the series to {0}".format(str(converter)))
 77     return wrapper
 78 

TypeError: cannot convert the series to <class 'float'>

任何帮助将不胜感激。

约翰

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    我认为使用 dataframe.apply() 会更容易

    http://pandas.pydata.org/pandas-docs/dev/generated/pandas.DataFrame.apply.html

    那么语法将是 df.apply(func, axis = 1) 以将函数 func 应用于每一行。

    这个问题的答案类似:

    Apply function to each row of pandas dataframe to create two new columns

    【讨论】:

    • 您好 JohnE,虽然我认为在这个特定实例中的速度不会成为问题,但当我查看回溯测试算法时,我确实看到未来需要更高效的代码。你介意通过一个简单的例子详细说明你的意思吗?同样,JonD 提供的方法现在很好,只是想知道“知识”。谢谢你们俩
    • 不错的答案,我投了赞成票,但有一个快速警告:这在较大的数据集上可能会很慢。一种更难(但更有效)的方法是对函数进行矢量化。 @John 我添加了一个明确显示这一点的答案。
    【解决方案2】:

    @JonD 的答案很好,但如果您的数据框有超过几行,这里有一个替代答案会更快:

    from scipy.stats import norm
    
    def BS2(df):
        d1 = (np.log(df.S/df.X)+(.001+df.v*df.v/2)*df['T'])/(df.v*np.sqrt(df['T']))
        d2 = d1-df.v*np.sqrt(df['T'])
        return (df.S*norm.cdf(d1)-df.X*np.exp(-.001*df['T'])*norm.cdf(d2))
    

    变化:

    1. 重点是对函数进行矢量化。语法方面的主要变化是显式使用 sqrtlogexp 的 numpy 版本。否则,您无需进行太多更改,因为 numpy/pandas 以元素方式支持基本的数学运算。
    2. 用来自 scipy 的 norm.cdf 替换了用户编写的 CND。更快的 b/c 内置函数几乎总是尽可能快。
    3. 这是次要的,但我在df.X 和其他人上使用了快捷符号,但df['T'] 需要写出,因为df.T 将被解释为df.transpose()。我想这是一个很好的例子,说明为什么你应该避免使用快捷方式但我很懒...

    顺便说一句,如果您想要更快的速度,接下来要尝试的是使用 numpy 而不是 pandas。您还可以检查其他人是否已经编写了 Black-Scholes 函数/库(可能,尽管我对此一无所知)。

    【讨论】:

    • 刚刚将代码更改为您的建议,就像一个魅力!
    猜你喜欢
    • 1970-01-01
    • 2017-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-12
    • 1970-01-01
    相关资源
    最近更新 更多