You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 05:14:58