Pandas 高效的 VWAP 计算
Pandas Efficient VWAP Calculation
我有下面的代码,使用它我可以通过三行 Pandas 代码计算成交量加权平均价格。
import numpy as np
import pandas as pd
from pandas.io.data import DataReader
import datetime as dt
df = DataReader(['AAPL'], 'yahoo', dt.datetime(2013, 12, 30), dt.datetime(2014, 12, 30))
df['Cum_Vol'] = df['Volume'].cumsum()
df['Cum_Vol_Price'] = (df['Volume'] * (df['High'] + df['Low'] + df['Close'] ) /3).cumsum()
df['VWAP'] = df['Cum_Vol_Price'] / df['Cum_Vol']
我正在尝试找到一种无需使用 cumsum()
作为练习来编写此代码的方法。我正在尝试找到一种解决方案,该解决方案一次性提供 VWAP
列。我尝试了下面的行,使用 .apply()
。逻辑在那里,但问题是我无法在第 n 行中存储值以便在第 (n+1) 行中使用。您如何在 pandas
中处理此问题 - 仅使用外部连音符或字典临时存储累积值?
df['Cum_Vol']= np.nan
df['Cum_Vol_Price'] = np.nan
# calculate running cumulatives by apply - assume df row index is 0 to N
df['Cum_Vol'] = df.apply(lambda x: df.iloc[x.name-1]['Cum_Vol'] + x['Volume'] if int(x.name)>0 else x['Volume'], axis=1)
上面的问题有没有一次性解决的方法?
编辑:
我的主要动机是了解幕后发生的事情。所以,它主要是为了锻炼而不是任何正当理由。我相信大小为 N 的 Series 上的每个 cumsum 的时间复杂度为 N(?)。所以我想知道,不是 运行 两个单独的 cumsum,我们能否一次计算两者 - 沿着 this 的路线。很高兴接受对此的回答 - 而不是工作代码。
进入一次通过与一行开始变得有点语义化。区别一下:你可以用 1 行 pandas、1 行 numpy 或几行 numba 来做到这一点。
from numba import jit
df=pd.DataFrame( np.random.randn(10000,3), columns=['v','h','l'] )
df['vwap_pandas'] = (df.v*(df.h+df.l)/2).cumsum() / df.v.cumsum()
@jit
def vwap():
tmp1 = np.zeros_like(v)
tmp2 = np.zeros_like(v)
for i in range(0,len(v)):
tmp1[i] = tmp1[i-1] + v[i] * ( h[i] + l[i] ) / 2.
tmp2[i] = tmp2[i-1] + v[i]
return tmp1 / tmp2
v = df.v.values
h = df.h.values
l = df.l.values
df['vwap_numpy'] = np.cumsum(v*(h+l)/2) / np.cumsum(v)
df['vwap_numba'] = vwap()
时间安排:
%timeit (df.v*(df.h+df.l)/2).cumsum() / df.v.cumsum() # pandas
1000 loops, best of 3: 829 µs per loop
%timeit np.cumsum(v*(h+l)/2) / np.cumsum(v) # numpy
10000 loops, best of 3: 165 µs per loop
%timeit vwap() # numba
10000 loops, best of 3: 87.4 µs per loop
快速编辑:只想感谢 John 的原创 post :)
你可以通过@jit-ing numpy 的版本获得更快的结果:
@jit
def np_vwap():
return np.cumsum(v*(h+l)/2) / np.cumsum(v)
这让我 50.9 µs per loop
而不是 74.5 µs per loop
使用上面的 vwap 版本。
我有下面的代码,使用它我可以通过三行 Pandas 代码计算成交量加权平均价格。
import numpy as np
import pandas as pd
from pandas.io.data import DataReader
import datetime as dt
df = DataReader(['AAPL'], 'yahoo', dt.datetime(2013, 12, 30), dt.datetime(2014, 12, 30))
df['Cum_Vol'] = df['Volume'].cumsum()
df['Cum_Vol_Price'] = (df['Volume'] * (df['High'] + df['Low'] + df['Close'] ) /3).cumsum()
df['VWAP'] = df['Cum_Vol_Price'] / df['Cum_Vol']
我正在尝试找到一种无需使用 cumsum()
作为练习来编写此代码的方法。我正在尝试找到一种解决方案,该解决方案一次性提供 VWAP
列。我尝试了下面的行,使用 .apply()
。逻辑在那里,但问题是我无法在第 n 行中存储值以便在第 (n+1) 行中使用。您如何在 pandas
中处理此问题 - 仅使用外部连音符或字典临时存储累积值?
df['Cum_Vol']= np.nan
df['Cum_Vol_Price'] = np.nan
# calculate running cumulatives by apply - assume df row index is 0 to N
df['Cum_Vol'] = df.apply(lambda x: df.iloc[x.name-1]['Cum_Vol'] + x['Volume'] if int(x.name)>0 else x['Volume'], axis=1)
上面的问题有没有一次性解决的方法?
编辑:
我的主要动机是了解幕后发生的事情。所以,它主要是为了锻炼而不是任何正当理由。我相信大小为 N 的 Series 上的每个 cumsum 的时间复杂度为 N(?)。所以我想知道,不是 运行 两个单独的 cumsum,我们能否一次计算两者 - 沿着 this 的路线。很高兴接受对此的回答 - 而不是工作代码。
进入一次通过与一行开始变得有点语义化。区别一下:你可以用 1 行 pandas、1 行 numpy 或几行 numba 来做到这一点。
from numba import jit
df=pd.DataFrame( np.random.randn(10000,3), columns=['v','h','l'] )
df['vwap_pandas'] = (df.v*(df.h+df.l)/2).cumsum() / df.v.cumsum()
@jit
def vwap():
tmp1 = np.zeros_like(v)
tmp2 = np.zeros_like(v)
for i in range(0,len(v)):
tmp1[i] = tmp1[i-1] + v[i] * ( h[i] + l[i] ) / 2.
tmp2[i] = tmp2[i-1] + v[i]
return tmp1 / tmp2
v = df.v.values
h = df.h.values
l = df.l.values
df['vwap_numpy'] = np.cumsum(v*(h+l)/2) / np.cumsum(v)
df['vwap_numba'] = vwap()
时间安排:
%timeit (df.v*(df.h+df.l)/2).cumsum() / df.v.cumsum() # pandas
1000 loops, best of 3: 829 µs per loop
%timeit np.cumsum(v*(h+l)/2) / np.cumsum(v) # numpy
10000 loops, best of 3: 165 µs per loop
%timeit vwap() # numba
10000 loops, best of 3: 87.4 µs per loop
快速编辑:只想感谢 John 的原创 post :)
你可以通过@jit-ing numpy 的版本获得更快的结果:
@jit
def np_vwap():
return np.cumsum(v*(h+l)/2) / np.cumsum(v)
这让我 50.9 µs per loop
而不是 74.5 µs per loop
使用上面的 vwap 版本。