如何使用具有要价和出价的 pandas 数据框计算成交量加权平均价格 (VWAP)?
How to calculate Volume Weighted Average Price (VWAP) using a pandas dataframe with ask and bid price?
如果我的 table 如下所示,我该如何创建另一个名为 vwap 的列来计算 vwap?
time bid_size bid ask ask_size trade trade_size phase
0 2019-01-07 07:45:01.064515 495 152.52 152.54 19 NaN NaN OPEN
1 2019-01-07 07:45:01.110072 31 152.53 152.54 19 NaN NaN OPEN
2 2019-01-07 07:45:01.116596 32 152.53 152.54 19 NaN NaN OPEN
3 2019-01-07 07:45:01.116860 32 152.53 152.54 21 NaN NaN OPEN
4 2019-01-07 07:45:01.116905 34 152.53 152.54 21 NaN NaN OPEN
5 2019-01-07 07:45:01.116982 34 152.53 152.54 31 NaN NaN OPEN
6 2019-01-07 07:45:01.147901 38 152.53 152.54 31 NaN NaN OPEN
7 2019-01-07 07:45:01.189971 38 152.53 152.54 31 ask 15.0 OPEN
8 2019-01-07 07:45:01.189971 38 152.53 152.54 16 NaN NaN OPEN
9 2019-01-07 07:45:01.190766 37 152.53 152.54 16 NaN NaN OPEN
10 2019-01-07 07:45:01.190856 37 152.53 152.54 15 NaN NaN OPEN
11 2019-01-07 07:45:01.190856 37 152.53 152.54 16 ask 1.0 OPEN
12 2019-01-07 07:45:01.193938 37 152.53 152.55 108 NaN NaN OPEN
13 2019-01-07 07:45:01.193938 37 152.53 152.54 15 ask 15.0 OPEN
14 2019-01-07 07:45:01.194326 2 152.54 152.55 108 NaN NaN OPEN
15 2019-01-07 07:45:01.194453 2 152.54 152.55 97 NaN NaN OPEN
16 2019-01-07 07:45:01.194479 6 152.54 152.55 97 NaN NaN OPEN
17 2019-01-07 07:45:01.194507 19 152.54 152.55 97 NaN NaN OPEN
18 2019-01-07 07:45:01.194532 19 152.54 152.55 77 NaN NaN OPEN
19 2019-01-07 07:45:01.194598 19 152.54 152.55 79 NaN NaN OPEN
抱歉,table 看不清楚,最右边的第二列是trade_size,左边是交易,显示交易的方向(买价或卖价)。如果 trade_size 和 trade 都是 NaN,则表明在该时间戳没有交易发生。
如果 df['trade'] == "ask",交易价格将是列 'ask' 中的价格,如果 df['trade] == "bid",交易价格将是列 'bid' 中的价格。由于有2个价格,请问如何计算vwap,df['vwap']?
我的想法是使用np.cumsum()。
这是一种可能的方法
追加 VMAP
列满 NaN
s
df['VMAP'] = np.nan
计算VMAP
(基于 equation ) and assign values based on ask
or bid
,
for trade in ['ask','bid']:
# Find indexes of `ask` or `buy`
bid_idx = df[df.trade==trade].index
# Slice DF based on `ask` or `buy`, using indexes
df.loc[bid_idx, 'VMAP'] = (
(df.loc[bid_idx, 'trade_size'] * df.loc[bid_idx, trade]).cumsum()
/
(df.loc[bid_idx, 'trade_size']).cumsum()
)
print(df.iloc[:,1:])
time bid_size bid ask ask_size trade trade_size phase VMAP
0 07:45:01.064515 495 152.52 152.54 19 NaN NaN OPEN NaN
1 07:45:01.110072 31 152.53 152.54 19 NaN NaN OPEN NaN
2 07:45:01.116596 32 152.53 152.54 19 NaN NaN OPEN NaN
3 07:45:01.116860 32 152.53 152.54 21 NaN NaN OPEN NaN
4 07:45:01.116905 34 152.53 152.54 21 NaN NaN OPEN NaN
5 07:45:01.116982 34 152.53 152.54 31 NaN NaN OPEN NaN
6 07:45:01.147901 38 152.53 152.54 31 NaN NaN OPEN NaN
7 07:45:01.189971 38 152.53 152.54 31 ask 15.0 OPEN 152.54
8 07:45:01.189971 38 152.53 152.54 16 NaN NaN OPEN NaN
9 07:45:01.190766 37 152.53 152.54 16 NaN NaN OPEN NaN
10 07:45:01.190856 37 152.53 152.54 15 NaN NaN OPEN NaN
11 07:45:01.190856 37 152.53 152.54 16 ask 1.0 OPEN 152.54
12 07:45:01.193938 37 152.53 152.55 108 NaN NaN OPEN NaN
13 07:45:01.193938 37 152.53 152.54 15 ask 15.0 OPEN 152.54
14 07:45:01.194326 2 152.54 152.55 108 NaN NaN OPEN NaN
15 07:45:01.194453 2 152.54 152.55 97 NaN NaN OPEN NaN
16 07:45:01.194479 6 152.54 152.55 97 NaN NaN OPEN NaN
17 07:45:01.194507 19 152.54 152.55 97 NaN NaN OPEN NaN
18 07:45:01.194532 19 152.54 152.55 77 NaN NaN OPEN NaN
19 07:45:01.194598 19 152.54 152.55 79 NaN NaN OPEN NaN
编辑
与@edinho
一样,VMAP
与trade_price
列相同。
好的,就在这里
df['trade_price'] = df.apply(lambda x: x['bid'] if x['trade']=='bid' else x['ask'], axis=1)
df['vwap'] = (df['trade_price'] * df['trade_size']).cumsum() / df['trade_size'].fillna(0).cumsum()
第一行:
它将 trade_price 保存在一个新列中,因此以后更容易检索它。
如果你愿意,你可以删除这一行并创建一个函数(也许这样更容易阅读)。不过我更喜欢看中间结果。
Q:为什么没有交易也有价值?
答:因为 lambda 的编写方式。 else
捕获 ask
价格。但这不会有什么不同,因为下一步。
第二行:
真正的计算在这里进行。
第一部分计算直到那一刻的总交易量(如您所说,使用累计总和使生活更轻松)。
第二部分计算直到那一刻的总交易量(同样是累计总和)。
如果你愿意,你可以打破这条线并制作更多的中间列。
问:为什么 fillna(0)
?
A: 所以总体积不会得到 NaNs
并且你不会得到除法错误
问:为什么 vwap
列中有这么多 NaNs
?
A: 因为没有贸易的线路。你可以填写0s
,但最好保留'no trade'信息。
Ps.: 你可能会得到错误的结果,因为它只考虑同一个方向的量价。但是,您可以尝试反转一些信号以按照您预期的方式固定交易量(例如:将 ask
价格更改为负数)。
此代码输出:
trade_price vwap
1 152.54 NaN
2 152.54 NaN
3 152.54 NaN
4 152.54 NaN
5 152.54 NaN
6 152.54 NaN
7 152.54 NaN
8 152.54 152.54
9 152.54 NaN
10 152.54 NaN
11 152.54 NaN
12 152.54 152.54
13 152.55 NaN
14 152.54 152.54
15 152.55 NaN
16 152.55 NaN
17 152.55 NaN
18 152.55 NaN
19 152.55 NaN
20 152.55 NaN
您可以使用 np.where
根据 trade
列中的值从正确的列(bid
或 ask
)中为您提供价格。请注意,这会在没有交易发生时为您提供出价,但因为随后乘以 NaN
交易规模,所以这无关紧要。我也转发了VWAP。
volume = df['trade_size']
price = np.where(df['trade'].eq('ask'), df['ask'], df['bid'])
df = df.assign(VWAP=((volume * price).cumsum() / vol.cumsum()).ffill())
>>> df
time bid_size bid ask ask_size trade trade_size phase VWAP
0 2019-01-07 07:45:01.064515 495 152.52 152.54 19 NaN NaN OPEN NaN
1 2019-01-07 07:45:01.110072 31 152.53 152.54 19 NaN NaN OPEN NaN
2 2019-01-07 07:45:01.116596 32 152.53 152.54 19 NaN NaN OPEN NaN
3 2019-01-07 07:45:01.116860 32 152.53 152.54 21 NaN NaN OPEN NaN
4 2019-01-07 07:45:01.116905 34 152.53 152.54 21 NaN NaN OPEN NaN
5 2019-01-07 07:45:01.116982 34 152.53 152.54 31 NaN NaN OPEN NaN
6 2019-01-07 07:45:01.147901 38 152.53 152.54 31 NaN NaN OPEN NaN
7 2019-01-07 07:45:01.189971 38 152.53 152.54 31 ask 15.0 OPEN 152.54
8 2019-01-07 07:45:01.189971 38 152.53 152.54 16 NaN NaN OPEN 152.54
9 2019-01-07 07:45:01.190766 37 152.53 152.54 16 NaN NaN OPEN 152.54
10 2019-01-07 07:45:01.190856 37 152.53 152.54 15 NaN NaN OPEN 152.54
11 2019-01-07 07:45:01.190856 37 152.53 152.54 16 ask 1.0 OPEN 152.54
12 2019-01-07 07:45:01.193938 37 152.53 152.55 108 NaN NaN OPEN 152.54
13 2019-01-07 07:45:01.193938 37 152.53 152.54 15 ask 15.0 OPEN 152.54
14 2019-01-07 07:45:01.194326 2 152.54 152.55 108 NaN NaN OPEN 152.54
15 2019-01-07 07:45:01.194453 2 152.54 152.55 97 NaN NaN OPEN 152.54
16 2019-01-07 07:45:01.194479 6 152.54 152.55 97 NaN NaN OPEN 152.54
17 2019-01-07 07:45:01.194507 19 152.54 152.55 97 NaN NaN OPEN 152.54
18 2019-01-07 07:45:01.194532 19 152.54 152.55 77 NaN NaN OPEN 152.54
19 2019-01-07 07:45:01.194598 19 152.54 152.55 79 NaN NaN OPEN 152.54
如果我的 table 如下所示,我该如何创建另一个名为 vwap 的列来计算 vwap?
time bid_size bid ask ask_size trade trade_size phase
0 2019-01-07 07:45:01.064515 495 152.52 152.54 19 NaN NaN OPEN
1 2019-01-07 07:45:01.110072 31 152.53 152.54 19 NaN NaN OPEN
2 2019-01-07 07:45:01.116596 32 152.53 152.54 19 NaN NaN OPEN
3 2019-01-07 07:45:01.116860 32 152.53 152.54 21 NaN NaN OPEN
4 2019-01-07 07:45:01.116905 34 152.53 152.54 21 NaN NaN OPEN
5 2019-01-07 07:45:01.116982 34 152.53 152.54 31 NaN NaN OPEN
6 2019-01-07 07:45:01.147901 38 152.53 152.54 31 NaN NaN OPEN
7 2019-01-07 07:45:01.189971 38 152.53 152.54 31 ask 15.0 OPEN
8 2019-01-07 07:45:01.189971 38 152.53 152.54 16 NaN NaN OPEN
9 2019-01-07 07:45:01.190766 37 152.53 152.54 16 NaN NaN OPEN
10 2019-01-07 07:45:01.190856 37 152.53 152.54 15 NaN NaN OPEN
11 2019-01-07 07:45:01.190856 37 152.53 152.54 16 ask 1.0 OPEN
12 2019-01-07 07:45:01.193938 37 152.53 152.55 108 NaN NaN OPEN
13 2019-01-07 07:45:01.193938 37 152.53 152.54 15 ask 15.0 OPEN
14 2019-01-07 07:45:01.194326 2 152.54 152.55 108 NaN NaN OPEN
15 2019-01-07 07:45:01.194453 2 152.54 152.55 97 NaN NaN OPEN
16 2019-01-07 07:45:01.194479 6 152.54 152.55 97 NaN NaN OPEN
17 2019-01-07 07:45:01.194507 19 152.54 152.55 97 NaN NaN OPEN
18 2019-01-07 07:45:01.194532 19 152.54 152.55 77 NaN NaN OPEN
19 2019-01-07 07:45:01.194598 19 152.54 152.55 79 NaN NaN OPEN
抱歉,table 看不清楚,最右边的第二列是trade_size,左边是交易,显示交易的方向(买价或卖价)。如果 trade_size 和 trade 都是 NaN,则表明在该时间戳没有交易发生。
如果 df['trade'] == "ask",交易价格将是列 'ask' 中的价格,如果 df['trade] == "bid",交易价格将是列 'bid' 中的价格。由于有2个价格,请问如何计算vwap,df['vwap']?
我的想法是使用np.cumsum()。
这是一种可能的方法
追加 VMAP
列满 NaN
s
df['VMAP'] = np.nan
计算VMAP
(基于ask
or bid
,
for trade in ['ask','bid']:
# Find indexes of `ask` or `buy`
bid_idx = df[df.trade==trade].index
# Slice DF based on `ask` or `buy`, using indexes
df.loc[bid_idx, 'VMAP'] = (
(df.loc[bid_idx, 'trade_size'] * df.loc[bid_idx, trade]).cumsum()
/
(df.loc[bid_idx, 'trade_size']).cumsum()
)
print(df.iloc[:,1:])
time bid_size bid ask ask_size trade trade_size phase VMAP
0 07:45:01.064515 495 152.52 152.54 19 NaN NaN OPEN NaN
1 07:45:01.110072 31 152.53 152.54 19 NaN NaN OPEN NaN
2 07:45:01.116596 32 152.53 152.54 19 NaN NaN OPEN NaN
3 07:45:01.116860 32 152.53 152.54 21 NaN NaN OPEN NaN
4 07:45:01.116905 34 152.53 152.54 21 NaN NaN OPEN NaN
5 07:45:01.116982 34 152.53 152.54 31 NaN NaN OPEN NaN
6 07:45:01.147901 38 152.53 152.54 31 NaN NaN OPEN NaN
7 07:45:01.189971 38 152.53 152.54 31 ask 15.0 OPEN 152.54
8 07:45:01.189971 38 152.53 152.54 16 NaN NaN OPEN NaN
9 07:45:01.190766 37 152.53 152.54 16 NaN NaN OPEN NaN
10 07:45:01.190856 37 152.53 152.54 15 NaN NaN OPEN NaN
11 07:45:01.190856 37 152.53 152.54 16 ask 1.0 OPEN 152.54
12 07:45:01.193938 37 152.53 152.55 108 NaN NaN OPEN NaN
13 07:45:01.193938 37 152.53 152.54 15 ask 15.0 OPEN 152.54
14 07:45:01.194326 2 152.54 152.55 108 NaN NaN OPEN NaN
15 07:45:01.194453 2 152.54 152.55 97 NaN NaN OPEN NaN
16 07:45:01.194479 6 152.54 152.55 97 NaN NaN OPEN NaN
17 07:45:01.194507 19 152.54 152.55 97 NaN NaN OPEN NaN
18 07:45:01.194532 19 152.54 152.55 77 NaN NaN OPEN NaN
19 07:45:01.194598 19 152.54 152.55 79 NaN NaN OPEN NaN
编辑
与@edinho
VMAP
与trade_price
列相同。
好的,就在这里
df['trade_price'] = df.apply(lambda x: x['bid'] if x['trade']=='bid' else x['ask'], axis=1)
df['vwap'] = (df['trade_price'] * df['trade_size']).cumsum() / df['trade_size'].fillna(0).cumsum()
第一行:
它将 trade_price 保存在一个新列中,因此以后更容易检索它。
如果你愿意,你可以删除这一行并创建一个函数(也许这样更容易阅读)。不过我更喜欢看中间结果。
Q:为什么没有交易也有价值?
答:因为 lambda 的编写方式。 else
捕获 ask
价格。但这不会有什么不同,因为下一步。
第二行:
真正的计算在这里进行。
第一部分计算直到那一刻的总交易量(如您所说,使用累计总和使生活更轻松)。
第二部分计算直到那一刻的总交易量(同样是累计总和)。
如果你愿意,你可以打破这条线并制作更多的中间列。
问:为什么 fillna(0)
?
A: 所以总体积不会得到 NaNs
并且你不会得到除法错误
问:为什么 vwap
列中有这么多 NaNs
?
A: 因为没有贸易的线路。你可以填写0s
,但最好保留'no trade'信息。
Ps.: 你可能会得到错误的结果,因为它只考虑同一个方向的量价。但是,您可以尝试反转一些信号以按照您预期的方式固定交易量(例如:将 ask
价格更改为负数)。
此代码输出:
trade_price vwap
1 152.54 NaN
2 152.54 NaN
3 152.54 NaN
4 152.54 NaN
5 152.54 NaN
6 152.54 NaN
7 152.54 NaN
8 152.54 152.54
9 152.54 NaN
10 152.54 NaN
11 152.54 NaN
12 152.54 152.54
13 152.55 NaN
14 152.54 152.54
15 152.55 NaN
16 152.55 NaN
17 152.55 NaN
18 152.55 NaN
19 152.55 NaN
20 152.55 NaN
您可以使用 np.where
根据 trade
列中的值从正确的列(bid
或 ask
)中为您提供价格。请注意,这会在没有交易发生时为您提供出价,但因为随后乘以 NaN
交易规模,所以这无关紧要。我也转发了VWAP。
volume = df['trade_size']
price = np.where(df['trade'].eq('ask'), df['ask'], df['bid'])
df = df.assign(VWAP=((volume * price).cumsum() / vol.cumsum()).ffill())
>>> df
time bid_size bid ask ask_size trade trade_size phase VWAP
0 2019-01-07 07:45:01.064515 495 152.52 152.54 19 NaN NaN OPEN NaN
1 2019-01-07 07:45:01.110072 31 152.53 152.54 19 NaN NaN OPEN NaN
2 2019-01-07 07:45:01.116596 32 152.53 152.54 19 NaN NaN OPEN NaN
3 2019-01-07 07:45:01.116860 32 152.53 152.54 21 NaN NaN OPEN NaN
4 2019-01-07 07:45:01.116905 34 152.53 152.54 21 NaN NaN OPEN NaN
5 2019-01-07 07:45:01.116982 34 152.53 152.54 31 NaN NaN OPEN NaN
6 2019-01-07 07:45:01.147901 38 152.53 152.54 31 NaN NaN OPEN NaN
7 2019-01-07 07:45:01.189971 38 152.53 152.54 31 ask 15.0 OPEN 152.54
8 2019-01-07 07:45:01.189971 38 152.53 152.54 16 NaN NaN OPEN 152.54
9 2019-01-07 07:45:01.190766 37 152.53 152.54 16 NaN NaN OPEN 152.54
10 2019-01-07 07:45:01.190856 37 152.53 152.54 15 NaN NaN OPEN 152.54
11 2019-01-07 07:45:01.190856 37 152.53 152.54 16 ask 1.0 OPEN 152.54
12 2019-01-07 07:45:01.193938 37 152.53 152.55 108 NaN NaN OPEN 152.54
13 2019-01-07 07:45:01.193938 37 152.53 152.54 15 ask 15.0 OPEN 152.54
14 2019-01-07 07:45:01.194326 2 152.54 152.55 108 NaN NaN OPEN 152.54
15 2019-01-07 07:45:01.194453 2 152.54 152.55 97 NaN NaN OPEN 152.54
16 2019-01-07 07:45:01.194479 6 152.54 152.55 97 NaN NaN OPEN 152.54
17 2019-01-07 07:45:01.194507 19 152.54 152.55 97 NaN NaN OPEN 152.54
18 2019-01-07 07:45:01.194532 19 152.54 152.55 77 NaN NaN OPEN 152.54
19 2019-01-07 07:45:01.194598 19 152.54 152.55 79 NaN NaN OPEN 152.54