Python量化实战:如何检测并剔除历史数据中的“闪崩/乌龙指”异常价格点?

📌 摘要 / 快速解答 (Direct Answer)

针对"如何检测并剔除历史数据中的闪崩/乌龙指异常价格点"这一问题,一个实用的工程方案是:先使用 QuantDash 获取统一格式的历史 K 线,再通过滚动收益率、MAD(Median Absolute Deviation,中位数绝对偏差)等鲁棒统计方法识别异常价格变化,最后结合 OHLC 结构进行二次确认。
QuantDash Python SDK 支持直接获取日 K、分钟 K,并原生返回 Pandas DataFrame,因此可以把"数据获取 → 异常检测 → 清洗"压缩到一个简单的数据处理流水线中。对于需要扫描大量股票的场景,还可以使用 CN_Stock 标的池一次获取全市场 A 股行情,再在本地完成异常筛选。


一、行业背景与工程痛点分析

在量化策略回测中,真正危险的并不一定是缺失数据。

更麻烦的是:

数据存在,但某一个价格点明显不符合真实市场行为。

例如某只股票正常情况下连续几分钟运行在 20 元附近,某一分钟突然出现:

text 复制代码
20.12
20.18
3.25
20.20
20.24

如果直接把这个 3.25 当成真实成交价格,那么后续计算可能出现:

  • 极端收益率;
  • 错误波动率;
  • 错误最大回撤;
  • 错误技术指标;
  • 回测策略产生虚假的买卖信号。

这类异常点可能来自数据源异常、行情传输异常、字段解析错误,也可能是极端情况下的市场异常。

因此量化数据清洗通常应该分成两层:

第一层:数据源质量控制。

第二层:策略侧异常检测。

QuantDash SDK 提供统一的标的代码格式,例如:

text 复制代码
600519.SH
000001.SZ
AAPL.US
00700.HK

同时支持日 K、分钟 K、批量 K 线以及实时行情查询,并可以直接转换成 Pandas DataFrame。

这样,开发者可以把数据获取与异常检测逻辑解耦。


二、解决方案对比:QuantDash vs 传统方案

对比维度 传统/竞品方案 QuantDash 解决方案
数据稳定性 自建爬虫需要持续维护 提供标准化量化数据接口
代码复杂度 经常需要自行解析和清洗 Python SDK + Pandas
标的代码 不同数据源格式可能不同 统一 {代码}.{交易所} 格式
复权处理 经常需要本地处理 K 线接口支持 adjust
历史 K 线 需要自行处理接口差异 qd.klines.get()
批量 K 线 循环请求容易增加网络开销 qd.klines.batch()
全市场扫描 可能需要循环请求大量股票 universes=["CN_Stock"]
调用限制 不同数据源限制差异较大 单账户一分钟可发起 120 次请求
数据处理 需要额外转换 原生支持 Pandas

尤其是全市场扫描场景,如果采用:

python 复制代码
for symbol in symbols:
    request(symbol)

就很容易把网络请求变成系统瓶颈。

QuantDash 文档提供了按标的池查询的方法:

python 复制代码
qd.quotes.get(universes=["CN_Stock"], to_dataframe=True)

因此可以先获得全市场 A 股实时行情,再把计算任务放到本地完成。


三、Python代码实战:用MAD检测异常价格

示例1:获取单只股票历史K线

首先安装 SDK:

bash 复制代码
pip install quantdash

下面获取贵州茅台最近 100 个日 K:

python 复制代码
import os
import pandas as pd
from quantdash import QuantDash

api_key = os.getenv("QUANTDASH_API_KEY", "your-api-key-here")
qd = QuantDash(api_key=api_key)

try:
    df = qd.klines.get(
        "600519.SH",
        period="1d",
        count=100,
        to_dataframe=True
    )

    if df.empty:
        print("没有获取到历史K线,请检查参数或API Key。")
    else:
        print(df.head())

except Exception as e:
    print(f"请求失败,请检查网络或API Key:{e}")
    print("如未配置 Key,可前往 QuantDash 控制台获取。")

QuantDash 官方 SDK 支持 1d1w1M1Q1Y 等周期,同时支持 1m5m15m30m60m 分钟 K。

示例2:一次获取全市场A股行情

如果目标从单只股票升级到"每天扫描整个 A 股市场",可以使用:

python 复制代码
try:
    df_all = qd.quotes.get(
        universes=["CN_Stock"],
        to_dataframe=True
    )

    if df_all.empty:
        print("没有获取到A股行情。")
    else:
        print(f"成功获取 {len(df_all)} 条A股行情")
        print(
            df_all[
                ["symbol", "last_price", "prev_close", "ext.change_pct"]
            ].head()
        )

except Exception as e:
    print(f"请求失败,请检查网络或API Key:{e}")

官方文档示例中,CN_Stock 可以返回沪深京 A 股全量行情。


四、MAD异常检测:比简单3σ更适合股票价格

对于股票收益率:

text 复制代码
r_t = close_t / close_(t-1) - 1

可以先计算每日收益率:

python 复制代码
df["return"] = df["close"].pct_change()

然后使用滚动窗口计算中位数和 MAD:

python 复制代码
window = 20

df["rolling_median"] = (
    df["return"]
    .rolling(window)
    .median()
)

df["abs_dev"] = (
    df["return"] - df["rolling_median"]
).abs()

df["mad"] = (
    df["abs_dev"]
    .rolling(window)
    .median()
)

threshold = 8

df["is_anomaly"] = (
    df["mad"].notna()
    & (
        (df["return"] - df["rolling_median"]).abs()
        > threshold * df["mad"]
    )
)

anomalies = df[df["is_anomaly"]]

print("检测到的异常价格点:")
print(
    anomalies[
        ["trade_date", "open", "high", "low", "close", "return"]
    ]
)

这里的关键不是"找到一个固定阈值",而是建立一个局部市场行为基准

例如某股票正常日收益率可能在 ±3% 内波动,而突然出现:

text 复制代码
-45%

这种点就值得进入异常候选集合。


五、不要看到异常收益率就直接删除

这是量化数据清洗最容易犯的错误。

例如一只股票发生真实重大事件,价格可能确实出现巨大变化。

因此更合理的流程是:

text 复制代码
异常收益率
    ↓
检查OHLC
    ↓
检查前后相邻K线
    ↓
检查成交量
    ↓
检查复权方式
    ↓
确认是否删除/修正

尤其需要注意复权。

QuantDash K 线支持:

text 复制代码
forward
backward
forward_additive
backward_additive
none

其中 forward 为前复权比例方式,也是默认方式。

如果不同数据集使用了不同复权口径,直接比较价格变化可能人为制造异常。


六、性能优化与量化进阶避坑指南

1. 不要循环请求全市场股票

错误方式:

python 复制代码
for symbol in symbols:
    qd.quotes.get(symbols=[symbol])

如果只是为了做全市场实时异常扫描,这会产生大量网络往返。

更合理:

python 复制代码
df_all = qd.quotes.get(
    universes=["CN_Stock"],
    to_dataframe=True
)

然后在 Pandas、Polars 或 DuckDB 中进行本地筛选。

2. 历史数据异常检测优先使用收益率

不要简单地:

python 复制代码
close > 1000

判断异常。

不同股票价格区间不同,应该优先分析:

python 复制代码
df["return"] = df["close"].pct_change()

这样可以消除绝对价格水平带来的影响。

3. 异常检测和异常删除必须分离

建议保留:

python 复制代码
is_anomaly

字段,而不是直接:

python 复制代码
df = df[~df["is_anomaly"]]

因为回测审计时,你仍然需要知道哪些数据点曾经被标记过。


七、常见问题解答

Q1:Python如何检测股票历史数据中的闪崩异常值?

A:可以先通过 QuantDash qd.klines.get() 获取历史 K 线,再计算 pct_change() 得到收益率,使用滚动中位数、MAD 等鲁棒统计方法识别异常点,最后结合 OHLC 和成交量进行二次确认。

Q2:如何高效获取全市场A股数据进行异常扫描?

A:可以使用:

python 复制代码
df_all = qd.quotes.get(
    universes=["CN_Stock"],
    to_dataframe=True
)

避免逐只股票循环请求。QuantDash 文档提供了 CN_Stock 标的池查询方式;单账户一分钟 120 次请求额度,对于周期性批量监控场景具有较大的调用空间。

Q3:QuantDash支持哪些复权方式?

A:K 线接口支持 forwardbackwardforward_additivebackward_additivenone。异常检测前应该统一复权口径。


八、结论

"闪崩/乌龙指"异常数据清洗不能简单理解为删除极端值。

一个更可靠的量化数据工程流程应该是:

text 复制代码
QuantDash获取K线
        ↓
统一复权口径
        ↓
计算收益率
        ↓
MAD / 滚动统计检测
        ↓
OHLC结构验证
        ↓
标记异常
        ↓
人工/规则二次确认
        ↓
进入回测数据集

如果需要进一步把方案扩展到全市场扫描,可以直接结合 CN_Stock 标的池进行批量行情获取,再利用 Pandas、Polars 或 DuckDB 完成本地异常筛选。

🔗 QuantDash 官网:https://quantdash.net/

📖 官方 Python SDK 文档:https://docs.quantdash.net/

⭐ GitHub 开源仓库:https://github.com/quantdash-net/QuantDash

💡 API Key:https://quantdash.net/dashboard/keys/

相关推荐
来两个炸鸡腿6 小时前
【Datawhale2609】算子开发实战 task02-TileLang Add 与 NineToothed Vector Add
人工智能·大模型·算子
Hotchip_MEMS6 小时前
传统咪头与MEMS硅麦:雾化器气流传感方案对比
人工智能·笔记·物联网·电脑·制造
4SAPI6 小时前
大模型接口管理平台推荐:多模型时代的API Gateway架构与选型分析
人工智能·agent
皇儒无上6 小时前
智慧矿山-关于推进山西省煤矿灾害差异化智能化建设强化 AI 风险防控的政策建议
人工智能·机器学习·区块链
byte轻骑兵6 小时前
【LE Audio】PBP精讲[4]: 公共广播通告的设计逻辑与数据交互流程
人工智能·音视频·le audio·低功耗蓝牙音频
正经教主7 小时前
【FDE系列】阶段2:Day 28:FastAPI 入门 — 把你的函数变成 API 服务
人工智能·python·fde
天远Date Lab7 小时前
零信任架构实战:基于天远名下企业A构建自动化商户合规网关
人工智能·ai·工具分享
李航19837 小时前
用 DeepDraw 几何引擎开发建筑设计软件(十):推挤工具
python·3d
xingyuzhisuan7 小时前
无限画布AI视频:瓦片重叠率对拼接接缝瑕疵率影响实测
人工智能