计算熊猫的Midprice

时间:2013-04-18 12:21:52

标签: python 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

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

1 个答案:

答案 0 :(得分:1)

正如我在评论中尝试传达的那样,你无法按照你尝试的方式对if分支进行向量化,因此虽然代码在过去没有引发异常,但几乎可以肯定没有做你想要的。这就是array s(现在DataFrame s)在调用bool()时出错的原因,以帮助避免此错误。

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

通常当我需要做这样的前熊猫之类的事情时,我只是计算了两个分支然后合并了结果(利用了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的一个小优点是它在传递标量时也能正常工作。

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