Skip to main content
 首页 » 编程设计

python之计算 Pandas 的中价

2025年05月04日8www_RR

我在 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

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

请您参考如下方法:

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

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

通常,当我需要做类似 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]) 

但在 numpy 和 pandas 中,我们也可以使用 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 的一个小优点是它在传递标量时也能正常工作。

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