如何通过Pandas参数配置正确重采样工作日特定时段OHLCV数据?
工作日时段OHLCV序列重采样参数配置方案
我有一组仅包含工作日、每日09:00至17:54的1分钟OHLCV历史数据,需要将其重采样为其他频率。但使用resample或groupby时,部分频率(如'120T')会出现起止时间偏移(比如起始时间变为08:00);调整参数后,日(D)、周(W)、月(M)等频率仍存在日期偏移、NaN值、结果异常问题。请问是否无需手动编写算法,仅通过resample或groupby参数配置即可解决这些问题?
测试代码
数据生成与过滤代码
import pandas as pd import numpy as np # 生成1分钟频率的OHLCV时间序列(1年随机数据,仅用于测试重采样语法) np.random.seed(123) start_datetime = pd.Timestamp('2022-01-02 00:00') end_datetime = pd.Timestamp('2023-01-02 23:59') total_minutes = int((end_datetime - start_datetime).total_seconds() // 60) datetime_range = pd.date_range(start=start_datetime, periods=total_minutes + 1, freq='1min') open_prices = np.random.randint(100, 501, total_minutes + 1) high_prices = np.random.randint(100, 501, total_minutes + 1) low_prices = np.random.randint(100, 501, total_minutes + 1) close_prices = np.random.randint(100, 501, total_minutes + 1) volume = np.random.randint(100, 501, total_minutes + 1) df = pd.DataFrame({ "datetime": datetime_range, "Open": open_prices, "High": high_prices, "Low": low_prices, "Close": close_prices, "Volume": volume }) # 过滤:仅保留工作日 df = df[~df['datetime'].dt.weekday.isin([5, 6])] # 过滤:仅保留营业时间(09:00-17:54) df = df[(df['datetime'].dt.time >= pd.Timestamp('09:00').time()) & (df['datetime'].dt.time <= pd.Timestamp('17:54').time())] # 重置索引 df = df.reset_index(drop=True) display(df.info()) display(df) df.to_csv("df_mytest_resample.csv", index=True, sep=';', decimal=',')
原重采样代码(存在问题)
# 转换时间格式并设置为索引 df['datetime'] = pd.to_datetime(df['datetime'], format='%Y-%m-%d %H:%M') df = df.set_index('datetime') agg_dict = {"Open":"first", "High":"max", "Low":"min", "Close":"last", "Volume":"sum"} df_15T = df.resample('15T', label='right', closed='right', origin='').agg(agg_dict) df_D = df.resample('D', label='right', closed='right', origin='').agg(agg_dict) df_S = df.resample('W', label='right', closed='right', origin='').agg(agg_dict) df_M = df.resample('M', label='right', closed='right', origin='').agg(agg_dict) # 月频率结果异常 display('15分钟分组 - 出现时间偏移', df_15T.tail(30)) display('日分组 - 日期偏移+出现NaN(原数据对应日期有值)', df_D.tail(30)) display('周分组 - OHLCV结果混乱', df_S.tail(30)) display('月分组 - 结果无意义', df_M.tail(30))
参数配置解决方案
核心是通过resample的**origin、label、closed参数**,结合工作日专属频率代码来匹配数据的实际时间范围:
关键参数说明
origin: 指定重采样的起始基准时间,设为数据的第一个有效时间点(如df.index.min()),彻底避免时间偏移。label: 用区间的左端点标记分组(label='left'),符合OHLCV数据常规标注逻辑(比如9:00-9:15的K线标记为9:00)。closed: 区间的右端点关闭(closed='right'),确保每个时段的最后一分钟被包含在当前分组内。- 频率代码替换:用工作日专属频率(
B=工作日、W-FRI=周频以周五结束、BM=月频最后一个工作日)替代通用频率,直接过滤非工作日空值。
修正后的重采样代码
# 转换时间格式并设置为索引 df['datetime'] = pd.to_datetime(df['datetime']) df = df.set_index('datetime') agg_dict = {"Open":"first", "High":"max", "Low":"min", "Close":"last", "Volume":"sum"} # 获取数据的第一个有效时间点作为重采样基准 origin_time = df.index.min() # 15分钟频率:以实际数据起始时间为基准,左标记+右闭合 df_15T = df.resample('15T', label='left', closed='right', origin=origin_time).agg(agg_dict) # 日频率:用工作日频率B,自动过滤非工作日空值 df_D = df.resample('B', label='left', closed='right', origin=origin_time).agg(agg_dict) # 周频率:用W-FRI(周五结束的周),匹配工作日周期 df_W = df.resample('W-FRI', label='left', closed='right', origin=origin_time).agg(agg_dict) # 月频率:用BM(月最后一个工作日),仅保留有效工作日分组 df_M = df.resample('BM', label='left', closed='right', origin=origin_time).agg(agg_dict) # 验证修正结果 display('15分钟分组(修正后)', df_15T.tail(30)) display('工作日分组(修正后)', df_D.tail(30)) display('周分组(周五结束,修正后)', df_W.tail(30)) display('月分组(最后一个工作日,修正后)', df_M.tail(30))
额外说明
- 如果需要严格匹配9:00-17:54的时段边界(避免生成17:54之后的空分组),可以在重采样后添加过滤逻辑:
df_15T = df_15T[df_15T.index.time <= pd.Timestamp('17:54').time()]。 - 对于自定义时段需求,可结合
groupby(pd.Grouper(freq='15T', origin=origin_time))实现,效果与resample一致。
内容的提问来源于stack exchange,提问作者Denier Pardon
相关产品推荐
相关产品推荐

