2

我正在处理 Pandas 中的盘中时间和报价数据,并努力寻找一种计算加权中间价的好方法。我目前将数据表示为四个数据帧(bid_price、bid_quantity、ask_price、ask_quantity),每个数据帧的列是单独的工具,索引是时间戳。(因此可以将单个投标价格引用为:

bid_price['AAPL'][datetime(2013,1,1,9,30,0,0)]

我希望应用的中点公式取决于工具的买卖差价。如果当前价差大于最小刻度增量,则中点将是当时买入价和卖出价的简单平均值。如果点差等于最小值,则根据买卖数量对中点进行加权。

这是当前代码:

def get_midprice(bid_price, bid_quantity, ask_price, ask_quantity, tick_increment=0.01):
    if (ask_price - bid_price) > tick_increment:
        return (ask_price + bid_price) / 2
    else:
        return ((bid_price * ask_quantity) + (ask_price * bid_quantity)) / (bid_quantity + ask_quantity)

这适用于单个数据点,并且在以前版本的 pandas 上,它在传递 4 个 DataFrame 时也有效。现在,4 个数据帧引发了异常:

raise ValueError("Cannot call bool() on DataFrame.")
ValueError: Cannot call bool() on DataFrame.

我相信这是由于这种变化:https ://github.com/pydata/pandas/pull/1073

这个问题显然可以通过循环来解决,但是在大型数据集上,这非常慢。有没有更好的办法?

4

1 回答 1

1

正如我试图在评论中传达的那样,您无法if按照您尝试的方式对分支进行矢量化,因此虽然代码过去不会引发异常,但几乎可以肯定它没有按照您的意愿进行操作至。这就是为什么arrays(现在DataFrame是 s)在bool()被调用时会出错,以帮助避免这个错误。

解决这个问题的一种方法是一个 apply-elementwise 函数,它DataFrame通过在(有效)压缩的相应元素上应用一个函数来构建一个新函数。可能有一个,虽然我没用过。(我支持添加一个。有时它很方便,在我们自己开发的 n 维 C# 库中,我有一个 apply-to-matched-elements 函数。)

通常当我需要做这样的 pre-pandas 时,我只计算两个分支,然后合并结果(利用 False ~ 0 和 True ~ 1 的事实):

>>> a = np.arange(10)
>>> a > 3
array([False, False, False, False,  True,  True,  True,  True,  True,  True], dtype=bool)
>>> w = a > 3
>>> (a**2) * w + (1000) * (1-w)
array([1000, 1000, 1000, 1000,   16,   25,   36,   49,   64,   81])

但在两者中numpypandas我们也可以使用where,因此您的代码的一个版本是:

def get_midprice(bp, bq, ap, aq, ti):

    above = (ap + bp)/2
    not_above = ((bp*aq) + (ap*bq))/(bq+aq)
    use_above = (ap - bp) > ti

    combined = not_above.where(use_above, above)

    return combined

这种方法的缺点是您必须计算两个分支,并且它使用更多的内存。在实践中它很少给我带来问题,但是 YMMV。请注意,使用乘法的一个小优点(即使它有点慢)而不是where它在传递标量时也可以工作。

最后,您还可以考虑更改格式以将信息保持在一起,可能使用分层多索引,但我没有太多经验。

于 2013-04-18T15:12:30.103 回答