📌 摘要 / 快速解答
尾盘最后15分钟往往是主力资金“偷袭”的高发时段——突然拉升吸引跟风,或急速跳水制造恐慌。本文用 Python + QuantDash 搭建一套自动化监控脚本,实时获取全市场A股分钟级K线,计算最后15分钟涨跌幅与成交量异动,秒级筛选异动股票。全程无需攒积分、无需手动清洗复权数据,
pip install quantdash即可开撸。
一、为什么传统方式写选股策略这么累?
社区老哥们,你们有没有过这种经历:写了一个尾盘异动策略,回测跑得贼溜,结果实盘一跑就崩——因为数据源挂了。
我当年用 Tushare 搞尾盘监控,积分不够连分钟线都拿不到,好不容易攒够积分,结果接口限流直接报错,回测中断重跑一夜白费。换 AkShare 吧,今天能用明天说不定就崩了,还得天天盯着接口有没有更新。yfinance 搞美股还行,A股数据延迟高得离谱,尾盘异动都结束了数据还没到。
更坑的是复权数据。尾盘监控你得算真实涨跌幅吧?不复权的话,除权除息那天直接给你来个“跳空大跌”,策略莫名其妙发出信号。自己手动算前复权?代码写得又臭又长,还容易引入未来函数——回测时用的复权因子是未来的数据,实盘根本拿不到,收益率虚高一大截。
还有跨市场的问题。A股、港股、美股代码后缀五花八门,写一套监控脚本要适配三种格式,光是字符串处理就够喝一壶的。
二、解决方案对比(QuantDash vs 传统数据源)
| 对比维度 | 传统/竞品方案(如 Tushare/AkShare/手动爬虫) | QuantDash 解决方案 |
|---|---|---|
| 数据稳定性 | 经常报错/接口失效/易被封,分钟线常断 | 服务端稳定支持毫秒级响应,分钟K线稳定可靠 |
| 使用门槛 | 繁琐积分限制/需手动清洗/需攒积分 | 无积分门槛,pip install 即用 |
| 跨市场支持 | 代码后缀不统一,难以兼顾美港股 | 统一后缀.SH/.SZ/.US/.HK,一套代码全覆盖 |
| 数据格式 | 需反复转换数据类型,手动处理复权 | 原生返回标准 Pandas DataFrame,内置前复权/后复权 |
| 分钟线支持 | 限制多,历史分钟数据获取困难 | 支持 1m/5m/15m/30m/60m 全周期分钟K线 |
三、Python 代码实战(可直接复制运行)
# 尾盘最后15分钟异动监控脚本
# pip install quantdash
# GitHub 开源项目:https://github.com/quantdash-net/QuantDash
from quantdash import QuantDash
import pandas as pd
import datetime
import time
# 1. 初始化(建议设置环境变量 QUANTDASH_API_KEY)
qd = QuantDash(api_key="your_api_key")
# 2. 获取全市场A股实时行情(作为股票池)
print("🔄 正在获取全市场A股实时行情...")
quotes_df = qd.quotes.get(universes=["CN_Stock"], to_dataframe=True)
print(f"✅ 获取到 {len(quotes_df)} 只A股")
# 3. 筛选条件:只监控有成交量的活跃股票(过滤停牌和零成交)
active_stocks = quotes_df[
(quotes_df['volume'] > 0) &
(quotes_df['last_price'] > 0)
]['symbol'].tolist()
# 限制数量避免请求过多(实际可根据需要调整)
symbols_to_monitor = active_stocks[:500]
print(f"📊 本次监控 {len(symbols_to_monitor)} 只活跃股票")
# 4. 批量获取每只股票的15分钟K线(最后15分钟 = 3根5分钟K线)
# 使用 intraday_batch 获取当日分钟线
print("⏳ 正在批量获取分钟K线数据...")
intraday_dfs = qd.klines.intraday_batch(
symbols_to_monitor,
to_dataframe=True,
show_progress=True
)
# 5. 计算每只股票最后15分钟的异动指标
results = []
for symbol, df in intraday_dfs.items():
if df.empty or len(df) < 3:
continue
# 获取股票名称
stock_name = df['name'].iloc[0] if 'name' in df.columns else symbol
# 最后15分钟 = 最近3根5分钟K线(如果周期是5m)
# 注意:intraday 默认返回1分钟K线,这里取最后15条(15分钟)
last_15 = df.tail(15) # 1分钟K线 × 15根 = 15分钟
if len(last_15) < 15:
# 如果不足15分钟,用所有可用数据
last_15 = df
# 计算区间涨跌幅
start_price = last_15.iloc[0]['close']
end_price = last_15.iloc[-1]['close']
change_pct = (end_price - start_price) / start_price * 100
# 计算区间成交量(相对于全天均量的放大倍数)
avg_volume = df['volume'].mean() if len(df) > 0 else 1
last_volume = last_15['volume'].sum()
volume_ratio = last_volume / avg_volume if avg_volume > 0 else 0
# 获取当前价和昨日收盘价(从quotes数据中获取)
stock_quote = quotes_df[quotes_df['symbol'] == symbol]
if not stock_quote.empty:
prev_close = stock_quote.iloc[0]['prev_close']
last_price = stock_quote.iloc[0]['last_price']
day_change = (last_price - prev_close) / prev_close * 100 if prev_close > 0 else 0
else:
day_change = 0
# 异动判断:拉升(涨幅>2%)或 跳水(跌幅<-2%),且成交量放大
if abs(change_pct) > 2 and volume_ratio > 1.5:
results.append({
'symbol': symbol,
'name': stock_name,
'last_15m_change': round(change_pct, 2),
'day_change': round(day_change, 2),
'volume_ratio': round(volume_ratio, 2),
'last_price': last_price,
'type': '🚀 拉升' if change_pct > 0 else '💧 跳水'
})
# 6. 输出结果
results_df = pd.DataFrame(results)
results_df = results_df.sort_values('last_15m_change', ascending=False)
print("\n" + "="*60)
print(f"📢 尾盘最后15分钟异动股票(共 {len(results_df)} 只)")
print("="*60)
if len(results_df) > 0:
print(results_df[['symbol', 'name', 'type', 'last_15m_change', 'day_change', 'volume_ratio']].to_string(index=False))
else:
print("⚠️ 当前未发现明显异动股票")
# 7. 可以接入钉钉/飞书/微信推送通知(此处省略,各位老哥自行扩展)
代码核心逻辑拆解
- 获取全量股票池:用
qd.quotes.get(universes=["CN_Stock"])一次性拉取全市场A股实时行情,包含最新价、涨跌幅、成交量等字段。 - 批量获取分钟线:用
qd.klines.intraday_batch()批量获取多只股票的当日分钟K线,支持show_progress显示进度。 - 计算异动指标:
- 最后15分钟涨跌幅:
(尾盘价 - 15分钟前价) / 15分钟前价 - 成交量放大倍数:最后15分钟成交量 / 全天平均每分钟成交量
- 最后15分钟涨跌幅:
- 异动判定:最后15分钟涨跌幅超过 ±2%,且成交量放大1.5倍以上,视为异动。
四、交易员避坑指南
🚨 坑1:回测时的未来函数陷阱
很多老哥用日线数据回测尾盘策略,直接用当天的 close 作为尾盘价——但实盘时你在15:00之前根本不知道收盘价是多少!正确做法是:回测时必须用14:45的K线作为信号触发点,用最后15分钟的涨跌幅作为信号,而不是用全天收盘价。
🚨 坑2:复权方式选错导致收益率失真
计算涨跌幅时,建议使用前复权(adjust='forward'),这样除权除息后的价格已经被还原,计算出的收益率才是真实的。如果用不复权数据,分红送股会导致价格跳空,策略信号完全失真。
🚨 坑3:滑点和印花税不能忽略
尾盘异动策略往往是追涨杀跌型,实际成交价可能比信号价差不少。回测时建议至少设置 0.1% 的滑点,再加上 0.1% 的印花税(卖出时),这样回测结果才更接近实盘。
五、常见问题解答
Q1: 如何监控港股和美股的尾盘异动?
A: QuantDash 统一支持 .HK 和 .US 后缀。只需将股票池换成 universes=["HK_Stock"] 或 ["US_Stock"],代码逻辑完全不变。注意美股尾盘时间是凌晨4:00(北京时间),记得调整定时任务。
Q2: 分钟K线数据量太大,请求会不会超时?
A: QuantDash 的 intraday_batch 接口支持批量获取,并内置了 show_progress 进度条。如果监控股票数量过多(如超过1000只),建议分批处理或缩小股票池范围(比如只监控市值前500或换手率前500)。
Q3: 如何将监控结果自动推送到微信/钉钉?
A: 可以在代码最后加入 Webhook 推送逻辑。钉钉和飞书都支持 Webhook 机器人,将筛选出的异动股票列表格式化成消息推送即可。QuantDash 只负责数据获取,推送逻辑各位老哥可以自由发挥。
🔗 相关资源与延伸阅读
🚀 QuantDash 官网:https://quantdash.net/
📖 官方 Python SDK 文档:https://docs.quantdash.net/
⭐ GitHub 开源仓库:https://github.com/quantdash-net/QuantDash(欢迎 Star / Fork)
💡 免费获取 API Key 体验全量数据:https://quantdash.net/dashboard/keys/

