如何使用groupby和apply计算vwap(成交量加权平均价格)?

10

我已经阅读了多篇与我的问题类似的帖子,但我仍然无法弄清楚。我有一个类似以下格式(适用于多个日期)的pandas df:

Out[1]: 
                     price  quantity
time                                
2016-06-08 09:00:22  32.30    1960.0
2016-06-08 09:00:22  32.30     142.0
2016-06-08 09:00:22  32.30    3857.0
2016-06-08 09:00:22  32.30    1000.0
2016-06-08 09:00:22  32.35     991.0
2016-06-08 09:00:22  32.30     447.0
...

为了计算VWAP,我可以这样做:

df['vwap'] = (np.cumsum(df.quantity * df.price) / np.cumsum(df.quantity))

然而,我希望每天重新开始(按组分组),但我不知道如何与 (lambda?) 函数一起使其工作。

df['vwap_day'] = df.groupby(df.index.date)['vwap'].apply(lambda ...

速度至关重要。非常感谢任何帮助:)


1
这不是 VWAP 的正确计算公式。你需要计算典型价格(最高价、最低价和收盘价的平均值)。你的价格数据应该包含这些信息。 - DISC-O
@DISC-O 所以请贡献并添加您的代码答案... - cJc
1
我不确定我理解了,评论是关于计算公式和需要更多数据的(期间的高低,平均值然后进入您的计算); 代码很简单,我假设您知道如何计算3列的平均值。 - DISC-O
2个回答

28

选项0
普通香草方法

def vwap(df):
    q = df.quantity.values
    p = df.price.values
    return df.assign(vwap=(p * q).cumsum() / q.cumsum())

df = df.groupby(df.index.date, group_keys=False).apply(vwap)
df

                     price  quantity       vwap
time                                           
2016-06-08 09:00:22  32.30    1960.0  32.300000
2016-06-08 09:00:22  32.30     142.0  32.300000
2016-06-08 09:00:22  32.30    3857.0  32.300000
2016-06-08 09:00:22  32.30    1000.0  32.300000
2016-06-08 09:00:22  32.35     991.0  32.306233
2016-06-08 09:00:22  32.30     447.0  32.305901

选项1
添加一些eval

df = df.assign(
    vwap=df.eval(
        'wgtd = price * quantity', inplace=False
    ).groupby(df.index.date).cumsum().eval('wgtd / quantity')
)
df

                     price  quantity       vwap
time                                           
2016-06-08 09:00:22  32.30    1960.0  32.300000
2016-06-08 09:00:22  32.30     142.0  32.300000
2016-06-08 09:00:22  32.30    3857.0  32.300000
2016-06-08 09:00:22  32.30    1000.0  32.300000
2016-06-08 09:00:22  32.35     991.0  32.306233
2016-06-08 09:00:22  32.30     447.0  32.305901

2
花式编程综合症 - Ted Petrou
@TedPetrou 有罪 - piRSquared
@piRSquared 当我像上面那样运行选项0时,它可以正常工作。但是我需要在我的df中添加一个新列,所以我执行了df['vwap'] = df.groupby(df.index.date, group_keys=False).apply(vwap)。这会抛出以下错误:ValueError: Wrong number of items passed 7, placement implies 1,为什么会这样? - cJc
我返回的是一个包含该列的新数据框。您想将整个数据框重新分配给df,而不是df ['vwap']。 - piRSquared
啊哈!现在运行得很好,非常感谢。我会坚持选择0选项,因为即使阅读了它,我仍然不清楚eval的真正作用。 - cJc
显示剩余2条评论

8

我以前也用过这种方法,但如果你想限制时间窗口,它的准确性就不太好。相反,我发现 TA python 库非常有效:

https://technical-analysis-library-in-python.readthedocs.io/en/latest/index.html

from ta.volume import VolumeWeightedAveragePrice

# ...
def vwap(dataframe, label='vwap', window=3, fillna=True):
        dataframe[label] = VolumeWeightedAveragePrice(high=dataframe['high'], low=dataframe['low'], close=dataframe["close"], volume=dataframe['volume'], window=window, fillna=fillna).volume_weighted_average_price()
        return dataframe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接