# 市场阶段(情绪周期)与主线识别 本文说明市场环境页的阶段体系与主线识别的口径、阈值来源、持久化设计、已知偏差与运行方式。它与原有的 5 档环境 state 并存,不替代任何既有消费方。 ## 功能边界 阶段体系回答"市场处于情绪周期什么位置",主线识别回答"当前/某阶段内什么板块概念在领涨"。两者都只用本地已存储数据(`consecutive_limit_ups`、`amount`、概念映射快照),不依赖扩展数据源,2020-08 起全历史可回算。 明确不做的: - 挖掘、回测环境过滤、因子 regime 统计仍用原 5 档 `state`,本期不切换到阶段体系。 - 概念成分是当前快照,不改成 timeseries 积累模式(见「快照回填偏差」)。 - 不生成任何交易信号;阶段与主线仅供研究分析。 ## 与 5 档 state 的关系 | | `state`(原有) | `phase`(本期新增) | |---|---|---| | 驱动量 | 赚钱/投机/抗跌/趋势 4 维综合分 | 连板梯队:高度、宽度、晋级率、梯队完整度 | | 档位 | 强势/偏强/震荡/偏弱/弱势(5 档) | 冰点/启动/主升/高潮/退潮/修复(6 阶段) | | 消费方 | 回测环境过滤、挖掘、策略页 | 市场环境页分析与主线识别 | | 持续性 | 日频打分,切换频繁(历史 76.6% 天数发生切换,平均段长 1.1-1.5 天) | EMA 平滑 + 2 日确认,平均段长 9.7 天 | `state`/`score` 列原样保留,新列(`phase`、`first_board`、`ge2_count`、`ge3_count`、`ge5_count`、`ladder_completeness`、`promo_rate`、`promo_pool`)对既有消费方透明。 ## 每日梯队指标 全部由已存储的 `consecutive_limit_ups` 列向量化派生,实现在 `backend/app/services/market_phase.py`: - `first_board`:首板(1 连板)家数。 - `ge2_count` / `ge3_count` / `ge5_count`:N 板以上家数(宽度)。 - `promo_rate` 晋级率:昨日连板池今日继续封板的比例。昨日连板数用 `consec.shift(1).over("symbol")` 按个股前一日连接(跨批次边界也正确,`_compute_batch` 在 warmup 截断前计算);池不足 10 家记 `null`(小样本噪声),不填 0。 - `ladder_completeness` 梯队完整度:2..height 档位中非空档位占比;height < 3 时为 `null`。 - 高度(`max_consecutive`)与封板率(`seal_rate`)沿用 regime 已有列。 ## 阶段规则 词汇与优先级:`climax 高潮 > rally 主升 > ebb 退潮 > ignite 启动 > ice 冰点 > repair 修复(兜底)`。冰点排在退潮前判定——长期死市不应被标成"自高位退潮"。 阈值标定自 2020-08~2026-08 全市场 1454 个交易日的 p10/p60/p90 分位数,全部集中在模块顶部常量,调整只改那里: | 阶段 | 核心条件(EMA 平滑后) | |---|---| | 高潮 climax | ge2 ≥ 50(p90 的 2 倍)或首板 ≥ 220(p90 的 2.5 倍),历史占比 <2% | | 主升 rally | 高度 ≥7 且 ge2 ≥15 且晋级率 ≥0.23(全中位以上);或晋级率 ≥0.30(p85+)配合高度 ≥5、ge2 ≥12 | | 退潮 ebb | 晋级率 <0.15(p20)且宽度自 5 日前高位(ge2>12 或高度>6)回落;或晋级率 <0.13 且封板率 <0.57 双弱 | | 启动 ignite | 宽度/高度自低位扩张(ge2 较 5 日前 +3 且 ≥8,或高度抬升且 ≥5)且晋级率恢复到 ~0.19-0.20 | | 冰点 ice | 高度 ≤4、ge2 ≤6、首板 ≤24 同时贴地(均 ~p10) | | 修复 repair | 兜底 | **持续性设计**:驱动量先做 EMA 平滑(alpha=1/3,约 5 日),原始标签出来后再做 2 日确认(切换需连续 2 日出现新标签才生效)。 **弱档否决**:5 档 `state ∈ {weak, lean_weak}` 时,正向阶段(主升/高潮/启动)一律降为修复。这修复了一类错标:连板梯队强但大盘崩的交易日(如 2024-01 微盘流动性危机)会被梯队指标误判为主升/启动——涨停生态与大盘背离时,以大盘弱势为准。 **回填验收**(1454 天真实数据):平均段长 9.7 天(对比原 5 档的 1.1-1.5 天)。抽查:2024-09-24→10-08 为启动→主升→高潮(九二四行情);2024-01/02 微盘崩为退潮/冰点;高潮 6 年仅 2 段(2024-10-08、2024-10-31 ST 重组潮 17 板),均为真实极端期。 已知特性,如实说明:退潮/冰点天然是短段(平均 2.8/2.5 天)——恐慌释放本身快于趋势形成;修复是占比最高的兜底段(~74% 天数),A股大部分时间没有处于可辨认的周期位置。 ## 主线识别 实现在 `backend/app/services/market_mainline.py`。复用 `rps_rotation` 的概念映射加载,窄扫描 `kline_daily_enriched` 的 symbol/date/consecutive_limit_ups/amount 四列,按 (date, 概念/行业) 聚合: - `limit_up_count` 涨停家数、`ge2_count` 二板以上家数、`max_boards` 最高板、`boards_sum`、`rungs_filled` 梯队档位数、龙头股(按连板数、成交额排序取第一)。 - 主线分 = 当日截面 rank 归一后 `0.35*涨停数 + 0.25*最高板 + 0.25*梯队档位数 + 0.15*二板宽度`。这是"同板块涨停越多、梯队越完整越是主升主线"判据的直接量化。 - 每概念当日涨停 <3 家不参与排名;每日持久化 top30 到 `data/mainline_history/part.parquet`(upsert 按 date+kind 整日替换)。 - 行业维度取前两级(如 `计算机-软件开发`),作为概念维度的交叉验证。 ### 宽基/风格标签过滤 融资融券(~7700 家)、沪深股通(~3300 家)这类超大概念会垄断 top1,需要过滤。配置存于用户偏好(`preferences.json`),市场环境页「过滤」面板可改: - 成员数上限:默认 600,超过视为宽基/风格标签不参与排名(夹取范围 50-5000)。保留华为概念(2006)、人工智能(2166)等真主题。 - 成员数下限:默认 4(夹取 1-200)。 - 名称黑名单:手动屏蔽任意概念,支持逗号/分号/空格分隔。 修改保存后自动触发全量主线重算(`POST /api/regime/mainline/recompute`,秒级)。API 层为 `PUT /api/preferences/mainline-filter`。 ### 快照回填偏差 概念成分为**当前快照回看历史**(本地自 2026-07 起留存,无历史版本)。新纳入指数或改名的个股会出现在旧时段、成分调整会错归属,因此早年主线存在归属漂移,越近越准。此口径限制以 `membership_note` 字段随 API 返回并在页面展示。若后续把 ext 概念同步改为按月累积快照,主线历史精度会逐月自然提升。 ## API 与运行 - `GET /api/regime/phases?start&end`:连续阶段段列表(阶段、区间、天数、高度/宽度/晋级率/封板率均值、段内 top 主线)。 - `GET /api/regime/mainline?start&end&top&kind`:窗口内主线排行(top1 天数、日均分、最高板)与每日明细。 - `POST /api/regime/mainline/recompute`:过滤配置变更后的全量重算(两类维度)。 - `POST /api/regime/recompute`:扩展为重算 regime 后自动重标 phase 并回填主线。 - daily pipeline 在 regime 步骤后追加主线增量(复用 `pipeline_regime_enabled` 开关,软失败不阻塞)。 阶段标签由 `regime_builder.refresh_phase_labels` 在每次 regime upsert 后对全量历史重标(1454 行,开销可忽略)——因为 EMA 与 2 日确认依赖完整序列。 ## 测试 - `backend/tests/test_market_phase.py`:梯队聚合、晋级率(池不足记 null)、梯队完整度、阶段序列规则、弱档否决、持续性(噪声下不出现 1 日翻转)、refresh 往返。 - `backend/tests/test_market_mainline.py`:概念/行业聚合、宽基过滤、黑名单、最少涨停家数、同日 upsert 替换、增量补齐、偏好读写与夹取。