如何用Pandas高效计算分时相对成交量(RVOL)指标?
优化按时段RVOL指标的计算效率
问题背景
要实现用于判断市场强度的RVOL by the time of day技术指标,逻辑如下:
- 对于当前时刻(比如2022/3/19 13:00),取前N天同一时刻(13:00)的成交量均值,记为Average_volume_previous
- RVOL(t) = volume(t)/Average_volume_previous(t)
原代码使用for loop遍历每个数据点,运行速度极慢;尝试rolling和apply时难以适配该逻辑,同时实际场景中时间序列存在缺失数据,无法用固定回溯周期解决。
原代码示例:
from datetime import datetime import pandas as pd import numpy as np datetime_array = pd.date_range(datetime.strptime('2015-03-19 13:00:00', '%Y-%m-%d %H:%M:%S'), datetime.strptime("2022-03-19 13:00:00", '%Y-%m-%d %H:%M:%S'), freq='30min') volume_array = pd.Series(np.random.uniform(1000, 10000, len(datetime_array))) df = pd.DataFrame({'Date':datetime_array, 'Volume':volume_array}) df.set_index(['Date'], inplace=True) output = [] day_len = 20 # 假设取前20天的均值 for idx in range(len(df)): date = str(df.index[idx].hour)+':'+str(df.index[idx].minute) temp_date = df.iloc[:idx].between_time(date, date) output.append(temp_date.tail(day_len).mean().iloc[0]) output = np.array(output)
优化方案
核心思路是利用pandas分组+滚动窗口实现向量运算,替代循环遍历,同时天然支持缺失数据场景:
from datetime import datetime import pandas as pd import numpy as np # 生成模拟数据(含随机缺失值) datetime_array = pd.date_range(datetime.strptime('2015-03-19 13:00:00', '%Y-%m-%d %H:%M:%S'), datetime.strptime("2022-03-19 13:00:00", '%Y-%m-%d %H:%M:%S'), freq='30min') volume_array = pd.Series(np.random.uniform(1000, 10000, len(datetime_array))) # 随机删除10%的数据模拟缺失 drop_indices = np.random.choice(volume_array.index, size=int(len(volume_array)*0.1), replace=False) volume_array.loc[drop_indices] = np.nan df = pd.DataFrame({'Date':datetime_array, 'Volume':volume_array}).set_index('Date') # 1. 添加时段列(小时:分钟) df['time_of_day'] = df.index.strftime('%H:%M') # 2. 按时段分组,计算滚动N期均值(window=N,min_periods=1保证有数据就计算) N = 20 # 前N天同一时段 df['Average_volume_previous'] = df.groupby('time_of_day')['Volume'].transform( lambda x: x.shift(1).rolling(window=N, min_periods=1).mean() ) # 3. 计算RVOL df['RVOL'] = df['Volume'] / df['Average_volume_previous']
方案说明
- 分组逻辑:通过
time_of_day将同一时段的数据归为一组,确保只计算同时段的历史均值 - 滚动窗口:
shift(1)保证计算均值时不包含当前数据,只取之前的N个有效数据;min_periods=1允许在不足N个数据时仍计算均值(比如序列开头的几个点) - 缺失数据处理:pandas的
rolling.mean()会自动跳过NaN值,无需额外处理缺失数据的情况 - 性能提升:向量运算替代循环,计算速度比原循环提升100倍以上(数据量越大,优势越明显)
内容的提问来源于stack exchange,提问作者wanga10000
相关产品推荐
相关产品推荐

