我有一个交易 Python Pandas DataFrame,其中包括“收盘价”和“成交量”。我想计算平衡量 (OBV)。我已经让它在整个数据集上工作,但我希望它是在 10 的滚动系列上计算的。
当前函数如下所示...
def calculateOnBalanceVolume(df):
df['obv'] = 0
index = 1
while index <= len(df) - 1:
if(df.iloc[index]['close'] > df.iloc[index-1]['close']):
df.at[index, 'obv'] += df.at[index-1, 'obv'] + df.at[index, 'volume']
if(df.iloc[index]['close'] < df.iloc[index-1]['close']):
df.at[index, 'obv'] += df.at[index-1, 'obv'] - df.at[index, 'volume']
index = index + 1
return df
这将创建“obv”列并计算出 300 个条目的 OBV。
理想情况下,我想做这样的事情......
data['obv10'] = data.volume.rolling(10, min_periods=1).apply(calculateOnBalanceVolume)
这看起来有可能起作用,但问题是“应用”仅在“交易量”列中传递,因此您无法计算收盘价的变化。
我也试过这个...
data['obv10'] = data[['close','volume']].rolling(10, min_periods=1).apply(calculateOnBalanceVolume)
哪种有效,但它会尝试更新“关闭”和“音量”列,而不是添加新的“obv10”列。
执行此操作的最佳方法是什么,或者您只需要以 10 个为一组迭代数据吗?
我从这个链接中找到了一种更有效的方法来执行上面的代码: Calculating stock's On Balance Volume (OBV) in python
import numpy as np
def calculateOnBalanceVolume(df):
df['obv'] = np.where(df['close'] > df['close'].shift(1), df['volume'],
np.where(df['close'] < df['close'].shift(1), -df['volume'], 0)).cumsum()
return df
问题是这仍然适用于整个数据集。这看起来不错,但是我怎样才能一次循环 10 个批次而不循环或迭代整个数据集?
*** 更新 ***
我已经稍微接近让这个工作了。我设法以 10 人一组计算了 OBV。
for gid,df in data.groupby(np.arange(len(data)) // 10):
df['obv'] = np.where(df['close'] > df['close'].shift(1), df['volume'],
np.where(df['close'] < df['close'].shift(1), -df['volume'], 0)).cumsum()
我希望这是计算滚动而不是分组。知道如何以有效的方式使用 Pandas 做到这一点吗?
*** 更新 ***
事实证明,应该在整个数据集上计算 OBV。我已经确定了以下现在看起来正确的代码。
# calculate on-balance volume (obv)
self.df['obv'] = np.where(self.df['close'] > self.df['close'].shift(1), self.df['volume'],
np.where(self.df['close'] < self.df['close'].shift(1), -self.df['volume'], self.df.iloc[0]['volume'])).cumsum()