首页 > 解决方案 > 使用 Python Pandas 计算基础体积 (OBV)

问题描述

我有一个交易 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()

标签: pythonpandasdata-sciencetradingtechnical-indicator

解决方案


推荐阅读