首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >我用StockApi做竞价策略:3 个接口、4 分钟时间窗,开盘前输出当日观察池

我用StockApi做竞价策略:3 个接口、4 分钟时间窗,开盘前输出当日观察池

原创
作者头像
用户7273352
发布于 2026-10-30 14:47:51
发布于 2026-10-30 14:47:51
1530
举报
文章被收录于专栏:量化接口量化接口

9:26 增强版板块竞价:开盘前 4 分钟定当日方向

本文由 StockApi 智能体基于增强版热点板块竞价、板块所属个股与竞价涨停委托单接口整理撰写,代码可直接运行复现。

引言

9:25 集合竞价结束的那一刻,当天市场的方向偏好其实已经写在竞价数据里了:哪些板块竞价抢筹、哪些板块竞价出货、哪些票的涨停委托单堆了几千万——这些信息比盘中任何时段都干净,因为没有盘中资金的反复骗线。

但大多数人对竞价数据的用法停留在"看集合竞价涨幅排行",缺两个关键动作:按板块聚合(个股竞价涨幅是散的,板块竞价涨幅才是方向)和看委托结构(竞价成交额可以是对倒,挂单买不上涨停的委买额才是真抢筹)。这篇用增强版板块竞价接口 + 板块所属个股接口 + 竞价涨停委托单接口,把 9:26 之后的前 4 分钟变成一个标准化的方向判断流程。

策略原理

本篇用到的StockApi三个接口

接口(中文名)

路径

在策略里做什么

增强版热点板块竞价

/v1/base/bkjjzq

9:26 更新,板块竞价涨幅 + 上涨/下跌家数(热点与极速下跌板块都有)

增强版板块竞价所属个股

/v1/base/zqbkCodeList

拉出竞价强势板块的成分股

竞价涨停委托单

/v1/base/jjztwtd

9:26 更新,竞价阶段挂涨停价的委托单明细(type=1 主板 / type=2 创业板)

字段中文对照

字段

中文含义

备注

bkCode / bkName

板块代码 / 板块名称

板块聚合的核心标识

jjzf

竞价涨幅

板块口径与个股口径都有,注意区分

szjs / xdjs

上涨家数 / 下跌家数

家数比涨幅更难被单票操纵

wme

委买额

竞价挂涨停价的买单金额,真抢筹的核心证据

je

净额

委买减委卖,正值代表排队方向向上

jjcje

竞价成交额

有量没委托额 = 可能对倒

jjhs

竞价换手率

竞价就高换手,分歧大

zl

主力

是否主力资金在竞价排队

lb

连板

昨日连板数

bk

板块

票所属板块

4 分钟流程(9:26—9:30)

  1. 板块聚合(增强版板块竞价接口):取竞价涨幅 jjzf ≥ 2% 且上涨家数占比 ≥ 70%(szjs / (szjs + xdjs))的板块——家数占比排除了"一只权重票拉起来的假强势板块"。
  2. 成分确认(板块所属个股接口):对每个候选板块拉成分股,标记成分里出现在竞价涨幅前列的票。
  3. 委托验证(竞价涨停委托单接口):候选票若在涨停委托单里,要求 wme(委买额)≥ 3000 万、zl(主力)排队、je(净额)为正——委买额是排队的钱,成交额是已成的钱,排队的钱才是今天的预期。
  4. 执行:通过验证的票进入当日观察池,开盘不追高(开盘涨幅 ≤ 5% 才参与),尾盘按当日表现决定去留。

与盘中信号的区别:竞价涨停委托单 9 点 26 分更新一次,是全天唯一的"预期快照";开盘后这个信息就融进了价格里,所以这个策略有严格的时间窗,9:30 之前不跑完就没意义。

为什么"委买额"比"成交额"诚实

竞价成交有两部分:真成交和对倒。庄家可以在竞价里左手卖右手做出 5000 万成交额,但挂在涨停价上的委买单没法对倒——那是真金白银排队等着买的钱,撤单会有记录。所以判断"这个板块今天是真抢筹还是做样子",看委买额与成交额的关系:

组合

解读

动作

成交额大 + 委买额大

真抢筹,买卖双方都在抢

重点观察

成交额大 + 委买额小

竞价已完成,开盘可能高开出货

回避

成交额小 + 委买额大

一字预期,买不进

放弃(买进的可能是坑)

成交额小 + 委买额小

没有资金关注

忽略

Python 完整实现

代码语言:python
复制
import os
import time
import requests
import pandas as pd

TOKEN = os.getenv("STOCKAPI_TOKEN", "你的Token")
BASE = "https://www.stockapi.com.cn/v1"

def call(path, **params):
    params["token"] = TOKEN
    r = requests.get(f"{BASE}{path}", params=params, timeout=15)
    r.raise_for_status()
    d = r.json()
    if d.get("code") == 20000:
        return d["data"]
    raise RuntimeError(f"{path} 调用失败: {d.get('msg')}")

# ---------- 1. 竞价强势板块(9:26 后调用) ----------
def strong_boards(trade_date):
    rows = call("/base/bkjjzq", tradeDate=trade_date) or []
    df = pd.DataFrame(rows)
    if df.empty:
        return df
    for c in ["jjzf", "szjs", "xdjs"]:
        df[c] = pd.to_numeric(df[c], errors="coerce")
    df["ratio"] = df["szjs"] / (df["szjs"] + df["xdjs"]).replace(0, pd.NA)
    return df[(df["jjzf"] >= 2) & (df["ratio"] >= 0.7)].sort_values("jjzf", ascending=False)

# ---------- 2. 板块成分股 ----------
def board_members(trade_date, bk_code):
    rows = call("/base/zqbkCodeList", tradeDate=trade_date, bkCode=bk_code) or []
    df = pd.DataFrame(rows)
    if not df.empty:
        df["code"] = df["code"].astype(str).str.zfill(6)
    return df

# ---------- 3. 竞价涨停委托单(主板 + 创业板各拉一次) ----------
def jj_zt_orders(trade_date):
    frames = []
    for t in (1, 2):
        df = pd.DataFrame(call("/base/jjztwtd", date=trade_date, type=t) or [])
        if not df.empty:
            frames.append(df)
        time.sleep(0.05)
    if not frames:
        return pd.DataFrame()
    df = pd.concat(frames, ignore_index=True)
    for c in ["wme", "je", "jjcje", "jjhs"]:
        if c in df.columns:
            df[c] = pd.to_numeric(df[c], errors="coerce")
    df["code"] = df["code"].astype(str).str.zfill(6)
    return df

# ---------- 4. 主流程:4 分钟方向判断 ----------
def morning_plan(trade_date):
    boards = strong_boards(trade_date)
    orders = jj_zt_orders(trade_date)
    plan = []
    for _, b in boards.iterrows():
        members = board_members(trade_date, b["bkCode"])
        if members.empty or orders.empty:
            continue
        merged = members.merge(orders, on="code", how="inner")
        hot = merged[(merged["wme"] >= 3e7) & (merged["je"] > 0) &
                     (merged["zl"] == 1)]
        for _, m in hot.iterrows():
            plan.append({"板块": b["bkName"], "代码": m["code"],
                         "名称": m.get("name", ""), "委买额(万)": m["wme"] / 1e4})
    return pd.DataFrame(plan)

plan = morning_plan("2026-10-29")   # 交易日 9:26 之后运行
print(plan.sort_values("委买额(万)", ascending=False).head(10).to_string(index=False))

回测指标怎么读

指标

典型量级(示意)

说明

每日入选票数

3—10 只

仓位分散在 3—5 只即可

观察池当日跑赢板块概率

60%—70%

委买额验证是核心增量

开盘高开 > 5% 的票

后续收益显著变差

这就是"不追高"规则的来源

最长使用窗口

9:26—9:30

数据 9:26 更新,开盘后失效

用竞价数据回测需把每日 9:26 快照落库积累;接口本身的按日查询支持取历史某日的竞价快照,可直接逐日回放。

参数与风控

参数

默认

调整方向

板块竞价涨幅

2%

弱市放宽到 1%,强市提高到 3%

上涨家数占比

70%

防"单票拉板块"的硬过滤,不建议放宽

委买额下限

3000 万

小市值活跃票可降到 2000 万

开盘参与上限

+5%

超过就等回踩,不追

风控三条:

  1. 时间窗纪律:9:30 之前没跑完就放弃当天,竞价策略过期即作废,绝不盘中补跑。
  2. 竞价委托单有两张(主板 type=1、创业板 type=2),只拉一张会漏一半票。
  3. 竞价数据是"预期"不是"事实",开盘后 15 分钟内的量价验证(量能放大、不破竞价低点)才是执行的确认条件。

常见问题(FAQ)

Q:增强版和普通版板块竞价接口有什么区别?

A:增强版(bkjjzq)多了上涨/下跌家数(szjs/xdjs),普通版只有涨幅。家数占比是排除"单票拉板块"假信号的关键,建议直接用增强版。两者都是 9:26 更新、40 次/秒。

Q:9:26 接口还没出数据怎么办?

A:接口按交易日查询,盘中 9:26 后重试即可;如果做历史回放,直接传历史日期拉当天的快照,与盘中行为一致。

Q:这个策略和「竞价抢筹」那篇的区别?

A:竞价抢筹那篇的核心是个股委托成交比(委托金额表 × 成交金额表交叉),定位选个股;这篇的核心是板块聚合 + 委托结构验证,定位定当日方向。两篇可以配合:先用本篇定板块方向,再用委托成交比在板块内挑票。


免责声明:本文为策略研究与技术分享,不构成任何投资建议。市场有风险,入市需谨慎。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 引言
  • 策略原理
  • 为什么"委买额"比"成交额"诚实
  • Python 完整实现
  • 回测指标怎么读
  • 参数与风控
  • 常见问题(FAQ)
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档