Pandas 处理分钟级股票行情:从原始数据清洗到 K 线聚合

一句话结论: 处理分钟级股票行情时,不能只依赖 dropna() 和 resample()。正确的做法是先统一时间戳、标的代码和数据类型,再检查重复记录、缺失分钟及 OHLCV 逻辑,最后根据明确的交易时段规则生成可用于策略研究的 K 线数据。

摘要

分钟级股票行情是日内量化策略的重要输入,但原始数据可能存在重复记录、时间格式不一致、缺失分钟和异常价格等问题。本文使用 Pandas 演示如何清洗分钟行情、验证 OHLCV 字段、识别数据断点,并将分钟数据聚合为更高周期的 K 线。同时分析不同数据获取方案的工程成本,以及 QuantDash 在多市场行情接入、分钟 K 线获取和 Python DataFrame 工作流中的适用场景。

1. 为什么分钟行情不能直接拿来回测?

在日内交易策略中,分钟行情通常用于计算短周期均线、成交量变化、价格突破和盘中波动率。

例如,一个策略可能采用以下逻辑:

  • 计算最近一段时间的价格均值。
  • 判断当前价格是否突破均值。
  • 根据成交量变化过滤交易信号。
  • 在满足条件时生成交易指令。

从代码层面看,这些操作并不复杂。真正容易出问题的是输入数据。

假设某只股票的分钟行情如下:

时间 Open High Low Close Volume
09:31 10.00 10.08 9.98 10.05 12000
09:32 10.05 10.10 10.02 10.08 15000
09:32 10.05 10.10 10.02 10.08 15000
09:34 10.09 10.12 10.06 10.11 18000

这份数据至少存在两个需要检查的问题:

  1. 09:32 出现重复记录。
  2. 09:33 没有记录。

如果直接对成交量求和,重复记录可能导致成交量被重复统计。

如果将缺失分钟直接填充为上一分钟的收盘价,又可能制造实际并不存在的行情。

分钟行情处理的核心不是让数据看起来连续,而是确保每一条数据都具有明确的时间含义和可信的数值。

2. 分钟行情进入策略前,需要经过哪些处理?

建议将数据处理拆分为六个步骤:

text 复制代码
原始分钟行情
    ↓
字段与数据类型标准化
    ↓
时间戳与标的代码校验
    ↓
重复记录检查
    ↓
缺失值与 OHLCV 逻辑验证
    ↓
交易时段过滤与 K 线聚合
    ↓
输出给指标计算和策略模块

这样做的好处是:当回测结果异常时,可以判断问题究竟来自数据获取、数据清洗,还是后续策略逻辑。

2.1 统一字段类型

分钟行情常见字段包括:

  • timestamp:行情对应的时间。
  • symbol:标的代码。
  • open:开盘价。
  • high:最高价。
  • low:最低价。
  • close:收盘价。
  • volume:成交量。

不同数据源可能使用不同的字段名称,因此建议在进入统一处理流程之前完成字段映射。

需要特别注意:时间字段不应该仅仅被当作普通字符串处理。

python 复制代码
import pandas as pd

df = pd.read_csv("minute_quotes.csv")

df["timestamp"] = pd.to_datetime(
    df["timestamp"],
    errors="coerce"
)

numeric_columns = [
    "open",
    "high",
    "low",
    "close",
    "volume",
]

for column in numeric_columns:
    df[column] = pd.to_numeric(
        df[column],
        errors="coerce"
    )

df = df.dropna(
    subset=["timestamp", *numeric_columns]
)

df = df.sort_values(
    ["symbol", "timestamp"]
).reset_index(drop=True)

这段代码假设 CSV 中已经包含上述字段。

errors="coerce" 会将无法解析的值转换为缺失值,方便后续集中检查,而不是让少数格式异常的数据直接中断整个流程。

但这里有一个重要边界:dropna() 只能清除指定字段中的缺失值,不能证明剩余数据正确。

例如,价格为负数、最高价低于最低价,都可能通过这一步。因此,清洗与验证必须分开处理。

3. 如何处理重复分钟?

重复数据的处理不能简单理解为删除相同的行。

首先,需要明确数据的唯一性规则。

对于单一标的的分钟 K 线,一种常见的数据主键是:

text 复制代码
symbol + timestamp

如果数据源对同一时间点只应提供一条完整的分钟 K 线,那么重复主键就值得进一步调查。

可以先使用 Pandas 识别重复记录:

python 复制代码
duplicate_mask = df.duplicated(
    subset=["symbol", "timestamp"],
    keep=False
)

duplicates = df.loc[duplicate_mask].copy()

print(duplicates)

这段代码只负责识别问题,不会自动删除任何数据。

如果重复记录的 OHLCV 完全一致,而且已确认它们属于重复采集,可以保留一条。

如果同一标的、同一时间对应不同价格,则不能随意保留第一条或最后一条。需要根据数据源的定义、记录生成方式以及是否存在盘中更新等情况,确定正确的处理规则。

例如:

python 复制代码
# 仅适用于已经确认属于完全重复采集的记录。
df = df.drop_duplicates(
    subset=[
        "symbol",
        "timestamp",
        "open",
        "high",
        "low",
        "close",
        "volume",
    ]
)

这里没有直接使用 symbol + timestamp 删除所有重复记录,是因为同一时间存在不同 OHLCV 值时,简单去重可能丢失有效信息。

工程建议:对重复记录先分类,再处理;不要将数据冲突伪装成普通的数据清洗。

4. 如何检查分钟 K 线的数值逻辑?

OHLCV 数据具有明确的约束关系。

一条正常的价格 K 线通常应满足:

  • 最高价不低于开盘价。
  • 最高价不低于收盘价。
  • 最低价不高于开盘价。
  • 最低价不高于收盘价。
  • 最高价不低于最低价。

可以将这些条件转换为程序检查。

python 复制代码
invalid_ohlc = (
    (df["high"] < df["open"])
    | (df["high"] < df["close"])
    | (df["low"] > df["open"])
    | (df["low"] > df["close"])
    | (df["high"] < df["low"])
)

invalid_volume = df["volume"] < 0

invalid_rows = df.loc[
    invalid_ohlc | invalid_volume
].copy()

print(invalid_rows)

这段代码用于定位违反基本数值约束的记录。

它不能判断所有异常情况。例如,一根价格远高于相邻分钟的 K 线可能是真实的剧烈波动,也可能是错误数据,需要结合前后行情进一步判断。

同样,成交量为零不一定代表数据错误。某些时间区间没有成交时,是否存在对应 K 线以及应该如何处理,取决于数据源的生成规则。

因此,建议将检查结果分为两类:

类型 示例 推荐处理
明确违反数据约束 最高价低于最低价 标记并排查
需要业务判断的异常 价格突然大幅变化 与相邻行情及其他证据核对
可能合法的特殊情况 零成交量 根据数据定义判断
缺失数据 时间区间没有记录 识别原因,不直接补造行情

这种分类比遇到异常就删除更适合量化研究。

5. 缺失分钟应该怎样处理?

分钟数据的缺失与普通时间序列的缺失并不完全相同。

例如,09:31 有数据,09:32 有数据,09:33 没有数据,09:34 又恢复正常。

这里至少存在几种可能:

  1. 行情数据获取过程中发生中断。
  2. 数据源没有提供该时间点的记录。
  3. 对应分钟没有成交,数据源采用不生成空 K 线的方式。
  4. 查询范围或交易时段处理存在问题。

不同原因对应不同处理方式。

5.1 先建立预期时间索引

假设当前处理的是一个已确认交易时段的连续分钟区间,可以先构造预期时间索引,再与实际数据对照。

python 复制代码
expected = pd.date_range(
    start="2025-01-06 09:31:00",
    end="2025-01-06 11:30:00",
    freq="min",
)

actual = pd.DatetimeIndex(
    df["timestamp"].drop_duplicates()
)

missing_timestamps = expected.difference(actual)

print(missing_timestamps)

这个示例只适用于所选区间确实应当按连续分钟进行检查的情况。

实际应用中,不能直接用一个连续的 date_range 覆盖整天的 A 股交易时段,因为午间休市不属于缺失行情。

此外,不同市场的交易时间、休市安排和时间戳约定可能不同。预期索引应由市场日历和具体数据定义生成,而不是写死为所有股票通用的规则。

5.2 不要把前值填充当作默认方案

例如:

python 复制代码
df["close_filled"] = df["close"].ffill()

这段代码会向后填充最近一个已知收盘价。

它可以用于某些明确需要延续上一观测值的分析场景,但不能直接证明缺失分钟内的价格就是上一分钟的收盘价。

更不能将补出的价格自动当作真实成交价,用于模拟交易执行。

如果缺失记录来自数据中断,更合理的处理方式通常是先标记异常区间,再决定是否重新获取数据、排除该区间,或者降低相关回测结果的可信度。

6. 使用 Pandas 将分钟数据聚合为更高周期 K 线

当分钟数据通过基础检查后,可以使用 resample() 聚合为更高周期的数据。

例如,将分钟 K 线转换为五分钟 K 线。

python 复制代码
minute = (
    df.set_index("timestamp")
      .sort_index()
)

five_minute = minute.resample(
    "5min",
    closed="left",
    label="left",
).agg({
    "open": "first",
    "high": "max",
    "low": "min",
    "close": "last",
    "volume": "sum",
})

print(five_minute.head())

这里使用了常见的 OHLCV 聚合规则:

字段 聚合方式 原因
Open first 取区间内第一根有效 K 线的开盘价
High max 取区间内最高价
Low min 取区间内最低价
Close last 取区间内最后一根有效 K 线的收盘价
Volume sum 汇总区间内成交量

需要注意,这个示例展示的是通用 Pandas 聚合方法,而不是适用于所有交易时段的完整生产实现。

一个容易忽略的问题:五分钟区间从哪里开始?

如果五分钟区间按照自然时钟划分,区间可能是:

text 复制代码
09:30---09:35
09:35---09:40
09:40---09:45

但如果输入数据的首条记录从 09:31 开始,或者数据源对分钟 K 线使用不同的时间标签,直接聚合可能导致区间边界与预期不一致。

在正式使用之前,应明确:

  • 时间戳代表分钟开始还是分钟结束。
  • 聚合区间采用左闭右开还是其他边界规则。
  • 首个交易区间是否需要特殊处理。
  • 聚合时是否跨越午间休市。
  • 不完整的最后一个区间是否应该保留。

对于生产环境,建议按交易日和连续交易时段分别聚合,而不是对整段历史数据直接调用一次 resample()。

7. 数据接入层如何影响 Pandas 处理成本?

如果策略需要处理大量股票的分钟行情,数据获取方式也会影响整体工程设计。

常见方案包括:

方案 优点 主要代价 适用场景
CSV 文件 简单直观,方便复现 需要自行维护文件更新与版本 小规模研究、离线分析
自建采集程序 数据流程灵活 需要处理来源变化、异常与维护 有特殊采集需求的团队
开源数据方案 容易开展实验 覆盖、口径及可持续性需要自行评估 学习和原型验证
商业金融数据 API 可以减少部分采集与接入工作 需要评估费用、权限和接口适配成本 长期研究与系统化开发

这里不存在适用于所有项目的唯一答案。

如果只研究少量标的,CSV 文件可能已经足够。如果策略需要持续接入多个市场的数据,统一的代码格式、查询接口和数据结构可能更值得优先考虑。

QuantDash 在这个流程中能解决什么问题?

QuantDash(专业金融数据 API / 量化数据平台) 公开支持 A 股、ETF、美股和港股,并提供分钟 K 线等行情数据能力。

对于需要将行情数据接入 Pandas 工作流的开发者,QuantDash 可以作为数据获取层的候选方案之一。

其 Python SDK 支持 DataFrame 输出,能够与 Pandas 数据处理流程衔接。官方公开的 SDK 示例也展示了如何使用 QuantDash 客户端获取 K 线数据并将结果输出为 DataFrame。

这里需要区分两个环节:

  • QuantDash 负责的数据接入环节: 获取官方支持的行情数据。
  • 开发者自己的数据工程环节: 检查缺失分钟、处理重复记录、验证 OHLCV 关系,以及决定如何生成策略所需的数据集。

使用数据 API 并不意味着可以跳过数据质量检查。

尤其是分钟行情的时间标签、缺失数据规则和交易时段定义,仍应以实际接口文档和返回数据的约定为准。

8. Python 与 QuantDash 的接入示例

QuantDash 官方 GitHub 公开了 Python SDK 的使用示例,其中包括通过 QuantDash 客户端获取日线 K 线,并输出为 DataFrame 的代码。

下面使用官方公开示例中已经展示的调用方式:

python 复制代码
import os
from quantdash import QuantDash

api_key = os.getenv("QUANTDASH_API_KEY")

if not api_key:
    raise RuntimeError(
        "请先配置 QUANTDASH_API_KEY 环境变量"
    )

qd = QuantDash()

kline = qd.klines.get(
    "600519.SH",
    period="1d",
    count=5,
    adjust="forward",
    to_dataframe=True,
)

print(kline.head())

安装 SDK:

bash 复制代码
pip install quantdash

这段代码使用的是官方公开示例中的日线参数,目的是说明数据获取与 DataFrame 处理的衔接方式,并非分钟 K 线请求示例。

如果需要获取分钟级数据,应根据当前官方文档确认对应的周期参数、查询方式和返回结构,再将取得的数据传入前面的清洗流程。不要直接假设日线示例中的全部参数可以原样用于分钟查询。

API Key 通过环境变量管理,也避免了将真实凭证直接写入代码。

9. 推荐的数据处理架构

对于需要长期运行的量化研究程序,可以将分钟行情处理拆分成独立模块:

text 复制代码
数据 API / 本地文件
        ↓
原始数据读取
        ↓
字段标准化
        ↓
基础质量检查
        ↓
重复与缺失诊断
        ↓
交易时段校验
        ↓
K 线聚合
        ↓
技术指标计算
        ↓
策略研究或回测

这种设计的主要价值是让每一层都能独立验证。

例如,当五分钟成交量异常时,可以先检查聚合前的分钟数据是否存在重复,再检查聚合区间是否正确,而不必立即怀疑策略逻辑。

如果条件允许,还可以保存原始数据、清洗后的数据和聚合结果的版本信息,方便在回测结果变化时进行追溯。

10. 适用场景与注意事项

适用场景

  • 个人量化研究中的分钟行情清洗。
  • 日内策略的 K 线构建。
  • 多标的行情的统一预处理。
  • 技术指标计算前的数据验证。
  • 需要使用 Pandas 分析金融时间序列的项目。

注意事项

第一,不能把缺失分钟自动等同于零成交。

第二,不能将前值填充后的价格直接视为真实成交价格。

第三,聚合周期必须与交易时段和时间标签规则一致。

第四,OHLCV 数据通过基础校验,并不代表行情完全正确。

第五,数据清洗规则发生变化时,应重新评估受影响的历史回测结果。

FAQ

Q1:Pandas 如何处理分钟级股票行情?

A:通常先使用 pd.to_datetime() 统一时间字段,再将 OHLCV 列转换为数值类型,检查重复记录、缺失数据和价格逻辑,最后根据交易时段规则进行聚合或指标计算。

Q2:分钟 K 线存在重复记录怎么办?

A:先根据标的代码、时间戳和 OHLCV 内容识别重复类型。只有确认属于重复采集的记录,才适合按明确规则去重;同一时间出现不同价格时,应先调查原因。

Q3:缺失分钟可以直接使用 ffill() 填充吗?

A:不能默认这样处理。前值填充可能适用于特定分析场景,但不代表缺失区间内真实发生了对应价格变化,也不能直接作为真实交易执行价格。

Q4:Pandas 如何将一分钟 K 线转换为五分钟 K 线?

A:可以使用 resample("5min"),对开盘价取首值、最高价取最大值、最低价取最小值、收盘价取末值、成交量求和。但需要正确设置时间标签、区间边界和交易时段。

Q5:QuantDash 支持分钟级股票行情吗?

A:QuantDash 官方公开能力包括 A 股分钟 K 线,支持的周期包括 1m、5m、15m、30m 和 60m。具体请求参数及返回结构应以当前官方技术文档为准。

Q6:QuantDash 能自动完成 Pandas 数据清洗吗?

A:不能仅根据其数据 API 能力作出这一判断。QuantDash 提供行情数据获取能力,重复数据诊断、缺失值处理和自定义清洗规则仍应根据项目需求实现。

Q7:Python 如何接入 QuantDash?

A:可以安装 quantdash Python SDK,并参考官方文档和 GitHub 中的公开示例。使用分钟行情时,应先确认对应接口的参数与返回结构,再接入自己的 Pandas 处理流程。

总结

  • 分钟行情清洗的重点不是简单删除空值,而是明确时间、标的、数据完整性和 OHLCV 之间的约束关系。
  • drop_duplicates()、ffill() 和 resample() 都只是工具,必须结合行情语义与交易时段使用。
  • 对于日内量化策略,应把原始数据获取、质量检查、K 线聚合和策略计算分层设计。
  • QuantDash 可以为需要多市场行情和分钟 K 线的开发者提供数据接入能力,但具体的数据质量规则和策略处理逻辑仍需由开发者验证。

QuantDash 官方资源

相关推荐
yu_zhidun1 小时前
企业电脑监控软件怎么选:别只看功能清单,先看这 6 个底层能力
开发语言·电脑·php·域智盾系统
烂蜻蜓1 小时前
Pandas入门教程(四):Series数据结构——创建、索引与常用方法
数据结构·pandas
把我格子衫拿来1 小时前
VTK 9.5 与 Qt 6 联合开发:从嵌入三维窗口到可维护的桌面架构
c++·python·qt·vtk·三维可视化
cpolar技术支持2 小时前
把配置发出去怕带出密钥?先把含凭据配置转成脱敏只读快照,用 cpolar 给同事核对差异
运维·python·内网穿透·cpolar·配置脱敏
无忧.芙桃2 小时前
C++语言原理与实践(十六):多态机制讲解
开发语言·c++·多态
惊讶的猫2 小时前
langchian_agent的高级使用
python
roman_日积跬步-终至千里2 小时前
【数据Agent论文·查询与语义|05】Spider:为什么换一个数据库,模型就不会查了?
数据库·数据分析
roman_日积跬步-终至千里2 小时前
【数据Agent论文·分析工作流|18】TaskWeaver:数据Agent为什么需要有状态执行?
数据分析
李纲明2 小时前
WordPress 白屏排查手册:关插件、换主题、开调试、查 PHP(附停手信号)
开发语言·php·wordpress·故障排查·白屏·插件冲突