ashare-pre-st-filter

star 12.4k

A 股 ST/*ST 风险预测框架 — 基于最新中报/三季报或业绩预告/快报,预测下一财年是否会因营收、利润、净资产、分红不达标而被风险警示,并将新浪监管处罚记录作为独立证据面纳入风险等级。仅适用于 A 股,不预测财务造假。

HKUDS By HKUDS schedule Updated 4/30/2026

name: ashare-pre-st-filter description: A 股 ST/*ST 风险预测框架 — 基于最新中报/三季报或业绩预告/快报,预测下一财年是否会因营收、利润、净资产、分红不达标而被风险警示,并将新浪监管处罚记录作为独立证据面纳入风险等级。仅适用于 A 股,不预测财务造假。 category: risk-analysis

依赖:本 skill 必须配合 tushare skill 使用,缺数据时回退到 akshare skill

A 股 ST/*ST 风险预测

适用范围

  • 仅 A 股主板 / 创业板 / 科创板。港股、美股、加密、商品、北交所8xxxxx.BJ 监管规则与本 skill 阈值不一致)均不适用,本 skill 直接拒绝。
  • 仅做"下一财年是否会被 ST/*ST"的前瞻预测,不做财务造假预测。
  • 输出双轴结果:触线风险等级 + 预测可信度

触发条件

用户提问形如:

  • "分析 000729.SZ 的 ST 风险"
  • "600xxx 下个年报会不会被 ST"
  • "帮我看一下 300xxx 是否有退市风险"

收到此类请求时,按下面"分析流程"执行;其他场景不要主动启用本 skill。

数据获取规范(tushare 优先 → akshare 兜底)

铁律

  1. 所有财务/基本面/分红/审计/ST 状态数据,必须先调用 tushare skill,按下表指定的接口名、ts_codeperiod 拉取。
  2. 当 tushare 接口因积分不足、token 缺失或返回空时,回退到 akshare skill 对应函数。
  3. akshare 兜底数据必须在最终输出"备注"中显式标注数据源:akshare(非官方聚合,不保证完整性,建议核对原始公告)不允许只用 akshare 给出"高可信度"预测——akshare 兜底的红线项可信度强制降一档(高→中高,中高→中,中→低)。
  4. 监管处罚(E2)走本 skill 自带的 scripts/fetch_sina_penalties.py,不经过 tushare/akshare。

数据需求映射表

数据需求 tushare 接口(首选) 抓取参数 / 时间窗口 akshare 兜底 akshare 注意事项
当前 ST 状态 stock_st 最近一个交易日 stock_zh_a_st_em() 仅返回当前 ST/退市整理板列表,历史不可查
历史改名 namechange ts_code 全历史 stock_zh_a_new_em()(仅新股,无改名) akshare 无完整改名接口,必要时跳过
股票基础信息(板块判断) stock_basic list_status='L' stock_individual_info_em(symbol) 字段名不同,需自行映射
业绩预告 forecast ts_code + 最近 2 个 period({Y}0630/{Y}0930/{Y}1231 stock_yjyg_em(date='YYYYMMDD') 按报告期日期反查,需先按 period 拉全市场再筛 ts_code
业绩快报 express 同上,最近 2 个 period stock_yjbb_em(date='YYYYMMDD') 同上,全市场快照需筛
利润表 income ts_code + 最近 5 个 period(过去 4 年年报 {Y}1231 + 最新中报/三季报) stock_financial_report_sina(stock='sh600000', symbol='利润表') 单位不一致(万元 vs 元),需做归一;季报缺失常见
资产负债表 balancesheet 同上 stock_financial_report_sina(stock='sh600000', symbol='资产负债表') 同上
现金流量表 cashflow 同上 stock_financial_report_sina(stock='sh600000', symbol='现金流量表') 同上
财务指标(扣非净利润等) fina_indicator ts_code + 最近 5 个 period stock_financial_analysis_indicator(symbol='600000') 字段中文,扣非字段名为"扣除非经常性损益后的净利润"
审计意见 fina_audit ts_code + 最近 2 个年报 period akshare 无对应接口 缺失时在输出中标注"审计意见数据缺失",不得跳过——必须提示用户去官网查
分红 dividend ts_code + 近 5 年 div_proc='实施' stock_history_dividend_detail(symbol='600000', indicator='分红') 字段中文,需把"派息"金额×总股本得到现金分红总额
日线行情(1 元退市预警) daily ts_code + 最近 30 个交易日 stock_zh_a_hist(symbol='600000', period='daily', adjust='') 必须用不复权价格判断 1 元退市线
每日指标(市值) daily_basic ts_code + 最近一个交易日 stock_zh_a_spot_em() 全市场快照筛 代码=600000 字段名为"总市值"(单位:元,东方财富 push2 原始口径,akshare 不做缩放),换算成亿元需 /1e8。⚠️ 不要与 tushare daily_basic.total_mv(万元)混淆——本列是 akshare 兜底口径
财报披露日期 disclosure_date ts_code + 当前年度 akshare 无对应接口 缺失时按经验估算(4/30 年报、8/31 中报、10/31 三季报)
监管处罚 走本 skill 自带 sina 脚本 见 E2 章节

时间窗口口径统一

按数据类型分别处理,禁止用单一 60 天经验值统一对齐

  • 财务报表(income / balancesheet / cashflow / fina_indicator):以 disclosure_date 实际公告日为准;该接口不可用时按法定截止日(年报 4/30、中报 8/31、三季报 10/31、一季报 4/30)做兜底。在公告日 +1 天起方可视该 period 为"最新可得"。
  • "过去 N 年年报":一律 period = {Y}1231,不要用日历年起止。
  • 业绩预告 forecast / 业绩快报 express:只取 ann_date ≥ 当前年度 1 月 1 日 的记录;按 ann_date 倒序取最新一条,老 period 的预告对预测无效。
  • dividend:按 (end_date, ann_date, cash_div_tax) 三元组强制去重——tushare 同一笔分红会出现 3-4 行(预案/股东大会通过/实施),直接累加会三倍误算。

第一步:当前状态核查(M0)

判断公司当前是否已被风险警示,并据此调整分析方向(不一刀切结束)

调用顺序:

  1. 优先调用 stock_st(tushare skill,3000 积分),按当前最近交易日查询;记录 type / type_name
  2. 如积分不足,回退到 namechange(免费):拉取 ts_code 全部历史改名记录,取按 start_date 排序的最新一条;判断 name 前缀。
  3. 兜底用 stock_basic.name 做名称确认。

分支处理

当前状态 分析方向 是否继续
正常股票 预测下一财年是否会被 ST/*ST (默认流程)
已 ST(普通) 改为预测:是否会进一步转 *ST 或退市;R1-R4 阈值需更严格(亏损链门槛降一年)
已 *ST 改为预测:是否会被强制退市;重点看 R1 营收 + R2 净资产 + E1 审计意见
已退市整理期 / 已摘牌 直接结束

第二步:板块阈值表(决定红线)

先用 ts_code 前缀判断板块,再套用对应阈值。不要混用。

板块 代码识别 营收红线 市值退市线 三年累计分红阈值
主板 60xxxx.SH / 00xxxx.SZ(除 30 / 688 开头外) 净利润为负 且 营收 < 3 亿 市值 < 5 亿 累计 < 5000 万 且 < 年均净利润 30%
创业板 30xxxx.SZ 净利润为负 且 营收 < 1 亿 市值 < 3 亿 累计 < 3000 万 且 < 年均净利润 30%(研发豁免:研发投入占营收 ≥ 5% 或近三年累计 ≥ 6000 万)
科创板 688xxx.SH 净利润为负 且 营收 < 1 亿 市值 < 3 亿 累计 < 3000 万 且 < 年均净利润 30%(研发豁免:研发投入占营收 ≥ 5% 或近三年累计 ≥ 6000 万)

第三步:预测时点选择

按"最新可得证据"原则确定基准时点,从下到上择优:

基准时点 数据接口 可信度基线 适用季节
业绩预告 forecast forecast 1 月底 / 7 月中旬 / 10 月底高发期
业绩快报 express express 1-4 月年报前夕
三季报 income/balancesheet/cashflow (period=YYYYMMDD,9 月末) 中高 10 月底披露后到次年年报前
中报 同上,6 月末 period 8 月底披露后到三季报前
去年年报 同上,12 月末 period 仅作为基准对照

证据优先级(同一指标多个来源时,高的覆盖低的):

forecast / express > 三季报 > 中报 > 去年年报 > 经验外推

输出时必须在每个预测项明示采用了哪一级证据。如果存在 forecast 给出的全年净利润区间,禁止再用三季报机械年化覆盖

第四步:四项可预测红线

R1 营收 + 净利润红线

目标:预测全年营收、归母净利润和扣非净利润,按监管口径"扣非前后孰低者"判定。

口径关键:监管原文是 min(n_income, profit_dedt) < 0revenue < 板块阈值 —— 必须同时预测扣非净利润,不能只用归母。仅看归母会漏掉"归母为正但扣非为负"的造壳公司。

预测方法(按基准时点选用,至少一种)

  • forecast 直采法:若 forecast 给出 net_profit_min / net_profit_max,直接取区间作为全年归母预测;扣非用过去两年扣非率(profit_dedt / n_income 中位数)折算;可信度=高。营收红线仍需结合最新报表外推。
  • express 直采法:若 express 已披露,revenue / n_income 即为全年快报值;扣非同样按过去两年率折算(express 一般无扣非字段);可信度=高。
  • Q4 单季回补法(三季报基准):
    • Q1Q3_revenue = 三季报营业收入
    • Q4_revenue_est = 过去两年 Q4 营收占全年比例的中位数 × 当前年化预估值
    • revenue_full_year_est = Q1Q3_revenue + Q4_revenue_est
    • n_income / profit_dedt 同法处理
    • 可信度=中高
  • 下半年情景外推法(中报基准,强季节性公司必须用):
    • 取过去两年 H2 营收占全年比例均值,给出悲观/基准/乐观三情景
    • revenue_full_year_est = H1_revenue / H1_share_avg
    • 可信度=中
  • 同比延续法(中报基准,弱季节性公司可用):
    • revenue_full_year_est = H1_revenue × (last_year_full_revenue / last_year_H1_revenue)
    • 可信度=中

禁止:H1 直接乘 2、Q1-Q3 直接乘 4/3。任何机械年化强制降到"低"可信度并在输出中注明。

触线判定(口径:worst_profit = min(n_income_est, profit_dedt_est)):

  • 高风险:worst_profit < 0revenue_est < 板块阈值
  • 中风险:worst_profit < 0 但营收达标;或营收逼近阈值(< 阈值 × 1.2)
  • 低风险:上述均不满足

系数说明:R1 中风险的 1.2 是预测项预警 buffer(预测本身有误差,需窄 buffer);R4 高风险的 1.5 是双年联动判定 buffer(两年都亏且营收接近阈值才是真退市信号,需宽 buffer)。两个系数不同是有意为之,不要错误地统一

R2 年末净资产红线

目标:判断年末归母股东权益是否可能转负。

方法

  1. 取最新一期 balancesheet.total_hldr_eqy_exc_min_int(最新中报或三季报),记为 current_eq
  2. 计算 eq_year_end_est = current_eq + 剩余季度净利润预测 − 当前年度已实施现金分红总额
    • 剩余季度净利润:中报基准用 R1 的 H2 预测,三季报基准用 R1 的 Q4 预测。
    • 已实施分红总额:见 R3 的去重 + 量纲公式 cash_div_tax / 10 × total_share

触线判定(统一相对阈值,单位:元):

  • 高风险:current_eq < 0eq_year_end_est < 0
  • 中风险:0 ≤ eq_year_end_est < 1e8(1 亿元)
  • 低风险:eq_year_end_est ≥ 1e8

注意:商誉减值、长期股权投资减值在 Q3/Q4 集中确认,应在备注提示"若计提大额减值,净资产可能进一步下行",但不得在没有公告依据时擅自减值

R3 分红达标前瞻

目标:判断"近三年累计现金分红 < 年均净利润 30% 且 < 板块累计阈值"是否会在下一次年度考核时同时满足(监管原文:两条件同时触发才警示)。

单笔分红量纲公式必须用此公式,不要用 cash_div_tax × base_share):

cash_dividend_total = cash_div_tax / 10 × total_share

其中 cash_div_tax 来自 dividend(每 10 股派现金额,含税),total_share 来自 daily_basic.total_share(最新总股本,单位万股 → 需 ×1e4 换成股)或 stock_basic。tushare dividend.base_share 字段对很多公司为 None,禁止直接使用

方法

  1. dividend 拉取该 ts_code 近五年记录,按 (end_date, ann_date, cash_div_tax) 三元组强制去重——同一笔分红 tushare 会返回"预案/股东大会通过/实施"3-4 行。
  2. 折算系数(按 div_proc 状态):实施=1.0 / 股东大会通过=0.7 / 预案=0.5;同一 end_date 取系数最高那条。
  3. income 拉取近三年完整年度归母净利润(period=YYYY1231)。
  4. 计算考核窗口 = [当前年-2, 当前年],即"过去两年已落地分红 + 本年度预计分红"。
  5. 本年度预计分红:
    • dividend 已查到本年度记录:按上面折算系数计入。
    • 否则用"过去两年平均分红率"× R1 预测全年净利润(基准情景)做估算,可信度降一档。
  6. 与年均净利润比较:
    • 条件 A:cumulative_div_3y < 30% × avg_n_income_3y
    • 条件 B:cumulative_div_3y < 板块累计阈值
  7. 创业板 / 科创板若研发投入占比满足豁免条件,备注提示"研发达标可能豁免"。

触线判定

  • 高风险:A 和 B 同时满足 过去三年至少一年净利润为正(即"盈利年份未达标"——监管以盈利年为基准)。
  • 中风险:仅一个条件满足;或本年度分红尚未公告。
  • 低风险:累计分红已稳定达标;或过去三年累计净利润 ≤ 0(无分红基础,按 R1 联动)。

禁止:本年度尚未公告分红时,不得断言"必然不达标",只能给出概率。

R4 连续亏损 / 扣非亏损链

目标:判断是否会触发"连续两年扣非前后净利润孰低者为负" → *ST。

口径关键:监管原文是连续两年(不是三年),且 *ST 财务类强制退市的法定条件是 "亏损 + 营收<板块阈值" 必须同时满足——只看亏损链会系统性高估风险(实证:闻泰科技 2024 年亏损但营收超千亿,不会被 *ST)。

方法

  1. 取过去一年完整年报的 n_incomefina_indicator.profit_dedt,记 worst_last = min(n_income, profit_dedt)revenue_last
  2. 用 R1 已经预测好的 worst_profit_estrevenue_full_year_est(基准情景),对应当前年度。
  3. 检查两年的 worst < 0 组合,并叠加营收联动条件

触线判定(双条件,亏损链 + 营收联动):

  • 高风险:worst_last < 0worst_profit_est < 0(R1 当前年命中高风险 revenue_full_year_est < 板块阈值 × 1.5)——即两年均亏 + 营收处于退市风险区间。
  • 中风险:(a) 连续两年均亏但营收远超阈值(≥ 阈值 × 1.5)——亏损链成立但不会触发财务类 *ST,仍可能因经营恶化转 ST;(b) 仅 worst_profit_est < 0(当前年预测亏损,去年盈利,未形成连续);(c) 仅 worst_last < 0 但当前年预测为正且接近 0(< 板块阈值 × 0.5)。
  • 低风险:worst_last ≥ 0worst_profit_est ≥ 0

为什么要叠加营收:A 股 *ST 财务类强制退市的法定条件是"扣非前后净利润孰低 < 0 营收 < 板块阈值",二者必须同时满足。仅亏损不达营收阈值的公司(如大型周期股短期亏损)会被市场和监管视作"周期性亏损"而非"持续经营存疑"。

第五步:三项事实/临界证据面(不参与预测可信度)

E1 审计意见(事实)

调用 fina_audit,取最近 2 个完整年报:

  • 高风险:最新年报 audit_result 含"无法表示意见"或"否定意见";或单次出现"保留意见"(实证支持:上交所近年规范类 *ST 案例多为单次保留即触发)。
  • 中风险:连续两年同一负面结论但本期已修正;或带强调事项段的无保留意见涉及持续经营。
  • 低风险:标准无保留意见。

禁止预测下一份审计意见——审计是事后行为。

akshare 兜底缺失时的人工核查路径fina_audit 无 akshare 替代接口,必须给出可点击 URL):

来源 URL 模板 查询方式
巨潮资讯网(公告原文,权威) http://www.cninfo.com.cn/new/disclosure/stock?orgId=&stockCode={code6} 进入页面后筛选"定期报告 → 年度报告",下载 PDF 在第十节"财务报告 → 审计报告"查 审计意见类型
巨潮高级搜索(按关键词) http://www.cninfo.com.cn/new/fulltextSearch/full?searchkey={code6}+审计报告&sdate=&edate=&isfulltext=false&sortName=time&sortType=desc 直接命中含"审计报告"标题的公告
上交所信息披露 http://www.sse.com.cn/disclosure/listedinfo/regular/?stockCode={code6} 仅限 60xxxx / 688xxx
深交所信息披露 http://www.szse.cn/disclosure/listed/notice/index.html?stock={code6} 仅限 00xxxx / 30xxxx

其中 {code6} 为 6 位股票代码(去掉 .SH / .SZ 后缀)。强制要求:当 fina_audit 返回空时,输出报告的"备注"必须列出上面巨潮的两条 URL 之一,便于用户人工核查;不得只写一句"审计意见数据缺失"了事。

E2 监管处罚(事实,双窗口:上一财年 + 过去 12 个月)

这是本 skill 的关键证据面。

窗口规则(双窗口策略,单次抓取在内存中切片)

  • 窗口 A — [当前年-1 的 1 月 1 日, 当前年-1 的 12 月 31 日](上一个完整财年):用于 reason_normalized 单条评级。
  • 窗口 B — [分析日 - 365 天, 分析日](过去 12 个月滚动):用于频次增强规则
  • 若分析时点已经在 5 月之后且最新年报已披露完毕,窗口 A 可改为 [最新年报 end_date - 365 天, 最新年报 end_date]

调用方式(推荐:单次拉全量 + 内存切片)

python agent/src/skills/ashare-pre-st-filter/scripts/fetch_sina_penalties.py \
  --ts-code 000729.SZ --stock-name 燕京啤酒 --no-filter

返回页面全量记录后,由 LLM 在内存中按窗口 A、窗口 B 切两份。也可以用 --start-date / --end-date 单独抓取,但同一次分析避免发起两次 HTTP

输出 JSON 列表,字段:ann_date / event_type / title / reason / reason_normalized / content / issuer / issuer_normalized / subject_normalized / target_relevance / e2_countable / source_url

相关性铁律:调用脚本时必须传入 --stock-name {股票简称}(来自 stock_basic.name),必要时用 --alias 补充曾用名/简称。新浪页面可能收录“某个人证券账户交易列表里出现目标股票”的记录,这类记录只说明目标股票被交易过,不是上市公司/股东/董监高处罚。脚本会将其标为 target_relevance=security_mention_onlye2_countable=false,E2 频次统计必须排除。

subject_normalized 字段(用于频次权重折算):

  • company — 处罚主体是公司本身(默认;不含个人身份关键词时归此类)
  • shareholder — 控股股东 / 实控人 / 5% 以上大股东
  • officer — 董事 / 监事 / 高管(董事长、总经理、董秘、财务总监等)

风险等级判定

命中 reason_normalized 等级贡献
财务造假 / 虚假陈述 / 信息披露违规 高(强烈预警)
违规担保 / 占用资金 高(直接触及 ST 红线)
内幕交易 / 市场操纵 / 违规减持
其他/unknown 低(仅作背景)

频次增强规则(治理质量预警,窗口 B)

监管函本身反映公司治理与内控质量,密集出现是"规范类 ST"(保留意见、内控非标、信披重大缺陷)的强领先指标。但处罚主体不同,治理含义不同:股东减持违规、董监高短线交易反映的是个人合规问题,不应等同于"公司治理失序"。

主体加权计数(按 subject_normalized 折算后再查表):

加权条数 = Σ 单条权重
  其中:subject_normalized == "company"     → 权重 1.0
        subject_normalized == "officer"     → 权重 0.5
        subject_normalized == "shareholder" → 权重 0.5
过去 12 个月监管函/问询/警示函加权条数 频次等级
≥ 5.0 极高
3.0 - 4.5
2.0 - 2.5
< 2.0

判定来源:仅当 e2_countable=true 时,脚本输出的 event_type ∈ {警示, 问讯, 监管关注, 监管函}issuer_normalized ∈ {上交所, 深交所, 北交所, 证监会, 地方证监局} 才计入条数;条数按 subject_normalized 折算后再查表。target_relevance=security_mention_only 的记录必须排除。

输出要求:必须同时给出"原始条数"和"加权条数"两个数字,便于用户审阅折算逻辑。例如:窗口 B 命中 6 条(公司 2 条 + 股东 3 条 + 高管 1 条 → 加权 4.0 条),频次等级:高

E2 综合等级合成规则(解决单条评级与频次叠加的问题):

E2_单条等级 = 窗口 A 内所有 reason_normalized 单条等级的最大值
E2_频次等级 = 窗口 B 频次表查得
E2_综合等级 = max(E2_单条等级, E2_频次等级)

叠加加成:若同时满足 E2_频次等级 ≥ 高E2_单条等级 ≥ 高(含财务造假/虚假陈述/违规担保/占用资金)→ 直升极高

为什么要这条规则:纯量化红线只能捕捉"财务类 ST",无法预警"规范类 ST"。频次规则把"治理失序"作为前瞻信号纳入。

注意:处罚证据只抬升风险等级,不影响预测可信度——这是事实证据,不是预测项。

E3 交易类临界预警(事实)

调用 daily(近 30 个交易日,必须 adjust='' 不复权)和 daily_basic(最新一日,单位:万元):

1 元退市预警(用 daily.close不复权):

  • 高风险:近 20 个交易日中收盘价 < 1 元的天数 ≥ 10
  • 中风险:≥ 1 但 < 10
  • 低风险:0 天

市值退市预警(用 daily_basic.total_mv,单位万元 → ×1e4 换算成元 → /1e8 换算成亿元):

板块 高风险阈值 中风险阈值
主板 < 5 亿 < 5 × 1.5 = 7.5 亿
创业板 / 科创板 < 3 亿 < 3 × 1.5 = 4.5 亿

第六步:双轴输出模板

每次分析必须按下面模板输出。风险等级 + 可信度两个维度都要给

## ST 风险预测:{name}({ts_code})

### 当前状态
- 是否已 ST/*ST:{是 / 否}
- 板块:{主板 / 创业板 / 科创板}
- 基准预测时点:{forecast / express / 三季报(period) / 中报(period)}

### 量化红线预测(双轴)

| 红线 | 基准情景结论 | 风险等级 | 可信度 | 主要证据 |
|------|-------------|---------|-------|---------|
| R1 营收+净利润 | 全年营收预测 X 亿,净利润 Y 亿 | 高/中/低 | 高/中高/中/低 | forecast/三季报/... |
| R2 年末净资产 | 当前 X 亿,年末预计 Y 亿 | 高/中/低 | 高/中高/中/低 | balancesheet + R1 |
| R3 分红达标 | 三年累计预计 X,对应阈值 Y | 高/中/低 | 中/低 | dividend + income |
| R4 连续亏损链 | 过去两年 + 当前年是否均亏 | 高/中/低 | 同 R1 | income + fina_indicator |

### 事实证据面(不参与预测可信度)

| 证据 | 结论 | 影响 |
|------|------|------|
| E1 审计意见 | 最新结论 | 抬升/无影响 |
| E2 监管处罚(窗口 A 上一财年 / 窗口 B 过去 12 个月) | A 命中 Na 条(最高单条等级:…),B 原始 Nb_raw 条 / 加权 Nb_w 条(公司 a + 股东 b + 高管 c → a×1.0+b×0.5+c×0.5),频次等级:…,E2_综合等级:… | 抬升/无影响 |
| E3 交易类临界 | 收盘价/市值情况 | 抬升/无影响 |

### 综合结论
- **下一财年被 ST/*ST 风险等级**:{极高 / 高 / 中 / 低}
- **预测综合可信度**:{高 / 中高 / 中 / 低}
- **关键风险点**(最多 3 条):...
- **缓解信号**(如有):...

### 备注
- 数据时点:{所用最新报告期}
- 已忽略的不可预测项:财务造假、未来审计意见
- 季节性提醒(如适用):...

禁止事项

  1. 不预测财务造假(事前不可知)。
  2. 不预测下一份审计意见(事后才出)。
  3. 不在没有公告依据时擅自计提减值。
  4. 不混用板块阈值(主板 vs 创业板/科创板的营收/市值/分红阈值不同)。
  5. 不把机械年化(H1×2、Q1Q3×4/3)伪装成"高可信度"。
  6. 不在港股 / 美股 / 加密 / 北交所8xxxxx.BJ,监管规则与本 skill 阈值不一致)上启用本 skill。
  7. 不把"违规处罚记录"计入预测可信度(仅抬升风险等级)。
  8. 不在 R3 分红计算中使用 cash_div_tax × base_share(base_share 经常为 None,会得 0);必须用 cash_div_tax / 10 × total_share,且按 (end_date, ann_date, cash_div_tax) 三元组去重。
  9. 不在 R1 触线判定中只用 n_income;必须用 min(n_income, profit_dedt),否则会漏掉造壳公司。
  10. 不把 R4 写成"连续三年";监管原文是"连续两年"。且 R4 高风险必须叠加营收联动条件——仅"连续两年亏损"不构成 *ST 财务类强制退市,必须同时满足"营收 < 板块阈值 × 1.5"或 R1 已命中高风险,否则只能给中风险。
  11. 不把 E2 监管处罚"按主体一刀切"计数——必须用 subject_normalized 加权(公司 ×1.0 / 股东 ×0.5 / 董监高 ×0.5),否则股东动荡的公司会被系统性高估。

依赖的 tushare 接口清单

用途 接口 备注
当前 ST 状态 stock_st 3000 积分;不可用时回退 namechange
历史改名 namechange 免费
板块判断 stock_basic 免费
利润表 income 2000 积分,多 period 拉取
资产负债表 balancesheet 2000 积分
财务指标(扣非等) fina_indicator 2000 积分
业绩预告 forecast 2000 积分
业绩快报 express 2000 积分
审计意见 fina_audit 500 积分
分红 dividend 2000 积分
日线 daily 免费
每日指标(市值) daily_basic 免费
财报披露日期 disclosure_date 500 积分

自带脚本

调用方式:

# 单次拉全量(推荐:本 skill 双窗口策略由 LLM 在内存中切片)
python agent/src/skills/ashare-pre-st-filter/scripts/fetch_sina_penalties.py \
  --ts-code 000729.SZ --stock-name 燕京啤酒 --no-filter

# 或指定单一窗口
python agent/src/skills/ashare-pre-st-filter/scripts/fetch_sina_penalties.py \
  --ts-code 000729.SZ --stock-name 燕京啤酒 --start-date 2025-01-01 --end-date 2025-12-31

正常情况下输出 JSON 到 stdout;网络/解析失败或参数非法时返回 {"source": "unavailable", "error": "..."} 到 stdout 并以非零退出码结束(不抛 traceback),便于 LLM 兜底处理。

端到端调用伪代码

用于减少 LLM 调用顺序漂移,按下列骨架组织:

import os, json, subprocess
import tushare as ts

ts_code = '000729.SZ'
pro = ts.pro_api(os.environ['TUSHARE_TOKEN'])

# === Step 0: M0 当前状态 ===
basic = pro.stock_basic(ts_code=ts_code, fields='ts_code,name,market').to_dict('records')[0]
st_hit = pro.stock_st()  # 失败则回退 namechange
name_chg = pro.namechange(ts_code=ts_code).sort_values('start_date', ascending=False)

# === Step 1: 板块判断 ===
board = '科创板' if ts_code.startswith('688') else '创业板' if ts_code.startswith('30') else '主板'
threshold_revenue = 1e8 if board != '主板' else 3e8
threshold_mv = 3e8 if board != '主板' else 5e8

# === Step 2: 拉财务(最新 5 期 + 过去 4 年年报) ===
income = pro.income(ts_code=ts_code).sort_values('end_date', ascending=False).drop_duplicates('end_date')
balance = pro.balancesheet(ts_code=ts_code).sort_values('end_date', ascending=False).drop_duplicates('end_date')
fina_ind = pro.fina_indicator(ts_code=ts_code).sort_values('end_date', ascending=False).drop_duplicates('end_date')
forecast = pro.forecast(ts_code=ts_code).sort_values('ann_date', ascending=False)
express = pro.express(ts_code=ts_code).sort_values('ann_date', ascending=False)

# === Step 3: R1-R4 计算(按各章节口径,注意 min(n_income, profit_dedt)) ===
# ... 略

# === Step 4: E1 审计 ===
audit = pro.fina_audit(ts_code=ts_code).sort_values('end_date', ascending=False).head(2)

# === Step 5: E2 监管处罚(双窗口 + 主体加权)===
from datetime import date, timedelta
result = subprocess.run([
    'python', 'agent/src/skills/ashare-pre-st-filter/scripts/fetch_sina_penalties.py',
    '--ts-code', ts_code, '--stock-name', basic['name'], '--no-filter',
], capture_output=True, text=True)
penalties = json.loads(result.stdout).get('records', [])

# 在内存中切双窗口(避免两次 HTTP)
this_year = date.today().year
win_a_start, win_a_end = f'{this_year-1}-01-01', f'{this_year-1}-12-31'
win_b_start = (date.today() - timedelta(days=365)).isoformat()
win_b_end   = date.today().isoformat()

def _in(rec, s, e):
    d = rec.get('ann_date') or ''
    return bool(d) and s <= d <= e

win_a = [r for r in penalties if _in(r, win_a_start, win_a_end)]
win_b = [r for r in penalties if _in(r, win_b_start, win_b_end)]

# 窗口 A:单条等级取最高
REASON_LEVEL = {
    '财务造假': 3, '虚假陈述': 3, '信息披露违规': 3,
    '违规担保': 3, '占用资金': 3,
    '内幕交易': 2, '市场操纵': 2, '违规减持': 2,
}
levels_a = [REASON_LEVEL.get(r['reason_normalized'], 1) for r in win_a]
e2_single = max(levels_a) if levels_a else 0

# 窗口 B:原始条数 + 主体加权条数
FREQ_EVENT_TYPES = {'警示', '问讯', '监管关注', '监管函', '警示函'}
FREQ_ISSUERS = {'上交所', '深交所', '北交所', '证监会', '地方证监局'}
SUBJECT_WEIGHT = {'company': 1.0, 'shareholder': 0.5, 'officer': 0.5}

freq_pool = [r for r in win_b
             if r.get('e2_countable', True)
             and (r['event_type'] in FREQ_EVENT_TYPES
                  or r['issuer_normalized'] in FREQ_ISSUERS)]
nb_raw = len(freq_pool)
nb_weighted = round(sum(SUBJECT_WEIGHT.get(r['subject_normalized'], 1.0)
                        for r in freq_pool), 1)

# 频次等级(基于加权条数)
if nb_weighted >= 5.0:    e2_freq = 4   # 极高
elif nb_weighted >= 3.0:  e2_freq = 3   # 高
elif nb_weighted >= 2.0:  e2_freq = 2   # 中
else:                     e2_freq = 1   # 低

e2_overall = max(e2_single, e2_freq)
# 叠加加成:频次高 + 单条高同时命中 → 直升极高
if e2_freq >= 3 and e2_single >= 3:
    e2_overall = 4

# === Step 6: E3 交易临界 ===
daily = pro.daily(ts_code=ts_code).sort_values('trade_date', ascending=False).head(30)
daily_basic = pro.daily_basic(ts_code=ts_code).sort_values('trade_date', ascending=False).head(1).iloc[0]
total_mv_yi = daily_basic['total_mv'] * 1e4 / 1e8  # 万元 → 亿元

# === Step 7: 双轴合成输出 ===
# 风险等级 = max(R1, R2, R3, R4, E1, E2_综合, E3)
# 可信度 = 加权平均(R1, R2, R3, R4 各项可信度),akshare 兜底项降一档
Install via CLI
npx skills add https://github.com/HKUDS/Vibe-Trading --skill ashare-pre-st-filter
Repository Details
star Stars 12,356
call_split Forks 2,381
navigation Branch main
article Path SKILL.md
More from Creator