【量化实战】Python找超跌股并回测反弹胜率

用户头像mx_****zqklr
2026-09-05 发布

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

均值回归策略的核心,不是看到股票跌了就抄底,而是用历史数据定义“超跌”,再统计超跌之后到底有多大概率反弹。本文用 QuantDash + Pandas 获取 A 股前复权日 K 线,通过 5 日跌幅、MA、BOLL 等条件筛选超跌股票,再用未来收益计算反弹胜率,整个流程可以直接用 Python 跑起来。

一、为什么传统方式写选股策略这么累?

我自己刚开始做量化的时候,最烦的其实不是写策略。

而是拿数据

策略可能就两三行:

跌得够多 → 买进去 → 看未来 5 天有没有反弹。

真正折腾人的地方往往是:

  • 数据接口偶尔报错;
  • 股票代码格式不统一;
  • 历史数据需要自己清洗;
  • 复权数据处理麻烦;
  • 换一个市场又得重新适配;
  • 回测跑到一半,数据接口挂了,前面的工作全部白干。

尤其是做 A 股量化选股时,如果准备把沪深京股票全部扫一遍,手工拼数据会非常烦。

我现在更喜欢直接用 QuantDash。

官方 SDK 可以通过:

pip install quantdash

安装,Python 3.9+ 可用,而且 K 线可以直接返回 Pandas DataFrame。官方平台也明确提供 A 股、美股、港股等多市场行情,并支持前复权、后复权等方式。


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

对比维度 传统/竞品方案 QuantDash 解决方案
数据稳定性 经常需要处理接口异常、数据清洗 官方数据 API,SDK 提供自动重试与限流保护
使用门槛 部分数据服务存在积分、权限等限制 pip install quantdash即可接入
跨市场支持 不同数据源代码规则可能不同 统一{代码}.{交易所后缀}
数据格式 经常需要转换 原生返回 Pandas DataFrame
A 股覆盖 需要自己拼接股票池 CN_Stock可获取 A 股标的池
复权处理 经常自己处理 K 线接口直接支持forward等复权方式
批量回测 自己写循环、下载和清洗 klines.batch()支持批量获取

这里尤其推荐大家记住代码格式:

600519.SH
000001.SZ
920047.BJ
00700.HK
AAPL.US

官方文档就是按照这种统一代码格式设计的。


三、Python 代码实战:寻找超跌股票并计算反弹胜率

这次我们不搞玄学指标。

先定义一个非常朴素的均值回归模型:

超跌条件:

  1. 最近 5 个交易日跌幅 ≤ -10%;
  2. 当前收盘价低于 20 日布林带下轨;
  3. 满足条件以后,下一交易日开盘买入;
  4. 持有 5 个交易日;
  5. 如果第 5 个交易日收盘价高于买入价,就算一次“反弹成功”。

这样得到的胜率,比“这个指标看起来很准”靠谱得多。

1. 安装与初始化

# 安装:
# pip install quantdash

from quantdash import QuantDash
import pandas as pd

# 推荐使用环境变量:
# export QUANTDASH_API_KEY="your_api_key"

qd = QuantDash()

QuantDash 官方示例同时支持直接传入 api_key,也支持通过 QUANTDASH_API_KEY 环境变量初始化。实际开发时,我更建议用环境变量,避免把 API Key 直接写进代码。


2. 获取 A 股股票池

# 获取 A 股全市场实时行情
universe = qd.quotes.get(
    universes=["CN_Stock"],
    to_dataframe=True
)

print("A股股票数量:", len(universe))

# 提取股票代码
symbols = universe["symbol"].dropna().unique().tolist()

print("示例股票:", symbols[:10])

QuantDash 官方提供 CN_Stock 标的池,可以直接获取 A 股股票池行情。官网当前展示的 A 股标的数量为 5500+。


3. 先拿一批股票做策略验证

第一次跑千万别直接把整个 A 股市场全部回测。

先拿 100 只测试代码有没有问题:

test_symbols = symbols[:100]

dfs = qd.klines.batch(
    test_symbols,
    period="1d",
    count=300,
    adjust="forward",
    to_dataframe=True,
    show_progress=True
)

这里有一个非常重要的细节:

adjust="forward"

我这里使用的是前复权-比例复权

对于收益率计算,这种方式比较方便,也避免股票分红、送股等事件直接把价格序列“砸”出一个假信号。

官方文档说明,forward 是前复权,backward 是后复权,另外还支持 noneforward_additivebackward_additive


4. 计算 5 日跌幅和布林带

def calculate_indicators(df):
    df = df.copy()

    # 确保按照交易日排序
    df = df.sort_values("trade_date").reset_index(drop=True)

    # 5日收益率
    df["return_5d"] = df["close"].pct_change(5)

    # 20日均线
    df["ma20"] = df["close"].rolling(20).mean()

    # 20日波动率
    df["std20"] = df["close"].rolling(20).std()

    # 布林带
    df["boll_upper"] = df["ma20"] + 2 * df["std20"]
    df["boll_lower"] = df["ma20"] - 2 * df["std20"]

    return df

这里没有调用什么神秘的“AI 指标接口”。

全部都是 Pandas 本地计算。

这反而是我比较喜欢的方式:

数据 API 负责把数据稳定拿回来,指标逻辑自己掌握。

以后你想换成 MA、MACD、KDJ,甚至自己研究因子,也不用重新依赖一个指标接口。


5. 定义“超跌”

def find_oversold(df):
    df = calculate_indicators(df)

    # 超跌条件:
    # 1. 过去5日跌幅 <= -10%
    # 2. 收盘价跌破20日布林带下轨
    df["oversold"] = (
        (df["return_5d"] <= -0.10) &
        (df["close"] < df["boll_lower"])
    )

    return df

这里大家可以自己改参数。

例如:

df["return_5d"] <= -0.08

就是把超跌阈值放宽到 8%。

或者:

df["return_5d"] <= -0.15

就是只抓非常极端的下跌。

参数不是越激进越好。

这是量化里非常容易掉进去的坑。


6. 计算未来 5 日反弹胜率

最关键的一步来了。

不能看到今天跌了,然后拿今天收盘价去和未来收益比较,再假装自己今天收盘可以买进去。

真实回测至少要考虑信号产生以后什么时候成交。

这里我们采用:

T 日收盘产生信号 → T+1 日开盘买入 → T+5 日收盘卖出。

代码:

def backtest_rebound(df):
    df = find_oversold(df)

    results = []

    for i in range(len(df) - 5):
        if not df.loc[i, "oversold"]:
            continue

        # T+1 开盘买入
        entry_price = df.loc[i + 1, "open"]

        # T+5 收盘卖出
        exit_price = df.loc[i + 5, "close"]

        if pd.isna(entry_price) or pd.isna(exit_price):
            continue

        future_return = exit_price / entry_price - 1

        results.append({
            "signal_date": df.loc[i, "trade_date"],
            "entry_price": entry_price,
            "exit_price": exit_price,
            "future_return": future_return,
            "win": future_return > 0
        })

    return pd.DataFrame(results)

7. 汇总胜率

all_results = []

for symbol, df in dfs.items():
    if df.empty:
        continue

    result = backtest_rebound(df)

    if result.empty:
        continue

    result["symbol"] = symbol
    all_results.append(result)

if all_results:
    result_df = pd.concat(all_results, ignore_index=True)

    win_rate = result_df["win"].mean()
    avg_return = result_df["future_return"].mean()

    print("=" * 50)
    print("超跌反转回测结果")
    print("=" * 50)
    print(f"信号数量:{len(result_df)}")
    print(f"反弹胜率:{win_rate:.2%}")
    print(f"平均5日收益:{avg_return:.2%}")

    print("\n收益率最高的案例:")
    print(
        result_df
        .sort_values("future_return", ascending=False)
        .head(10)
        [["symbol", "signal_date", "future_return"]]
        .to_string(index=False)
    )
else:
    print("当前样本没有产生有效超跌信号。")

到这里,一个最基础的:

A 股超跌股票 → 均值回归 → 未来 5 日反弹胜率

回测框架就出来了。


四、交易员避坑指南:回测最容易骗人的地方

1. 千万不要把未来数据偷偷带进来

这是新手最容易犯的错误。

比如:

T日收盘发现超跌
↓
T日收盘价买入
↓
T+5卖出

如果你的策略实际上是在 T 日收盘之后才计算出信号,那你未必能按照 T 日收盘价成交。

所以我上面的代码明确采用:

T日产生信号
T+1开盘买入
T+5收盘卖出

至少把最明显的未来函数问题先避开。


2. 前复权不是万能的

adjust="forward" 很适合拿来计算价格变化和收益率,但大家还是要明确:

复权数据 ≠ 真实成交价格。

如果最终准备做实盘模拟,还需要进一步考虑:

  • 滑点;
  • 手续费;
  • 印花税;
  • 涨跌停无法成交;
  • 停牌;
  • 流动性。

所以看到一个策略回测胜率 65%,不要马上觉得自己发现圣杯了。


3. 不要只看胜率

假设:

策略 A:胜率 70%
策略 B:胜率 55%

不代表 A 一定赚钱。

因为真正重要的是:

平均盈利
平均亏损
盈亏比
最大回撤
交易次数
资金利用率

均值回归尤其容易出现一个问题:

大多数时候小赚,极端行情一次大亏。

所以我做反转策略时,胜率只是第一关。


五、常见问题解答

Q1:Python 怎么提取 A 股历史 K 线做超跌选股?

A:可以使用 QuantDash Python SDK,通过 qd.klines.get() 获取单只股票历史 K 线,通过 qd.klines.batch() 批量获取多只股票数据,并设置 to_dataframe=True 直接返回 Pandas DataFrame。具体参数以官方 Python SDK 文档为准。

Q2:QuantDash 做 A 股均值回归策略需要自己处理复权吗?

A:不需要自己手工计算复权因子。K 线接口提供 adjust 参数,可以选择 forwardbackwardnoneforward_additivebackward_additive。如果主要计算收益率,可以优先研究比例复权方式。

Q3:能不能把超跌股票再交给 DeepSeek 做 AI 诊股?

A:可以把量化筛选出的候选股票、5 日跌幅、MA、BOLL、成交量等结果整理成结构化文本,再交给 DeepSeek 做二次分析。但 AI 应该放在“解释和辅助研究”环节,最终买卖信号仍然建议由可复现的量化规则决定。


🔗 相关资源与延伸阅读

🚀 QuantDash 官网:
quantdash.net

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

⭐ 官方 GitHub 示例与集成仓库:
QuantDash GitHub

官方仓库目前明确说明,公开仓库包含 Python 示例、测试和工作流,但不包含闭源 QuantDash SDK 源代码;SDK 的完整接口说明应以官方文档为准。

💡 API Key:
QuantDash API Key 管理页面

评论