Przeglądaj źródła

feat(roi-control): productionize daily ROI workflow

刘立冬 4 dni temu
rodzic
commit
345714b6bf
31 zmienionych plików z 3075 dodań i 189 usunięć
  1. 7 0
      AGENTS.md
  2. 4 2
      examples/auto_put_ad_mini/.env.example
  3. 1 1
      examples/auto_put_ad_mini/docs/ad_automation_platform_architecture_plan_2026-07-25.md
  4. 118 0
      examples/auto_put_ad_mini/docs/roi/T15成熟系数计算说明.md
  5. 373 0
      examples/auto_put_ad_mini/docs/roi/T15成熟系数迁移指南.md
  6. 48 6
      examples/auto_put_ad_mini/docs/unified_services_deployment.md
  7. 153 0
      examples/auto_put_ad_mini/refresh_roi_fission_multiplier.py
  8. 42 0
      examples/auto_put_ad_mini/roi_control/data/fission_multiplier/20260712_A0-A15_v1/T15分级回退系数_中文_20260712.csv
  9. 111 0
      examples/auto_put_ad_mini/roi_control/data/fission_multiplier/20260712_A0-A15_v1/公众号T15成熟系数_中文_20260712.csv
  10. 41 0
      examples/auto_put_ad_mini/roi_control/data/fission_multiplier/20260712_A0-A15_v1/小程序T15成熟系数_中文_20260712.csv
  11. 8 1
      examples/auto_put_ad_mini/roi_control/data_source.py
  12. 1 1
      examples/auto_put_ad_mini/roi_control/execution.py
  13. 50 18
      examples/auto_put_ad_mini/roi_control/feishu.py
  14. 581 0
      examples/auto_put_ad_mini/roi_control/fission_multiplier.py
  15. 423 0
      examples/auto_put_ad_mini/roi_control/fission_multiplier_refresh.py
  16. 118 13
      examples/auto_put_ad_mini/roi_control/metrics.py
  17. 47 0
      examples/auto_put_ad_mini/roi_control/policy.py
  18. 138 86
      examples/auto_put_ad_mini/roi_control/reporting.py
  19. 127 6
      examples/auto_put_ad_mini/roi_control/repository.py
  20. 39 12
      examples/auto_put_ad_mini/roi_control/rules.py
  21. 92 19
      examples/auto_put_ad_mini/roi_control/service.py
  22. 123 0
      examples/auto_put_ad_mini/roi_control/sql/fission_multiplier/20260712_A0-A15_v1/公众号合作即转_A0-A15_20260712.sql
  23. 121 0
      examples/auto_put_ad_mini/roi_control/sql/fission_multiplier/20260712_A0-A15_v1/小程序人群包转化目标_A0-A15_20260712.sql
  24. 34 19
      examples/auto_put_ad_mini/test_roi_control_metrics.py
  25. 7 1
      examples/auto_put_ad_mini/test_roi_control_policy.py
  26. 179 0
      examples/auto_put_ad_mini/test_roi_fission_multiplier.py
  27. 3 1
      examples/tencent_realtime_control/.env.example
  28. 8 1
      examples/tencent_realtime_control/README.md
  29. 2 2
      examples/tencent_realtime_control/realtime_config.py
  30. 39 0
      examples/tencent_realtime_control/schema.sql
  31. 37 0
      examples/tencent_realtime_control/storage.py

+ 7 - 0
AGENTS.md

@@ -32,6 +32,13 @@
 
 - ROI 是指导渠道、账户、广告和创意动作的核心北极星指标,必须作为独立领域模块维护,不能散落在飞书、腾讯 API 或调度代码中。
 - ROI 指标计算必须保持纯数据输入/输出,不能依赖飞书审批、腾讯写操作或具体动作执行器。动作策略只能消费一个明确的 `metric_version`。
+- 当前日级 ROI 指标版本为 `north_star_roi_t15_v3`,报表版本为 `roi_report_v4`,使用已发布参数 `20260712_A0-A15_v1`。T0 裂变收入是实际值,只预测 T1-T15 增量:`T0实际裂变收入 * (传播裂变系数-对T0裂变 - 1)`;预测总收入为 `首层实际效率收入 + T0实际裂变收入 + 预测T1-T15裂变收入`,禁止重复计算 T0。
+- 小程序传播裂变系数按 `人群包+转化目标精确 -> 人群包回退 -> 转化目标回退 -> 渠道回退` 匹配;公众号按 `合作方+公众号精确 -> 合作方回退 -> 渠道回退` 匹配。样本不足的精确实体不能使用自身系数。
+- 小程序日级 ODPS 数据必须保留 `广告优化目标`;缺失目标只能进入人群包回退,不得默认成关键页面访问。企微 ROI 口径未复核,当前按渠道/合作方保留快照和报表,临时参考系数为 1.0 并明确标注待补算;企微不进入阈值样本池且不得生成调控动作。
+- ROI 审批表金额和 UV 默认展示三日窗口的单日均值,UV 显示为整数;预测 ROI、实际 ROI、裂变率和阈值必须继续使用三日汇总后的加权口径,不能对每日比例做算术平均。原始三日汇总和每日明细字段保留为隐藏审计列。
+- ROI 审批表应展示所有进入阈值样本池的小程序和公众号实体,以及全部企微参考实体;不能只展示有动作的数据。每个渠道 Sheet 默认按预测 ROI 倒序排列。
+- 成熟参数是独立版本化只读资产。审计后的参数必须通过更新脚本发布到 MySQL 的 `roi_fission_parameter_release` 和 `roi_fission_parameter_value`;日级 ROI 只从数据库消费 `ROI_FISSION_PARAMETER_VERSION` 指定且通过内容哈希校验的版本,不能在日常任务中现场重算或静默回退到镜像文件。离线复算只能生成草稿,经恒等式、行数、匹配率和新旧结果对账后才能发布。
+- ROI 报表只上传一次,同一在线表链接发送到 ROI 通知群和 `FEISHU_OPERATOR_CHAT_ID` 投放审批群;群 ID 相同时必须去重。
 - ROI 公式、收入/成本归属、裂变口径或实体粒度发生语义变化时,必须升级指标版本并保存新快照;不得覆盖或重算成旧版本历史结果。
 - 策略阈值和动作语义使用独立 `policy_version`;指标版本与策略版本必须同时写入每个运行批次。
 - 每次运行必须保存完整实体快照、阈值配置、动作建议、可执行性原因和最终执行审计,不能只保存候选或飞书表格。

+ 4 - 2
examples/auto_put_ad_mini/.env.example

@@ -38,7 +38,9 @@ ROI_APPROVAL_TTL_MINUTES=120
 ROI_SCALE_RATIO=1.10
 ROI_SCALE_COOLDOWN_DAYS=3
 ROI_MAX_BASE_RATIO=2.00
-# 为空时依次复用 RTC_COMMAND_CHAT_ID / FEISHU_AD_PROJECT_CHAT_ID
+ROI_FISSION_PARAMETER_VERSION=20260712_A0-A15_v1
+# ROI报表发送到此群;同时抄送 FEISHU_OPERATOR_CHAT_ID,重复ID自动去重
+# 为空时依次复用 FEISHU_AD_PROJECT_CHAT_ID / RTC_COMMAND_CHAT_ID
 ROI_FEISHU_CHAT_ID=
 
 RTC_START_HOUR=12
@@ -46,7 +48,7 @@ RTC_STOP_HOUR=21
 RTC_POLL_SECONDS=600
 RTC_HIGH_CPM=250
 RTC_LOW_CPM=190
-RTC_BID_UP_RATIO=1.25
+RTC_BID_UP_RATIO=1.05
 RTC_MAX_PARTITION_LAG_HOURS=2
 RTC_APPLY_ENABLED=0
 RTC_COMMAND_ENABLED=1

+ 1 - 1
examples/auto_put_ad_mini/docs/ad_automation_platform_architecture_plan_2026-07-25.md

@@ -65,7 +65,7 @@
 
 实时 CPM 规则保持:
 
-- `CPM > 250`:基础出价上调 25%,每天最多一次。
+- `CPM > 250`:基础出价上调 5%,每天最多一次。
 - `190 <= CPM <= 250`:恢复基础出价和 CPM 策略暂停。
 - `CPM < 190`:恢复基础出价,将开始日期延后至次日,保持广告开启。
 - 默认每天 21:00:只恢复基础出价,不主动暂停广告。

+ 118 - 0
examples/auto_put_ad_mini/docs/roi/T15成熟系数计算说明.md

@@ -0,0 +1,118 @@
+# A0~A15成熟系数计算说明
+
+## 1. 最终口径
+
+本次固定使用`20260712`首层投放用户作为cohort,观察至`20260727`:
+
+| 项目 | 口径 |
+|---|---|
+| 观察周期 | A0~A15 |
+| 小程序实体 | 人群包 + 转化目标 |
+| 公众号实体 | 合作方 + 公众号 |
+| 首层 | `opengid_base_data.usersharedepth=0` |
+| 裂变活跃 | 同一首层rootSession在`user_share_log`中产生的`topic='click' AND usersharedepth>0`活跃用户 |
+| 去重 | 同一实体同一自然日按用户去重;隔日再次活跃重新计入 |
+| 排除 | 排除原首层cohort用户,避免把首层种子计作自身裂变后代 |
+
+小程序的空人群包统一记为“泛人群”,空或字符串`null`转化目标统一记为“未知”。
+
+## 2. 核心公式
+
+定义:
+
+```text
+U0       = A0活跃裂变UV
+Uk       = Ak自然日活跃裂变UV,k=1..15
+Utotal   = U0+U1+...+U15
+```
+
+最终用于ROI的参数:
+
+```text
+T1~T15相对T0尾部系数
+= (U1+...+U15) / U0
+
+T15成熟系数(相对T0)
+= Utotal / U0
+= 1 + T1~T15相对T0尾部系数
+```
+
+`T15成熟系数`已经包含A0当天,不得在收入中重复增加一次T0。
+
+## 3. 收入与ROI
+
+优先使用当天已经观测到的实际收入:
+
+```text
+预测T0~T15裂变总收入
+= T0实际裂变收入 × T15成熟系数
+
+预测总收入
+= 首层实际效率收入
+ + T0实际裂变收入 × T15成熟系数
+
+预测ROI
+= 预测总收入 / 投放成本
+```
+
+## 4. 样本状态和回退
+
+精确实体同时满足以下条件时标记为“可用”:
+
+```text
+首层UV >= 500
+且 A0活跃裂变UV >= 200
+```
+
+小程序参数回退顺序:
+
+```text
+人群包+转化目标
+→ 人群包总量比
+→ 转化目标总量比
+→ 小程序渠道总量比
+```
+
+公众号参数回退顺序:
+
+```text
+合作方+公众号
+→ 合作方总量比
+→ 公众号合作即转渠道总量比
+```
+
+所有回退系数都使用A0加权总量比:
+
+```text
+回退T15成熟系数
+= SUM(A0~A15累计裂变活跃人次)
+  / SUM(A0活跃裂变UV)
+```
+
+不能对各实体成熟系数做算术平均。
+
+## 5. 20260712真实结果摘要
+
+| 渠道 | 精确实体数 | 可用实体数 | 渠道回退T15系数 |
+|---|---:|---:|---:|
+| 小程序投流 | 40 | 21 | 2.608491 |
+| 公众号合作即转 | 110 | 93 | 2.476153 |
+
+样本不足实体仍保留在结果表,通过“样本状态”标记,并在正式使用时走分级回退。
+
+## 6. 运行方式
+
+```bash
+python3 calculate_final_t15_coefficients.py --cohort-date 20260712
+```
+
+输出:
+
+- `outputs/小程序T15成熟系数_中文_20260712.csv`
+- `outputs/公众号T15成熟系数_中文_20260712.csv`
+- `outputs/T15分级回退系数_中文_20260712.csv`
+- `outputs/最终T15成熟系数_中文_20260712.xlsx`
+- `outputs/小程序人群包转化目标_A0-A15_20260712.sql`
+- `outputs/公众号合作即转_A0-A15_20260712.sql`
+
+所有交付CSV和Excel使用中文表头;SQL保留源字段名称以确保可直接执行。

+ 373 - 0
examples/auto_put_ad_mini/docs/roi/T15成熟系数迁移指南.md

@@ -0,0 +1,373 @@
+# T15成熟系数迁移指南
+
+## 1. 迁移目标
+
+将当前工程的以下能力迁移到其他工程:
+
+1. 从ODPS读取首层用户和裂变活跃记录;
+2. 通过`rootSessionId`归因A0~A15裂变活跃;
+3. 计算相对T0的T15成熟系数;
+4. 生成小程序及公众号精确参数和分级回退参数;
+5. 使用成熟系数预测长期裂变收入和ROI;
+6. 保留可复算SQL、参数版本、中文数据表和审计能力。
+
+迁移有两种模式:
+
+| 模式 | 适用场景 | 迁移内容 |
+|---|---|---|
+| 只消费参数 | 新工程只计算日常ROI,不负责更新参数 | 参数CSV、参数加载和ROI公式 |
+| 完整复算 | 新工程需要定期重算成熟参数 | ODPS查询、算法模块、运行入口、测试、文档和参数文件 |
+
+推荐先按“只消费参数”接通ROI,再增加“完整复算”。
+
+## 2. 当前参数版本
+
+| 项目 | 当前值 |
+|---|---|
+| 参数版本 | `20260712_A0-A15_v1` |
+| 首层cohort日期 | `20260712` |
+| 观察截止日期 | `20260727` |
+| 小程序实体 | 人群包 + 转化目标 |
+| 公众号实体 | 合作方 + 公众号 |
+| 小程序渠道回退系数 | `2.608491` |
+| 公众号渠道回退系数 | `2.476153` |
+
+当前参数文件:
+
+- `outputs/小程序T15成熟系数_中文_20260712.csv`
+- `outputs/公众号T15成熟系数_中文_20260712.csv`
+- `outputs/T15分级回退系数_中文_20260712.csv`
+- `outputs/最终T15成熟系数_中文_20260712.xlsx`
+
+## 3. 需要迁移的文件
+
+### 3.1 只消费参数
+
+最低需要:
+
+```text
+outputs/小程序T15成熟系数_中文_20260712.csv
+outputs/公众号T15成熟系数_中文_20260712.csv
+outputs/T15分级回退系数_中文_20260712.csv
+T15成熟系数计算说明.md
+```
+
+新工程需自行实现或迁移一个参数加载器,将中文字段映射为内部字段:
+
+```text
+人群包
+转化目标
+合作方
+公众号
+样本状态
+T15成熟系数(相对T0)
+```
+
+### 3.2 完整复算
+
+除上述文件外,还需迁移:
+
+```text
+cohort_dau.py
+partner_cohort_dau.py
+partner_cohort_fission.py
+calculate_final_t15_coefficients.py
+odps_module.py
+tests/test_cohort_dau.py
+tests/test_partner_cohort_dau.py
+tests/test_final_t15_coefficients.py
+```
+
+保留本次完整执行SQL用于审计:
+
+```text
+outputs/小程序人群包转化目标_A0-A15_20260712.sql
+outputs/公众号合作即转_A0-A15_20260712.sql
+```
+
+Python依赖至少包括:
+
+```text
+pandas
+openpyxl
+python-dotenv
+pyodps
+```
+
+不要复制`.env`、AccessKey、飞书密钥或任何日志中的临时访问令牌。
+
+## 4. ODPS数据依赖
+
+### 4.1 `loghubods.opengid_base_data`
+
+首层cohort所需字段:
+
+| 字段 | 用途 |
+|---|---|
+| `dt` | 首层投放日期 |
+| `channel` | 区分小程序投流和公众号合作即转 |
+| `usersharedepth` | `0`定义首层 |
+| `hotsencetype` | 排除`1167` |
+| `videoid` | 沿用有效投放记录过滤 |
+| `mid` | 首层去重用户 |
+| `subsessionid` | 作为`rootSessionId`追踪后续裂变 |
+| `包名` | 小程序人群包 |
+| `广告优化目标` | 小程序转化目标 |
+| `合作方名` | 公众号合作方 |
+| `公众号名` | 公众号实体 |
+
+渠道值:
+
+```text
+小程序投流-稳定
+公众号合作-即转-稳定
+```
+
+### 4.2 `loghubods.user_share_log`
+
+裂变活跃所需字段:
+
+| 字段 | 用途 |
+|---|---|
+| `dt` | A0~A15观察日 |
+| `rootsessionid` | 关联首层root |
+| `topic` | 只保留`click` |
+| `machinecode` | 裂变活跃用户去重 |
+| `usersharedepth` | 只保留`>0`裂变层 |
+
+迁移前必须确认新环境能读取这两张表,并且`subsessionid`与`rootsessionid`仍是同一归因键。
+
+## 5. 算法口径
+
+### 5.1 首层cohort
+
+```text
+首层用户 = 投放日usersharedepth=0的去重mid
+root集合 = 首层记录的去重subsessionid
+```
+
+小程序归属:
+
+```text
+人群包:包名为空或字符串null时记为“泛人群”
+转化目标:为空或字符串null时记为“未知”
+```
+
+公众号归属:
+
+```text
+合作方名 + 公众号名
+```
+
+### 5.2 裂变活跃
+
+对投放日`S`:
+
+```text
+Ak活跃裂变UV
+= 首层root在S+k日产生的裂变层click用户数
+```
+
+过滤:
+
+```text
+topic='click'
+usersharedepth>0
+machinecode非空
+```
+
+去重和归因:
+
+- 同一实体、同一自然日按`machinecode`去重;
+- 同一用户隔日再次进入重新计入;
+- 排除原首层cohort用户;
+- 当前不做跨实体、跨cohort的全平台全局去重。
+
+### 5.3 成熟系数
+
+```text
+T1~T15相对T0尾部系数
+= SUM(A1..A15活跃裂变UV) / A0活跃裂变UV
+
+T15成熟系数(相对T0)
+= SUM(A0..A15活跃裂变UV) / A0活跃裂变UV
+= 1 + 尾部系数
+```
+
+T15成熟系数已经包含A0当天。
+
+## 6. 参数门槛和回退
+
+精确实体可用门槛:
+
+```text
+首层UV >= 500
+且 A0活跃裂变UV >= 200
+```
+
+小程序:
+
+```text
+人群包+转化目标精确值
+→ 人群包A0加权值
+→ 转化目标A0加权值
+→ 小程序渠道A0加权值
+```
+
+公众号:
+
+```text
+合作方+公众号精确值
+→ 合作方A0加权值
+→ 公众号合作即转渠道A0加权值
+```
+
+所有回退值必须使用总量比:
+
+```text
+SUM(A0~A15累计裂变活跃人次) / SUM(A0活跃裂变UV)
+```
+
+禁止对各实体成熟系数直接求算术平均。
+
+## 7. ROI接入
+
+日常ROI所需输入:
+
+```text
+首层实际效率收入
+T0实际裂变收入
+投放成本
+实体维度字段
+```
+
+公式:
+
+```text
+预测裂变总收入
+= T0实际裂变收入 × T15成熟系数
+
+预测总收入
+= 首层实际效率收入
+ + T0实际裂变收入 × T15成熟系数
+
+预测ROI
+= 预测总收入 / 投放成本
+```
+
+禁止写成:
+
+```text
+T0实际裂变收入 + T0实际裂变收入 × T15成熟系数
+```
+
+因为成熟系数已经包含T0。
+
+小程序日常数据必须提供`转化目标`才能命中最精确参数;如果暂时没有该字段,必须明确回退到人群包系数,不能把缺失目标默认匹配为“关键页面访问次数”。
+
+## 8. 推荐的工程结构
+
+```text
+new_project/
+├── config/
+│   └── maturity_version.py
+├── data/
+│   └── maturity/
+│       ├── 小程序T15成熟系数_中文_20260712.csv
+│       ├── 公众号T15成熟系数_中文_20260712.csv
+│       └── T15分级回退系数_中文_20260712.csv
+├── src/
+│   ├── maturity_query.py
+│   ├── maturity_loader.py
+│   └── roi_predictor.py
+├── sql/
+│   ├── 小程序人群包转化目标_A0-A15_20260712.sql
+│   └── 公众号合作即转_A0-A15_20260712.sql
+├── tests/
+│   ├── test_maturity_query.py
+│   ├── test_maturity_loader.py
+│   └── test_roi_predictor.py
+└── docs/
+    └── T15成熟系数迁移指南.md
+```
+
+参数版本建议集中配置:
+
+```python
+MATURITY_VERSION = "20260712_A0-A15_v1"
+COHORT_DATE = "20260712"
+HORIZON = 15
+```
+
+不要在日常ROI任务中临时重新计算cohort参数。参数应离线重算、验证、版本化后再发布。
+
+## 9. 迁移步骤
+
+### 阶段一:复制参数并接入ROI
+
+1. 复制3个中文CSV和本说明;
+2. 实现参数加载和分级回退;
+3. 接入`首层收入 + T0裂变收入 × 成熟系数`;
+4. 用固定样例验证没有重复计算T0;
+5. 与原工程对比同一批输入的逐实体系数和预测ROI。
+
+### 阶段二:迁移完整复算
+
+1. 复制查询生成器、运行入口和测试;
+2. 在新工程配置ODPS环境变量;
+3. 先运行SQL生成测试,不访问生产数据;
+4. 再运行一次固定`20260712`复算;
+5. 对比原工程40行小程序、110行公众号结果;
+6. 公式恒等式和回退系数全部通过后,才允许发布新参数。
+
+### 阶段三:建立参数发布流程
+
+1. 选择已完整成熟的cohort日期;
+2. 生成SQL、CSV、Excel和参数摘要;
+3. 人工审计异常系数和样本状态;
+4. 发布新版本,保留旧版本可回滚;
+5. 日常ROI任务仅切换明确的参数版本。
+
+## 10. 验收清单
+
+- [ ] 所有输出表头为中文;
+- [ ] 所有记录的首层投放日期一致;
+- [ ] 观察截止日等于首层日期加15天;
+- [ ] `A0-A15累计裂变活跃人次=SUM(A0..A15)`;
+- [ ] `T15成熟系数=累计活跃人次/A0活跃裂变UV`;
+- [ ] 尾部系数等于成熟系数减1;
+- [ ] 转化目标只出现明确值或“未知”;
+- [ ] 小程序精确、公众号精确和回退匹配率已输出;
+- [ ] 样本不足实体不会使用自身不稳定系数;
+- [ ] ROI没有重复增加T0收入;
+- [ ] 新旧工程使用相同输入时结果一致;
+- [ ] 参数文件、SQL和代码中不存在凭据。
+
+## 11. 当前遗留问题
+
+1. **单cohort波动**:当前正式参数只取`20260712`一个投放日,可能受当天人群结构影响;后续可评估多个成熟cohort按总量合并。
+2. **T15以后长尾**:历史对比显示T16~T30会使裂变收入部分增加约10%;当前按用户决定固定T15,因此属于明确接受的低估。
+3. **尾部ARPU假设**:当前默认T1~T15裂变用户ARPU与T0裂变ARPU一致,尚未按cohort年龄单独估算ARPU。
+4. **跨实体重复**:当前实体内部按用户日去重,但不做跨人群包、跨转化目标或跨公众号的全平台去重;汇总不能直接视为全平台严格DAU。
+5. **转化目标接入**:当前日常ROI旧流程尚未加载“人群包+转化目标”新参数,迁移工程必须确认日常数据是否包含转化目标。
+6. **收入边界**:接入前必须再次确认“首层实际效率收入”不包含准备单独放大的T0裂变收入,避免收入重复。
+7. **公众号新账号**:首层UV不超过500的公众号不会进入精确参数查询;应使用合作方或渠道回退。
+8. **企微渠道**:企微T0裂变口径仍待复核,本次迁移不包含企微成熟系数。
+9. **源表稳定性**:`opengid_base_data`与`user_share_log`生产逻辑变更时,需要重新做字段血缘和归因覆盖验证。
+
+## 12. 回滚方案
+
+每次发布新参数必须保留:
+
+```text
+参数CSV
+完整SQL
+生成日期
+cohort日期
+观察截止日期
+代码版本
+渠道回退系数
+行数和可用行数
+```
+
+如果新工程出现系数匹配率下降、ROI异常抬升或收入重复,应立即切回上一参数版本,而不是在线修改参数值。

+ 48 - 6
examples/auto_put_ad_mini/docs/unified_services_deployment.md

@@ -45,7 +45,7 @@ RTC_STOP_HOUR=21
 RTC_POLL_SECONDS=600
 RTC_HIGH_CPM=250
 RTC_LOW_CPM=190
-RTC_BID_UP_RATIO=1.25
+RTC_BID_UP_RATIO=1.05
 RTC_MAX_PARTITION_LAG_HOURS=2
 RTC_APPLY_ENABLED=0
 RTC_COMMAND_ENABLED=1
@@ -71,6 +71,7 @@ ROI_APPROVAL_TTL_MINUTES=120
 ROI_SCALE_RATIO=1.10
 ROI_SCALE_COOLDOWN_DAYS=3
 ROI_MAX_BASE_RATIO=2.00
+ROI_FISSION_PARAMETER_VERSION=20260712_A0-A15_v1
 ROI_FEISHU_CHAT_ID=oc_xxx
 ```
 
@@ -154,11 +155,28 @@ docker compose --env-file /dev/null run --rm \
 
 日级 ROI 单独分两阶段启用:
 
-1. 设置 `DAILY_ROI_ENABLED=1`、`ROI_APPLY_ENABLED=0`,观察 11:00 的 ODPS 计算、数据库快照、只读飞书表和整批审批提示。
-2. 使用 `确认 roi_<run_id>` 验证控制服务明确提示写操作关闭。
-3. 核对阈值、账户可执行范围和动作数量后,再设置 `ROI_APPLY_ENABLED=1`。
-4. 生产审批有效期默认 120 分钟;过期批次不能执行。拒绝整批使用 `拒绝 roi_<run_id>`。
-5. 不允许 `DAILY_ROI_ENABLED=0`、`ROI_APPLY_ENABLED=1`,两个服务都会在启动阶段拒绝该配置。
+当前 `north_star_roi_t15_v3` 使用版本化传播裂变参数,报表版本为 `roi_report_v4`。小程序按人群包和转化目标、
+公众号按合作方和公众号匹配传播裂变系数;企微口径未确认,当前按渠道/合作方使用临时参考系数 1.0 保留展示,但不进入阈值和调控。T0 收入是实际值,
+只预测 T1-T15 增量。日级任务不会现场重算 cohort 参数。部署前应保持
+`ROI_FISSION_PARAMETER_VERSION=20260712_A0-A15_v1`。参数必须先发布到 MySQL,
+启动日志、数据库发布版本和 Excel 摘要中的参数版本、cohort 日期必须一致。
+ROI 在线表只上传一次,并发送到 `ROI_FEISHU_CHAT_ID` 和
+`FEISHU_OPERATOR_CHAT_ID`;两个变量相同时只发送一次。
+生产环境应让 `RTC_COMMAND_CHAT_ID` 与 `FEISHU_OPERATOR_CHAT_ID` 指向同一个
+投放审批群,确保审批群中的 `确认/拒绝` 命令由唯一 WebSocket 消费者处理。
+
+审批表默认展示三日窗口的日均首层 UV、日均首层效率收入、日均 LTV 预测效率收入和
+日均成本;预测 ROI 仍按三日预测收入总和除以三日成本总和计算。三日汇总和每日明细
+保留为隐藏审计列,不参与日均展示。
+小程序和公众号 Sheet 展示所有进入阈值样本池的实体,企微 Sheet 展示全部参考实体;
+各 Sheet 默认按预测 ROI 倒序排列,动作列不参与排序。
+
+1. 首次部署先执行下方参数发布命令并完成回读校验。
+2. 设置 `DAILY_ROI_ENABLED=1`、`ROI_APPLY_ENABLED=0`,观察 11:00 的 ODPS 计算、数据库快照、只读飞书表和整批审批提示。
+3. 使用 `确认 roi_<run_id>` 验证控制服务明确提示写操作关闭。
+4. 核对阈值、账户可执行范围和动作数量后,再设置 `ROI_APPLY_ENABLED=1`。
+5. 生产审批有效期默认 120 分钟;过期批次不能执行。拒绝整批使用 `拒绝 roi_<run_id>`。
+6. 不允许 `DAILY_ROI_ENABLED=0`、`ROI_APPLY_ENABLED=1`,两个服务都会在启动阶段拒绝该配置。
 
 首次启用前可手工运行一个“不发飞书、不写腾讯”的计算批次。该命令会读取 ODPS、
 初始化/写入 ROI 数据库快照并在挂载目录生成本地 Excel:
@@ -172,6 +190,30 @@ docker compose run --rm ad_daily_service \
 确认数据库快照和本地报告后,再增加 `--send-feishu` 验证只读在线表和整批命令。
 此时必须保持 `ROI_APPLY_ENABLED=0`;回复确认只应得到“写操作关闭”的提示。
 
+离线复算新参数必须与日级任务分开执行。以下命令默认只生成 SQL,不访问 ODPS:
+
+```bash
+docker compose run --rm ad_daily_service \
+  python /app/examples/auto_put_ad_mini/refresh_roi_fission_multiplier.py \
+  --cohort-date 20260712 \
+  --sql-only
+```
+
+去掉 `--sql-only` 才会执行两条只读 cohort SQL 并生成草稿 CSV/Excel。草稿不会自动
+进入生产;必须审计并在 `roi_control/fission_multiplier.py` 登记版本和文件 SHA256。
+首次上线或切换版本前,显式发布到 MySQL:
+
+```bash
+docker compose run --rm ad_daily_service \
+  python /app/examples/auto_put_ad_mini/refresh_roi_fission_multiplier.py \
+  --publish-version 20260712_A0-A15_v1 \
+  --published-by production-deploy
+```
+
+脚本会初始化参数表、写入不可变版本并立即回读校验。相同版本相同内容重复执行会
+安全跳过;相同版本内容不同会拒绝覆盖。发布成功后再设置
+`ROI_FISSION_PARAMETER_VERSION` 并启用日级 ROI。
+
 ## 6. 验收与回滚
 
 验收:

+ 153 - 0
examples/auto_put_ad_mini/refresh_roi_fission_multiplier.py

@@ -0,0 +1,153 @@
+#!/usr/bin/env python3
+"""Generate propagation-fission drafts or publish an audited DB release."""
+
+from __future__ import annotations
+
+import argparse
+import os
+import sys
+from datetime import datetime
+from pathlib import Path
+
+from dotenv import load_dotenv
+
+HERE = Path(__file__).resolve().parent
+ROOT = HERE.parents[1]
+RTC_DIR = ROOT / "examples" / "tencent_realtime_control"
+for path in (ROOT, HERE, RTC_DIR):
+    if str(path) not in sys.path:
+        sys.path.insert(0, str(path))
+load_dotenv(HERE / ".env", override=False)
+load_dotenv(Path.cwd() / ".env", override=False)
+
+from roi_control.fission_multiplier import (
+    DEFAULT_FISSION_PARAMETER_VERSION,
+    FISSION_HORIZON_DAYS,
+    load_fission_multiplier_parameters,
+    parameter_content_sha256,
+    parameter_values,
+    parameters_from_database,
+)
+from roi_control.fission_multiplier_refresh import (
+    HORIZON,
+    build_gzh_activity_curve_sql,
+    build_miniapp_activity_curve_sql,
+    write_draft_release,
+)
+from roi_control.odps_client import ODPSClient
+from roi_control.repository import (
+    load_fission_parameter_release,
+    publish_fission_parameter_release,
+)
+from storage import initialize_schema
+
+
+def build_parser() -> argparse.ArgumentParser:
+    parser = argparse.ArgumentParser(description="复算或发布传播裂变系数参数")
+    mode = parser.add_mutually_exclusive_group(required=True)
+    mode.add_argument("--cohort-date", help="YYYYMMDD,复算并生成参数草稿")
+    mode.add_argument(
+        "--publish-version",
+        help=(
+            "将已审计并登记SHA256的参数版本发布到MySQL;例如 "
+            f"{DEFAULT_FISSION_PARAMETER_VERSION}"
+        ),
+    )
+    parser.add_argument(
+        "--output-dir",
+        help="草稿输出目录;默认 outputs/roi_fission_drafts/<cohort-date>",
+    )
+    parser.add_argument(
+        "--sql-only",
+        action="store_true",
+        help="只生成SQL,不查询ODPS",
+    )
+    parser.add_argument(
+        "--published-by",
+        default=os.getenv(
+            "ROI_PARAMETER_PUBLISHED_BY",
+            os.getenv("USER", "manual"),
+        ),
+        help="参数发布人或发布任务标识",
+    )
+    return parser
+
+
+def publish_version(version: str, published_by: str) -> int:
+    parameters = load_fission_multiplier_parameters(version)
+    release = parameters.release
+    metadata = parameters.snapshot()
+    metadata["file_sha256"] = dict(release.file_sha256)
+    initialize_schema()
+    created = publish_fission_parameter_release(
+        {
+            "version": release.version,
+            "cohort_date": datetime.strptime(release.cohort_date, "%Y%m%d").date(),
+            "observation_end_date": datetime.strptime(
+                release.observation_end_date, "%Y%m%d"
+            ).date(),
+            "horizon_days": FISSION_HORIZON_DAYS,
+            "run_suffix": release.run_suffix,
+            "content_sha256": parameter_content_sha256(parameters),
+            "metadata": metadata,
+        },
+        parameter_values(parameters),
+        published_by=published_by,
+    )
+    loaded = parameters_from_database(*load_fission_parameter_release(version))
+    if parameter_content_sha256(loaded) != parameter_content_sha256(parameters):
+        raise RuntimeError(f"传播裂变系数发布后回读校验失败: {version}")
+    action = "发布完成" if created else "已存在且内容一致,跳过"
+    print(
+        f"参数{action}: version={version} values={len(parameter_values(parameters))}",
+        flush=True,
+    )
+    return 0
+
+
+def main() -> int:
+    args = build_parser().parse_args()
+    if args.publish_version:
+        if args.sql_only:
+            raise ValueError("--sql-only不能与--publish-version同时使用")
+        return publish_version(args.publish_version, args.published_by)
+
+    output_dir = Path(
+        args.output_dir
+        or f"outputs/roi_fission_drafts/{args.cohort_date}"
+    ).expanduser().resolve()
+    output_dir.mkdir(parents=True, exist_ok=True)
+
+    miniapp_sql = build_miniapp_activity_curve_sql(args.cohort_date, HORIZON)
+    gzh_sql = build_gzh_activity_curve_sql(args.cohort_date, HORIZON)
+    miniapp_sql_path = output_dir / f"小程序人群包转化目标_A0-A15_{args.cohort_date}.sql"
+    gzh_sql_path = output_dir / f"公众号合作即转_A0-A15_{args.cohort_date}.sql"
+    miniapp_sql_path.write_text(miniapp_sql + "\n", encoding="utf-8")
+    gzh_sql_path.write_text(gzh_sql + "\n", encoding="utf-8")
+    print(f"SQL已生成: {miniapp_sql_path}")
+    print(f"SQL已生成: {gzh_sql_path}")
+    if args.sql_only:
+        return 0
+
+    client = ODPSClient()
+    print("[1/2] 查询小程序 cohort", flush=True)
+    miniapp_raw = client.execute_sql(miniapp_sql)
+    print("[2/2] 查询公众号 cohort", flush=True)
+    gzh_raw = client.execute_sql(gzh_sql)
+    paths = write_draft_release(
+        output_dir,
+        args.cohort_date,
+        miniapp_raw,
+        gzh_raw,
+    )
+    print(
+        f"草稿完成: 小程序={len(miniapp_raw)}行 公众号={len(gzh_raw)}行 "
+        f"workbook={paths['workbook']}",
+        flush=True,
+    )
+    print("提示: 草稿不会自动发布;审计后需登记版本和SHA256。", flush=True)
+    return 0
+
+
+if __name__ == "__main__":
+    raise SystemExit(main())

+ 42 - 0
examples/auto_put_ad_mini/roi_control/data/fission_multiplier/20260712_A0-A15_v1/T15分级回退系数_中文_20260712.csv

@@ -0,0 +1,42 @@
+参数层级,人群包,转化目标,合作方,公众号,首层UV,A0活跃裂变UV,A0-A15累计裂变活跃人次,T1-T15相对T0尾部系数,T15成熟系数(相对T0),样本状态
+小程序人群包回退,Q-R50*泛知识*时政历史,,,,1,0,0,,,首层UV不足500
+小程序人群包回退,Q-回流100-180人群,,,,1,0,0,,,首层UV不足500
+小程序人群包回退,Q-回流330以上人群,,,,2,0,0,,,首层UV不足500
+小程序人群包回退,R50*全品类,,,,24145,14530,33136,1.2805230557467309,2.280523055746731,可用
+小程序人群包回退,R50*同感个体*个人情感,,,,40695,41559,104623,1.5174571091700955,2.5174571091700955,可用
+小程序人群包回退,R50*同感个体*退休榜样,,,,12479,15092,48696,2.226610124569308,3.226610124569308,可用
+小程序人群包回退,R50*已转化,,,,42283,40124,107329,1.6749327086033297,2.67493270860333,可用
+小程序人群包回退,R50*泛惊奇*奇观技艺,,,,17512,17625,40451,1.2950921985815602,2.2950921985815604,可用
+小程序人群包回退,R50*泛知识*时政历史,,,,36950,51241,128270,1.5032688667278156,2.5032688667278156,可用
+小程序人群包回退,R50*泛知识*生活科普,,,,17058,16652,44056,1.6456882056209465,2.6456882056209463,可用
+小程序人群包回退,R50*泛祝福,,,,4437,5066,9495,0.874259771022503,1.8742597710225029,可用
+小程序人群包回退,R500*全品类,,,,7075,18467,49567,1.6840851248172415,2.6840851248172415,可用
+小程序人群包回退,cell*year*商业,,,,11290,3712,8602,1.3173491379310345,2.3173491379310347,可用
+小程序人群包回退,unexp*day*商业,,,,302,173,320,0.8497109826589595,1.8497109826589595,首层UV不足500
+小程序人群包回退,wx*商业,,,,27674,19687,52510,1.6672423426626708,2.667242342662671,可用
+小程序人群包回退,中老年*p75,,,,5296,1743,4015,1.3034997131382673,2.3034997131382675,可用
+小程序人群包回退,回流100-180人群,,,,3639,2896,6808,1.350828729281768,2.350828729281768,可用
+小程序人群包回退,回流180-330人群,,,,20419,27444,71627,1.609932954379828,2.609932954379828,可用
+小程序人群包回退,回流330以上人群,,,,53657,127090,352412,1.7729325674718703,2.7729325674718703,可用
+小程序人群包回退,回流50-100人群,,,,988,586,2146,2.6621160409556315,3.6621160409556315,可用
+小程序人群包回退,泛人群,,,,200755,85200,214558,1.5182863849765258,2.518286384976526,可用
+小程序人群包回退,泛人群*已转化,,,,39272,12608,29524,1.3416878172588833,2.341687817258883,可用
+小程序人群包回退,祝福*p75,,,,1,0,0,,,首层UV不足500
+小程序转化目标回退,,关键页面访问次数,,,535231,490433,1280261,1.6104707472784254,2.610470747278425,可用
+小程序转化目标回退,,未知,,,2952,1641,4335,1.6416819012797075,2.6416819012797075,可用
+小程序转化目标回退,,点击,,,27748,9421,23549,1.4996284895446343,2.499628489544634,可用
+小程序渠道回退,,,,,565931,501495,1308145,1.6084906130669299,2.60849061306693,可用
+公众号合作方回退,,,gzlq,,13909,2124,5857,1.7575329566854991,2.757532956685499,可用
+公众号合作方回退,,,hnct,,105570,15540,41279,1.6563063063063064,2.6563063063063064,可用
+公众号合作方回退,,,hnhy,,22468,2562,5458,1.130366900858704,2.130366900858704,可用
+公众号合作方回退,,,hnld,,31166,7772,23336,2.002573340195574,3.002573340195574,可用
+公众号合作方回退,,,hnsd,,28123,8778,25325,1.8850535429482798,2.8850535429482798,可用
+公众号合作方回退,,,jxyy,,55946,10439,27889,1.671616055177699,2.671616055177699,可用
+公众号合作方回退,,,llf,,4603,501,893,0.782435129740519,1.782435129740519,可用
+公众号合作方回退,,,szhx,,347245,60816,156017,1.565393975269666,2.5653939752696657,可用
+公众号合作方回退,,,wxm,,29548,4619,13618,1.9482571985278199,2.94825719852782,可用
+公众号合作方回退,,,xs,,91146,14913,31783,1.131227787836116,2.1312277878361163,可用
+公众号合作方回退,,,yy,,70761,10215,19278,0.8872246696035242,1.8872246696035242,可用
+公众号合作方回退,,,zc,,110330,21747,46236,1.1260863567388606,2.1260863567388606,可用
+公众号合作方回退,,,zzqc,,13921,3812,8719,1.2872507869884575,2.2872507869884573,可用
+公众号渠道回退,,,,,924736,163838,405688,1.4761532733553877,2.4761532733553877,可用

+ 111 - 0
examples/auto_put_ad_mini/roi_control/data/fission_multiplier/20260712_A0-A15_v1/公众号T15成熟系数_中文_20260712.csv

@@ -0,0 +1,111 @@
+首层投放日期,渠道,合作方,公众号,首层UV,根会话数,A0-A15累计裂变活跃人次,每首层累计裂变活跃人次,T1-T15相对T0尾部系数,T15成熟系数(相对T0),稳态DAU倍数,A0活跃裂变UV,A0活跃率,A1活跃裂变UV,A1活跃率,A2活跃裂变UV,A2活跃率,A3活跃裂变UV,A3活跃率,A4活跃裂变UV,A4活跃率,A5活跃裂变UV,A5活跃率,A6活跃裂变UV,A6活跃率,A7活跃裂变UV,A7活跃率,A8活跃裂变UV,A8活跃率,A9活跃裂变UV,A9活跃率,A10活跃裂变UV,A10活跃率,A11活跃裂变UV,A11活跃率,A12活跃裂变UV,A12活跃率,A13活跃裂变UV,A13活跃率,A14活跃裂变UV,A14活跃率,A15活跃裂变UV,A15活跃率,样本状态,参数层级
+20260712,公众号合作-即转-稳定,xs,生活妙说,46823,56299,11292,0.241163530743438,1.446803900325027,2.446803900325027,1.241163530743438,4615,0.0985626721910172,1854,0.0395959250795549,920,0.0196484633620229,665,0.0142024218866796,608,0.0129850714392499,563,0.0120240052965422,390,0.0083292399034662,301,0.0064284646434444,263,0.0056168976784913,188,0.0040151207739786,238,0.0050829720436537,205,0.0043781902056681,108,0.0023065587424983,147,0.0031394827328449,126,0.0026909851995814,101,0.0021570595647438,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,jxyy,秀阅,40008,49014,21210,0.5301439712057588,1.757768820699519,2.757768820699519,1.5301439712057587,7691,0.1922365526894621,5009,0.1251999600079984,1789,0.0447160567886422,1111,0.0277694461107778,870,0.021745650869826,545,0.013622275544891,518,0.0129474105178964,630,0.015746850629874,548,0.0136972605478904,629,0.0157218556288742,448,0.0111977604479104,273,0.0068236352729454,296,0.0073985202959408,350,0.00874825034993,285,0.007123575284943,218,0.0054489102179564,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,尊闻,39430,49275,22757,0.5771493786457013,1.546380217075081,2.546380217075081,1.5771493786457014,8937,0.2266548313466903,5004,0.1269084453461831,1828,0.0463606391072787,1128,0.0286076591427846,909,0.0230535125538929,618,0.0156733451686533,493,0.0125031701749936,639,0.0162059345675881,399,0.0101191985797616,374,0.0094851635810296,422,0.0107025107785949,252,0.0063910727872178,265,0.0067207709865584,256,0.0064925183870149,667,0.0169160537661678,566,0.0143545523712908,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,世暖,34178,38989,15382,0.4500555913160513,2.2065874504898897,3.2065874504898897,1.450055591316051,4797,0.1403534437357364,4445,0.1300544209725554,1480,0.0433027093451928,1009,0.0295219146819591,812,0.0237579729650652,625,0.0182866171221253,416,0.0121715723564866,321,0.0093920065539235,257,0.0075194569606179,280,0.0081924044707121,195,0.0057054245421031,154,0.0045058224588916,175,0.005120252794195,159,0.0046521153958686,131,0.0038328749487974,126,0.0036865820118204,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,核闻,28154,35972,6299,0.2237337500887973,1.3286506469500925,2.3286506469500923,1.2237337500887973,2705,0.0960787099524046,1379,0.0489806066633515,474,0.0168359735739148,349,0.0123961071250976,311,0.0110463877246572,157,0.0055764722597144,129,0.0045819421751793,153,0.0054343965333522,127,0.0045109043119982,106,0.003765006748597,110,0.0039070824749591,51,0.0018114655111174,64,0.0022732116217944,92,0.0032677417063294,55,0.0019535412374795,37,0.0013142004688498,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,hnct,持说,27086,28923,12694,0.4686553939304437,1.1213235294117647,2.1213235294117645,1.468655393930444,5984,0.2209259395997932,2204,0.0813704496788008,933,0.0344458391789116,724,0.0267296758473011,454,0.0167614265672303,263,0.0097098131876246,257,0.0094882965369563,169,0.0062393856604888,180,0.0066454995200472,191,0.0070516133796057,157,0.0057963523591523,151,0.005574835708484,442,0.0163183932658938,268,0.0098944103965148,178,0.0065716606364911,139,0.0051318024071476,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,公闻,26177,30553,6836,0.261145280207816,1.4353402208763806,2.4353402208763804,1.261145280207816,2807,0.1072315391374107,1729,0.0660503495434923,682,0.0260534056614585,339,0.0129502998815754,241,0.0092065553730374,174,0.0066470565763838,122,0.004660579898384,112,0.0042785651526148,79,0.0030179164915765,98,0.003743744508538,88,0.0033617297627688,73,0.002788707644115,55,0.0021010811017305,134,0.0051189975933071,55,0.0021010811017305,48,0.001833670779692,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,登闻,24067,28865,9396,0.3904101051231977,1.738560186534538,2.738560186534538,1.3904101051231978,3431,0.1425603523496904,2360,0.0980595836622761,970,0.0403041509120372,585,0.0243071425603523,293,0.0121743466156978,272,0.0113017825237877,302,0.0125483026550878,269,0.0111771305106577,172,0.007146715419454,141,0.0058586446171105,142,0.0059001952881539,110,0.0045705738147671,90,0.0037395603939003,63,0.0026176922757302,86,0.003573357709727,110,0.0045705738147671,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,hnct,世悟,23530,26019,7763,0.3299192520186995,2.1815573770491805,3.1815573770491805,1.3299192520186995,2440,0.1036974075648108,2229,0.0947301317467063,790,0.0335741606459838,584,0.0248193795155121,323,0.0137271568210794,250,0.0106247343816404,178,0.007564810879728,166,0.0070548236294092,154,0.0065448363790905,107,0.0045473863153421,102,0.0043348916277093,70,0.0029749256268593,155,0.006587335316617,88,0.0037399065023374,68,0.0028899277518062,59,0.0025074373140671,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,hnhy,大丫情感微聊,22468,24848,5458,0.2429232686487449,1.130366900858704,2.130366900858704,1.2429232686487448,2562,0.1140288410183371,1556,0.0692540502047356,452,0.0201175004450774,240,0.0106818586434039,136,0.0060530532312622,119,0.0052964215773544,71,0.0031600498486736,46,0.0020473562399857,30,0.0013352323304254,47,0.0020918639843332,71,0.0031600498486736,26,0.0011572013530354,25,0.0011126936086879,26,0.0011572013530354,28,0.0012462168417304,23,0.0010236781199928,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,世享,20384,24598,9793,0.4804258241758242,1.2116079494128276,2.2116079494128273,1.480425824175824,4428,0.2172291993720565,2157,0.1058182888540031,724,0.0355180533751962,525,0.0257554945054945,317,0.0155514128728414,332,0.016287284144427,271,0.0132947409733124,180,0.0088304552590266,124,0.0060832025117739,109,0.0053473312401883,112,0.0054945054945054,106,0.0052001569858712,95,0.0046605180533751,74,0.0036302982731554,89,0.0043661695447409,150,0.0073587127158555,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,账号已迁移,20260,22432,10023,0.4947186574531095,1.308914996544575,2.308914996544575,1.4947186574531095,4341,0.2142645607107601,2339,0.1154491609081934,888,0.0438302073050345,596,0.0294175715695952,342,0.0168805528134254,243,0.0119940769990128,177,0.008736426456071,128,0.0063178677196446,151,0.0074531095755182,188,0.009279368213228,135,0.0066633761105626,146,0.0072063178677196,77,0.0038005923000987,124,0.0061204343534057,61,0.0030108588351431,87,0.0042941757156959,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,晚辰,19945,23660,9699,0.486287290047631,1.0089063794531896,2.00890637945319,1.486287290047631,4828,0.2420656806217097,2035,0.1020305841062923,663,0.0332414138881925,460,0.0230634244171471,261,0.0130859864627726,223,0.0111807470543995,133,0.0066683379293055,164,0.0082226121835046,195,0.0097768864377036,82,0.0041113060917523,139,0.0069691652043118,84,0.0042115818500877,79,0.0039608924542491,134,0.0067184758084733,118,0.0059162697417899,101,0.0050639257959388,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,hnct,鉴研,19761,22860,8145,0.4121754971914377,2.0133185349611544,3.0133185349611544,1.4121754971914378,2703,0.1367845756793684,2111,0.106826577602348,788,0.0398765244673852,463,0.0234299883609129,337,0.0170537928242497,436,0.0220636607459136,237,0.0119933201761044,257,0.0130054147057335,181,0.009159455493143,117,0.00592075299833,102,0.0051616821011082,85,0.0043014017509235,72,0.0036435403066646,108,0.0054653104599969,80,0.0040483781185162,68,0.0034411214007388,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,yy,生活朝暮雨,16538,21707,4509,0.2726448179949208,0.768235294117647,1.7682352941176471,1.2726448179949208,2550,0.1541903494981255,794,0.0480106421574555,334,0.0201959124440682,178,0.0107630910630064,88,0.0053210787277784,95,0.0057443463538517,68,0.0041117426532833,52,0.0031442737936872,40,0.0024186721489902,48,0.0029024065787882,77,0.0046559438868061,71,0.0042931430644576,34,0.0020558713266416,32,0.0019349377191921,25,0.0015116700931188,23,0.0013907364856693,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,hnld,史海通览,16427,23479,13562,0.8255920131490838,2.0510686164229472,3.0510686164229472,1.825592013149084,4445,0.2705911000182626,3484,0.2120898520728069,1486,0.0904608266877701,950,0.057831618676569,597,0.0363426066841176,569,0.0346380958178608,367,0.0223412674255798,316,0.0192366226334692,325,0.0197845011261946,237,0.0144274669751019,138,0.0084008035551226,128,0.0077920496743166,130,0.0079138004504778,119,0.0072441711815912,112,0.006818043465027,159,0.0096791867048152,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,jxyy,献读,15938,20890,6679,0.4190613627807755,1.430494905385735,2.430494905385735,1.4190613627807755,2748,0.1724181202158363,1433,0.0899109047559292,633,0.0397164010540845,318,0.0199523152214832,311,0.0195131133140921,256,0.0160622411845902,197,0.0123603965365792,105,0.0065880286108671,92,0.0057723679257121,120,0.0075291755552766,81,0.0050821934998117,89,0.0055841385368302,61,0.0038273309072656,64,0.0040155602961475,27,0.0016940644999372,144,0.009035010666332,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,五洲战事,15734,23922,6729,0.4276725562476166,1.1588065447545717,2.158806544754572,1.427672556247617,3117,0.1981060124570992,1216,0.0772848608109825,597,0.0379433074869708,475,0.03018939875429,277,0.0176051862209228,198,0.0125842125333672,237,0.0150629210626668,138,0.0087708147959832,129,0.0081988051353756,51,0.0032413880767764,45,0.002860048303038,54,0.0034320579636456,46,0.0029236049319944,48,0.0030507181899072,64,0.0040676242532096,37,0.0023515952713868,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,xs,锦读,15252,20563,6267,0.4108969315499606,0.9608886107634544,1.9608886107634544,1.4108969315499609,3196,0.2095462890112772,1205,0.0790060319958038,501,0.0328481510621557,307,0.0201285077366902,218,0.0142932074482035,132,0.008654602675059,106,0.0069499082087595,83,0.0054419092578022,120,0.00786782061369,69,0.0045239968528717,91,0.0059664306320482,50,0.0032782585890375,64,0.004196170993968,54,0.0035405192761605,31,0.0020325203252032,40,0.00262260687123,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,hnld,唐宋说史,14739,20116,9774,0.6631386118461225,1.9377817853922452,2.937781785392245,1.6631386118461229,3327,0.2257276613067372,2297,0.1558450369767284,1005,0.0681864441278241,477,0.0323631182576837,406,0.0275459664834792,390,0.026460411154081,209,0.0141800664902639,153,0.0103806228373702,209,0.0141800664902639,152,0.0103127756292828,234,0.0158762466924486,184,0.0124838862880792,229,0.0155370106520116,222,0.0150620801953999,153,0.0103806228373702,127,0.0086165954270981,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,度闻,14436,17528,7345,0.5087974508174009,1.5990799716914366,2.599079971691437,1.508797450817401,2826,0.1957605985037406,1604,0.1111111111111111,719,0.0498060404544195,321,0.0222360764754779,189,0.0130922693266832,158,0.0109448600720421,210,0.0145469659185369,333,0.0230673316708229,225,0.0155860349127182,324,0.0224438902743142,120,0.0083125519534497,101,0.0069963978941535,63,0.004364089775561,51,0.0035328345802161,38,0.0026323081185924,63,0.004364089775561,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,宁七,14383,16793,8991,0.6251129806020997,1.9771523178807944,2.977152317880795,1.6251129806020996,3020,0.2099701035945213,1906,0.1325175554474031,870,0.0604880762010707,671,0.0466522978516304,623,0.0433150246819161,407,0.028297295418202,326,0.0226656469443092,231,0.0160606271292498,233,0.0161996801779879,153,0.0106375582284641,126,0.0087603420704998,100,0.0069526524369046,90,0.0062573871932142,77,0.0053535423764166,98,0.0068135993881665,60,0.0041715914621428,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,慧闻,13439,16210,5938,0.4418483518118907,1.3752,2.3752,1.4418483518118907,2500,0.1860257459632413,1227,0.0913014361187588,436,0.0324428900959892,276,0.0205372423543418,267,0.0198675496688741,182,0.0135426743061239,206,0.015328521467371,205,0.0152541111689857,100,0.0074410298385296,158,0.0117568271448768,84,0.0062504650643649,77,0.0057295929756678,50,0.0037205149192648,59,0.0043902076047324,37,0.0027531810402559,74,0.0055063620805119,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zzqc,奇事博文,13389,18517,8462,0.632011352602883,1.2601495726495726,2.260149572649573,1.632011352602883,3744,0.2796325341698409,1462,0.1091941145716633,807,0.0602733587273134,546,0.0407797445664351,333,0.0248711628949137,205,0.0153110762566285,229,0.017103592501307,154,0.0115019792366868,140,0.0104563447606243,142,0.0106057211143476,190,0.0141907536037045,147,0.0109791619986556,108,0.0080663231010531,97,0.0072447531555754,68,0.0050787960265889,90,0.0067219359175442,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,hnct,账号已迁移,12440,14266,3468,0.2787781350482315,1.3448275862068966,2.3448275862068964,1.2787781350482317,1479,0.1188906752411575,811,0.065192926045016,213,0.0171221864951768,267,0.0214630225080385,180,0.0144694533762057,95,0.007636655948553,101,0.0081189710610932,55,0.0044212218649517,49,0.0039389067524115,44,0.0035369774919614,66,0.0053054662379421,17,0.0013665594855305,26,0.0020900321543408,27,0.0021704180064308,18,0.0014469453376205,20,0.0016077170418006,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,晚暖,12231,14183,3275,0.2677622434796827,1.5250578257517349,2.525057825751735,1.2677622434796827,1297,0.1060420243643201,962,0.0786526040389175,286,0.0233832066061646,137,0.0112010465211348,81,0.0066225165562913,72,0.0058866813833701,106,0.0086665031477393,67,0.0054778840650805,51,0.0041697326465538,28,0.0022892649824217,24,0.00196222712779,21,0.0017169487368162,48,0.00392445425558,39,0.0031886190826588,27,0.0022075055187637,29,0.0023710244460796,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,hnsd,今查,12215,17591,11465,0.9386000818665576,1.75999037072701,2.75999037072701,1.9386000818665576,4154,0.3400736799017601,2905,0.2378223495702005,1145,0.0937372083503888,762,0.0623823168235775,521,0.0426524764633647,385,0.0315186246418338,336,0.0275071633237822,260,0.0212853049529267,204,0.0167007777322963,205,0.0167826442898076,171,0.0139991813344248,97,0.0079410560785918,96,0.0078591895210806,86,0.007040523945968,66,0.0054031927957429,72,0.0058943921408104,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,晚闻,12015,14196,5681,0.4728256346233874,2.2444317532838376,3.2444317532838376,1.4728256346233874,1751,0.1457344985434873,1626,0.1353308364544319,528,0.0439450686641697,343,0.0285476487723678,264,0.0219725343320848,174,0.014481897627965,136,0.0113191843528922,91,0.0075738660008322,123,0.0102372034956304,97,0.0080732417811069,67,0.0055763628797336,67,0.0055763628797336,88,0.0073241781106949,59,0.0049105285060341,173,0.0143986683312526,94,0.0078235538909696,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,递闻,11656,14059,5606,0.4809540150995195,1.6074418604651164,2.607441860465116,1.4809540150995195,2150,0.1844543582704186,1434,0.1230267673301304,474,0.040665751544269,245,0.02101921757035,261,0.022391901166781,141,0.0120967741935483,204,0.0175017158544955,178,0.0152711050102951,102,0.0087508579272477,82,0.0070350034317089,85,0.0072923816060398,52,0.0044612216884008,66,0.0056623198352779,40,0.0034317089910775,35,0.0030027453671928,57,0.0048901853122855,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,魏谈,11126,15847,6901,0.6202588531367967,1.0338933097553786,2.033893309755378,1.6202588531367967,3393,0.3049613517886033,1276,0.1146863203307567,667,0.0599496674456228,357,0.0320870034154233,213,0.0191443465755887,140,0.0125831385942836,123,0.011055186050692,137,0.0123134999101204,84,0.0075498831565701,77,0.006920726226856,38,0.0034154233327341,123,0.011055186050692,85,0.0076397627179579,85,0.0076397627179579,65,0.0058421714902031,38,0.0034154233327341,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,千嵩,10999,14916,7775,0.7068824438585326,1.4573324905183311,2.4573324905183314,1.7068824438585326,3164,0.2876625147740703,1913,0.1739249022638421,698,0.0634603145740521,424,0.0385489589962723,258,0.0234566778798072,241,0.0219110828257114,230,0.0209109919083553,197,0.0179107191562869,126,0.0114555868715337,111,0.0100918265296845,84,0.0076370579143558,73,0.0066369669969997,88,0.0080007273388489,56,0.0050913719429039,54,0.0049095372306573,58,0.0052732066551504,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,wxm,风亭书笺,10747,14110,4326,0.4025309388666604,1.1727774987443496,2.1727774987443498,1.4025309388666605,1991,0.1852610030706243,749,0.0696938680562017,321,0.029868800595515,238,0.022145715083279,169,0.0157253186935889,174,0.0161905648087838,105,0.0097701684190937,64,0.0059551502744952,88,0.0081883316274309,60,0.0055829533823392,63,0.0058621010514562,43,0.0040011165906764,76,0.007071740950963,102,0.0094910207499767,41,0.0038150181445984,42,0.0039080673676374,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,yy,账号已迁移,9859,12166,2405,0.2439395476214626,0.6438824333561176,1.6438824333561175,1.2439395476214623,1463,0.1483923318795009,436,0.0442235520843899,114,0.0115630388477533,54,0.0054772289278831,38,0.0038543462825844,52,0.0052743685972208,59,0.005984379754539,28,0.0028400446292727,27,0.0027386144639415,10,0.0010143016533116,16,0.0016228826452987,25,0.0025357541332792,18,0.001825742975961,20,0.0020286033066233,25,0.0025357541332792,20,0.0020286033066233,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,边际透视,9587,12452,2168,0.226139563992907,1.0205032618825722,2.020503261882572,1.2261395639929071,1073,0.1119223949097736,401,0.0418274747053301,176,0.018358193386878,152,0.0158548033795765,110,0.0114738708667987,36,0.0037550850109523,22,0.0022947741733597,26,0.0027120058412433,14,0.0014603108375925,42,0.0043809325127777,43,0.0044852404297486,20,0.0020861583394179,13,0.0013560029206216,16,0.0016689266715343,12,0.0012516950036507,12,0.0012516950036507,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,实闻,9063,9765,4284,0.4726911618669315,1.2162441800310395,2.21624418003104,1.4726911618669316,1933,0.2132847842877634,980,0.1081319651329581,289,0.0318878958402295,148,0.0163301335098753,221,0.0243848615248813,142,0.0156681010702857,108,0.0119165839126117,85,0.0093787928941851,42,0.0046342270771267,43,0.0047445658170583,67,0.0073926955754165,44,0.0048549045569899,35,0.0038618558976056,60,0.0066203243958953,54,0.0059582919563058,33,0.0036411784177424,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,慧九,8994,10912,3567,0.3965977318212141,1.4857142857142858,2.4857142857142858,1.3965977318212142,1435,0.1595508116522125,955,0.1061818990438069,260,0.0289081609962197,141,0.0156771180787191,104,0.0115632643984878,64,0.007115855014454,95,0.0105625972870802,65,0.0072270402490549,53,0.0058928174338447,27,0.0030020013342228,33,0.0036691127418278,19,0.002112519457416,86,0.0095619301756726,141,0.0156771180787191,39,0.0043362241494329,50,0.0055592617300422,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,边际早读,8729,11481,3604,0.4128766181693206,1.2510930668332292,2.251093066833229,1.4128766181693206,1601,0.1834116164509107,722,0.0827127964257074,351,0.0402107916141597,193,0.0221102073547943,145,0.0166112956810631,67,0.0076755642112498,96,0.0109978233474624,111,0.0127162332455034,55,0.006300836292817,30,0.003436819796082,35,0.004009623095429,24,0.0027494558368656,29,0.0033222591362126,92,0.0105395807079848,38,0.0043533050750372,15,0.001718409898041,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,xs,账号已迁移,8223,10835,3578,0.435121002067372,0.8098128477491148,1.8098128477491149,1.435121002067372,1977,0.2404232032105071,487,0.0592241274474036,282,0.0342940532652316,98,0.0119177915602578,83,0.0100936397908305,131,0.0159309254529976,69,0.0083910981393651,75,0.009120758847136,47,0.0057156755442052,46,0.0055940654262434,64,0.0077830475495561,38,0.0046211844825489,55,0.0066885564878997,60,0.0072966070777088,35,0.0042563541286635,31,0.0037699136568162,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,hnsd,今速查,8012,12244,6131,0.7652271592611083,1.8279520295202951,2.8279520295202953,1.7652271592611082,2168,0.2705941088367449,1653,0.2063155267099351,631,0.0787568647029455,343,0.0428107838242636,149,0.0185971043434847,177,0.0220918622066899,183,0.0228407388916625,152,0.018971542685971,110,0.0137294058911632,138,0.0172241637543684,69,0.0086120818771842,44,0.0054917623564653,53,0.0066150773839241,50,0.0062406390414378,160,0.0199700449326011,51,0.0063654518222666,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,世听,7500,8295,4235,0.5646666666666667,2.3241758241758244,3.3241758241758244,1.5646666666666669,1274,0.1698666666666666,851,0.1134666666666666,317,0.0422666666666666,465,0.062,366,0.0488,130,0.0173333333333333,149,0.0198666666666666,131,0.0174666666666666,61,0.0081333333333333,100,0.0133333333333333,92,0.0122666666666666,62,0.0082666666666666,36,0.0048,37,0.0049333333333333,95,0.0126666666666666,69,0.0092,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,hnsd,今查查,7209,11031,7340,1.0181717297822166,2.2010466637592674,3.2010466637592674,2.0181717297822166,2293,0.3180746289360521,1463,0.2029407684838396,974,0.1351088916631987,485,0.0672770148425579,296,0.0410597863781384,302,0.0418920793452628,331,0.0459148286863642,222,0.0307948397836038,185,0.0256623664863365,192,0.0266333749479816,135,0.0187265917602996,168,0.0233042030794839,97,0.0134554029685115,85,0.0117908170342627,58,0.0080454986822028,54,0.0074906367041198,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,yy,日常饮食小记,6555,8393,1959,0.2988558352402746,1.7436974789915969,2.7436974789915967,1.2988558352402746,714,0.1089244851258581,400,0.061022120518688,143,0.0218154080854309,203,0.0309687261632341,64,0.00976353928299,102,0.0155606407322654,103,0.0157131960335621,41,0.0062547673531655,42,0.0064073226544622,25,0.003813882532418,24,0.0036613272311212,32,0.004881769641495,17,0.0025934401220442,14,0.002135774218154,14,0.002135774218154,21,0.0032036613272311,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,yy,探秘异闻录,6414,8360,2708,0.4222014343623324,1.0561883067577829,2.056188306757783,1.4222014343623324,1317,0.2053320860617399,453,0.0706267539756782,201,0.0313376987839102,171,0.0266604303086997,69,0.010757717492984,42,0.0065481758652946,28,0.0043654505768631,24,0.0037418147801683,47,0.007327720611163,42,0.0065481758652946,44,0.006859993763642,73,0.0113813532896788,38,0.0059245400685999,64,0.0099781727471156,67,0.0104458995946367,28,0.0043654505768631,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,海伦望世,6321,9235,2418,0.3825344091124822,1.0684345594525235,2.0684345594525233,1.3825344091124825,1169,0.1849390919158361,437,0.0691346305964246,262,0.0414491377946527,100,0.0158202816010125,99,0.0156620787850023,58,0.0091757633285872,37,0.0058535041923746,38,0.0060117070083847,31,0.0049042872963138,24,0.0037968675842429,17,0.0026894478721721,36,0.0056953013763644,17,0.0026894478721721,14,0.0022148394241417,45,0.0071191267204556,34,0.0053788957443442,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,wxm,九派畅谈,6182,7942,2846,0.4603688126819799,2.539800995024875,3.539800995024875,1.4603688126819798,804,0.1300549983824005,837,0.1353930766742154,344,0.0556454221934649,168,0.0271756713037851,152,0.0245875121319961,63,0.0101908767389194,40,0.0064703979294726,35,0.0056615981882885,48,0.0077644775153671,33,0.0053380782918149,97,0.0156907149789712,97,0.0156907149789712,38,0.006146878032999,38,0.006146878032999,25,0.0040439987059204,27,0.004367518602394,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,慧余,5930,6627,2862,0.4826306913996627,1.8477611940298508,2.8477611940298506,1.4826306913996627,1005,0.169477234401349,574,0.096795952782462,230,0.0387858347386172,101,0.0170320404721753,215,0.036256323777403,147,0.0247892074198988,88,0.0148397976391231,60,0.0101180438448566,48,0.0080944350758853,100,0.0168634064080944,79,0.0133220910623946,51,0.0086003372681281,49,0.0082630691399662,38,0.0064080944350758,49,0.0082630691399662,28,0.0047217537942664,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,wxm,滨海融媒民生指南,5884,8159,2068,0.3514615907545887,2.277337559429477,3.277337559429477,1.3514615907545888,631,0.1072399728076138,409,0.0695105370496261,176,0.0299116247450713,128,0.0217539089055064,87,0.0147858599592114,50,0.0084976206662134,37,0.0062882392929979,82,0.01393609789259,93,0.015805574439157,46,0.0078178110129163,29,0.0049286199864038,19,0.0032290958531611,74,0.0125764785859959,102,0.0173351461590754,57,0.0096872875594833,48,0.0081577158395649,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,海伦观世,5870,8222,3283,0.5592844974446337,0.977710843373494,1.977710843373494,1.5592844974446338,1660,0.282793867120954,548,0.0933560477001703,189,0.0321976149914821,171,0.0291311754684838,102,0.0173764906303236,70,0.0119250425894378,49,0.0083475298126064,40,0.0068143100511073,51,0.0086882453151618,101,0.0172061328790459,114,0.0194207836456558,46,0.0078364565587734,20,0.0034071550255536,45,0.0076660988074957,49,0.0083475298126064,28,0.0047700170357751,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,yy,鸿运生活志,5824,7060,1116,0.1916208791208791,1.029090909090909,2.0290909090909093,1.191620879120879,550,0.0944368131868131,197,0.0338255494505494,119,0.0204326923076923,44,0.007554945054945,94,0.0161401098901098,24,0.0041208791208791,16,0.0027472527472527,8,0.0013736263736263,10,0.0017170329670329,9,0.0015453296703296,11,0.0018887362637362,7,0.001201923076923,7,0.001201923076923,7,0.001201923076923,11,0.0018887362637362,2,0.0003434065934065,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,hnct,韵染书香,5726,6783,1896,0.3311212015368495,1.5972602739726027,2.5972602739726027,1.3311212015368494,730,0.1274886482710443,506,0.0883688438700663,197,0.0344044708347886,85,0.0148445686342996,77,0.0134474327628361,110,0.0192106182326231,43,0.0075096053091163,33,0.0057631854697869,21,0.0036674816625916,17,0.0029689137268599,18,0.0031435557107928,13,0.0022703457911281,8,0.0013971358714634,14,0.0024449877750611,7,0.0012224938875305,17,0.0029689137268599,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,hnct,悟探,5671,6831,2643,0.4660553694233821,2.227106227106227,3.227106227106227,1.466055369423382,819,0.1444189737259742,536,0.0945159583847645,229,0.0403808852054311,220,0.0387938635161347,111,0.0195732675013225,41,0.0072297654734614,153,0.0269793687180391,117,0.0206312819608534,186,0.0327984482454593,91,0.0160465526362193,33,0.0058190795274202,23,0.0040557220948686,34,0.0059954152706753,21,0.0037030506083583,14,0.0024687004055722,15,0.0026450361488273,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,gzlq,深浓春种,5578,8894,3057,0.548045894585873,1.7640144665461122,2.764014466546112,1.548045894585873,1106,0.1982789530297597,854,0.1531014700609537,328,0.0588024381498745,191,0.0342416636787379,85,0.0152384367156686,75,0.0134456794550017,51,0.0091430620294012,48,0.0086052348512011,28,0.0050197203298673,74,0.0132664037289351,39,0.0069917533166009,57,0.0102187163858013,27,0.0048404446038006,44,0.0078881319469343,21,0.0037647902474005,29,0.005198996055934,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,顶闻,4972,6143,2150,0.4324215607401448,1.8897849462365592,2.889784946236559,1.4324215607401447,744,0.1496379726468222,606,0.1218825422365245,246,0.0494770716009654,186,0.0374094931617055,72,0.0144810941271118,62,0.0124698310539018,48,0.0096540627514078,19,0.0038213998390989,27,0.0054304102976669,38,0.0076427996781979,37,0.0074416733708769,16,0.0032180209171359,16,0.0032180209171359,12,0.0024135156878519,11,0.0022123893805309,10,0.0020112630732099,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,五洲早读,4926,7867,2864,0.5814047909053999,1.302250803858521,2.302250803858521,1.5814047909054,1244,0.2525375558262281,558,0.1132764920828258,271,0.0550142103126268,188,0.0381648396264717,126,0.02557856272838,52,0.0105562322371092,40,0.0081201786439301,47,0.0095412099066179,31,0.0062931384490458,18,0.0036540803897685,20,0.004060089321965,70,0.0142103126268777,30,0.0060901339829476,46,0.0093382054405196,49,0.0099472188388144,74,0.0150223304912708,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,四海早讯,4908,6653,2163,0.4407090464547677,1.4607508532423208,2.460750853242321,1.4407090464547676,879,0.1790953545232274,480,0.097799511002445,161,0.03280358598207,111,0.0226161369193154,132,0.0268948655256723,102,0.0207823960880195,72,0.0146699266503667,47,0.0095762021189894,26,0.0052974735126324,26,0.0052974735126324,15,0.0030562347188264,35,0.0071312143439282,26,0.0052974735126324,15,0.0030562347188264,15,0.0030562347188264,21,0.0042787286063569,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,千说,4893,5678,1818,0.3715511955855303,1.4567567567567568,2.4567567567567568,1.3715511955855304,740,0.1512364602493358,406,0.0829756795422031,188,0.0384222358471285,154,0.0314735336194563,67,0.0136930308604128,52,0.0106274269364398,34,0.0069487022276721,17,0.003474351113836,20,0.0040874718986306,15,0.003065603923973,23,0.0047005926834253,24,0.0049049662783568,18,0.0036787247087676,25,0.0051093398732883,23,0.0047005926834253,12,0.0024524831391784,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,xs,海伦融媒拾光纪,4683,7183,2761,0.5895793294896434,1.4050522648083623,2.4050522648083623,1.5895793294896434,1148,0.2451420029895366,553,0.1180866965620328,216,0.0461242793081358,142,0.0303224428784966,153,0.0326713645099295,86,0.0183642963912022,61,0.0130258381379457,35,0.007473841554559,89,0.0190049113815929,32,0.0068332265641682,85,0.0181507580610719,39,0.00832799487508,33,0.0070467648942985,30,0.0064061499039077,30,0.0064061499039077,29,0.0061926115737774,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,yy,生活畅聊吧,4640,5664,1361,0.2933189655172414,0.9810771470160116,1.9810771470160116,1.2933189655172417,687,0.1480603448275862,235,0.0506465517241379,133,0.0286637931034482,57,0.0122844827586206,83,0.0178879310344827,40,0.0086206896551724,18,0.0038793103448275,15,0.0032327586206896,16,0.0034482758620689,12,0.0025862068965517,12,0.0025862068965517,29,0.00625,9,0.0019396551724137,6,0.0012931034482758,5,0.0010775862068965,4,0.0008620689655172,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,yy,古史奇谈集,4504,5662,1355,0.3008436944937833,0.5903755868544601,1.59037558685446,1.3008436944937831,852,0.1891651865008881,223,0.0495115452930728,95,0.0210923623445825,53,0.0117673179396092,28,0.0062166962699822,14,0.0031083481349911,19,0.0042184724689165,13,0.002886323268206,13,0.002886323268206,13,0.002886323268206,8,0.0017761989342806,6,0.0013321492007104,5,0.0011101243339253,1,0.000222024866785,3,0.0006660746003552,9,0.0019982238010657,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,gzlq,梦魂秋姌,4477,6929,1202,0.2684833593924503,1.6770601336302895,2.6770601336302895,1.2684833593924505,449,0.1002903730176457,262,0.0585213312486039,81,0.0180924726379271,61,0.0136251954433772,29,0.0064775519320973,58,0.0129551038641947,26,0.0058074603529148,22,0.0049140049140049,32,0.0071476435112798,28,0.0062541880723698,66,0.0147420147420147,25,0.0055840964931874,21,0.0046906410542774,17,0.0037971856153674,7,0.0015635470180924,18,0.0040205494750949,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,虎观天下,4475,5555,2440,0.5452513966480447,1.9151732377538828,2.915173237753883,1.5452513966480446,837,0.1870391061452514,303,0.0677094972067039,134,0.0299441340782122,54,0.0120670391061452,80,0.017877094972067,39,0.0087150837988826,30,0.0067039106145251,54,0.0120670391061452,94,0.0210055865921787,40,0.0089385474860335,45,0.0100558659217877,45,0.0100558659217877,39,0.0087150837988826,36,0.0080446927374301,385,0.0860335195530726,225,0.0502793296089385,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,边际见闻,4349,5629,1345,0.3092664980455277,0.9050991501416432,1.905099150141643,1.3092664980455275,706,0.1623361692343067,207,0.0475971487698321,188,0.0432283283513451,74,0.017015405840423,42,0.0096573925040239,38,0.008737640836974,24,0.0055185100022993,16,0.0036790066681995,12,0.0027592550011496,11,0.0025293170843872,6,0.0013796275005748,5,0.0011496895838123,2,0.0004598758335249,4,0.0009197516670498,7,0.0016095654173373,3,0.0006898137502874,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,szhx,世妙,4139,5821,2305,0.5568978014013046,2.278805120910384,3.278805120910384,1.5568978014013046,703,0.169847789321092,499,0.1205605218651848,144,0.0347910123218168,96,0.0231940082145445,77,0.0186035274220826,69,0.0166706934042039,67,0.0161874848997342,35,0.0084561488282193,25,0.0060401063058709,40,0.0096641700893935,52,0.0125634211162116,39,0.0094225658371587,84,0.0202947571877265,121,0.0292341145204155,177,0.0427639526455665,77,0.0186035274220826,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,边际阅读,3974,4823,1593,0.4008555611474584,0.9962406015037594,1.9962406015037597,1.4008555611474585,798,0.2008052340211374,358,0.0900855561147458,146,0.0367388022143935,59,0.0148465022647206,48,0.0120785103170608,34,0.0085556114745848,27,0.0067941620533467,10,0.0025163563160543,25,0.0062908907901358,17,0.0042778057372924,13,0.0032712632108706,9,0.0022647206844489,8,0.0020130850528434,18,0.0045294413688978,14,0.003522898842476,9,0.0022647206844489,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,gzlq,账号已迁移,3854,6760,1598,0.4146341463414634,1.8084358523725832,2.8084358523725834,1.4146341463414631,569,0.1476388168137,402,0.1043072132848988,175,0.0454073689673067,111,0.0288012454592631,55,0.0142708873897249,69,0.0179034769071094,56,0.0145303580695381,60,0.0155682407887908,22,0.0057083549558899,17,0.004411001556824,16,0.0041515308770108,6,0.001556824078879,15,0.0038920601971977,3,0.0007784120394395,3,0.0007784120394395,19,0.0049299429164504,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,hnct,安略,3666,4825,1397,0.3810692853246045,2.449382716049383,3.449382716049383,1.3810692853246045,405,0.1104746317512275,292,0.0796508456082924,125,0.0340971085651936,83,0.0226404800872885,142,0.03873431533006,112,0.0305510092744135,51,0.013911620294599,22,0.006001091107474,17,0.0046372067648663,27,0.0073649754500818,12,0.0032733224222585,41,0.0111838516093835,31,0.008456082924168,19,0.0051827605019094,10,0.0027277686852154,8,0.0021822149481723,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,wxm,妙招集锦百宝箱,3652,4360,3115,0.8529572836801752,2.7941534713763705,3.7941534713763705,1.852957283680175,821,0.2248083242059145,418,0.1144578313253012,229,0.0627053669222344,132,0.036144578313253,201,0.055038335158817,227,0.062157721796276,120,0.0328587075575027,56,0.0153340635268346,62,0.0169769989047097,136,0.0372398685651697,84,0.0230010952902519,164,0.044906900328587,205,0.0561336254107338,134,0.0366922234392113,72,0.0197152245345016,54,0.0147864184008762,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,边际早评,3576,5404,2085,0.5830536912751678,1.1232179226069243,2.1232179226069245,1.5830536912751678,982,0.2746085011185682,388,0.1085011185682326,172,0.0480984340044742,75,0.0209731543624161,121,0.0338366890380313,64,0.017897091722595,45,0.0125838926174496,69,0.0192953020134228,30,0.0083892617449664,21,0.0058724832214765,46,0.0128635346756152,12,0.0033557046979865,21,0.0058724832214765,11,0.003076062639821,10,0.0027964205816554,18,0.0050335570469798,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,海伦看实,3561,5105,1168,0.3279977534400449,1.0103270223752152,2.010327022375215,1.327997753440045,581,0.1631564167368716,184,0.0516708789665824,87,0.0244313395113732,58,0.0162875596742488,42,0.0117944397641112,78,0.0219039595619208,31,0.0087054198258916,12,0.0033698399326032,17,0.0047739399045212,16,0.0044931199101376,12,0.0033698399326032,8,0.0022465599550688,19,0.0053355798932884,7,0.0019657399606852,9,0.0025273799494524,7,0.0019657399606852,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,xs,海融灼见,3536,5047,1609,0.4550339366515837,1.3386627906976745,2.3386627906976742,1.4550339366515836,688,0.1945701357466063,337,0.0953054298642533,149,0.0421380090497737,65,0.0183823529411764,29,0.0082013574660633,47,0.0132918552036199,24,0.006787330316742,27,0.0076357466063348,58,0.0164027149321266,29,0.0082013574660633,24,0.006787330316742,17,0.0048076923076923,24,0.006787330316742,34,0.0096153846153846,33,0.0093325791855203,24,0.006787330316742,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,hnct,澄名,3345,4196,1451,0.4337817638266069,1.919517102615694,2.919517102615694,1.4337817638266068,497,0.1485799701046337,371,0.1109118086696562,97,0.028998505231689,72,0.02152466367713,43,0.0128550074738415,76,0.0227204783258594,45,0.0134529147982062,20,0.0059790732436472,18,0.0053811659192825,42,0.0125560538116591,27,0.0080717488789237,15,0.0044843049327354,24,0.0071748878923766,19,0.0056801195814648,22,0.0065769805680119,63,0.0188340807174887,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,xs,海伦洞察,3298,3836,1641,0.4975742874469375,0.720125786163522,1.720125786163522,1.4975742874469375,954,0.2892662219526986,256,0.0776228016979987,119,0.0360824742268041,72,0.0218314129775621,41,0.0124317768344451,37,0.0112189205579138,24,0.0072771376591873,26,0.007883565797453,5,0.001516070345664,13,0.0039417828987265,12,0.0036385688295936,5,0.001516070345664,6,0.0018192844147968,27,0.0081867798665858,31,0.009399636143117,13,0.0039417828987265,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,wxm,俏生活巧招录,3083,4042,1263,0.4096659098280895,2.3951612903225805,3.3951612903225805,1.4096659098280897,372,0.1206616931560168,286,0.092766785598443,74,0.0240025948751216,176,0.0570872526759649,94,0.0304897826792085,47,0.0152448913396042,11,0.0035679532922478,59,0.0191372040220564,53,0.0171910476808303,21,0.0068115471942912,16,0.0051897502432695,12,0.0038923126824521,21,0.0068115471942912,5,0.0016217969510217,6,0.001946156341226,10,0.0032435939020434,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,xs,海伦融媒观天下,2944,4126,1175,0.399116847826087,0.7993874425727412,1.7993874425727412,1.399116847826087,653,0.2218070652173913,187,0.0635190217391304,66,0.0224184782608695,60,0.0203804347826086,27,0.0091711956521739,17,0.0057744565217391,8,0.0027173913043478,12,0.0040760869565217,56,0.0190217391304347,33,0.0112092391304347,10,0.0033967391304347,11,0.0037364130434782,12,0.0040760869565217,10,0.0033967391304347,9,0.0030570652173913,4,0.0013586956521739,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,伍洲早讯,2935,3527,619,0.2109028960817717,0.6462765957446809,1.6462765957446808,1.2109028960817718,376,0.1281090289608177,109,0.0371379897785349,29,0.0098807495741056,25,0.0085178875638841,12,0.0040885860306643,6,0.0020442930153321,5,0.0017035775127768,6,0.0020442930153321,1,0.0003407155025553,8,0.0027257240204429,7,0.0023850085178875,7,0.0023850085178875,14,0.0047700170357751,7,0.0023850085178875,6,0.0020442930153321,1,0.0003407155025553,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,边际漫读,2792,3612,797,0.285458452722063,1.2077562326869806,2.2077562326869806,1.2854584527220632,361,0.1292979942693409,172,0.0616045845272206,119,0.0426217765042979,31,0.0111031518624641,20,0.0071633237822349,11,0.0039398280802292,15,0.0053724928366762,9,0.0032234957020057,10,0.0035816618911174,2,0.0007163323782234,17,0.0060888252148997,3,0.0010744985673352,18,0.0064469914040114,2,0.0007163323782234,3,0.0010744985673352,4,0.0014326647564469,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,hnct,言趣异语,2692,3318,1289,0.4788261515601783,3.198697068403909,4.198697068403908,1.4788261515601784,307,0.1140416047548291,398,0.1478454680534918,228,0.0846953937592867,169,0.062778603268945,54,0.0200594353640416,36,0.013372956909361,22,0.0081723625557206,21,0.0078008915304606,9,0.0033432392273402,9,0.0033432392273402,8,0.0029717682020802,4,0.0014858841010401,8,0.0029717682020802,6,0.0022288261515601,7,0.0026002971768202,3,0.00111441307578,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,llf,枫史,2583,3757,562,0.2175764614789005,0.7186544342507645,1.7186544342507646,1.2175764614789004,327,0.1265969802555168,122,0.0472319008904374,48,0.0185830429732868,16,0.0061943476577622,5,0.0019357336430507,4,0.0015485869144405,6,0.0023228803716608,8,0.0030971738288811,7,0.002710027100271,5,0.0019357336430507,5,0.0019357336430507,3,0.0011614401858304,1,0.0003871467286101,1,0.0003871467286101,1,0.0003871467286101,3,0.0011614401858304,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,yy,异闻怪谈,2555,3129,387,0.1514677103718199,1.0806451612903225,2.0806451612903225,1.15146771037182,186,0.07279843444227,109,0.0426614481409002,32,0.0125244618395303,9,0.0035225048923679,11,0.0043052837573385,10,0.0039138943248532,3,0.0011741682974559,2,0.0007827788649706,4,0.0015655577299412,1,0.0003913894324853,0,0.0,6,0.0023483365949119,2,0.0007827788649706,6,0.0023483365949119,3,0.0011741682974559,3,0.0011741682974559,A0裂变UV不足200,合作方+公众号
+20260712,公众号合作-即转-稳定,xs,相伴共度,2373,3357,1538,0.6481247366203119,1.061662198391421,2.0616621983914207,1.648124736620312,746,0.314369995785925,230,0.0969237252423093,100,0.0421407501053518,83,0.034976822587442,28,0.0117994100294985,22,0.0092709650231774,30,0.0126422250316055,38,0.0160134850400337,19,0.0080067425200168,21,0.0088495575221238,18,0.0075853350189633,8,0.0033712600084281,12,0.0050568900126422,68,0.0286557100716392,46,0.0193847450484618,69,0.0290771175726927,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,yy,生活知晚,2296,2697,516,0.2247386759581881,0.7671232876712328,1.7671232876712328,1.2247386759581882,292,0.127177700348432,141,0.0614111498257839,24,0.0104529616724738,19,0.0082752613240418,8,0.0034843205574912,5,0.002177700348432,3,0.0013066202090592,2,0.0008710801393728,0,0.0,0,0.0,0,0.0,2,0.0008710801393728,1,0.0004355400696864,0,0.0,1,0.0004355400696864,18,0.0078397212543554,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,海伦观点,2292,2834,508,0.2216404886561954,0.9389312977099236,1.9389312977099236,1.2216404886561951,262,0.1143106457242583,119,0.0519197207678883,28,0.0122164048865619,31,0.0135253054101221,9,0.0039267015706806,11,0.0047993019197207,5,0.0021815008726003,5,0.0021815008726003,6,0.0026178010471204,2,0.0008726003490401,3,0.0013089005235602,4,0.0017452006980802,2,0.0008726003490401,3,0.0013089005235602,9,0.0039267015706806,9,0.0039267015706806,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,四海早阅,2144,2854,715,0.3334888059701492,1.3993288590604027,2.3993288590604025,1.3334888059701493,298,0.1389925373134328,77,0.0359141791044776,42,0.0195895522388059,29,0.013526119402985,43,0.0200559701492537,54,0.0251865671641791,21,0.0097947761194029,32,0.0149253731343283,21,0.0097947761194029,17,0.0079291044776119,26,0.0121268656716417,19,0.0088619402985074,6,0.0027985074626865,10,0.0046641791044776,13,0.0060634328358208,7,0.0032649253731343,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,yy,生活沐朝夕,2119,2895,961,0.4535158093440302,0.945344129554656,1.945344129554656,1.45351580934403,494,0.2331288343558282,141,0.0665408211420481,64,0.0302029259084473,42,0.0198206701274185,36,0.0169891458235016,35,0.0165172251061821,23,0.0108541764983482,14,0.0066068900424728,21,0.0099103350637092,41,0.0193487494100991,7,0.0033034450212364,6,0.0028315243039169,9,0.0042472864558754,6,0.0028315243039169,12,0.0056630486078338,10,0.0047192071731949,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,llf,镜史,2020,2634,331,0.1638613861386138,0.9022988505747126,1.9022988505747127,1.1638613861386138,174,0.0861386138613861,31,0.0153465346534653,23,0.0113861386138613,21,0.0103960396039603,6,0.0029702970297029,5,0.0024752475247524,5,0.0024752475247524,7,0.0034653465346534,12,0.0059405940594059,5,0.0024752475247524,8,0.0039603960396039,4,0.0019801980198019,2,0.0009900990099009,2,0.0009900990099009,15,0.0074257425742574,11,0.0054455445544554,A0裂变UV不足200,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,海伦观事,1990,3246,1088,0.5467336683417086,1.3397849462365592,2.339784946236559,1.5467336683417086,465,0.2336683417085427,253,0.1271356783919598,102,0.0512562814070351,27,0.0135678391959798,21,0.0105527638190954,10,0.0050251256281407,37,0.0185929648241206,15,0.007537688442211,29,0.014572864321608,23,0.0115577889447236,33,0.0165829145728643,22,0.0110552763819095,16,0.0080402010050251,15,0.007537688442211,8,0.0040201005025125,12,0.0060301507537688,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,yy,生活甜记,1880,2458,101,0.0537234042553191,0.463768115942029,1.463768115942029,1.0537234042553192,69,0.0367021276595744,12,0.0063829787234042,8,0.0042553191489361,1,0.000531914893617,0,0.0,4,0.002127659574468,2,0.001063829787234,0,0.0,0,0.0,1,0.000531914893617,1,0.000531914893617,0,0.0,0,0.0,3,0.001595744680851,0,0.0,0,0.0,A0裂变UV不足200,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,边际看实,1692,2103,387,0.2287234042553191,0.5860655737704918,1.5860655737704918,1.2287234042553192,244,0.1442080378250591,53,0.0313238770685579,12,0.0070921985815602,15,0.0088652482269503,6,0.0035460992907801,11,0.0065011820330969,14,0.0082742316784869,3,0.00177304964539,4,0.0023640661938534,3,0.00177304964539,7,0.0041371158392434,5,0.0029550827423167,2,0.0011820330969267,2,0.0011820330969267,3,0.00177304964539,3,0.00177304964539,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,yy,拾序生活集,1671,2077,400,0.2393776181926989,0.4925373134328358,1.492537313432836,1.239377618192699,268,0.1603830041891083,46,0.0275284260921603,44,0.0263315380011968,14,0.0083782166367444,8,0.0047875523638539,4,0.0023937761819269,2,0.0011968880909634,2,0.0011968880909634,1,0.0005984440454817,3,0.0017953321364452,1,0.0005984440454817,3,0.0017953321364452,0,0.0,0,0.0,2,0.0011968880909634,2,0.0011968880909634,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,hnct,世若,1653,2358,533,0.322444041137326,2.028409090909091,3.028409090909091,1.322444041137326,176,0.1064730792498487,198,0.1197822141560798,38,0.0229885057471264,21,0.0127041742286751,9,0.0054446460980036,10,0.0060496067755595,7,0.0042347247428917,15,0.0090744101633393,24,0.014519056261343,2,0.0012099213551119,5,0.0030248033877797,3,0.0018148820326678,7,0.0042347247428917,2,0.0012099213551119,4,0.0024198427102238,12,0.0072595281306715,A0裂变UV不足200,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,海伦事奇,1638,2369,548,0.3345543345543345,0.6023391812865497,1.6023391812865495,1.3345543345543345,342,0.2087912087912088,87,0.0531135531135531,18,0.0109890109890109,30,0.0183150183150183,10,0.0061050061050061,10,0.0061050061050061,17,0.0103785103785103,6,0.0036630036630036,6,0.0036630036630036,6,0.0036630036630036,4,0.0024420024420024,0,0.0,1,0.0006105006105006,4,0.0024420024420024,3,0.0018315018315018,4,0.0024420024420024,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,边际视角,1520,1982,553,0.3638157894736842,1.135135135135135,2.135135135135135,1.3638157894736842,259,0.1703947368421052,101,0.0664473684210526,51,0.0335526315789473,25,0.0164473684210526,18,0.0118421052631578,21,0.0138157894736842,19,0.0125,6,0.0039473684210526,4,0.0026315789473684,10,0.006578947368421,15,0.0098684210526315,14,0.0092105263157894,3,0.0019736842105263,3,0.0019736842105263,2,0.0013157894736842,2,0.0013157894736842,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,yy,生活静流年,1449,1795,626,0.4320220841959972,0.6344647519582245,1.6344647519582245,1.4320220841959972,383,0.26432022084196,98,0.0676328502415458,33,0.0227743271221532,29,0.0200138026224982,16,0.0110420979986197,11,0.007591442374051,5,0.0034506556245686,3,0.0020703933747412,4,0.0027605244996549,3,0.0020703933747412,4,0.0027605244996549,1,0.0006901311249137,17,0.0117322291235334,10,0.0069013112491373,3,0.0020703933747412,6,0.0041407867494824,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,海伦奇谈,1370,1814,687,0.5014598540145986,0.6634382566585957,1.6634382566585957,1.5014598540145987,413,0.3014598540145985,132,0.0963503649635036,41,0.02992700729927,24,0.0175182481751824,18,0.0131386861313868,12,0.0087591240875912,7,0.0051094890510948,10,0.0072992700729927,1,0.0007299270072992,4,0.002919708029197,6,0.0043795620437956,2,0.0014598540145985,2,0.0014598540145985,6,0.0043795620437956,7,0.0051094890510948,2,0.0014598540145985,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,五洲早阅,1342,1662,862,0.6423248882265276,1.636085626911315,2.636085626911315,1.6423248882265276,327,0.2436661698956781,109,0.0812220566318926,47,0.0350223546944858,121,0.0901639344262295,94,0.0700447093889716,64,0.0476900149031296,23,0.0171385991058122,20,0.014903129657228,14,0.0104321907600596,12,0.0089418777943368,10,0.007451564828614,7,0.0052160953800298,5,0.003725782414307,4,0.0029806259314456,1,0.0007451564828614,4,0.0029806259314456,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,yy,生活藏烟火,1202,1665,246,0.2046589018302828,1.2162162162162162,2.216216216216216,1.204658901830283,111,0.0923460898502495,66,0.0549084858569051,19,0.0158069883527454,5,0.0041597337770382,2,0.0016638935108153,2,0.0016638935108153,8,0.0066555740432612,0,0.0,7,0.0058236272878535,3,0.0024958402662229,2,0.0016638935108153,0,0.0,0,0.0,12,0.0099833610648918,6,0.0049916805324459,3,0.0024958402662229,A0裂变UV不足200,合作方+公众号
+20260712,公众号合作-即转-稳定,xs,海伦融媒知天下,1198,1581,526,0.4390651085141903,0.5795795795795796,1.5795795795795795,1.4390651085141903,333,0.2779632721202003,82,0.0684474123539232,37,0.0308848080133555,19,0.0158597662771285,6,0.005008347245409,6,0.005008347245409,5,0.0041736227045075,4,0.003338898163606,3,0.0025041736227045,6,0.005008347245409,1,0.0008347245409015,4,0.003338898163606,5,0.0041736227045075,10,0.008347245409015,4,0.003338898163606,1,0.0008347245409015,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,xs,海伦融媒视角,1169,1643,666,0.5697177074422584,0.8551532033426184,1.8551532033426184,1.5697177074422584,359,0.3071000855431993,132,0.1129170230966638,85,0.0727117194183062,35,0.029940119760479,19,0.0162532078699743,7,0.0059880239520958,6,0.0051325919589392,5,0.0042771599657827,3,0.0025662959794696,4,0.0034217279726261,3,0.0025662959794696,1,0.0008554319931565,0,0.0,4,0.0034217279726261,2,0.001710863986313,1,0.0008554319931565,可用,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,海伦晚事,1135,1646,196,0.1726872246696035,0.5076923076923077,1.5076923076923077,1.1726872246696036,130,0.1145374449339207,25,0.0220264317180616,7,0.0061674008810572,6,0.0052863436123348,8,0.0070484581497797,0,0.0,4,0.0035242290748898,1,0.0008810572687224,4,0.0035242290748898,2,0.0017621145374449,2,0.0017621145374449,1,0.0008810572687224,1,0.0008810572687224,2,0.0017621145374449,2,0.0017621145374449,1,0.0008810572687224,A0裂变UV不足200,合作方+公众号
+20260712,公众号合作-即转-稳定,yy,生活闻故事,1074,1229,171,0.159217877094972,0.7448979591836735,1.7448979591836735,1.159217877094972,98,0.0912476722532588,22,0.0204841713221601,6,0.0055865921787709,11,0.01024208566108,0,0.0,1,0.0009310986964618,6,0.0055865921787709,3,0.0027932960893854,8,0.0074487895716946,3,0.0027932960893854,4,0.0037243947858473,4,0.0037243947858473,2,0.0018621973929236,1,0.0009310986964618,2,0.0018621973929236,0,0.0,A0裂变UV不足200,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,边际快读,1010,1340,260,0.2574257425742574,2.1707317073170733,3.1707317073170733,1.2574257425742574,82,0.0811881188118811,41,0.0405940594059405,18,0.0178217821782178,39,0.0386138613861386,18,0.0178217821782178,7,0.0069306930693069,12,0.0118811881188118,13,0.0128712871287128,5,0.0049504950495049,3,0.0029702970297029,1,0.0009900990099009,1,0.0009900990099009,3,0.0029702970297029,3,0.0029702970297029,7,0.0069306930693069,7,0.0069306930693069,A0裂变UV不足200,合作方+公众号
+20260712,公众号合作-即转-稳定,xs,览说,934,1179,337,0.360813704496788,2.2095238095238097,3.2095238095238097,1.360813704496788,105,0.1124197002141327,82,0.0877944325481798,25,0.0267665952890792,25,0.0267665952890792,41,0.0438972162740899,17,0.0182012847965738,6,0.006423982869379,4,0.0042826552462526,2,0.0021413276231263,3,0.0032119914346895,8,0.0085653104925053,3,0.0032119914346895,1,0.0010706638115631,6,0.006423982869379,1,0.0010706638115631,8,0.0085653104925053,A0裂变UV不足200,合作方+公众号
+20260712,公众号合作-即转-稳定,yy,生活浅喜,932,1309,266,0.2854077253218884,1.509433962264151,2.509433962264151,1.2854077253218883,106,0.1137339055793991,17,0.0182403433476394,9,0.009656652360515,7,0.0075107296137339,10,0.0107296137339055,8,0.0085836909871244,4,0.0042918454935622,2,0.0021459227467811,1,0.0010729613733905,1,0.0010729613733905,49,0.0525751072961373,18,0.01931330472103,1,0.0010729613733905,3,0.0032188841201716,16,0.0171673819742489,14,0.0150214592274678,A0裂变UV不足200,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,四海战讯,823,1195,100,0.1215066828675577,0.4492753623188406,1.4492753623188406,1.1215066828675575,69,0.0838396111786148,12,0.0145808019441069,8,0.0097205346294046,2,0.0024301336573511,4,0.0048602673147023,2,0.0024301336573511,0,0.0,0,0.0,3,0.0036452004860267,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,A0裂变UV不足200,合作方+公众号
+20260712,公众号合作-即转-稳定,xs,海伦融媒独报,713,1021,393,0.5511921458625526,1.8273381294964028,2.827338129496403,1.5511921458625526,139,0.1949509116409537,34,0.0476858345021037,34,0.0476858345021037,14,0.0196353436185133,15,0.0210378681626928,27,0.0378681626928471,7,0.0098176718092566,31,0.0434782608695652,29,0.0406732117812061,7,0.0098176718092566,5,0.0070126227208976,31,0.0434782608695652,4,0.005610098176718,3,0.0042075736325385,9,0.0126227208976157,4,0.005610098176718,A0裂变UV不足200,合作方+公众号
+20260712,公众号合作-即转-稳定,yy,生活听雨,711,903,95,0.1336146272855133,1.0212765957446808,2.021276595744681,1.1336146272855134,47,0.0661040787623066,21,0.0295358649789029,18,0.0253164556962025,2,0.0028129395218002,0,0.0,0,0.0,1,0.0014064697609001,0,0.0,1,0.0014064697609001,0,0.0,0,0.0,2,0.0028129395218002,0,0.0,2,0.0028129395218002,1,0.0014064697609001,0,0.0,A0裂变UV不足200,合作方+公众号
+20260712,公众号合作-即转-稳定,hnsd,快查今,687,887,389,0.5662299854439592,1.3865030674846626,2.3865030674846626,1.5662299854439592,163,0.2372634643377001,64,0.0931586608442503,45,0.0655021834061135,14,0.0203784570596797,15,0.0218340611353711,9,0.0131004366812227,16,0.0232896652110625,7,0.0101892285298398,9,0.0131004366812227,27,0.0393013100436681,3,0.0043668122270742,3,0.0043668122270742,1,0.0014556040756914,5,0.007278020378457,8,0.0116448326055312,0,0.0,A0裂变UV不足200,合作方+公众号
+20260712,公众号合作-即转-稳定,yy,奇闻幻彩集,538,831,96,0.1784386617100371,2.4285714285714284,3.4285714285714284,1.178438661710037,28,0.0520446096654275,46,0.0855018587360594,9,0.0167286245353159,4,0.0074349442379182,4,0.0074349442379182,2,0.0037174721189591,0,0.0,1,0.0018587360594795,0,0.0,1,0.0018587360594795,0,0.0,1,0.0018587360594795,0,0.0,0,0.0,0,0.0,0,0.0,A0裂变UV不足200,合作方+公众号
+20260712,公众号合作-即转-稳定,zzqc,高山兮兮,532,703,257,0.4830827067669173,2.7794117647058822,3.7794117647058822,1.4830827067669172,68,0.1278195488721804,82,0.1541353383458646,28,0.0526315789473684,7,0.0131578947368421,5,0.0093984962406015,18,0.0338345864661654,22,0.0413533834586466,7,0.0131578947368421,3,0.0056390977443609,4,0.0075187969924812,0,0.0,2,0.0037593984962406,3,0.0056390977443609,2,0.0037593984962406,5,0.0093984962406015,1,0.0018796992481203,A0裂变UV不足200,合作方+公众号
+20260712,公众号合作-即转-稳定,zc,边际看读,511,663,155,0.3033268101761252,0.9620253164556962,1.962025316455696,1.3033268101761253,79,0.1545988258317025,37,0.0724070450097847,21,0.0410958904109589,4,0.0078277886497064,3,0.0058708414872798,2,0.0039138943248532,3,0.0058708414872798,2,0.0039138943248532,1,0.0019569471624266,0,0.0,0,0.0,1,0.0019569471624266,2,0.0039138943248532,0,0.0,0,0.0,0,0.0,A0裂变UV不足200,合作方+公众号

+ 41 - 0
examples/auto_put_ad_mini/roi_control/data/fission_multiplier/20260712_A0-A15_v1/小程序T15成熟系数_中文_20260712.csv

@@ -0,0 +1,41 @@
+首层投放日期,人群包,转化目标,首层UV,根会话数,A0-A15累计裂变活跃人次,每首层累计裂变活跃人次,T1-T15相对T0尾部系数,T15成熟系数(相对T0),稳态DAU倍数,A0活跃裂变UV,A0活跃率,A1活跃裂变UV,A1活跃率,A2活跃裂变UV,A2活跃率,A3活跃裂变UV,A3活跃率,A4活跃裂变UV,A4活跃率,A5活跃裂变UV,A5活跃率,A6活跃裂变UV,A6活跃率,A7活跃裂变UV,A7活跃率,A8活跃裂变UV,A8活跃率,A9活跃裂变UV,A9活跃率,A10活跃裂变UV,A10活跃率,A11活跃裂变UV,A11活跃率,A12活跃裂变UV,A12活跃率,A13活跃裂变UV,A13活跃率,A14活跃裂变UV,A14活跃率,A15活跃裂变UV,A15活跃率,样本状态,参数层级
+20260712,泛人群,关键页面访问次数,199054,295200,210231,1.0561505923015866,1.5158985651200918,2.515898565120092,2.0561505923015866,83561,0.4197906095833291,41456,0.2082650938941191,19736,0.0991489746500949,13123,0.0659268339244627,9366,0.0470525586021883,7180,0.03607061400424,6521,0.0327599545851879,5251,0.0263797763420981,4360,0.0219036040471429,3635,0.018261376309946,3046,0.0153023802586232,3030,0.0152220000602851,2755,0.0138404654013483,2596,0.0130416871803631,2401,0.012062053513117,2214,0.01112260994504,可用,人群包+转化目标
+20260712,回流330以上人群,关键页面访问次数,53546,102405,352412,6.581481343144213,1.7729325674718703,2.7729325674718703,7.581481343144213,127090,2.3734732753146828,74112,1.3840809771037983,36016,0.6726179359802786,22584,0.4217681993052702,15528,0.2899936503193516,12879,0.2405221678556754,11365,0.2122474134389123,10070,0.1880626003809808,8248,0.1540357823180069,7011,0.1309341500765696,5769,0.107739140178538,5199,0.0970940873267844,4168,0.0778396145370335,4669,0.0871960557277854,4138,0.0772793485974676,3566,0.0665969446830762,可用,人群包+转化目标
+20260712,R50*已转化,关键页面访问次数,42171,71854,107329,2.54509022788172,1.6749327086033297,2.67493270860333,3.54509022788172,40124,0.9514595338028504,23109,0.5479832112114961,10228,0.242536340138958,6800,0.1612482511678641,4862,0.1152924995850228,3965,0.0940219582177325,2986,0.0708069526451827,2504,0.0593772971947546,2359,0.0559389153683811,2015,0.0477816508975362,1879,0.0445566858741789,1546,0.0366602641625761,1263,0.0299494913566194,1180,0.027981314173247,1415,0.0335538640297835,1094,0.0259419980555357,可用,人群包+转化目标
+20260712,R50*同感个体*个人情感,关键页面访问次数,40483,78337,104623,2.5843687473754415,1.5174571091700957,2.5174571091700955,3.5843687473754415,41559,1.0265790578761456,21116,0.5216016599560309,9629,0.2378529259195217,6016,0.1486055875305683,4590,0.1133809253266803,4072,0.1005854309216214,3002,0.07415458340538,2447,0.0604451251142454,2421,0.0598028802213274,1936,0.0478225427957414,1627,0.0401897092606773,1359,0.0335696465182916,1345,0.0332238223451819,1263,0.0311982807598251,1260,0.031124175579873,981,0.0242323938443297,可用,人群包+转化目标
+20260712,泛人群*已转化,关键页面访问次数,39151,64574,29524,0.7541058976782202,1.3416878172588833,2.341687817258883,1.7541058976782202,12608,0.3220351970575464,5266,0.1345048657760976,2858,0.0729994125309698,1563,0.0399223519194912,1293,0.033025976347986,990,0.0252867104288523,939,0.0239840617097903,723,0.0184669612525861,642,0.0163980485811345,476,0.0121580547112462,437,0.0111619115731398,344,0.0087864933207325,351,0.0089652882429567,404,0.0103190212255114,345,0.0088120354524788,285,0.0072795075476999,可用,人群包+转化目标
+20260712,R50*泛知识*时政历史,关键页面访问次数,36893,57308,128270,3.4768113192204484,1.5032688667278156,2.5032688667278156,4.476811319220449,51241,1.3889084650204646,26426,0.7162876426422357,12364,0.3351313257257474,7466,0.2023690130919144,5825,0.1578890304393787,4127,0.1118640392486379,3387,0.0918060336649228,3392,0.0919415607296777,2632,0.0713414468869433,2146,0.0581682161927736,1838,0.049819749003876,1654,0.0448323530208982,1352,0.0366465183097064,1498,0.0406039086005475,1512,0.040983384381861,1410,0.0382186322608624,可用,人群包+转化目标
+20260712,R50*全品类,关键页面访问次数,24105,31417,33129,1.3743621655258245,1.2803551762114538,2.2803551762114536,2.3743621655258247,14528,0.6026965359883841,6518,0.2704003318813524,2773,0.1150383737813731,1920,0.0796515245799626,1380,0.0572495332918481,838,0.0347645716656295,903,0.0374611076540136,821,0.0340593237917444,548,0.022733872640531,403,0.0167185231279817,391,0.0162207010993569,309,0.0128189172370877,448,0.0185853557353246,549,0.022775357809583,455,0.018875751918689,345,0.014312383322962,可用,人群包+转化目标
+20260712,回流180-330人群,关键页面访问次数,20419,31335,71627,3.5078603261668055,1.609932954379828,2.609932954379828,4.5078603261668055,27444,1.3440423135315147,13237,0.6482687692835104,7042,0.3448748714432636,4725,0.2314021254713747,3029,0.1483422302757236,2800,0.1371271854645183,2123,0.1039717909789901,2103,0.102992311082815,1897,0.0929036681522111,1414,0.0692492286595817,1188,0.0581811058328027,927,0.0453988931877173,785,0.0384445859248738,867,0.0424604534991919,1133,0.0554875361183211,913,0.0447132572603947,可用,人群包+转化目标
+20260712,wx*商业,点击,18159,32686,17748,0.9773665950768214,1.5947368421052632,2.594736842105263,1.9773665950768216,6840,0.3766727242689575,3659,0.2014978798391982,1743,0.0959854617545019,1117,0.0615121978082493,962,0.052976485489289,685,0.0377223415386309,458,0.0252216531747342,346,0.0190539126603887,294,0.0161903188501569,211,0.011619582576133,198,0.010903684123575,263,0.0144831763863648,259,0.0142628999394239,212,0.0116746516878682,277,0.015254143950658,224,0.012335481028691,可用,人群包+转化目标
+20260712,R50*泛惊奇*奇观技艺,关键页面访问次数,17472,25724,40451,2.3151900183150182,1.2950921985815602,2.2950921985815604,3.3151900183150182,17625,1.0087568681318682,8559,0.4898695054945055,3569,0.2042696886446886,2097,0.1200206043956044,1642,0.0939789377289377,1182,0.0676510989010989,894,0.0511675824175824,884,0.050595238095238,688,0.0393772893772893,550,0.0314789377289377,495,0.0283310439560439,601,0.0343978937728937,554,0.0317078754578754,429,0.0245535714285714,359,0.0205471611721611,323,0.0184867216117216,可用,人群包+转化目标
+20260712,R50*泛知识*生活科普,关键页面访问次数,16968,29588,44055,2.596357850070721,1.6456281527744414,2.6456281527744414,3.596357850070721,16652,0.9813767090994814,9777,0.5762022630834512,4397,0.2591348420556341,2745,0.1617751060820367,1597,0.0941183404054691,1230,0.0724893917963225,913,0.0538071664309288,1236,0.0728429985855728,1021,0.0601720886374351,989,0.0582861857614332,659,0.0388378123526638,572,0.0337105139085337,806,0.0475011786892975,566,0.0333569071192833,427,0.0251650165016501,468,0.0275813295615275,可用,人群包+转化目标
+20260712,R50*同感个体*退休榜样,关键页面访问次数,12479,19647,48696,3.902235756070198,2.226610124569308,3.226610124569308,4.902235756070198,15092,1.2093917781873549,12855,1.0301306194406603,5073,0.4065229585703983,3384,0.2711755749659428,2317,0.1856719288404519,1998,0.1601089830915938,1494,0.1197211315009215,1363,0.1092234954723936,1143,0.0915938777145604,741,0.0593797579934289,1013,0.0811763763122045,627,0.0502444106098245,431,0.0345380238801186,417,0.033416139113711,384,0.030771696450036,364,0.0291690039265966,可用,人群包+转化目标
+20260712,cell*year*商业,点击,9589,15473,5801,0.6049640212743769,1.2475784579620302,2.2475784579620304,1.6049640212743768,2581,0.269162582125352,1111,0.1158619251225362,410,0.0427573261028261,275,0.0286786943372614,206,0.0214829492126394,167,0.0174157889248096,152,0.0158514965064135,199,0.0207529460840546,176,0.0183543643758473,203,0.0211700907289602,91,0.0094900406716028,54,0.0056314527062258,49,0.0051100219000938,62,0.0064657419960371,32,0.0033371571592449,33,0.0034414433204713,可用,人群包+转化目标
+20260712,wx*商业,关键页面访问次数,9244,16358,34762,3.760493292946777,1.7058457227368258,2.7058457227368256,4.7604932929467765,12847,1.389766334919948,6998,0.7570315880571181,3534,0.3823020337516227,2071,0.2240372133275638,1450,0.1568585028126352,1340,0.1449588922544353,1108,0.1198615318044136,1026,0.1109909130246646,692,0.0748593682388576,721,0.0779965382951103,649,0.0702077022933794,452,0.0488965815664214,544,0.0588489831241886,533,0.0576590220683686,464,0.0501947209000432,333,0.0360233665080051,可用,人群包+转化目标
+20260712,R500*全品类,关键页面访问次数,7068,10423,49567,7.01287492925863,1.6840851248172417,2.6840851248172415,8.01287492925863,18467,2.6127617430673458,9528,1.3480475382003396,4890,0.6918505942275043,3484,0.4929258630447085,2367,0.3348896434634975,1994,0.2821165817770232,1697,0.2400962082625919,1444,0.2043010752688172,1113,0.1574702886247877,1107,0.1566213921901528,853,0.1206847764572722,726,0.1027164685908319,578,0.0817770232031692,472,0.0667798528579513,489,0.0691850594227504,358,0.0506508205998868,可用,人群包+转化目标
+20260712,中老年*p75,关键页面访问次数,5296,7592,4015,0.758119335347432,1.3034997131382673,2.3034997131382675,1.758119335347432,1743,0.3291163141993957,696,0.1314199395770392,400,0.0755287009063444,277,0.0523036253776435,191,0.0360649546827794,115,0.021714501510574,82,0.0154833836858006,106,0.0200151057401812,122,0.023036253776435,52,0.0098187311178247,64,0.0120845921450151,36,0.0067975830815709,29,0.0054758308157099,44,0.0083081570996978,35,0.0066087613293051,23,0.0043429003021148,可用,人群包+转化目标
+20260712,R50*泛祝福,关键页面访问次数,4329,5754,9495,2.1933471933471935,0.874259771022503,1.8742597710225029,3.1933471933471935,5066,1.1702471702471702,1520,0.3511203511203511,714,0.1649341649341649,468,0.1081081081081081,322,0.0743820743820743,193,0.0445830445830445,201,0.0464310464310464,146,0.0337260337260337,149,0.0344190344190344,121,0.0279510279510279,193,0.0445830445830445,95,0.0219450219450219,88,0.0203280203280203,84,0.0194040194040194,63,0.0145530145530145,72,0.0166320166320166,可用,人群包+转化目标
+20260712,回流100-180人群,关键页面访问次数,3638,4900,6808,1.8713578889499725,1.350828729281768,2.350828729281768,2.8713578889499725,2896,0.7960417811984607,1544,0.4244090159428257,709,0.1948873007146783,435,0.1195711929631665,192,0.0527762506871907,200,0.0549752611324903,143,0.0393073117097306,112,0.0307861462341946,90,0.0247388675096206,61,0.0167674546454095,69,0.0189664650907091,82,0.022539857064321,53,0.0145684442001099,97,0.0266630016492578,54,0.0148433205057724,71,0.019516217702034,可用,人群包+转化目标
+20260712,泛人群,未知,1701,2449,4327,2.5437977660199884,1.6400244051250763,2.640024405125076,3.5437977660199884,1639,0.9635508524397414,683,0.4015285126396237,328,0.1928277483833039,266,0.1563786008230452,193,0.1134626690182245,224,0.1316872427983539,238,0.139917695473251,123,0.0723104056437389,167,0.098177542621987,61,0.0358612580834803,60,0.0352733686067019,29,0.0170487948265726,88,0.0517342739564961,92,0.0540858318636096,98,0.0576131687242798,38,0.0223398001175778,可用,人群包+转化目标
+20260712,cell*year*商业,关键页面访问次数,1628,2559,2801,1.7205159705159705,1.4765694076038904,2.47656940760389,2.7205159705159705,1131,0.6947174447174447,520,0.3194103194103194,309,0.1898034398034398,187,0.1148648648648648,74,0.0454545454545454,73,0.0448402948402948,48,0.0294840294840294,64,0.0393120393120393,39,0.0239557739557739,68,0.0417690417690417,99,0.0608108108108108,72,0.0442260442260442,32,0.0196560196560196,29,0.0178132678132678,16,0.0098280098280098,40,0.0245700245700245,可用,人群包+转化目标
+20260712,回流50-100人群,关键页面访问次数,988,1290,2146,2.172064777327935,2.6621160409556315,3.662116040955631,3.172064777327935,586,0.5931174089068826,472,0.4777327935222672,135,0.1366396761133603,130,0.131578947368421,114,0.1153846153846153,63,0.0637651821862348,56,0.0566801619433198,60,0.0607287449392712,139,0.1406882591093117,163,0.1649797570850202,54,0.0546558704453441,50,0.0506072874493927,59,0.0597165991902834,30,0.0303643724696356,22,0.0222672064777327,13,0.0131578947368421,可用,人群包+转化目标
+20260712,unexp*day*商业,关键页面访问次数,298,466,320,1.0738255033557047,0.8497109826589595,1.8497109826589595,2.073825503355705,173,0.5805369127516778,77,0.2583892617449664,30,0.1006711409395973,10,0.0335570469798657,8,0.0268456375838926,1,0.0033557046979865,4,0.0134228187919463,1,0.0033557046979865,4,0.0134228187919463,3,0.0100671140939597,2,0.0067114093959731,2,0.0067114093959731,1,0.0033557046979865,1,0.0033557046979865,2,0.0067114093959731,1,0.0033557046979865,首层UV不足500,人群包+转化目标
+20260712,wx*商业,未知,271,450,0,0.0,,,1.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,首层UV不足500,人群包+转化目标
+20260712,R50*同感个体*个人情感,未知,212,334,0,0.0,,,1.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,首层UV不足500,人群包+转化目标
+20260712,泛人群*已转化,未知,121,176,0,0.0,,,1.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,首层UV不足500,人群包+转化目标
+20260712,R50*已转化,未知,112,157,0,0.0,,,1.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,首层UV不足500,人群包+转化目标
+20260712,回流330以上人群,未知,111,169,0,0.0,,,1.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,首层UV不足500,人群包+转化目标
+20260712,R50*泛祝福,未知,108,152,0,0.0,,,1.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,首层UV不足500,人群包+转化目标
+20260712,R50*泛知识*生活科普,未知,90,127,1,0.0111111111111111,,,1.011111111111111,0,0.0,1,0.0111111111111111,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,首层UV不足500,人群包+转化目标
+20260712,cell*year*商业,未知,73,97,0,0.0,,,1.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,首层UV不足500,人群包+转化目标
+20260712,R50*泛知识*时政历史,未知,57,84,0,0.0,,,1.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,首层UV不足500,人群包+转化目标
+20260712,R50*全品类,未知,40,56,7,0.175,2.5,3.5,1.175,2,0.05,2,0.05,0,0.0,0,0.0,0,0.0,1,0.025,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,2,0.05,0,0.0,首层UV不足500,人群包+转化目标
+20260712,R50*泛惊奇*奇观技艺,未知,40,53,0,0.0,,,1.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,首层UV不足500,人群包+转化目标
+20260712,R500*全品类,未知,7,9,0,0.0,,,1.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,首层UV不足500,人群包+转化目标
+20260712,unexp*day*商业,未知,4,5,0,0.0,,,1.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,首层UV不足500,人群包+转化目标
+20260712,Q-回流330以上人群,未知,2,3,0,0.0,,,1.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,首层UV不足500,人群包+转化目标
+20260712,回流100-180人群,未知,1,1,0,0.0,,,1.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,首层UV不足500,人群包+转化目标
+20260712,Q-R50*泛知识*时政历史,未知,1,2,0,0.0,,,1.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,首层UV不足500,人群包+转化目标
+20260712,祝福*p75,关键页面访问次数,1,1,0,0.0,,,1.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,首层UV不足500,人群包+转化目标
+20260712,Q-回流100-180人群,未知,1,1,0,0.0,,,1.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,首层UV不足500,人群包+转化目标

+ 8 - 1
examples/auto_put_ad_mini/roi_control/data_source.py

@@ -54,6 +54,10 @@ def build_daily_sql(start_date: str, end_date: str) -> str:
       AND videoid IS NOT NULL
       AND NVL(hotsencetype, '') <> '1167'
     """
+    optimize_goal = (
+        "CASE WHEN 广告优化目标 IS NULL OR 广告优化目标='' "
+        "OR 广告优化目标='null' THEN '' ELSE 广告优化目标 END"
+    )
 
     return f"""
 SELECT
@@ -66,6 +70,7 @@ SELECT
   NVL(广告id, '') AS 广告id,
   MAX(NVL(广告名称, '')) AS 广告名称,
   NVL(包名, '') AS 包名,
+  {optimize_goal} AS 广告优化目标,
   NVL(创意id, '') AS 创意id,
   '' AS 合作方名,
   '' AS 公众号名,
@@ -80,7 +85,7 @@ WHERE {common_filter}
   AND 广告id IS NOT NULL
   AND 创意id IS NOT NULL
 GROUP BY
-  dt, channel, 账号id, 广告id, 包名, 创意id
+  dt, channel, 账号id, 广告id, 包名, {optimize_goal}, 创意id
 
 UNION ALL
 
@@ -94,6 +99,7 @@ SELECT
   '' AS 广告id,
   '' AS 广告名称,
   '' AS 包名,
+  '' AS 广告优化目标,
   '' AS 创意id,
   NVL(合作方名, '') AS 合作方名,
   NVL(公众号名, '') AS 公众号名,
@@ -120,6 +126,7 @@ SELECT
   '' AS 广告id,
   '' AS 广告名称,
   '' AS 包名,
+  '' AS 广告优化目标,
   '' AS 创意id,
   NVL(合作方名, '') AS 合作方名,
   MAX(NVL(公众号名, '')) AS 公众号名,

+ 1 - 1
examples/auto_put_ad_mini/roi_control/execution.py

@@ -304,7 +304,7 @@ def _execute_scale(
         raise ValueError(f"ad has no valid {bid_field}")
     base = int(state.get("base_bid_fen") or current)
     initial = int(state.get("initial_base_bid_fen") or base)
-    intraday_ratio = Decimal(os.getenv("RTC_BID_UP_RATIO", "1.25"))
+    intraday_ratio = Decimal(os.getenv("RTC_BID_UP_RATIO", "1.05"))
     plan = plan_scale_bid(
         current_bid_fen=current,
         base_bid_fen=base,

+ 50 - 18
examples/auto_put_ad_mini/roi_control/feishu.py

@@ -18,17 +18,29 @@ class RoiFeishuPublisher:
     def __init__(self, timeout: float = 30.0) -> None:
         self.app_id = os.getenv("FEISHU_APP_ID", "").strip()
         self.app_secret = os.getenv("FEISHU_APP_SECRET", "").strip()
-        self.chat_id = (
+        primary_chat_id = (
             os.getenv("ROI_FEISHU_CHAT_ID", "").strip()
-            or os.getenv("RTC_COMMAND_CHAT_ID", "").strip()
             or os.getenv("FEISHU_AD_PROJECT_CHAT_ID", "").strip()
+            or os.getenv("RTC_COMMAND_CHAT_ID", "").strip()
         )
+        operator_chat_id = os.getenv("FEISHU_OPERATOR_CHAT_ID", "").strip()
+        self.chat_ids = list(
+            dict.fromkeys(
+                chat_id
+                for chat_id in (primary_chat_id, operator_chat_id)
+                if chat_id
+            )
+        )
+        self.approval_chat_id = operator_chat_id or primary_chat_id
         missing = [
             name
             for name, value in {
                 "FEISHU_APP_ID": self.app_id,
                 "FEISHU_APP_SECRET": self.app_secret,
-                "ROI_FEISHU_CHAT_ID/RTC_COMMAND_CHAT_ID/FEISHU_AD_PROJECT_CHAT_ID": self.chat_id,
+                (
+                    "ROI_FEISHU_CHAT_ID/FEISHU_AD_PROJECT_CHAT_ID/"
+                    "RTC_COMMAND_CHAT_ID/FEISHU_OPERATOR_CHAT_ID"
+                ): self.chat_ids,
             }.items()
             if not value
         ]
@@ -126,15 +138,21 @@ class RoiFeishuPublisher:
         token: str,
         *,
         run_id: str,
+        batch_name: str,
+        chat_id: str,
+        can_approve: bool,
         url: str,
         summary: str,
         requires_approval: bool,
     ) -> str:
-        instructions = (
-            f"\n\n请在有效期内回复:`确认 {run_id}` 或 `拒绝 {run_id}`"
-            if requires_approval
-            else "\n\n本批次没有可执行动作,无需审批。"
-        )
+        if not requires_approval:
+            instructions = "\n\n本批次没有可执行动作,无需审批。"
+        elif can_approve:
+            instructions = (
+                f"\n\n请在有效期内回复:`确认 {run_id}` 或 `拒绝 {run_id}`"
+            )
+        else:
+            instructions = "\n\n本批次需要审批,请前往投放审批群处理。"
         card = {
             "config": {"wide_screen_mode": True},
             "header": {
@@ -146,7 +164,10 @@ class RoiFeishuPublisher:
                     "tag": "div",
                     "text": {
                         "tag": "lark_md",
-                        "content": f"批次:`{run_id}`\n{summary}{instructions}",
+                        "content": (
+                            f"批次:**{batch_name}**\n"
+                            f"审批ID:`{run_id}`\n{summary}{instructions}"
+                        ),
                     },
                 },
                 {"tag": "hr"},
@@ -168,7 +189,7 @@ class RoiFeishuPublisher:
             headers={**self._headers(token), "Content-Type": "application/json"},
             params={"receive_id_type": "chat_id"},
             json={
-                "receive_id": self.chat_id,
+                "receive_id": chat_id,
                 "msg_type": "interactive",
                 "content": json.dumps(card, ensure_ascii=False),
             },
@@ -180,6 +201,7 @@ class RoiFeishuPublisher:
         path: Path,
         *,
         run_id: str,
+        batch_name: str,
         summary: str,
         requires_approval: bool,
     ) -> dict[str, str]:
@@ -194,11 +216,21 @@ class RoiFeishuPublisher:
         if not url or not sheet_token:
             raise RuntimeError("ROI sheet import returned no URL/token")
         self._set_read_only_link(token, sheet_token)
-        message_id = self._send_card(
-            token,
-            run_id=run_id,
-            url=url,
-            summary=summary,
-            requires_approval=requires_approval,
-        )
-        return {"url": url, "sheet_token": sheet_token, "message_id": message_id}
+        message_ids = [
+            self._send_card(
+                token,
+                run_id=run_id,
+                batch_name=batch_name,
+                chat_id=chat_id,
+                can_approve=chat_id == self.approval_chat_id,
+                url=url,
+                summary=summary,
+                requires_approval=requires_approval,
+            )
+            for chat_id in self.chat_ids
+        ]
+        return {
+            "url": url,
+            "sheet_token": sheet_token,
+            "message_id": message_ids[0],
+        }

+ 581 - 0
examples/auto_put_ad_mini/roi_control/fission_multiplier.py

@@ -0,0 +1,581 @@
+"""Versioned T15 propagation-fission multipliers relative to T0.
+
+This module is deliberately independent from ODPS, policy, persistence,
+approval, and Tencent writes. Daily ROI consumes a published parameter release;
+it never recomputes cohort parameters during a production run.
+"""
+
+from __future__ import annotations
+
+import hashlib
+import json
+import math
+from dataclasses import dataclass
+from pathlib import Path
+from typing import Mapping
+
+import pandas as pd
+
+
+DEFAULT_FISSION_PARAMETER_VERSION = "20260712_A0-A15_v1"
+FISSION_HORIZON_DAYS = 15
+PARAMETER_ROOT = Path(__file__).resolve().parent / "data" / "fission_multiplier"
+SOURCE_MULTIPLIER_COLUMN = "T15成熟系数(相对T0)"
+DISPLAY_MULTIPLIER_COLUMN = "传播裂变系数-对T0裂变"
+
+MINIAPP_FILE = "小程序T15成熟系数_中文_20260712.csv"
+GZH_FILE = "公众号T15成熟系数_中文_20260712.csv"
+FALLBACK_FILE = "T15分级回退系数_中文_20260712.csv"
+
+MATCH_MINIAPP_EXACT = "miniapp_package_goal_exact"
+MATCH_MINIAPP_PACKAGE = "miniapp_package_fallback"
+MATCH_MINIAPP_GOAL = "miniapp_goal_fallback"
+MATCH_MINIAPP_CHANNEL = "miniapp_channel_fallback"
+MATCH_GZH_EXACT = "gzh_partner_account_exact"
+MATCH_GZH_PARTNER = "gzh_partner_fallback"
+MATCH_GZH_CHANNEL = "gzh_channel_fallback"
+MATCH_QIWEI_REFERENCE = "qiwei_channel_reference_pending"
+
+
+@dataclass(frozen=True)
+class ParameterRelease:
+    version: str
+    cohort_date: str
+    observation_end_date: str
+    run_suffix: str
+    file_sha256: Mapping[str, str]
+
+
+RELEASES: Mapping[str, ParameterRelease] = {
+    DEFAULT_FISSION_PARAMETER_VERSION: ParameterRelease(
+        version=DEFAULT_FISSION_PARAMETER_VERSION,
+        cohort_date="20260712",
+        observation_end_date="20260727",
+        run_suffix="f0712v1",
+        file_sha256={
+            MINIAPP_FILE: "9358408ad4957bbd22f689f8bbf66b7abe765f210e5af444d11e329815fee6a4",
+            GZH_FILE: "1f6f17b1403aa9b56a33195da3c324fbe06cbb714aa2ebabcdbceb891aa7a951",
+            FALLBACK_FILE: "6e4d517595ec2632dc54a65000abe94000b5313e77420547759b2419314d60ac",
+        },
+    )
+}
+
+
+@dataclass(frozen=True)
+class FissionMultiplierMatch:
+    multiplier: float
+    match_level: str
+    source: str
+
+
+@dataclass(frozen=True)
+class FissionMultiplierParameters:
+    release: ParameterRelease
+    miniapp_exact: Mapping[tuple[str, str], float]
+    miniapp_by_package: Mapping[str, float]
+    miniapp_by_goal: Mapping[str, float]
+    miniapp_channel: float
+    gzh_exact: Mapping[tuple[str, str], float]
+    gzh_by_partner: Mapping[str, float]
+    gzh_channel: float
+    miniapp_exact_rows: int
+    miniapp_exact_available_rows: int
+    gzh_exact_rows: int
+    gzh_exact_available_rows: int
+
+    def snapshot(self) -> dict[str, object]:
+        return {
+            "version": self.release.version,
+            "cohort_date": self.release.cohort_date,
+            "observation_end_date": self.release.observation_end_date,
+            "horizon_days": FISSION_HORIZON_DAYS,
+            "miniapp_exact_rows": self.miniapp_exact_rows,
+            "miniapp_exact_available_rows": self.miniapp_exact_available_rows,
+            "gzh_exact_rows": self.gzh_exact_rows,
+            "gzh_exact_available_rows": self.gzh_exact_available_rows,
+            "miniapp_channel_multiplier": self.miniapp_channel,
+            "gzh_channel_multiplier": self.gzh_channel,
+        }
+
+    def match(
+        self,
+        entity_type: str,
+        *,
+        package: object = "",
+        optimize_goal: object = "",
+        partner: object = "",
+        official_account: object = "",
+    ) -> FissionMultiplierMatch:
+        if entity_type == "self":
+            package_key = normalize_package(package)
+            goal_key = normalize_name(optimize_goal)
+            exact_key = (package_key, goal_key)
+            if goal_key and exact_key in self.miniapp_exact:
+                return FissionMultiplierMatch(
+                    self.miniapp_exact[exact_key],
+                    MATCH_MINIAPP_EXACT,
+                    f"人群包+转化目标精确:{package_key}|{goal_key}",
+                )
+            if package_key in self.miniapp_by_package:
+                return FissionMultiplierMatch(
+                    self.miniapp_by_package[package_key],
+                    MATCH_MINIAPP_PACKAGE,
+                    f"人群包回退:{package_key}",
+                )
+            if goal_key and goal_key in self.miniapp_by_goal:
+                return FissionMultiplierMatch(
+                    self.miniapp_by_goal[goal_key],
+                    MATCH_MINIAPP_GOAL,
+                    f"转化目标回退:{goal_key}",
+                )
+            return FissionMultiplierMatch(
+                self.miniapp_channel,
+                MATCH_MINIAPP_CHANNEL,
+                "小程序渠道回退",
+            )
+
+        if entity_type == "gzh":
+            partner_key = normalize_name(partner)
+            account_key = normalize_name(official_account)
+            exact_key = (partner_key, account_key)
+            if partner_key and account_key and exact_key in self.gzh_exact:
+                return FissionMultiplierMatch(
+                    self.gzh_exact[exact_key],
+                    MATCH_GZH_EXACT,
+                    f"合作方+公众号精确:{partner_key}|{account_key}",
+                )
+            if partner_key in self.gzh_by_partner:
+                return FissionMultiplierMatch(
+                    self.gzh_by_partner[partner_key],
+                    MATCH_GZH_PARTNER,
+                    f"合作方回退:{partner_key}",
+                )
+            return FissionMultiplierMatch(
+                self.gzh_channel,
+                MATCH_GZH_CHANNEL,
+                "公众号渠道回退",
+            )
+
+        if entity_type == "qiwei":
+            return FissionMultiplierMatch(
+                1.0,
+                MATCH_QIWEI_REFERENCE,
+                f"企微渠道临时参考系数1.0_待补算:{normalize_name(partner)}",
+            )
+
+        raise ValueError(f"不支持的ROI实体类型: {entity_type}")
+
+
+def parameter_values(
+    parameters: FissionMultiplierParameters,
+) -> list[dict[str, object]]:
+    """Serialize one validated release into database lookup rows."""
+
+    rows: list[dict[str, object]] = []
+
+    def append(
+        entity_type: str,
+        match_level: str,
+        key_primary: str,
+        key_secondary: str,
+        multiplier: float,
+    ) -> None:
+        rows.append(
+            {
+                "entity_type": entity_type,
+                "match_level": match_level,
+                "key_primary": key_primary,
+                "key_secondary": key_secondary,
+                "multiplier": float(multiplier),
+            }
+        )
+
+    for (package, goal), multiplier in parameters.miniapp_exact.items():
+        append("self", MATCH_MINIAPP_EXACT, package, goal, multiplier)
+    for package, multiplier in parameters.miniapp_by_package.items():
+        append("self", MATCH_MINIAPP_PACKAGE, package, "", multiplier)
+    for goal, multiplier in parameters.miniapp_by_goal.items():
+        append("self", MATCH_MINIAPP_GOAL, goal, "", multiplier)
+    append("self", MATCH_MINIAPP_CHANNEL, "", "", parameters.miniapp_channel)
+
+    for (partner, account), multiplier in parameters.gzh_exact.items():
+        append("gzh", MATCH_GZH_EXACT, partner, account, multiplier)
+    for partner, multiplier in parameters.gzh_by_partner.items():
+        append("gzh", MATCH_GZH_PARTNER, partner, "", multiplier)
+    append("gzh", MATCH_GZH_CHANNEL, "", "", parameters.gzh_channel)
+    return sorted(
+        rows,
+        key=lambda row: (
+            str(row["entity_type"]),
+            str(row["match_level"]),
+            str(row["key_primary"]),
+            str(row["key_secondary"]),
+        ),
+    )
+
+
+def parameter_content_sha256(
+    parameters: FissionMultiplierParameters,
+) -> str:
+    payload = {
+        "release": parameters.snapshot(),
+        "file_sha256": dict(parameters.release.file_sha256),
+        "values": parameter_values(parameters),
+    }
+    encoded = json.dumps(
+        payload,
+        ensure_ascii=False,
+        sort_keys=True,
+        separators=(",", ":"),
+    ).encode("utf-8")
+    return hashlib.sha256(encoded).hexdigest()
+
+
+def parameters_from_database(
+    release_row: Mapping[str, object],
+    value_rows: list[Mapping[str, object]],
+) -> FissionMultiplierParameters:
+    """Build runtime parameters from one published database version."""
+
+    metadata = json.loads(str(release_row.get("metadata_json") or "{}"))
+    file_sha256 = metadata.get("file_sha256") or {}
+    release = ParameterRelease(
+        version=str(release_row["version"]),
+        cohort_date=str(release_row["cohort_date"]).replace("-", ""),
+        observation_end_date=str(release_row["observation_end_date"]).replace(
+            "-", ""
+        ),
+        run_suffix=str(release_row["run_suffix"]),
+        file_sha256=file_sha256,
+    )
+    indexed: dict[tuple[str, str, str, str], float] = {}
+    for row in value_rows:
+        key = (
+            str(row["entity_type"]),
+            str(row["match_level"]),
+            str(row.get("key_primary") or ""),
+            str(row.get("key_secondary") or ""),
+        )
+        if key in indexed:
+            raise ValueError(f"数据库传播裂变系数存在重复匹配键: {key}")
+        multiplier = float(row["multiplier"])
+        if not math.isfinite(multiplier) or multiplier < 1:
+            raise ValueError(f"数据库传播裂变系数无效: {key}={multiplier}")
+        indexed[key] = multiplier
+
+    def values(entity_type: str, level: str) -> dict[tuple[str, str], float]:
+        return {
+            (primary, secondary): multiplier
+            for (entity, match_level, primary, secondary), multiplier in indexed.items()
+            if entity == entity_type and match_level == level
+        }
+
+    def single(entity_type: str, level: str) -> float:
+        matched = values(entity_type, level)
+        if set(matched) != {("", "")}:
+            raise ValueError(f"数据库{level}必须且只能有一条渠道参数")
+        return matched[("", "")]
+
+    mini_exact = values("self", MATCH_MINIAPP_EXACT)
+    mini_package = {
+        key[0]: multiplier
+        for key, multiplier in values("self", MATCH_MINIAPP_PACKAGE).items()
+    }
+    mini_goal = {
+        key[0]: multiplier
+        for key, multiplier in values("self", MATCH_MINIAPP_GOAL).items()
+    }
+    gzh_exact = values("gzh", MATCH_GZH_EXACT)
+    gzh_partner = {
+        key[0]: multiplier
+        for key, multiplier in values("gzh", MATCH_GZH_PARTNER).items()
+    }
+    result = FissionMultiplierParameters(
+        release=release,
+        miniapp_exact=mini_exact,
+        miniapp_by_package=mini_package,
+        miniapp_by_goal=mini_goal,
+        miniapp_channel=single("self", MATCH_MINIAPP_CHANNEL),
+        gzh_exact=gzh_exact,
+        gzh_by_partner=gzh_partner,
+        gzh_channel=single("gzh", MATCH_GZH_CHANNEL),
+        miniapp_exact_rows=int(metadata["miniapp_exact_rows"]),
+        miniapp_exact_available_rows=int(metadata["miniapp_exact_available_rows"]),
+        gzh_exact_rows=int(metadata["gzh_exact_rows"]),
+        gzh_exact_available_rows=int(metadata["gzh_exact_available_rows"]),
+    )
+    expected_hash = str(release_row["content_sha256"])
+    if parameter_content_sha256(result) != expected_hash:
+        raise ValueError(
+            f"数据库传播裂变系数内容校验失败: version={release.version}"
+        )
+    return result
+
+
+def normalize_name(value: object) -> str:
+    if value is None or pd.isna(value):
+        return ""
+    text = str(value).strip()
+    return "" if not text or text.lower() == "null" else text
+
+
+def normalize_package(value: object) -> str:
+    return normalize_name(value) or "泛人群"
+
+
+def _sha256(path: Path) -> str:
+    digest = hashlib.sha256()
+    with path.open("rb") as handle:
+        for chunk in iter(lambda: handle.read(1024 * 1024), b""):
+            digest.update(chunk)
+    return digest.hexdigest()
+
+
+def _read_parameter_file(
+    path: Path,
+    *,
+    required: set[str],
+    label: str,
+    expected_sha256: str,
+) -> pd.DataFrame:
+    if not path.is_file():
+        raise FileNotFoundError(f"{label}参数文件不存在: {path}")
+    actual_sha256 = _sha256(path)
+    if actual_sha256 != expected_sha256:
+        raise ValueError(
+            f"{label}参数文件校验失败: expected={expected_sha256} actual={actual_sha256}"
+        )
+    frame = pd.read_csv(path, encoding="utf-8-sig")
+    missing = sorted(required - set(frame.columns))
+    if missing:
+        raise ValueError(f"{label}参数缺少字段: {', '.join(missing)}")
+    return frame
+
+
+def _validated_multipliers(
+    frame: pd.DataFrame,
+    *,
+    label: str,
+) -> pd.DataFrame:
+    result = frame.copy()
+    numeric_columns = [
+        "首层UV",
+        "A0活跃裂变UV",
+        "A0-A15累计裂变活跃人次",
+        "T1-T15相对T0尾部系数",
+        SOURCE_MULTIPLIER_COLUMN,
+    ]
+    for column in numeric_columns:
+        if column in result:
+            result[column] = pd.to_numeric(result[column], errors="coerce")
+
+    checkable = result[
+        result["A0活跃裂变UV"].gt(0)
+        & result[SOURCE_MULTIPLIER_COLUMN].notna()
+    ]
+    if checkable.empty:
+        raise ValueError(f"{label}参数没有可校验的传播裂变系数")
+    expected = (
+        checkable["A0-A15累计裂变活跃人次"]
+        / checkable["A0活跃裂变UV"]
+    )
+    errors = (expected - checkable[SOURCE_MULTIPLIER_COLUMN]).abs()
+    if bool(errors.gt(1e-9).any()):
+        raise ValueError(f"{label}参数不满足累计活跃人次/A0恒等式")
+    tails = checkable["T1-T15相对T0尾部系数"]
+    tail_errors = (
+        tails - (checkable[SOURCE_MULTIPLIER_COLUMN] - 1)
+    ).abs()
+    if bool(tail_errors.gt(1e-9).any()):
+        raise ValueError(f"{label}参数不满足尾部系数=传播裂变系数-1")
+
+    available = result[result["样本状态"].eq("可用")].copy()
+    valid = available[SOURCE_MULTIPLIER_COLUMN].map(
+        lambda value: bool(pd.notna(value) and math.isfinite(float(value)) and value >= 1)
+    )
+    if not bool(valid.all()):
+        raise ValueError(f"{label}存在无效的可用传播裂变系数")
+    return result
+
+
+def _mapping(
+    frame: pd.DataFrame,
+    key_columns: list[str],
+    *,
+    normalizers: list,
+    label: str,
+) -> dict:
+    available = frame[frame["样本状态"].eq("可用")].copy()
+    keys = [
+        tuple(normalizer(row[column]) for column, normalizer in zip(key_columns, normalizers))
+        for _, row in available.iterrows()
+    ]
+    if any(not all(key) for key in keys):
+        raise ValueError(f"{label}存在空匹配键")
+    if len(keys) != len(set(keys)):
+        raise ValueError(f"{label}存在重复匹配键")
+    values = available[SOURCE_MULTIPLIER_COLUMN].astype(float).tolist()
+    if len(key_columns) == 1:
+        return {key[0]: value for key, value in zip(keys, values)}
+    return dict(zip(keys, values))
+
+
+def _single_channel_multiplier(frame: pd.DataFrame, level: str) -> float:
+    rows = frame[
+        frame["参数层级"].eq(level) & frame["样本状态"].eq("可用")
+    ]
+    if len(rows) != 1:
+        raise ValueError(f"{level}必须且只能有一条可用参数,实际为{len(rows)}")
+    return float(rows.iloc[0][SOURCE_MULTIPLIER_COLUMN])
+
+
+def load_fission_multiplier_parameters(
+    version: str = DEFAULT_FISSION_PARAMETER_VERSION,
+    *,
+    parameter_root: Path | None = None,
+) -> FissionMultiplierParameters:
+    try:
+        release = RELEASES[version]
+    except KeyError as exc:
+        raise ValueError(f"未知传播裂变系数参数版本: {version}") from exc
+    directory = (parameter_root or PARAMETER_ROOT) / version
+
+    exact_required = {
+        "首层投放日期",
+        "首层UV",
+        "A0活跃裂变UV",
+        "A0-A15累计裂变活跃人次",
+        "T1-T15相对T0尾部系数",
+        SOURCE_MULTIPLIER_COLUMN,
+        "样本状态",
+    }
+    miniapp = _read_parameter_file(
+        directory / MINIAPP_FILE,
+        required=exact_required | {"人群包", "转化目标"},
+        label="小程序",
+        expected_sha256=release.file_sha256[MINIAPP_FILE],
+    )
+    gzh = _read_parameter_file(
+        directory / GZH_FILE,
+        required=exact_required | {"合作方", "公众号"},
+        label="公众号",
+        expected_sha256=release.file_sha256[GZH_FILE],
+    )
+    fallback = _read_parameter_file(
+        directory / FALLBACK_FILE,
+        required={
+            "参数层级",
+            "人群包",
+            "转化目标",
+            "合作方",
+            "公众号",
+            "首层UV",
+            "A0活跃裂变UV",
+            "A0-A15累计裂变活跃人次",
+            "T1-T15相对T0尾部系数",
+            SOURCE_MULTIPLIER_COLUMN,
+            "样本状态",
+        },
+        label="分级回退",
+        expected_sha256=release.file_sha256[FALLBACK_FILE],
+    )
+    miniapp = _validated_multipliers(miniapp, label="小程序")
+    gzh = _validated_multipliers(gzh, label="公众号")
+    fallback = _validated_multipliers(fallback, label="分级回退")
+
+    for label, frame in (("小程序", miniapp), ("公众号", gzh)):
+        dates = {str(value) for value in frame["首层投放日期"].dropna()}
+        if dates != {release.cohort_date}:
+            raise ValueError(
+                f"{label}参数cohort日期不一致: expected={release.cohort_date} actual={sorted(dates)}"
+            )
+
+    mini_package_rows = fallback[fallback["参数层级"].eq("小程序人群包回退")]
+    mini_goal_rows = fallback[fallback["参数层级"].eq("小程序转化目标回退")]
+    gzh_partner_rows = fallback[fallback["参数层级"].eq("公众号合作方回退")]
+
+    return FissionMultiplierParameters(
+        release=release,
+        miniapp_exact=_mapping(
+            miniapp,
+            ["人群包", "转化目标"],
+            normalizers=[normalize_package, normalize_name],
+            label="小程序精确参数",
+        ),
+        miniapp_by_package=_mapping(
+            mini_package_rows,
+            ["人群包"],
+            normalizers=[normalize_package],
+            label="小程序人群包回退参数",
+        ),
+        miniapp_by_goal=_mapping(
+            mini_goal_rows,
+            ["转化目标"],
+            normalizers=[normalize_name],
+            label="小程序转化目标回退参数",
+        ),
+        miniapp_channel=_single_channel_multiplier(
+            fallback, "小程序渠道回退"
+        ),
+        gzh_exact=_mapping(
+            gzh,
+            ["合作方", "公众号"],
+            normalizers=[normalize_name, normalize_name],
+            label="公众号精确参数",
+        ),
+        gzh_by_partner=_mapping(
+            gzh_partner_rows,
+            ["合作方"],
+            normalizers=[normalize_name],
+            label="公众号合作方回退参数",
+        ),
+        gzh_channel=_single_channel_multiplier(
+            fallback, "公众号渠道回退"
+        ),
+        miniapp_exact_rows=len(miniapp),
+        miniapp_exact_available_rows=int(miniapp["样本状态"].eq("可用").sum()),
+        gzh_exact_rows=len(gzh),
+        gzh_exact_available_rows=int(gzh["样本状态"].eq("可用").sum()),
+    )
+
+
+def apply_fission_multiplier(
+    daily: pd.DataFrame,
+    parameters: FissionMultiplierParameters,
+) -> pd.DataFrame:
+    required = {"entity_type", "包名", "广告优化目标", "合作方名", "公众号名"}
+    missing = sorted(required - set(daily.columns))
+    if missing:
+        raise ValueError(f"传播裂变系数匹配缺少字段: {', '.join(missing)}")
+
+    result = daily.copy()
+    multipliers: list[float] = []
+    levels: list[str] = []
+    sources: list[str] = []
+    for row in result.to_dict("records"):
+        match = parameters.match(
+            str(row["entity_type"]),
+            package=row["包名"],
+            optimize_goal=row["广告优化目标"],
+            partner=row["合作方名"],
+            official_account=row["公众号名"],
+        )
+        multipliers.append(match.multiplier)
+        levels.append(match.match_level)
+        sources.append(match.source)
+
+    result[DISPLAY_MULTIPLIER_COLUMN] = multipliers
+    result["传播裂变系数匹配层级"] = levels
+    result["传播裂变系数来源"] = sources
+    result["传播裂变参数版本"] = parameters.release.version
+    result["传播裂变参数cohort日期"] = parameters.release.cohort_date
+    qiwei = result["entity_type"].eq("qiwei")
+    result["传播裂变参数状态"] = "正式参数"
+    result.loc[qiwei, "传播裂变参数状态"] = "临时参考系数1.0_待分渠道补算"
+    result["调控参与状态"] = "参与阈值和调控"
+    result.loc[qiwei, "调控参与状态"] = "仅展示_不进入阈值和调控"
+    result["ROI计算口径"] = (
+        "首层实际效率收入+T0实际裂变收入+预测T1-T15裂变收入"
+    )
+    result.loc[qiwei, "ROI计算口径"] = "仅使用实际T0_传播裂变系数临时取1"
+    return result

+ 423 - 0
examples/auto_put_ad_mini/roi_control/fission_multiplier_refresh.py

@@ -0,0 +1,423 @@
+"""Offline T15 cohort parameter recomputation.
+
+The functions here are read-only DataFrame/SQL transformations. Generated
+parameters are drafts; publishing requires adding a reviewed release to
+``fission_multiplier.RELEASES`` with file checksums.
+"""
+
+from __future__ import annotations
+
+from datetime import datetime, timedelta
+from pathlib import Path
+
+import pandas as pd
+from openpyxl.styles import Font
+
+
+HORIZON = 15
+
+
+def _parse_date(value: str) -> datetime:
+    try:
+        return datetime.strptime(value, "%Y%m%d")
+    except ValueError as exc:
+        raise ValueError(f"日期必须是YYYYMMDD,实际为: {value}") from exc
+
+
+def build_miniapp_activity_curve_sql(
+    cohort_date: str,
+    horizon: int = HORIZON,
+) -> str:
+    """Build the audited miniapp package + conversion-goal cohort SQL."""
+
+    start = _parse_date(cohort_date)
+    if horizon < 0:
+        raise ValueError("horizon不能小于0")
+    dates = [
+        (start + timedelta(days=lag)).strftime("%Y%m%d")
+        for lag in range(horizon + 1)
+    ]
+    end_date = dates[-1]
+    active_counts = ",\n".join(
+        f"    SUM(CASE WHEN active_dt='{date}' THEN 1 ELSE 0 END) AS a{lag}_active_uv"
+        for lag, date in enumerate(dates)
+    )
+    active_select = ",\n".join(
+        f"  NVL(a.a{lag}_active_uv,0) AS a{lag}_active_uv"
+        for lag in range(horizon + 1)
+    )
+    rate_select = ",\n".join(
+        f"  CASE WHEN b.first_uv>0 THEN NVL(a.a{lag}_active_uv,0)/b.first_uv END AS a{lag}_active_rate"
+        for lag in range(horizon + 1)
+    )
+    active_sum = "+".join(
+        f"NVL(a.a{lag}_active_uv,0)" for lag in range(horizon + 1)
+    )
+    return f"""
+WITH first_cohort AS (
+  SELECT DISTINCT
+    CASE WHEN 包名 IS NULL OR 包名='' OR 包名='null' THEN '泛人群' ELSE 包名 END AS package_name,
+    CASE WHEN 广告优化目标 IS NULL OR 广告优化目标='' OR 广告优化目标='null' THEN '未知' ELSE 广告优化目标 END AS optimize_goal,
+    mid AS first_mid,
+    subsessionid AS rootsessionid
+  FROM loghubods.opengid_base_data
+  WHERE dt='{cohort_date}'
+    AND channel='小程序投流-稳定'
+    AND usersharedepth=0
+    AND hotsencetype != 1167
+    AND videoid IS NOT NULL
+    AND mid IS NOT NULL
+    AND subsessionid IS NOT NULL
+),
+root_entity AS (
+  SELECT DISTINCT package_name, optimize_goal, rootsessionid FROM first_cohort
+),
+first_users AS (
+  SELECT DISTINCT package_name, optimize_goal, first_mid FROM first_cohort
+),
+base_stats AS (
+  SELECT package_name, optimize_goal,
+         COUNT(DISTINCT first_mid) AS first_uv,
+         COUNT(DISTINCT rootsessionid) AS root_session_cnt
+  FROM first_cohort
+  GROUP BY package_name, optimize_goal
+),
+raw_active_fission AS (
+  SELECT DISTINCT
+    r.package_name,
+    r.optimize_goal,
+    s.machinecode AS active_mid,
+    s.dt AS active_dt
+  FROM root_entity r
+  JOIN loghubods.user_share_log s
+    ON s.rootsessionid=r.rootsessionid
+  WHERE s.dt BETWEEN '{cohort_date}' AND '{end_date}'
+    AND s.topic='click'
+    AND s.machinecode IS NOT NULL
+    AND CAST(s.usersharedepth AS BIGINT)>0
+),
+active_fission AS (
+  SELECT c.*
+  FROM raw_active_fission c
+  LEFT JOIN first_users f
+    ON c.package_name=f.package_name AND c.optimize_goal=f.optimize_goal AND c.active_mid=f.first_mid
+  WHERE f.first_mid IS NULL
+),
+active_counts AS (
+  SELECT package_name, optimize_goal,
+{active_counts},
+    COUNT(*) AS active_person_days
+  FROM active_fission
+  GROUP BY package_name, optimize_goal
+)
+SELECT
+  '{cohort_date}' AS cohort_dt,
+  b.package_name,
+  b.optimize_goal,
+  b.first_uv,
+  b.root_session_cnt,
+{active_select},
+{rate_select},
+  NVL(a.active_person_days,0) AS active_person_days,
+  CASE WHEN b.first_uv>0 THEN ({active_sum})/b.first_uv END AS activity_rate_sum,
+  CASE WHEN NVL(a.a0_active_uv,0)>0
+       THEN (({active_sum})-NVL(a.a0_active_uv,0))/a.a0_active_uv
+  END AS active_tail_vs_a0,
+  CASE WHEN NVL(a.a0_active_uv,0)>0
+       THEN ({active_sum})/a.a0_active_uv
+  END AS activity_maturity_vs_a0,
+  CASE WHEN b.first_uv>0 THEN 1+({active_sum})/b.first_uv END AS steady_dau_multiplier
+FROM base_stats b
+LEFT JOIN active_counts a ON b.package_name=a.package_name AND b.optimize_goal=a.optimize_goal
+ORDER BY b.first_uv DESC
+""".strip()
+
+
+def build_gzh_activity_curve_sql(
+    cohort_date: str,
+    horizon: int = HORIZON,
+    min_first_uv: int = 500,
+) -> str:
+    """Build the audited official-account partner + account cohort SQL."""
+
+    start = _parse_date(cohort_date)
+    if horizon < 0:
+        raise ValueError("horizon不能小于0")
+    if min_first_uv < 0:
+        raise ValueError("首层UV门槛不能小于0")
+    dates = [
+        (start + timedelta(days=lag)).strftime("%Y%m%d")
+        for lag in range(horizon + 1)
+    ]
+    end_date = dates[-1]
+    active_counts = ",\n".join(
+        f"    SUM(CASE WHEN active_dt='{date}' THEN 1 ELSE 0 END) AS a{lag}_active_uv"
+        for lag, date in enumerate(dates)
+    )
+    active_select = ",\n".join(
+        f"  NVL(a.a{lag}_active_uv,0) AS a{lag}_active_uv"
+        for lag in range(horizon + 1)
+    )
+    rate_select = ",\n".join(
+        f"  CASE WHEN b.first_uv>0 THEN NVL(a.a{lag}_active_uv,0)/b.first_uv END AS a{lag}_active_rate"
+        for lag in range(horizon + 1)
+    )
+    active_sum = "+".join(
+        f"NVL(a.a{lag}_active_uv,0)" for lag in range(horizon + 1)
+    )
+    return f"""
+WITH first_cohort AS (
+  SELECT DISTINCT
+    CASE WHEN 合作方名 IS NULL OR 合作方名='' THEN 'null' ELSE 合作方名 END AS partner_name,
+    CASE WHEN 公众号名 IS NULL OR 公众号名='' THEN 'null' ELSE 公众号名 END AS account_name,
+    mid AS first_mid,
+    subsessionid AS rootsessionid
+  FROM loghubods.opengid_base_data
+  WHERE dt='{cohort_date}'
+    AND channel='公众号合作-即转-稳定'
+    AND usersharedepth=0
+    AND hotsencetype != 1167
+    AND videoid IS NOT NULL
+    AND mid IS NOT NULL
+    AND subsessionid IS NOT NULL
+),
+base_stats AS (
+  SELECT partner_name, account_name,
+         COUNT(DISTINCT first_mid) AS first_uv,
+         COUNT(DISTINCT rootsessionid) AS root_session_cnt
+  FROM first_cohort
+  GROUP BY partner_name, account_name
+  HAVING COUNT(DISTINCT first_mid)>{min_first_uv}
+),
+root_entity AS (
+  SELECT DISTINCT f.partner_name, f.account_name, f.rootsessionid
+  FROM first_cohort f
+  JOIN base_stats b ON f.partner_name=b.partner_name AND f.account_name=b.account_name
+),
+first_users AS (
+  SELECT DISTINCT f.partner_name, f.account_name, f.first_mid
+  FROM first_cohort f
+  JOIN base_stats b ON f.partner_name=b.partner_name AND f.account_name=b.account_name
+),
+raw_active_fission AS (
+  SELECT DISTINCT r.partner_name, r.account_name, s.machinecode AS active_mid, s.dt AS active_dt
+  FROM root_entity r
+  JOIN loghubods.user_share_log s
+    ON s.rootsessionid=r.rootsessionid
+  WHERE s.dt BETWEEN '{cohort_date}' AND '{end_date}'
+    AND s.topic='click'
+    AND s.machinecode IS NOT NULL
+    AND CAST(s.usersharedepth AS BIGINT)>0
+),
+active_fission AS (
+  SELECT c.*
+  FROM raw_active_fission c
+  LEFT JOIN first_users f
+    ON c.partner_name=f.partner_name AND c.account_name=f.account_name AND c.active_mid=f.first_mid
+  WHERE f.first_mid IS NULL
+),
+active_counts AS (
+  SELECT partner_name, account_name,
+{active_counts},
+    COUNT(*) AS active_person_days
+  FROM active_fission
+  GROUP BY partner_name, account_name
+)
+SELECT
+  '{cohort_date}' AS cohort_dt,
+  '公众号合作-即转-稳定' AS channel,
+  b.partner_name,
+  b.account_name,
+  b.first_uv,
+  b.root_session_cnt,
+{active_select},
+{rate_select},
+  NVL(a.active_person_days,0) AS active_person_days,
+  CASE WHEN b.first_uv>0 THEN ({active_sum})/b.first_uv END AS activity_rate_sum,
+  CASE WHEN NVL(a.a0_active_uv,0)>0
+       THEN (({active_sum})-NVL(a.a0_active_uv,0))/a.a0_active_uv
+  END AS active_tail_vs_a0,
+  CASE WHEN NVL(a.a0_active_uv,0)>0
+       THEN ({active_sum})/a.a0_active_uv
+  END AS activity_maturity_vs_a0,
+  CASE WHEN b.first_uv>0 THEN 1+({active_sum})/b.first_uv END AS steady_dau_multiplier
+FROM base_stats b
+LEFT JOIN active_counts a ON b.partner_name=a.partner_name AND b.account_name=a.account_name
+ORDER BY b.first_uv DESC
+""".strip()
+
+
+def _sample_status(first_uv: pd.Series, a0_uv: pd.Series) -> pd.Series:
+    status = pd.Series("可用", index=first_uv.index, dtype="object")
+    status.loc[first_uv < 500] = "首层UV不足500"
+    status.loc[(first_uv >= 500) & (a0_uv < 200)] = "A0裂变UV不足200"
+    return status
+
+
+def localize_exact(raw: pd.DataFrame, entity: str) -> pd.DataFrame:
+    result = raw.copy()
+    if "optimize_goal" in result:
+        result["optimize_goal"] = (
+            result["optimize_goal"]
+            .fillna("未知")
+            .replace({"": "未知", "null": "未知"})
+        )
+    for column in ["first_uv", "root_session_cnt", "active_person_days"]:
+        result[column] = pd.to_numeric(result[column], errors="coerce").fillna(0)
+    for lag in range(HORIZON + 1):
+        for suffix in ("active_uv", "active_rate"):
+            column = f"a{lag}_{suffix}"
+            result[column] = pd.to_numeric(result[column], errors="coerce").fillna(0)
+    for column in (
+        "activity_rate_sum",
+        "active_tail_vs_a0",
+        "activity_maturity_vs_a0",
+        "steady_dau_multiplier",
+    ):
+        result[column] = pd.to_numeric(result[column], errors="coerce")
+
+    mapping = {
+        "cohort_dt": "首层投放日期",
+        "channel": "渠道",
+        "package_name": "人群包",
+        "optimize_goal": "转化目标",
+        "partner_name": "合作方",
+        "account_name": "公众号",
+        "first_uv": "首层UV",
+        "root_session_cnt": "根会话数",
+        "active_person_days": "A0-A15累计裂变活跃人次",
+        "activity_rate_sum": "每首层累计裂变活跃人次",
+        "active_tail_vs_a0": "T1-T15相对T0尾部系数",
+        "activity_maturity_vs_a0": "T15成熟系数(相对T0)",
+        "steady_dau_multiplier": "稳态DAU倍数",
+    }
+    for lag in range(HORIZON + 1):
+        mapping[f"a{lag}_active_uv"] = f"A{lag}活跃裂变UV"
+        mapping[f"a{lag}_active_rate"] = f"A{lag}活跃率"
+    result["样本状态"] = _sample_status(result["first_uv"], result["a0_active_uv"])
+    result["参数层级"] = entity
+    mapping["样本状态"] = "样本状态"
+    mapping["参数层级"] = "参数层级"
+    available = {key: value for key, value in mapping.items() if key in result}
+    return result.rename(columns=available)[list(available.values())]
+
+
+def _rollup(raw: pd.DataFrame, groups: list[str], level: str) -> pd.DataFrame:
+    columns = ["first_uv", "a0_active_uv", "active_person_days"]
+    work = raw.copy()
+    for column in columns:
+        work[column] = pd.to_numeric(work[column], errors="coerce").fillna(0)
+    if groups:
+        result = work.groupby(groups, as_index=False, dropna=False)[columns].sum()
+    else:
+        result = pd.DataFrame([work[columns].sum()])
+    result["参数层级"] = level
+    result["T1-T15相对T0尾部系数"] = (
+        (result["active_person_days"] - result["a0_active_uv"])
+        / result["a0_active_uv"].replace(0, pd.NA)
+    )
+    result["T15成熟系数(相对T0)"] = (
+        result["active_person_days"]
+        / result["a0_active_uv"].replace(0, pd.NA)
+    )
+    result["样本状态"] = _sample_status(result["first_uv"], result["a0_active_uv"])
+    result = result.rename(
+        columns={
+            "package_name": "人群包",
+            "optimize_goal": "转化目标",
+            "partner_name": "合作方",
+            "account_name": "公众号",
+            "first_uv": "首层UV",
+            "a0_active_uv": "A0活跃裂变UV",
+            "active_person_days": "A0-A15累计裂变活跃人次",
+        }
+    )
+    for column in ("人群包", "转化目标", "合作方", "公众号"):
+        if column not in result:
+            result[column] = ""
+    return result[
+        [
+            "参数层级",
+            "人群包",
+            "转化目标",
+            "合作方",
+            "公众号",
+            "首层UV",
+            "A0活跃裂变UV",
+            "A0-A15累计裂变活跃人次",
+            "T1-T15相对T0尾部系数",
+            "T15成熟系数(相对T0)",
+            "样本状态",
+        ]
+    ]
+
+
+def build_release_frames(
+    miniapp_raw: pd.DataFrame,
+    gzh_raw: pd.DataFrame,
+) -> tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]:
+    miniapp = localize_exact(miniapp_raw, "人群包+转化目标")
+    gzh = localize_exact(gzh_raw, "合作方+公众号")
+    fallback = pd.concat(
+        [
+            _rollup(miniapp_raw, ["package_name"], "小程序人群包回退"),
+            _rollup(miniapp_raw, ["optimize_goal"], "小程序转化目标回退"),
+            _rollup(miniapp_raw, [], "小程序渠道回退"),
+            _rollup(gzh_raw, ["partner_name"], "公众号合作方回退"),
+            _rollup(gzh_raw, [], "公众号渠道回退"),
+        ],
+        ignore_index=True,
+    )
+    return miniapp, gzh, fallback
+
+
+def _format_workbook(path: Path) -> None:
+    from openpyxl import load_workbook
+
+    workbook = load_workbook(path)
+    for sheet in workbook.worksheets:
+        sheet.freeze_panes = "A2"
+        sheet.auto_filter.ref = sheet.dimensions
+        for cell in sheet[1]:
+            cell.font = Font(bold=True)
+        for cells in sheet.columns:
+            width = min(max(len(str(cell.value or "")) for cell in cells) + 2, 32)
+            sheet.column_dimensions[cells[0].column_letter].width = width
+    workbook.save(path)
+
+
+def write_draft_release(
+    output_dir: Path,
+    cohort_date: str,
+    miniapp_raw: pd.DataFrame,
+    gzh_raw: pd.DataFrame,
+) -> dict[str, Path]:
+    output_dir.mkdir(parents=True, exist_ok=True)
+    miniapp, gzh, fallback = build_release_frames(miniapp_raw, gzh_raw)
+    paths = {
+        "miniapp": output_dir / f"小程序T15成熟系数_中文_{cohort_date}.csv",
+        "gzh": output_dir / f"公众号T15成熟系数_中文_{cohort_date}.csv",
+        "fallback": output_dir / f"T15分级回退系数_中文_{cohort_date}.csv",
+        "workbook": output_dir / f"最终T15成熟系数_中文_{cohort_date}.xlsx",
+    }
+    miniapp.to_csv(paths["miniapp"], index=False, encoding="utf-8-sig")
+    gzh.to_csv(paths["gzh"], index=False, encoding="utf-8-sig")
+    fallback.to_csv(paths["fallback"], index=False, encoding="utf-8-sig")
+    notes = pd.DataFrame(
+        {
+            "项目": ["Cohort日期", "观察周期", "参数状态", "收入公式"],
+            "定义": [
+                cohort_date,
+                "A0至A15,同一用户同日去重、隔日重新计入",
+                "草稿;完成审计并登记版本与SHA256后才能被日级ROI消费",
+                "首层实际效率收入+T0实际裂变收入+T0实际裂变收入×(传播裂变系数-对T0裂变-1)",
+            ],
+        }
+    )
+    with pd.ExcelWriter(paths["workbook"], engine="openpyxl") as writer:
+        miniapp.to_excel(writer, sheet_name="小程序精确系数", index=False)
+        gzh.to_excel(writer, sheet_name="公众号精确系数", index=False)
+        fallback.to_excel(writer, sheet_name="分级回退系数", index=False)
+        notes.to_excel(writer, sheet_name="计算说明", index=False)
+    _format_workbook(paths["workbook"])
+    return paths

+ 118 - 13
examples/auto_put_ad_mini/roi_control/metrics.py

@@ -11,8 +11,15 @@ from typing import Dict, Iterable, List, Mapping, Sequence
 import numpy as np
 import pandas as pd
 
+from .fission_multiplier import (
+    DISPLAY_MULTIPLIER_COLUMN,
+    FissionMultiplierParameters,
+    apply_fission_multiplier,
+)
 
-METRIC_VERSION = "north_star_roi_v1"
+
+METRIC_VERSION = "north_star_roi_t15_v3"
+METRIC_RUN_SUFFIX = "m3"
 
 SELF_CHANNEL = "小程序投流-稳定"
 GZH_CHANNEL = "公众号合作-即转-稳定"
@@ -30,6 +37,7 @@ DIMENSION_COLUMNS = [
     "广告id",
     "广告名称",
     "包名",
+    "广告优化目标",
     "创意id",
     "合作方名",
     "公众号名",
@@ -49,14 +57,18 @@ ENTITY_KEYS: Mapping[str, Sequence[str]] = {
         "账号id",
         "广告id",
         "包名",
+        "广告优化目标",
         "创意id",
     ),
     ENTITY_GZH: ("channel", "合作方名", "公众号名"),
     ENTITY_QIWEI: ("channel", "合作方名"),
 }
 
-def prepare_daily_metrics(raw: pd.DataFrame) -> pd.DataFrame:
-    """清洗 ODPS 日聚合结果并计算统一 ROI。"""
+def prepare_daily_metrics(
+    raw: pd.DataFrame,
+    fission_parameters: FissionMultiplierParameters,
+) -> pd.DataFrame:
+    """清洗日聚合结果并计算实际 T0 与 T15 预测 ROI。"""
 
     raw = raw.rename(
         columns={
@@ -78,10 +90,29 @@ def prepare_daily_metrics(raw: pd.DataFrame) -> pd.DataFrame:
     for column in NUMERIC_COLUMNS:
         daily[column] = pd.to_numeric(daily[column], errors="coerce").fillna(0.0)
 
-    daily["全链路效率收入"] = daily["效率收入"] + daily["多层裂变收入"]
+    daily = apply_fission_multiplier(daily, fission_parameters)
+    daily["T0实际裂变收入"] = daily["多层裂变收入"]
+    daily["实际全链路效率收入"] = (
+        daily["效率收入"] + daily["T0实际裂变收入"]
+    )
+    daily["预测T1-T15裂变收入"] = daily["T0实际裂变收入"] * (
+        daily[DISPLAY_MULTIPLIER_COLUMN] - 1
+    )
+    daily["预测T0-T15裂变收入"] = (
+        daily["T0实际裂变收入"] + daily["预测T1-T15裂变收入"]
+    )
+    daily["预测全链路效率收入"] = (
+        daily["效率收入"] + daily["预测T0-T15裂变收入"]
+    )
+    daily["全链路效率收入"] = daily["预测全链路效率收入"]
+    daily["实际ROI"] = np.where(
+        daily["成本"] > 0,
+        daily["实际全链路效率收入"] / daily["成本"],
+        np.nan,
+    )
     daily["ROI"] = np.where(
         daily["成本"] > 0,
-        daily["全链路效率收入"] / daily["成本"],
+        daily["预测全链路效率收入"] / daily["成本"],
         np.nan,
     )
     daily["T0裂变率"] = np.where(
@@ -128,16 +159,53 @@ def _summarize_entity(
     for key_values, group in entity_daily.groupby(keys, dropna=False, sort=False):
         if not isinstance(key_values, tuple):
             key_values = (key_values,)
+        parameter_columns = [
+            DISPLAY_MULTIPLIER_COLUMN,
+            "传播裂变系数匹配层级",
+            "传播裂变系数来源",
+            "传播裂变参数版本",
+            "传播裂变参数cohort日期",
+            "传播裂变参数状态",
+            "调控参与状态",
+            "ROI计算口径",
+        ]
+        parameter_values = {
+            column: group[column].dropna().unique()
+            for column in parameter_columns
+        }
+        inconsistent = [
+            column for column, values in parameter_values.items() if len(values) != 1
+        ]
+        if inconsistent:
+            raise ValueError(
+                f"同一实体三日内传播裂变参数不一致: {key_values}; fields={inconsistent}"
+            )
         by_date = group.groupby("dt", as_index=False)[
-            ["首层UV", "T0裂变数", "成本", "效率收入", "多层裂变收入"]
+            [
+                "首层UV",
+                "T0裂变数",
+                "成本",
+                "效率收入",
+                "多层裂变收入",
+                "T0实际裂变收入",
+                "实际全链路效率收入",
+                "预测T1-T15裂变收入",
+                "预测T0-T15裂变收入",
+                "预测全链路效率收入",
+            ]
         ].sum()
         if set(by_date["dt"]) != set(expected_dates):
             continue
 
         by_date = by_date.set_index("dt").loc[list(expected_dates)]
-        daily_roi = np.where(
+        daily_actual_roi = np.where(
             by_date["成本"] > 0,
-            (by_date["效率收入"] + by_date["多层裂变收入"]) / by_date["成本"],
+            by_date["实际全链路效率收入"] / by_date["成本"],
+            np.nan,
+        )
+        daily_predicted_roi = np.where(
+            by_date["成本"] > 0,
+            by_date["预测全链路效率收入"] / by_date["成本"],
             np.nan,
         )
 
@@ -164,14 +232,48 @@ def _summarize_entity(
         record["三日最小单日成本"] = float(by_date["成本"].min())
         record["效率收入"] = float(by_date["效率收入"].sum())
         record["多层裂变收入"] = float(by_date["多层裂变收入"].sum())
-        record["全链路效率收入"] = record["效率收入"] + record["多层裂变收入"]
+        record["T0实际裂变收入"] = float(
+            by_date["T0实际裂变收入"].sum()
+        )
+        for column, values in parameter_values.items():
+            record[column] = values[0]
+        record[DISPLAY_MULTIPLIER_COLUMN] = float(
+            record[DISPLAY_MULTIPLIER_COLUMN]
+        )
+        record["实际全链路效率收入"] = float(
+            by_date["实际全链路效率收入"].sum()
+        )
+        record["预测T1-T15裂变收入"] = float(
+            by_date["预测T1-T15裂变收入"].sum()
+        )
+        record["预测T0-T15裂变收入"] = float(
+            by_date["预测T0-T15裂变收入"].sum()
+        )
+        record["预测全链路效率收入"] = float(
+            by_date["预测全链路效率收入"].sum()
+        )
+        record["全链路效率收入"] = record["预测全链路效率收入"]
+        record["实际ROI"] = (
+            record["实际全链路效率收入"] / record["成本"]
+            if record["成本"] > 0
+            else np.nan
+        )
         record["ROI"] = (
-            record["全链路效率收入"] / record["成本"]
+            record["预测全链路效率收入"] / record["成本"]
             if record["成本"] > 0
             else np.nan
         )
         for index, dt in enumerate(expected_dates):
-            roi_value = float(daily_roi[index]) if np.isfinite(daily_roi[index]) else np.nan
+            actual_roi = (
+                float(daily_actual_roi[index])
+                if np.isfinite(daily_actual_roi[index])
+                else np.nan
+            )
+            predicted_roi = (
+                float(daily_predicted_roi[index])
+                if np.isfinite(daily_predicted_roi[index])
+                else np.nan
+            )
             record[f"首层UV_{dt}"] = float(by_date.iloc[index]["首层UV"])
             record[f"T0裂变数_{dt}"] = float(by_date.iloc[index]["T0裂变数"])
             record[f"成本_{dt}"] = float(by_date.iloc[index]["成本"])
@@ -179,7 +281,8 @@ def _summarize_entity(
             record[f"多层裂变收入_{dt}"] = float(
                 by_date.iloc[index]["多层裂变收入"]
             )
-            record[f"ROI_{dt}"] = roi_value
+            record[f"实际ROI_{dt}"] = actual_roi
+            record[f"ROI_{dt}"] = predicted_roi
 
         if entity_type == ENTITY_SELF:
             record["广告age"] = int(ages.get(str(record.get("广告id", "")), 0))
@@ -192,11 +295,13 @@ def compute_roi_summary(
     raw_daily: pd.DataFrame,
     expected_dates: Iterable[str],
     ad_age: pd.DataFrame | None = None,
+    *,
+    fission_parameters: FissionMultiplierParameters,
 ) -> tuple[pd.DataFrame, list[str]]:
     """Return complete three-day entity ROI snapshots and normalized dates."""
 
     dates = _expected_three_days(expected_dates)
-    daily = prepare_daily_metrics(raw_daily)
+    daily = prepare_daily_metrics(raw_daily, fission_parameters)
     daily = daily[daily["dt"].isin(dates)].copy()
     ages = _age_map(ad_age)
     summaries = []

+ 47 - 0
examples/auto_put_ad_mini/roi_control/policy.py

@@ -8,6 +8,7 @@ from typing import Any
 
 import pandas as pd
 
+from .fission_multiplier import DISPLAY_MULTIPLIER_COLUMN
 from .metrics import ENTITY_KEYS, ENTITY_SELF
 
 
@@ -120,10 +121,32 @@ def annotate_execution(
                     "成本_20",
                     "效率收入_20",
                     "多层裂变收入_20",
+                    "实际ROI_20",
                     "ROI_20",
                 )
             )
         }
+        daily_metrics.update(
+            {
+                "fission_parameter_version": str(
+                    row.get("传播裂变参数版本") or ""
+                ),
+                "fission_cohort_date": str(
+                    row.get("传播裂变参数cohort日期") or ""
+                ),
+                "fission_match_level": str(
+                    row.get("传播裂变系数匹配层级") or ""
+                ),
+                "fission_source": str(row.get("传播裂变系数来源") or ""),
+                "fission_parameter_status": str(
+                    row.get("传播裂变参数状态") or ""
+                ),
+                "control_participation_status": str(
+                    row.get("调控参与状态") or ""
+                ),
+                "roi_method": str(row.get("ROI计算口径") or ""),
+            }
+        )
         snapshots.append(
             {
                 "entity_hash": _entity_hash(row),
@@ -135,8 +158,22 @@ def annotate_execution(
                 "adgroup_name": str(row.get("广告名称") or ""),
                 "dynamic_creative_id": creative_id,
                 "audience_name": str(row.get("包名") or ""),
+                "conversion_goal": str(row.get("广告优化目标") or ""),
                 "partner_name": str(row.get("合作方名") or ""),
                 "official_account_name": str(row.get("公众号名") or ""),
+                "fission_parameter_version": str(
+                    row.get("传播裂变参数版本") or ""
+                ),
+                "fission_cohort_date": str(
+                    row.get("传播裂变参数cohort日期") or ""
+                ),
+                "fission_multiplier_vs_t0": _finite(
+                    row.get(DISPLAY_MULTIPLIER_COLUMN)
+                ),
+                "fission_match_level": str(
+                    row.get("传播裂变系数匹配层级") or ""
+                ),
+                "fission_source": str(row.get("传播裂变系数来源") or ""),
                 "ad_age": safe_int(row.get("广告age")),
                 "avg_first_uv": _finite(row.get("日均首层UV")),
                 "first_uv": _finite(row.get("三日首层UV")),
@@ -145,6 +182,16 @@ def annotate_execution(
                 "cost": _finite(row.get("成本")),
                 "efficiency_revenue": _finite(row.get("效率收入")),
                 "fission_revenue": _finite(row.get("多层裂变收入")),
+                "actual_total_revenue": _finite(
+                    row.get("实际全链路效率收入")
+                ),
+                "actual_roi": _finite(row.get("实际ROI")),
+                "predicted_tail_revenue": _finite(
+                    row.get("预测T1-T15裂变收入")
+                ),
+                "predicted_fission_revenue": _finite(
+                    row.get("预测T0-T15裂变收入")
+                ),
                 "total_revenue": _finite(row.get("全链路效率收入")),
                 "roi": _finite(row.get("ROI")),
                 "stop_threshold": _finite(row.get("t_stop")),

+ 138 - 86
examples/auto_put_ad_mini/roi_control/reporting.py

@@ -3,7 +3,7 @@
 from __future__ import annotations
 
 from pathlib import Path
-from typing import Dict, Iterable, Mapping, Sequence
+from typing import Dict, Mapping, Sequence
 
 import numpy as np
 import pandas as pd
@@ -11,6 +11,7 @@ from openpyxl import Workbook
 from openpyxl.formatting.rule import ColorScaleRule
 from openpyxl.styles import Alignment, Font, PatternFill
 from openpyxl.utils import get_column_letter
+from .fission_multiplier import DISPLAY_MULTIPLIER_COLUMN
 from .metrics import ENTITY_GZH, ENTITY_QIWEI, ENTITY_SELF
 
 
@@ -19,6 +20,8 @@ HEADER_FONT = Font(color="FFFFFF", bold=True)
 STOP_FILL = PatternFill("solid", fgColor="F4CCCC")
 UP_FILL = PatternFill("solid", fgColor="D9EAD3")
 ADJUST_FILL = PatternFill("solid", fgColor="FFF2CC")
+REPORT_VERSION = "roi_report_v4"
+REPORT_RUN_SUFFIX = "r4"
 
 
 BASE_COLUMNS: Dict[str, Sequence[str]] = {
@@ -26,68 +29,47 @@ BASE_COLUMNS: Dict[str, Sequence[str]] = {
         "渠道",
         "代理名称",
         "账号id",
-        "账号名称",
         "广告id",
         "广告名称",
         "包名",
+        "广告优化目标",
         "创意id",
         "广告age",
         "日均首层UV",
-        "三日首层UV",
-        "三日T0裂变数",
-        "T0裂变率",
-        "效率收入",
-        "多层裂变收入",
-        "全链路效率收入",
-        "成本",
-        "三日最小单日成本",
-        "三日聚合ROI",
-        "关停线",
-        "扩量线",
+        "首层效率收入",
+        "LTV预测效率收入",
+        "日均成本",
+        DISPLAY_MULTIPLIER_COLUMN,
+        "预测ROI",
         "动作",
-        "执行模式",
-        "执行说明",
+        "关停线",
     ),
     "公众号即转": (
         "渠道",
         "合作方名",
         "公众号名",
         "日均首层UV",
-        "三日首层UV",
-        "三日T0裂变数",
-        "T0裂变率",
-        "效率收入",
-        "多层裂变收入",
-        "全链路效率收入",
-        "成本",
-        "三日最小单日成本",
-        "三日聚合ROI",
-        "关停线",
-        "扩量线",
-        "渠道内ROI排名百分位",
+        "首层效率收入",
+        "LTV预测效率收入",
+        "日均成本",
+        DISPLAY_MULTIPLIER_COLUMN,
+        "预测ROI",
         "动作",
-        "执行模式",
-        "执行说明",
+        "关停线",
     ),
     "企微群合作": (
         "渠道",
         "合作方名",
-        "公众号名",
         "日均首层UV",
-        "三日首层UV",
-        "三日T0裂变数",
-        "T0裂变率",
-        "效率收入",
-        "多层裂变收入",
-        "全链路效率收入",
-        "成本",
-        "三日最小单日成本",
-        "三日聚合ROI",
-        "关停线",
-        "扩量线",
+        "首层效率收入",
+        "LTV预测效率收入",
+        "日均成本",
+        DISPLAY_MULTIPLIER_COLUMN,
+        "传播裂变参数状态",
+        "调控参与状态",
+        "预测ROI",
         "动作",
-        "执行模式",
-        "执行说明",
+        "关停线",
     ),
 }
 
@@ -104,32 +86,50 @@ FREEZE_PANES = {
 }
 
 
-def _date_detail_columns(columns: Iterable[str]) -> list[str]:
-    result = [
-        column
-        for column in columns
-        if column.startswith(("首层UV_20", "成本_20", "ROI_20"))
-    ]
-    return sorted(result, key=lambda value: (value.rsplit("_", 1)[-1], value.split("_", 1)[0]))
-
-
 def _sheet_frame(candidates: pd.DataFrame, sheet_name: str) -> pd.DataFrame:
     entity_type = next(
         key for key, value in ENTITY_TO_SHEET.items() if value == sheet_name
     )
     subset = candidates[candidates["entity_type"].eq(entity_type)].copy()
     subset = subset.rename(columns={"channel": "渠道"})
-    subset["三日聚合ROI"] = subset["ROI"]
+    coverage_source = (
+        subset["覆盖天数"]
+        if "覆盖天数" in subset
+        else pd.Series(3, index=subset.index)
+    )
+    coverage_days = pd.to_numeric(
+        coverage_source, errors="coerce"
+    ).replace(0, np.nan)
+    subset["日均首层UV"] = pd.to_numeric(
+        subset.get("日均首层UV"), errors="coerce"
+    ).round().astype("Int64")
+    subset["首层效率收入"] = (
+        pd.to_numeric(subset.get("效率收入"), errors="coerce")
+        / coverage_days
+    )
+    subset["LTV预测效率收入"] = (
+        pd.to_numeric(
+            subset.get("预测全链路效率收入"), errors="coerce"
+        )
+        / coverage_days
+    )
+    subset["日均成本"] = (
+        pd.to_numeric(subset.get("成本"), errors="coerce") / coverage_days
+    )
+    subset["预测ROI"] = subset["ROI"]
     subset["关停线"] = subset["t_stop"]
     subset["扩量线"] = subset["t_up"]
-    date_columns = _date_detail_columns(subset.columns)
-    ordered = list(BASE_COLUMNS[sheet_name]) + date_columns
-    for column in ordered:
+    visible_columns = list(BASE_COLUMNS[sheet_name])
+    for column in visible_columns:
         if column not in subset:
             subset[column] = ""
+    hidden_columns = [
+        column for column in subset.columns if column not in visible_columns
+    ]
+    ordered = visible_columns + hidden_columns
     subset = subset[ordered]
     if not subset.empty:
-        subset = subset.sort_values(["动作", "三日聚合ROI"], ascending=[True, False])
+        subset = subset.sort_values("预测ROI", ascending=False)
     return subset
 
 
@@ -168,15 +168,20 @@ def _format_sheet(ws, sheet_name: str) -> None:
             for row in range(2, max_row + 1):
                 ws.cell(row, column_index).number_format = "0.000"
         elif "成本" in str(header) or header in {
+            "首层效率收入",
+            "LTV预测效率收入",
             "效率收入",
-            "多层裂变收入",
-            "全链路效率收入",
+            "T0实际裂变收入",
+            "实际全链路效率收入",
+            "预测T1-T15裂变收入",
+            "预测T0-T15裂变收入",
+            "预测全链路效率收入",
         }:
             for row in range(2, max_row + 1):
                 ws.cell(row, column_index).number_format = "#,##0.00"
         elif "UV" in str(header) or "裂变数" in str(header):
             for row in range(2, max_row + 1):
-                ws.cell(row, column_index).number_format = "#,##0.00"
+                ws.cell(row, column_index).number_format = "#,##0"
 
         if "ROI" in str(header) and max_row >= 2:
             letter = get_column_letter(column_index)
@@ -193,6 +198,9 @@ def _format_sheet(ws, sheet_name: str) -> None:
                 ),
             )
 
+        if column_index > len(BASE_COLUMNS[sheet_name]):
+            ws.column_dimensions[get_column_letter(column_index)].hidden = True
+
     action_column = headers.get("动作")
     if action_column:
         for row in range(2, max_row + 1):
@@ -210,20 +218,30 @@ def _write_summary(
     thresholds: pd.DataFrame,
     candidates: pd.DataFrame,
     expected_dates: Sequence[str],
-    qiwei_fission_is_zero: bool,
     rule_config: Mapping[str, object] | None,
 ) -> None:
-    ws = workbook.active
-    ws.title = "运行摘要"
+    ws = workbook.create_sheet("运行摘要")
+    self_min_uv = (rule_config or {}).get("self_min_avg_uv", 200)
+    partner_min_uv = (rule_config or {}).get("partner_min_avg_uv", 200)
+    min_daily_cost = (rule_config or {}).get("min_daily_cost", 100)
     rows = [
         ("统计窗口", f"{expected_dates[0]} 至 {expected_dates[-1]}"),
         ("首层口径", "usersharedepth='0'"),
         ("UV口径", "COUNT(DISTINCT mid)"),
-        ("ROI口径", "三日聚合:(三日效率收入 + 三日多层t0裂变收入) / 三日成本"),
-        ("阈值口径", "三类合格实体混入同一全局池:三日聚合ROI的P10=关停线、P80=扩量线"),
         (
-            "合格池口径",
-            "完整覆盖3天;UV、单日成本、广告age与分位门槛按本批次规则配置执行",
+            "ROI口径",
+            "T0裂变收入为实际值;仅预测T1-T15增量。预测总收入=首层实际效率收入+T0实际裂变收入+T0实际裂变收入×(传播裂变系数-对T0裂变-1)",
+        ),
+        (
+            "企微口径",
+            "企微按渠道/合作方保留展示,临时参考系数为1.0,待补算正式参数;不进入阈值样本池和调控。",
+        ),
+        ("阈值口径", "小程序和公众号合格实体进入同一全局池:三日聚合ROI的P10=关停线、P80=扩量线;企微不参与"),
+        (
+            "阈值样本条件",
+            f"连续3天数据完整;小程序日均首层UV>{self_min_uv:g};"
+            f"公众号日均首层UV>{partner_min_uv:g};连续3天每天成本>"
+            f"{min_daily_cost:g};三日成本>0且预测ROI有效;企微仅展示、不进入样本池",
         ),
         ("动作优先级", "关停 > 扩量 > 调整封面&落地页视频"),
         ("审批方式", "飞书消息整批确认或拒绝;表格仅用于查看,不做逐行审批"),
@@ -247,6 +265,21 @@ def _write_summary(
             "max_base_ratio",
         ):
             ws.append([key, rule_config.get(key)])
+        fission_multiplier = rule_config.get("fission_multiplier")
+        if isinstance(fission_multiplier, Mapping):
+            ws.append([])
+            ws.append(["传播裂变参数", "值"])
+            for key in (
+                "version",
+                "cohort_date",
+                "observation_end_date",
+                "horizon_days",
+                "miniapp_exact_available_rows",
+                "gzh_exact_available_rows",
+                "miniapp_channel_multiplier",
+                "gzh_channel_multiplier",
+            ):
+                ws.append([key, fission_multiplier.get(key)])
 
     ws.append([])
     display_thresholds = thresholds.rename(
@@ -259,7 +292,7 @@ def _write_summary(
         "阈值样本数",
         "小程序样本数",
         "公众号样本数",
-        "企微样本数",
+        "企微参考实体数",
     ]
     ws.append(threshold_columns)
     for values in display_thresholds[threshold_columns].itertuples(
@@ -271,17 +304,13 @@ def _write_summary(
     ws.append([])
     ws.append(["渠道", "建议动作数"])
     for entity_type, sheet_name in ENTITY_TO_SHEET.items():
-        count = int(candidates["entity_type"].eq(entity_type).sum())
-        ws.append([sheet_name, count])
-
-    if qiwei_fission_is_zero:
-        ws.append([])
-        ws.append(
-            [
-                "数据质量告警",
-                "企微群合作在统计窗口内的多层t0裂变收入合计为0;本报告严格按附件公式计算,未使用ARPU估算。",
-            ]
+        count = int(
+            (
+                candidates["entity_type"].eq(entity_type)
+                & candidates["动作"].ne("")
+            ).sum()
         )
+        ws.append([sheet_name, count])
 
     ws.column_dimensions["A"].width = 22
     ws.column_dimensions["B"].width = 92
@@ -297,25 +326,48 @@ def write_workbook(
     thresholds: pd.DataFrame,
     expected_dates: Sequence[str],
     output_path: Path,
-    qiwei_fission_is_zero: bool,
     rule_config: Mapping[str, object] | None = None,
+    fission_match_summary: pd.DataFrame | None = None,
 ) -> Path:
     output_path.parent.mkdir(parents=True, exist_ok=True)
     workbook = Workbook()
+    workbook.remove(workbook.active)
+
+    for sheet_name in BASE_COLUMNS:
+        ws = workbook.create_sheet(sheet_name)
+        frame = _sheet_frame(candidates, sheet_name)
+        _write_dataframe(ws, frame)
+        _format_sheet(ws, sheet_name)
+
+    if fission_match_summary is not None:
+        ws = workbook.create_sheet("传播裂变系数匹配")
+        _write_dataframe(ws, fission_match_summary)
+        ws.freeze_panes = "A2"
+        ws.auto_filter.ref = ws.dimensions
+        for cell in ws[1]:
+            cell.fill = HEADER_FILL
+            cell.font = HEADER_FONT
+        for column_index in range(1, ws.max_column + 1):
+            header = str(ws.cell(1, column_index).value or "")
+            values = [
+                str(ws.cell(row, column_index).value or "")
+                for row in range(1, ws.max_row + 1)
+            ]
+            width = min(max(max(map(len, values)), len(header)) + 2, 42)
+            ws.column_dimensions[get_column_letter(column_index)].width = max(
+                width, 11
+            )
+            if header == "匹配率":
+                for row in range(2, ws.max_row + 1):
+                    ws.cell(row, column_index).number_format = "0.00%"
+
     _write_summary(
         workbook,
         thresholds,
         candidates,
         expected_dates,
-        qiwei_fission_is_zero,
         rule_config,
     )
 
-    for sheet_name in BASE_COLUMNS:
-        ws = workbook.create_sheet(sheet_name)
-        frame = _sheet_frame(candidates, sheet_name)
-        _write_dataframe(ws, frame)
-        _format_sheet(ws, sheet_name)
-
     workbook.save(output_path)
     return output_path

+ 127 - 6
examples/auto_put_ad_mini/roi_control/repository.py

@@ -18,6 +18,16 @@ FINAL_STATUSES = {
 }
 
 
+def _is_expired(expires_at: datetime | None, now: datetime) -> bool:
+    if expires_at is None:
+        return False
+    if expires_at.tzinfo is None and now.tzinfo is not None:
+        now = now.replace(tzinfo=None)
+    elif expires_at.tzinfo is not None and now.tzinfo is None:
+        expires_at = expires_at.replace(tzinfo=None)
+    return now > expires_at
+
+
 def json_dumps(value: Any) -> str:
     def default(item: Any) -> Any:
         if isinstance(item, (datetime, date)):
@@ -33,6 +43,108 @@ def json_dumps(value: Any) -> str:
     return json.dumps(value, ensure_ascii=False, default=default)
 
 
+def publish_fission_parameter_release(
+    release: dict[str, Any],
+    values: Iterable[dict[str, Any]],
+    *,
+    published_by: str,
+) -> bool:
+    """Publish an immutable parameter version; return False if already present."""
+
+    value_rows = list(values)
+    connection = connect()
+    connection.autocommit(False)
+    try:
+        with connection.cursor() as cursor:
+            cursor.execute(
+                "SELECT content_sha256 FROM roi_fission_parameter_release "
+                "WHERE version=%s FOR UPDATE",
+                (release["version"],),
+            )
+            existing = cursor.fetchone()
+            if existing:
+                if existing["content_sha256"] != release["content_sha256"]:
+                    raise ValueError(
+                        "传播裂变系数版本已存在且内容不同,禁止覆盖: "
+                        f"{release['version']}"
+                    )
+                connection.rollback()
+                return False
+
+            cursor.execute(
+                """
+                INSERT INTO roi_fission_parameter_release
+                    (version, cohort_date, observation_end_date, horizon_days,
+                     run_suffix, content_sha256, metadata_json, published_by)
+                VALUES (%s,%s,%s,%s,%s,%s,%s,%s)
+                """,
+                (
+                    release["version"],
+                    release["cohort_date"],
+                    release["observation_end_date"],
+                    release["horizon_days"],
+                    release["run_suffix"],
+                    release["content_sha256"],
+                    json_dumps(release["metadata"]),
+                    published_by,
+                ),
+            )
+            cursor.executemany(
+                """
+                INSERT INTO roi_fission_parameter_value
+                    (version, entity_type, match_level, key_primary,
+                     key_secondary, multiplier)
+                VALUES (%s,%s,%s,%s,%s,%s)
+                """,
+                [
+                    (
+                        release["version"],
+                        row["entity_type"],
+                        row["match_level"],
+                        row["key_primary"],
+                        row["key_secondary"],
+                        row["multiplier"],
+                    )
+                    for row in value_rows
+                ],
+            )
+        connection.commit()
+        return True
+    except Exception:
+        connection.rollback()
+        raise
+    finally:
+        connection.close()
+
+
+def load_fission_parameter_release(
+    version: str,
+) -> tuple[dict[str, Any], list[dict[str, Any]]]:
+    connection = connect()
+    try:
+        with connection.cursor() as cursor:
+            cursor.execute(
+                "SELECT * FROM roi_fission_parameter_release WHERE version=%s",
+                (version,),
+            )
+            release = cursor.fetchone()
+            if not release:
+                raise ValueError(f"数据库不存在传播裂变系数版本: {version}")
+            cursor.execute(
+                """
+                SELECT entity_type, match_level, key_primary,
+                       key_secondary, multiplier
+                FROM roi_fission_parameter_value
+                WHERE version=%s
+                ORDER BY entity_type, match_level, key_primary, key_secondary
+                """,
+                (version,),
+            )
+            return release, list(cursor.fetchall())
+    finally:
+        connection.close()
+
+
 def create_or_load_run(record: dict[str, Any]) -> dict[str, Any]:
     connection = connect()
     try:
@@ -41,14 +153,17 @@ def create_or_load_run(record: dict[str, Any]) -> dict[str, Any]:
                 """
                 INSERT IGNORE INTO roi_metric_run
                     (run_id, run_key, metric_version, policy_version,
+                     fission_parameter_version, fission_cohort_date,
                      start_date, end_date, config_json, status)
-                VALUES (%s,%s,%s,%s,%s,%s,%s,'COMPUTING')
+                VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,'COMPUTING')
                 """,
                 (
                     record["run_id"],
                     record["run_key"],
                     record["metric_version"],
                     record["policy_version"],
+                    record["fission_parameter_version"],
+                    record["fission_cohort_date"],
                     record["start_date"],
                     record["end_date"],
                     json_dumps(record["config"]),
@@ -103,10 +218,16 @@ def replace_run_results(
             snapshot_columns = [
                 "run_id", "entity_hash", "entity_type", "channel",
                 "account_id", "account_name", "adgroup_id", "adgroup_name",
-                "dynamic_creative_id", "audience_name", "partner_name",
-                "official_account_name", "ad_age", "avg_first_uv", "first_uv",
+                "dynamic_creative_id", "audience_name", "conversion_goal",
+                "partner_name", "official_account_name",
+                "fission_parameter_version", "fission_cohort_date",
+                "fission_multiplier_vs_t0", "fission_match_level",
+                "fission_source", "ad_age",
+                "avg_first_uv", "first_uv",
                 "t0_fission_count", "t0_fission_rate", "cost",
-                "efficiency_revenue", "fission_revenue", "total_revenue", "roi",
+                "efficiency_revenue", "fission_revenue", "actual_total_revenue",
+                "actual_roi", "predicted_tail_revenue",
+                "predicted_fission_revenue", "total_revenue", "roi",
                 "stop_threshold", "scale_threshold", "recommended_action",
                 "action_reason", "execution_mode", "ineligible_reason",
                 "daily_metrics_json",
@@ -235,7 +356,7 @@ def reject_run(run_id: str, *, sender_open_id: str, now: datetime) -> dict[str,
                 return run
             if run["status"] != "PENDING_APPROVAL":
                 raise RuntimeError(f"ROI批次当前不可拒绝: {run['status']}")
-            if run.get("expires_at") and now > run["expires_at"]:
+            if _is_expired(run.get("expires_at"), now):
                 cursor.execute(
                     "UPDATE roi_metric_run SET status='EXPIRED' WHERE run_id=%s",
                     (run_id,),
@@ -279,7 +400,7 @@ def claim_run_for_execution(
                 connection.commit()
                 return run
             if run["status"] == "PENDING_APPROVAL":
-                if run.get("expires_at") and now > run["expires_at"]:
+                if _is_expired(run.get("expires_at"), now):
                     cursor.execute(
                         "UPDATE roi_metric_run SET status='EXPIRED' WHERE run_id=%s",
                         (run_id,),

+ 39 - 12
examples/auto_put_ad_mini/roi_control/rules.py

@@ -14,9 +14,11 @@ from .metrics import (
     ENTITY_SELF,
     compute_roi_summary,
 )
+from .fission_multiplier import FissionMultiplierParameters
 
 
 POLICY_VERSION = "roi_policy_v1"
+POLICY_RUN_SUFFIX = "p1"
 
 @dataclass(frozen=True)
 class RuleConfig:
@@ -31,25 +33,32 @@ class RuleConfig:
     gzh_adjust_rank_max: float = 0.30
 
 
-def compute_global_thresholds(
+def threshold_eligibility_mask(
     summary: pd.DataFrame,
-    expected_dates: list[str],
     config: RuleConfig,
-) -> pd.DataFrame:
+) -> pd.Series:
     self_eligible = (
         summary["entity_type"].eq(ENTITY_SELF)
         & summary["日均首层UV"].gt(config.self_min_avg_uv)
     )
-    partner_eligible = (
-        summary["entity_type"].isin([ENTITY_GZH, ENTITY_QIWEI])
+    gzh_eligible = (
+        summary["entity_type"].eq(ENTITY_GZH)
         & summary["日均首层UV"].gt(config.partner_min_avg_uv)
     )
-    valid = summary.loc[
-        (self_eligible | partner_eligible)
+    return (
+        (self_eligible | gzh_eligible)
         & summary["成本"].gt(0)
         & summary["三日最小单日成本"].gt(config.min_daily_cost)
         & np.isfinite(summary["ROI"])
-    ].copy()
+    )
+
+
+def compute_global_thresholds(
+    summary: pd.DataFrame,
+    expected_dates: list[str],
+    config: RuleConfig,
+) -> pd.DataFrame:
+    valid = summary.loc[threshold_eligibility_mask(summary, config)].copy()
     if valid.empty:
         raise ValueError("没有满足渠道UV门槛且三日聚合ROI有效的实体,无法计算全局阈值")
 
@@ -63,7 +72,9 @@ def compute_global_thresholds(
                 "阈值样本数": int(len(valid)),
                 "小程序样本数": int(type_counts.get(ENTITY_SELF, 0)),
                 "公众号样本数": int(type_counts.get(ENTITY_GZH, 0)),
-                "企微样本数": int(type_counts.get(ENTITY_QIWEI, 0)),
+                "企微参考实体数": int(
+                    summary["entity_type"].eq(ENTITY_QIWEI).sum()
+                ),
             }
         ]
     )
@@ -123,7 +134,7 @@ def apply_actions(
                     f"全局t_up,日均首层UV>{config.self_min_avg_uv:g},"
                     f"连续3天每天成本>{config.min_daily_cost:g}"
                 )
-        elif entity_type in (ENTITY_GZH, ENTITY_QIWEI):
+        elif entity_type == ENTITY_GZH:
             if stop_side and avg_uv > config.partner_min_avg_uv and cost_confident:
                 result.at[index, "动作"] = "关停"
                 result.at[index, "动作原因"] = (
@@ -138,7 +149,7 @@ def apply_actions(
                     f"日均首层UV>{config.partner_min_avg_uv:g},"
                     f"连续3天每天成本>{config.min_daily_cost:g}"
                 )
-            elif entity_type == ENTITY_GZH:
+            else:
                 rank_pct = row["渠道内ROI排名百分位"]
                 if (
                     np.isfinite(rank_pct)
@@ -158,9 +169,25 @@ def evaluate_rules(
     expected_dates: Iterable[str],
     ad_age: pd.DataFrame | None = None,
     config: RuleConfig = RuleConfig(),
+    *,
+    fission_parameters: FissionMultiplierParameters,
 ) -> tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]:
-    summary, dates = compute_roi_summary(raw_daily, expected_dates, ad_age)
+    summary, dates = compute_roi_summary(
+        raw_daily,
+        expected_dates,
+        ad_age,
+        fission_parameters=fission_parameters,
+    )
     thresholds = compute_global_thresholds(summary, dates, config)
     evaluated = apply_actions(summary, thresholds, config)
+    evaluated["阈值样本状态"] = "未达到阈值样本门槛"
+    evaluated.loc[
+        threshold_eligibility_mask(evaluated, config),
+        "阈值样本状态",
+    ] = "进入阈值样本池"
+    evaluated.loc[
+        evaluated["entity_type"].eq(ENTITY_QIWEI),
+        "阈值样本状态",
+    ] = "企微仅展示_不进入阈值样本池"
     candidates = evaluated[evaluated["动作"].ne("")].copy()
     return candidates, thresholds, evaluated

+ 92 - 19
examples/auto_put_ad_mini/roi_control/service.py

@@ -20,13 +20,24 @@ from .data_source import (
     resolve_end_date,
 )
 from .feishu import RoiFeishuPublisher
-from .metrics import ENTITY_QIWEI, METRIC_VERSION
+from .metrics import ENTITY_QIWEI, METRIC_RUN_SUFFIX, METRIC_VERSION
+from .fission_multiplier import (
+    DEFAULT_FISSION_PARAMETER_VERSION,
+    FissionMultiplierParameters,
+    parameters_from_database,
+)
 from .policy import annotate_execution
-from .reporting import write_workbook
-from .rules import POLICY_VERSION, RuleConfig, evaluate_rules
+from .reporting import REPORT_RUN_SUFFIX, REPORT_VERSION, write_workbook
+from .rules import (
+    POLICY_RUN_SUFFIX,
+    POLICY_VERSION,
+    RuleConfig,
+    evaluate_rules,
+)
 from .repository import (
     FINAL_STATUSES,
     create_or_load_run,
+    load_fission_parameter_release,
     mark_failed,
     mark_published,
     replace_run_results,
@@ -59,9 +70,19 @@ def _dates(start_date: str) -> list[str]:
     ]
 
 
-def _run_identity(end_date: str) -> tuple[str, str]:
-    run_id = f"roi_{end_date}_{METRIC_VERSION}_{POLICY_VERSION}"
-    run_key = f"{METRIC_VERSION}:{POLICY_VERSION}:{end_date}"
+def _run_identity(
+    end_date: str,
+    fission_parameters: FissionMultiplierParameters,
+) -> tuple[str, str]:
+    release = fission_parameters.release
+    run_id = (
+        f"roi_{end_date}_{METRIC_RUN_SUFFIX}_{POLICY_RUN_SUFFIX}_"
+        f"{release.run_suffix}_{REPORT_RUN_SUFFIX}"
+    )
+    run_key = (
+        f"{METRIC_VERSION}:{POLICY_VERSION}:{release.version}:"
+        f"{REPORT_VERSION}:{end_date}"
+    )
     return run_id, run_key
 
 
@@ -76,23 +97,40 @@ def run_daily_roi(
 
     config = RoiConfig.from_env()
     initialize_schema()
+    fission_version = os.getenv(
+        "ROI_FISSION_PARAMETER_VERSION",
+        DEFAULT_FISSION_PARAMETER_VERSION,
+    )
+    fission_parameters = parameters_from_database(
+        *load_fission_parameter_release(fission_version)
+    )
+    run_config = config.snapshot()
+    run_config["fission_multiplier"] = fission_parameters.snapshot()
+    run_config["report_version"] = REPORT_VERSION
     client = ODPSClient(project=os.getenv("ODPS_PROJECT", "loghubods"))
     end_date = resolve_end_date(client, requested_end_date)
     start_date, end_date = date_window(end_date)
     expected_dates = _dates(start_date)
-    run_id, run_key = _run_identity(end_date)
+    run_id, run_key = _run_identity(end_date, fission_parameters)
     run = create_or_load_run(
         {
             "run_id": run_id,
             "run_key": run_key,
             "metric_version": METRIC_VERSION,
             "policy_version": POLICY_VERSION,
+            "fission_parameter_version": fission_parameters.release.version,
+            "fission_cohort_date": datetime.strptime(
+                fission_parameters.release.cohort_date, "%Y%m%d"
+            ).date(),
             "start_date": datetime.strptime(start_date, "%Y%m%d").date(),
             "end_date": datetime.strptime(end_date, "%Y%m%d").date(),
-            "config": config.snapshot(),
+            "config": run_config,
         }
     )
-    if run.get("status") in FINAL_STATUSES | {"PENDING_APPROVAL", "EXECUTING"}:
+    reusable_statuses = FINAL_STATUSES | {"PENDING_APPROVAL", "EXECUTING"}
+    if run.get("status") in reusable_statuses or (
+        run.get("status") == "COMPUTED" and not send_feishu
+    ):
         logger.info("Reuse ROI run=%s status=%s", run_id, run.get("status"))
         return {
             "run_id": run_id,
@@ -102,7 +140,13 @@ def run_daily_roi(
         }
 
     try:
-        logger.info("ROI %s loading ODPS daily data %s..%s", run_id, start_date, end_date)
+        logger.info(
+            "ROI %s loading ODPS daily data %s..%s fission_parameter=%s",
+            run_id,
+            start_date,
+            end_date,
+            fission_parameters.release.version,
+        )
         daily = fetch_daily_data(client, start_date, end_date)
         ad_age = fetch_ad_age(client, end_date)
         _, thresholds, summary = evaluate_rules(
@@ -110,6 +154,7 @@ def run_daily_roi(
             expected_dates,
             ad_age,
             _rule_config(config),
+            fission_parameters=fission_parameters,
         )
         managed_ids = {
             int(row["account_id"])
@@ -120,7 +165,34 @@ def run_daily_roi(
             managed_ids,
             run_id,
         )
+        fission_match_summary = (
+            summary.groupby(
+                ["entity_type", "传播裂变系数匹配层级"],
+                as_index=False,
+                dropna=False,
+            )
+            .size()
+            .rename(
+                columns={
+                    "entity_type": "实体类型",
+                    "传播裂变系数匹配层级": "匹配层级",
+                    "size": "实体数",
+                }
+            )
+        )
+        channel_totals = fission_match_summary.groupby("实体类型")[
+            "实体数"
+        ].transform("sum")
+        fission_match_summary["渠道实体数"] = channel_totals
+        fission_match_summary["匹配率"] = (
+            fission_match_summary["实体数"] / channel_totals
+        )
+        fission_match_summary["参数版本"] = fission_parameters.release.version
         actionable_candidates = annotated[annotated["动作"].ne("")].copy()
+        report_rows = annotated[
+            annotated["阈值样本状态"].eq("进入阈值样本池")
+            | annotated["entity_type"].eq(ENTITY_QIWEI)
+        ].copy()
         for row in snapshots:
             row["run_id"] = run_id
         for row in actions:
@@ -133,24 +205,21 @@ def run_daily_roi(
             thresholds=threshold_record,
         )
 
-        qiwei_rows = daily[daily["entity_type"].eq(ENTITY_QIWEI)]
-        qiwei_fission_is_zero = bool(
-            not qiwei_rows.empty
-            and qiwei_rows["多层裂变收入"].fillna(0).sum() == 0
-        )
         output_dir.mkdir(parents=True, exist_ok=True)
-        output_path = output_dir / f"{run_id}.xlsx"
+        batch_name = f"ROI调控_{start_date}-{end_date}_LTV预测"
+        output_path = output_dir / f"{batch_name}.xlsx"
         write_workbook(
-            actionable_candidates,
+            report_rows,
             thresholds,
             expected_dates,
             output_path,
-            qiwei_fission_is_zero,
-            config.snapshot(),
+            run_config,
+            fission_match_summary,
         )
 
         result: dict[str, Any] = {
             "run_id": run_id,
+            "batch_name": batch_name,
             "status": "COMPUTED",
             "reused": False,
             "start_date": start_date,
@@ -159,6 +228,9 @@ def run_daily_roi(
             "candidate_count": len(actionable_candidates),
             "actionable_count": len(actions),
             "thresholds": threshold_record,
+            "fission_multiplier_matches": fission_match_summary.to_dict(
+                "records"
+            ),
             "report": str(output_path),
         }
         if not send_feishu:
@@ -178,6 +250,7 @@ def run_daily_roi(
             published = publisher.publish(
                 output_path,
                 run_id=run_id,
+                batch_name=batch_name,
                 summary=summary_text,
                 requires_approval=bool(actions),
             )

+ 123 - 0
examples/auto_put_ad_mini/roi_control/sql/fission_multiplier/20260712_A0-A15_v1/公众号合作即转_A0-A15_20260712.sql

@@ -0,0 +1,123 @@
+WITH first_cohort AS (
+  SELECT DISTINCT
+    CASE WHEN 合作方名 IS NULL OR 合作方名='' THEN 'null' ELSE 合作方名 END AS partner_name,
+    CASE WHEN 公众号名 IS NULL OR 公众号名='' THEN 'null' ELSE 公众号名 END AS account_name,
+    mid AS first_mid,
+    subsessionid AS rootsessionid
+  FROM loghubods.opengid_base_data
+  WHERE dt='20260712'
+    AND channel='公众号合作-即转-稳定'
+    AND usersharedepth=0
+    AND hotsencetype != 1167
+    AND videoid IS NOT NULL
+    AND mid IS NOT NULL
+    AND subsessionid IS NOT NULL
+),
+base_stats AS (
+  SELECT partner_name, account_name,
+         COUNT(DISTINCT first_mid) AS first_uv,
+         COUNT(DISTINCT rootsessionid) AS root_session_cnt
+  FROM first_cohort
+  GROUP BY partner_name, account_name
+  HAVING COUNT(DISTINCT first_mid)>500
+),
+root_entity AS (
+  SELECT DISTINCT f.partner_name, f.account_name, f.rootsessionid
+  FROM first_cohort f
+  JOIN base_stats b ON f.partner_name=b.partner_name AND f.account_name=b.account_name
+),
+first_users AS (
+  SELECT DISTINCT f.partner_name, f.account_name, f.first_mid
+  FROM first_cohort f
+  JOIN base_stats b ON f.partner_name=b.partner_name AND f.account_name=b.account_name
+),
+raw_active_fission AS (
+  SELECT DISTINCT r.partner_name, r.account_name, s.machinecode AS active_mid, s.dt AS active_dt
+  FROM root_entity r
+  JOIN loghubods.user_share_log s
+    ON s.rootsessionid=r.rootsessionid
+  WHERE s.dt BETWEEN '20260712' AND '20260727'
+    AND s.topic='click'
+    AND s.machinecode IS NOT NULL
+    AND CAST(s.usersharedepth AS BIGINT)>0
+),
+active_fission AS (
+  SELECT c.*
+  FROM raw_active_fission c
+  LEFT JOIN first_users f
+    ON c.partner_name=f.partner_name AND c.account_name=f.account_name AND c.active_mid=f.first_mid
+  WHERE f.first_mid IS NULL
+),
+active_counts AS (
+  SELECT partner_name, account_name,
+    SUM(CASE WHEN active_dt='20260712' THEN 1 ELSE 0 END) AS a0_active_uv,
+    SUM(CASE WHEN active_dt='20260713' THEN 1 ELSE 0 END) AS a1_active_uv,
+    SUM(CASE WHEN active_dt='20260714' THEN 1 ELSE 0 END) AS a2_active_uv,
+    SUM(CASE WHEN active_dt='20260715' THEN 1 ELSE 0 END) AS a3_active_uv,
+    SUM(CASE WHEN active_dt='20260716' THEN 1 ELSE 0 END) AS a4_active_uv,
+    SUM(CASE WHEN active_dt='20260717' THEN 1 ELSE 0 END) AS a5_active_uv,
+    SUM(CASE WHEN active_dt='20260718' THEN 1 ELSE 0 END) AS a6_active_uv,
+    SUM(CASE WHEN active_dt='20260719' THEN 1 ELSE 0 END) AS a7_active_uv,
+    SUM(CASE WHEN active_dt='20260720' THEN 1 ELSE 0 END) AS a8_active_uv,
+    SUM(CASE WHEN active_dt='20260721' THEN 1 ELSE 0 END) AS a9_active_uv,
+    SUM(CASE WHEN active_dt='20260722' THEN 1 ELSE 0 END) AS a10_active_uv,
+    SUM(CASE WHEN active_dt='20260723' THEN 1 ELSE 0 END) AS a11_active_uv,
+    SUM(CASE WHEN active_dt='20260724' THEN 1 ELSE 0 END) AS a12_active_uv,
+    SUM(CASE WHEN active_dt='20260725' THEN 1 ELSE 0 END) AS a13_active_uv,
+    SUM(CASE WHEN active_dt='20260726' THEN 1 ELSE 0 END) AS a14_active_uv,
+    SUM(CASE WHEN active_dt='20260727' THEN 1 ELSE 0 END) AS a15_active_uv,
+    COUNT(*) AS active_person_days
+  FROM active_fission
+  GROUP BY partner_name, account_name
+)
+SELECT
+  '20260712' AS cohort_dt,
+  '公众号合作-即转-稳定' AS channel,
+  b.partner_name,
+  b.account_name,
+  b.first_uv,
+  b.root_session_cnt,
+  NVL(a.a0_active_uv,0) AS a0_active_uv,
+  NVL(a.a1_active_uv,0) AS a1_active_uv,
+  NVL(a.a2_active_uv,0) AS a2_active_uv,
+  NVL(a.a3_active_uv,0) AS a3_active_uv,
+  NVL(a.a4_active_uv,0) AS a4_active_uv,
+  NVL(a.a5_active_uv,0) AS a5_active_uv,
+  NVL(a.a6_active_uv,0) AS a6_active_uv,
+  NVL(a.a7_active_uv,0) AS a7_active_uv,
+  NVL(a.a8_active_uv,0) AS a8_active_uv,
+  NVL(a.a9_active_uv,0) AS a9_active_uv,
+  NVL(a.a10_active_uv,0) AS a10_active_uv,
+  NVL(a.a11_active_uv,0) AS a11_active_uv,
+  NVL(a.a12_active_uv,0) AS a12_active_uv,
+  NVL(a.a13_active_uv,0) AS a13_active_uv,
+  NVL(a.a14_active_uv,0) AS a14_active_uv,
+  NVL(a.a15_active_uv,0) AS a15_active_uv,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a0_active_uv,0)/b.first_uv END AS a0_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a1_active_uv,0)/b.first_uv END AS a1_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a2_active_uv,0)/b.first_uv END AS a2_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a3_active_uv,0)/b.first_uv END AS a3_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a4_active_uv,0)/b.first_uv END AS a4_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a5_active_uv,0)/b.first_uv END AS a5_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a6_active_uv,0)/b.first_uv END AS a6_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a7_active_uv,0)/b.first_uv END AS a7_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a8_active_uv,0)/b.first_uv END AS a8_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a9_active_uv,0)/b.first_uv END AS a9_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a10_active_uv,0)/b.first_uv END AS a10_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a11_active_uv,0)/b.first_uv END AS a11_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a12_active_uv,0)/b.first_uv END AS a12_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a13_active_uv,0)/b.first_uv END AS a13_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a14_active_uv,0)/b.first_uv END AS a14_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a15_active_uv,0)/b.first_uv END AS a15_active_rate,
+  NVL(a.active_person_days,0) AS active_person_days,
+  CASE WHEN b.first_uv>0 THEN (NVL(a.a0_active_uv,0)+NVL(a.a1_active_uv,0)+NVL(a.a2_active_uv,0)+NVL(a.a3_active_uv,0)+NVL(a.a4_active_uv,0)+NVL(a.a5_active_uv,0)+NVL(a.a6_active_uv,0)+NVL(a.a7_active_uv,0)+NVL(a.a8_active_uv,0)+NVL(a.a9_active_uv,0)+NVL(a.a10_active_uv,0)+NVL(a.a11_active_uv,0)+NVL(a.a12_active_uv,0)+NVL(a.a13_active_uv,0)+NVL(a.a14_active_uv,0)+NVL(a.a15_active_uv,0))/b.first_uv END AS activity_rate_sum,
+  CASE WHEN NVL(a.a0_active_uv,0)>0
+       THEN ((NVL(a.a0_active_uv,0)+NVL(a.a1_active_uv,0)+NVL(a.a2_active_uv,0)+NVL(a.a3_active_uv,0)+NVL(a.a4_active_uv,0)+NVL(a.a5_active_uv,0)+NVL(a.a6_active_uv,0)+NVL(a.a7_active_uv,0)+NVL(a.a8_active_uv,0)+NVL(a.a9_active_uv,0)+NVL(a.a10_active_uv,0)+NVL(a.a11_active_uv,0)+NVL(a.a12_active_uv,0)+NVL(a.a13_active_uv,0)+NVL(a.a14_active_uv,0)+NVL(a.a15_active_uv,0))-NVL(a.a0_active_uv,0))/a.a0_active_uv
+  END AS active_tail_vs_a0,
+  CASE WHEN NVL(a.a0_active_uv,0)>0
+       THEN (NVL(a.a0_active_uv,0)+NVL(a.a1_active_uv,0)+NVL(a.a2_active_uv,0)+NVL(a.a3_active_uv,0)+NVL(a.a4_active_uv,0)+NVL(a.a5_active_uv,0)+NVL(a.a6_active_uv,0)+NVL(a.a7_active_uv,0)+NVL(a.a8_active_uv,0)+NVL(a.a9_active_uv,0)+NVL(a.a10_active_uv,0)+NVL(a.a11_active_uv,0)+NVL(a.a12_active_uv,0)+NVL(a.a13_active_uv,0)+NVL(a.a14_active_uv,0)+NVL(a.a15_active_uv,0))/a.a0_active_uv
+  END AS activity_maturity_vs_a0,
+  CASE WHEN b.first_uv>0 THEN 1+(NVL(a.a0_active_uv,0)+NVL(a.a1_active_uv,0)+NVL(a.a2_active_uv,0)+NVL(a.a3_active_uv,0)+NVL(a.a4_active_uv,0)+NVL(a.a5_active_uv,0)+NVL(a.a6_active_uv,0)+NVL(a.a7_active_uv,0)+NVL(a.a8_active_uv,0)+NVL(a.a9_active_uv,0)+NVL(a.a10_active_uv,0)+NVL(a.a11_active_uv,0)+NVL(a.a12_active_uv,0)+NVL(a.a13_active_uv,0)+NVL(a.a14_active_uv,0)+NVL(a.a15_active_uv,0))/b.first_uv END AS steady_dau_multiplier
+FROM base_stats b
+LEFT JOIN active_counts a ON b.partner_name=a.partner_name AND b.account_name=a.account_name
+ORDER BY b.first_uv DESC

+ 121 - 0
examples/auto_put_ad_mini/roi_control/sql/fission_multiplier/20260712_A0-A15_v1/小程序人群包转化目标_A0-A15_20260712.sql

@@ -0,0 +1,121 @@
+WITH first_cohort AS (
+  SELECT DISTINCT
+    CASE WHEN 包名 IS NULL OR 包名='' OR 包名='null' THEN '泛人群' ELSE 包名 END AS package_name,
+    CASE WHEN 广告优化目标 IS NULL OR 广告优化目标='' OR 广告优化目标='null' THEN '未知' ELSE 广告优化目标 END AS optimize_goal,
+    mid AS first_mid,
+    subsessionid AS rootsessionid
+  FROM loghubods.opengid_base_data
+  WHERE dt='20260712'
+    AND channel='小程序投流-稳定'
+    AND usersharedepth=0
+    AND hotsencetype != 1167
+    AND videoid IS NOT NULL
+    AND mid IS NOT NULL
+    AND subsessionid IS NOT NULL
+),
+root_entity AS (
+  SELECT DISTINCT package_name, optimize_goal, rootsessionid FROM first_cohort
+),
+first_users AS (
+  SELECT DISTINCT package_name, optimize_goal, first_mid FROM first_cohort
+),
+base_stats AS (
+  SELECT package_name, optimize_goal,
+         COUNT(DISTINCT first_mid) AS first_uv,
+         COUNT(DISTINCT rootsessionid) AS root_session_cnt
+  FROM first_cohort
+  GROUP BY package_name, optimize_goal
+),
+raw_active_fission AS (
+  SELECT DISTINCT
+    r.package_name,
+    r.optimize_goal,
+    s.machinecode AS active_mid,
+    s.dt AS active_dt
+  FROM root_entity r
+  JOIN loghubods.user_share_log s
+    ON s.rootsessionid=r.rootsessionid
+  WHERE s.dt BETWEEN '20260712' AND '20260727'
+    AND s.topic='click'
+    AND s.machinecode IS NOT NULL
+    AND CAST(s.usersharedepth AS BIGINT)>0
+),
+active_fission AS (
+  SELECT c.*
+  FROM raw_active_fission c
+  LEFT JOIN first_users f
+    ON c.package_name=f.package_name AND c.optimize_goal=f.optimize_goal AND c.active_mid=f.first_mid
+  WHERE f.first_mid IS NULL
+),
+active_counts AS (
+  SELECT package_name, optimize_goal,
+    SUM(CASE WHEN active_dt='20260712' THEN 1 ELSE 0 END) AS a0_active_uv,
+    SUM(CASE WHEN active_dt='20260713' THEN 1 ELSE 0 END) AS a1_active_uv,
+    SUM(CASE WHEN active_dt='20260714' THEN 1 ELSE 0 END) AS a2_active_uv,
+    SUM(CASE WHEN active_dt='20260715' THEN 1 ELSE 0 END) AS a3_active_uv,
+    SUM(CASE WHEN active_dt='20260716' THEN 1 ELSE 0 END) AS a4_active_uv,
+    SUM(CASE WHEN active_dt='20260717' THEN 1 ELSE 0 END) AS a5_active_uv,
+    SUM(CASE WHEN active_dt='20260718' THEN 1 ELSE 0 END) AS a6_active_uv,
+    SUM(CASE WHEN active_dt='20260719' THEN 1 ELSE 0 END) AS a7_active_uv,
+    SUM(CASE WHEN active_dt='20260720' THEN 1 ELSE 0 END) AS a8_active_uv,
+    SUM(CASE WHEN active_dt='20260721' THEN 1 ELSE 0 END) AS a9_active_uv,
+    SUM(CASE WHEN active_dt='20260722' THEN 1 ELSE 0 END) AS a10_active_uv,
+    SUM(CASE WHEN active_dt='20260723' THEN 1 ELSE 0 END) AS a11_active_uv,
+    SUM(CASE WHEN active_dt='20260724' THEN 1 ELSE 0 END) AS a12_active_uv,
+    SUM(CASE WHEN active_dt='20260725' THEN 1 ELSE 0 END) AS a13_active_uv,
+    SUM(CASE WHEN active_dt='20260726' THEN 1 ELSE 0 END) AS a14_active_uv,
+    SUM(CASE WHEN active_dt='20260727' THEN 1 ELSE 0 END) AS a15_active_uv,
+    COUNT(*) AS active_person_days
+  FROM active_fission
+  GROUP BY package_name, optimize_goal
+)
+SELECT
+  '20260712' AS cohort_dt,
+  b.package_name,
+  b.optimize_goal,
+  b.first_uv,
+  b.root_session_cnt,
+  NVL(a.a0_active_uv,0) AS a0_active_uv,
+  NVL(a.a1_active_uv,0) AS a1_active_uv,
+  NVL(a.a2_active_uv,0) AS a2_active_uv,
+  NVL(a.a3_active_uv,0) AS a3_active_uv,
+  NVL(a.a4_active_uv,0) AS a4_active_uv,
+  NVL(a.a5_active_uv,0) AS a5_active_uv,
+  NVL(a.a6_active_uv,0) AS a6_active_uv,
+  NVL(a.a7_active_uv,0) AS a7_active_uv,
+  NVL(a.a8_active_uv,0) AS a8_active_uv,
+  NVL(a.a9_active_uv,0) AS a9_active_uv,
+  NVL(a.a10_active_uv,0) AS a10_active_uv,
+  NVL(a.a11_active_uv,0) AS a11_active_uv,
+  NVL(a.a12_active_uv,0) AS a12_active_uv,
+  NVL(a.a13_active_uv,0) AS a13_active_uv,
+  NVL(a.a14_active_uv,0) AS a14_active_uv,
+  NVL(a.a15_active_uv,0) AS a15_active_uv,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a0_active_uv,0)/b.first_uv END AS a0_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a1_active_uv,0)/b.first_uv END AS a1_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a2_active_uv,0)/b.first_uv END AS a2_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a3_active_uv,0)/b.first_uv END AS a3_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a4_active_uv,0)/b.first_uv END AS a4_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a5_active_uv,0)/b.first_uv END AS a5_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a6_active_uv,0)/b.first_uv END AS a6_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a7_active_uv,0)/b.first_uv END AS a7_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a8_active_uv,0)/b.first_uv END AS a8_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a9_active_uv,0)/b.first_uv END AS a9_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a10_active_uv,0)/b.first_uv END AS a10_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a11_active_uv,0)/b.first_uv END AS a11_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a12_active_uv,0)/b.first_uv END AS a12_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a13_active_uv,0)/b.first_uv END AS a13_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a14_active_uv,0)/b.first_uv END AS a14_active_rate,
+  CASE WHEN b.first_uv>0 THEN NVL(a.a15_active_uv,0)/b.first_uv END AS a15_active_rate,
+  NVL(a.active_person_days,0) AS active_person_days,
+  CASE WHEN b.first_uv>0 THEN (NVL(a.a0_active_uv,0)+NVL(a.a1_active_uv,0)+NVL(a.a2_active_uv,0)+NVL(a.a3_active_uv,0)+NVL(a.a4_active_uv,0)+NVL(a.a5_active_uv,0)+NVL(a.a6_active_uv,0)+NVL(a.a7_active_uv,0)+NVL(a.a8_active_uv,0)+NVL(a.a9_active_uv,0)+NVL(a.a10_active_uv,0)+NVL(a.a11_active_uv,0)+NVL(a.a12_active_uv,0)+NVL(a.a13_active_uv,0)+NVL(a.a14_active_uv,0)+NVL(a.a15_active_uv,0))/b.first_uv END AS activity_rate_sum,
+  CASE WHEN NVL(a.a0_active_uv,0)>0
+       THEN ((NVL(a.a0_active_uv,0)+NVL(a.a1_active_uv,0)+NVL(a.a2_active_uv,0)+NVL(a.a3_active_uv,0)+NVL(a.a4_active_uv,0)+NVL(a.a5_active_uv,0)+NVL(a.a6_active_uv,0)+NVL(a.a7_active_uv,0)+NVL(a.a8_active_uv,0)+NVL(a.a9_active_uv,0)+NVL(a.a10_active_uv,0)+NVL(a.a11_active_uv,0)+NVL(a.a12_active_uv,0)+NVL(a.a13_active_uv,0)+NVL(a.a14_active_uv,0)+NVL(a.a15_active_uv,0))-NVL(a.a0_active_uv,0))/a.a0_active_uv
+  END AS active_tail_vs_a0,
+  CASE WHEN NVL(a.a0_active_uv,0)>0
+       THEN (NVL(a.a0_active_uv,0)+NVL(a.a1_active_uv,0)+NVL(a.a2_active_uv,0)+NVL(a.a3_active_uv,0)+NVL(a.a4_active_uv,0)+NVL(a.a5_active_uv,0)+NVL(a.a6_active_uv,0)+NVL(a.a7_active_uv,0)+NVL(a.a8_active_uv,0)+NVL(a.a9_active_uv,0)+NVL(a.a10_active_uv,0)+NVL(a.a11_active_uv,0)+NVL(a.a12_active_uv,0)+NVL(a.a13_active_uv,0)+NVL(a.a14_active_uv,0)+NVL(a.a15_active_uv,0))/a.a0_active_uv
+  END AS activity_maturity_vs_a0,
+  CASE WHEN b.first_uv>0 THEN 1+(NVL(a.a0_active_uv,0)+NVL(a.a1_active_uv,0)+NVL(a.a2_active_uv,0)+NVL(a.a3_active_uv,0)+NVL(a.a4_active_uv,0)+NVL(a.a5_active_uv,0)+NVL(a.a6_active_uv,0)+NVL(a.a7_active_uv,0)+NVL(a.a8_active_uv,0)+NVL(a.a9_active_uv,0)+NVL(a.a10_active_uv,0)+NVL(a.a11_active_uv,0)+NVL(a.a12_active_uv,0)+NVL(a.a13_active_uv,0)+NVL(a.a14_active_uv,0)+NVL(a.a15_active_uv,0))/b.first_uv END AS steady_dau_multiplier
+FROM base_stats b
+LEFT JOIN active_counts a ON b.package_name=a.package_name AND b.optimize_goal=a.optimize_goal
+ORDER BY b.first_uv DESC

+ 34 - 19
examples/auto_put_ad_mini/test_roi_control_metrics.py

@@ -10,10 +10,17 @@ from roi_control.metrics import (
     QIWEI_CHANNEL,
     SELF_CHANNEL,
 )
-from roi_control.rules import evaluate_rules
+from roi_control.fission_multiplier import load_fission_multiplier_parameters
+from roi_control.rules import evaluate_rules as _evaluate_rules
 
 
 DATES = ["20260720", "20260721", "20260722"]
+FISSION_PARAMETERS = load_fission_multiplier_parameters()
+
+
+def evaluate_rules(*args, **kwargs):
+    kwargs["fission_parameters"] = FISSION_PARAMETERS
+    return _evaluate_rules(*args, **kwargs)
 
 
 def row(entity_type, channel, entity_id, dt, roi, uv=600, age=10, cost=200.0):
@@ -27,6 +34,7 @@ def row(entity_type, channel, entity_id, dt, roi, uv=600, age=10, cost=200.0):
         "广告id": "",
         "广告名称": "",
         "包名": "",
+        "广告优化目标": "",
         "创意id": "",
         "合作方名": "",
         "公众号名": "",
@@ -45,6 +53,7 @@ def row(entity_type, channel, entity_id, dt, roi, uv=600, age=10, cost=200.0):
                 "广告id": entity_id,
                 "广告名称": f"广告{entity_id}",
                 "包名": "人群包",
+                "广告优化目标": "关键页面访问次数",
                 "创意id": f"creative-{entity_id}",
             }
         )
@@ -82,22 +91,24 @@ class RoiRulesTest(unittest.TestCase):
         self.assertIn("关停", actions)
         self.assertIn("扩量", actions)
         self.assertEqual(len(thresholds), 1)
-        self.assertEqual(thresholds.iloc[0]["阈值样本数"], len(summary))
+        self.assertEqual(
+            thresholds.iloc[0]["阈值样本数"],
+            int(summary["entity_type"].ne(ENTITY_QIWEI).sum()),
+        )
         self.assertTrue((summary["覆盖天数"] == 3).all())
         self.assertTrue((summary["t_stop"] == thresholds.iloc[0]["t_stop"]).all())
         self.assertTrue((summary["t_up"] == thresholds.iloc[0]["t_up"]).all())
+        qiwei = summary[summary["entity_type"].eq(ENTITY_QIWEI)]
+        self.assertEqual(len(qiwei), 2)
+        self.assertTrue(
+            qiwei["调控参与状态"].eq("仅展示_不进入阈值和调控").all()
+        )
 
-    def test_missing_day_is_not_candidate(self):
+    def test_qiwei_is_excluded_before_metric_and_action_evaluation(self):
         daily = self.build_daily()
-        missing = daily[
-            ~(
-                daily["entity_type"].eq(ENTITY_QIWEI)
-                & daily["合作方名"].eq("低ROI企微")
-                & daily["dt"].eq(DATES[-1])
-            )
-        ]
-        candidates, _, _ = evaluate_rules(missing, DATES)
-        self.assertFalse(candidates["合作方名"].eq("低ROI企微").any())
+        candidates, _, summary = evaluate_rules(daily, DATES)
+        self.assertTrue(summary["entity_type"].eq(ENTITY_QIWEI).any())
+        self.assertFalse(candidates["合作方名"].str.contains("企微").any())
 
     def test_no_complete_three_day_entity_fails_clearly(self):
         daily = self.build_daily()
@@ -105,7 +116,7 @@ class RoiRulesTest(unittest.TestCase):
         with self.assertRaisesRegex(ValueError, "连续三日数据"):
             evaluate_rules(incomplete, DATES)
 
-    def test_multi_layer_income_is_added_once(self):
+    def test_t0_income_is_scaled_once_without_duplicate_addition(self):
         daily = self.build_daily()
         mask = (
             daily["entity_type"].eq(ENTITY_GZH)
@@ -120,7 +131,11 @@ class RoiRulesTest(unittest.TestCase):
             summary["entity_type"].eq(ENTITY_GZH)
             & summary["公众号名"].eq("高ROI公众号")
         ].iloc[0]
-        self.assertAlmostEqual(target["ROI"], 3.0)
+        expected = (
+            100 + 200 * FISSION_PARAMETERS.gzh_channel
+        ) / 100
+        self.assertAlmostEqual(target["ROI"], expected)
+        self.assertAlmostEqual(target["实际ROI"], 3.0)
 
     def test_self_age_blocks_actions(self):
         daily = self.build_daily()
@@ -167,7 +182,7 @@ class RoiRulesTest(unittest.TestCase):
         self.assertEqual(len(target), 1)
         self.assertTrue(candidates["广告id"].eq("ad-9").any())
 
-    def test_global_threshold_pool_mixes_all_entity_types_after_uv_gate(self):
+    def test_global_threshold_pool_only_uses_miniapp_and_gzh(self):
         rows = []
         specifications = [
             (ENTITY_SELF, SELF_CHANNEL, "self-qualified", 1.0, 300),
@@ -181,13 +196,13 @@ class RoiRulesTest(unittest.TestCase):
 
         _, thresholds, summary = evaluate_rules(pd.DataFrame(rows), DATES)
         threshold = thresholds.iloc[0]
-        expected = pd.Series([1.0, 2.0, 3.0])
+        expected = pd.Series([1.0, 2.0])
         self.assertAlmostEqual(threshold["t_stop"], expected.quantile(0.10))
         self.assertAlmostEqual(threshold["t_up"], expected.quantile(0.80))
-        self.assertEqual(threshold["阈值样本数"], 3)
+        self.assertEqual(threshold["阈值样本数"], 2)
         self.assertEqual(threshold["小程序样本数"], 1)
         self.assertEqual(threshold["公众号样本数"], 1)
-        self.assertEqual(threshold["企微样本数"], 1)
+        self.assertEqual(threshold["企微参考实体数"], 1)
         self.assertEqual(len(summary), 4)
 
     def test_actions_use_three_day_aggregate_not_each_daily_roi(self):
@@ -197,7 +212,7 @@ class RoiRulesTest(unittest.TestCase):
             rows.append(row(ENTITY_GZH, GZH_CHANNEL, "波动公众号", dt, roi, uv=300))
         for dt in DATES:
             rows.append(row(ENTITY_SELF, SELF_CHANNEL, "基准创意", dt, 1.0, uv=600))
-            rows.append(row(ENTITY_QIWEI, QIWEI_CHANNEL, "基准企微", dt, 3.0, uv=300))
+            rows.append(row(ENTITY_GZH, GZH_CHANNEL, "基准公众号", dt, 3.0, uv=300))
 
         candidates, thresholds, summary = evaluate_rules(pd.DataFrame(rows), DATES)
         target = summary[summary["公众号名"].eq("波动公众号")].iloc[0]

+ 7 - 1
examples/auto_put_ad_mini/test_roi_control_policy.py

@@ -1,6 +1,6 @@
 import os
 import unittest
-from datetime import date
+from datetime import date, datetime
 from decimal import Decimal
 from unittest.mock import patch
 
@@ -17,9 +17,15 @@ from roi_control.policy import (
     MODE_NOTIFY_ONLY,
     annotate_execution,
 )
+from roi_control.repository import _is_expired
 
 
 class RoiControlPolicyTest(unittest.TestCase):
+    def test_mysql_naive_expiry_compares_with_aware_service_time(self):
+        expires_at = datetime(2026, 7, 28, 12, 0)
+        now = datetime.fromisoformat("2026-07-28T12:01:00+08:00")
+        self.assertTrue(_is_expired(expires_at, now))
+
     def test_actionability_is_separate_from_metric_recommendation(self):
         summary = pd.DataFrame(
             [

+ 179 - 0
examples/auto_put_ad_mini/test_roi_fission_multiplier.py

@@ -0,0 +1,179 @@
+import json
+import unittest
+from datetime import date
+from pathlib import Path
+
+import pandas as pd
+
+from roi_control.data_source import build_daily_sql
+from roi_control.fission_multiplier import (
+    DEFAULT_FISSION_PARAMETER_VERSION,
+    DISPLAY_MULTIPLIER_COLUMN,
+    MATCH_GZH_EXACT,
+    MATCH_GZH_PARTNER,
+    MATCH_MINIAPP_EXACT,
+    MATCH_MINIAPP_GOAL,
+    MATCH_MINIAPP_PACKAGE,
+    MATCH_QIWEI_REFERENCE,
+    load_fission_multiplier_parameters,
+    parameter_content_sha256,
+    parameter_values,
+    parameters_from_database,
+)
+from roi_control.metrics import prepare_daily_metrics
+from roi_control.fission_multiplier_refresh import (
+    build_gzh_activity_curve_sql,
+    build_miniapp_activity_curve_sql,
+)
+
+
+PROJECT_DIR = Path(__file__).resolve().parent
+
+
+class RoiFissionMultiplierTest(unittest.TestCase):
+    @classmethod
+    def setUpClass(cls):
+        cls.parameters = load_fission_multiplier_parameters()
+
+    def test_published_release_metadata_and_counts(self):
+        snapshot = self.parameters.snapshot()
+        self.assertEqual(snapshot["version"], DEFAULT_FISSION_PARAMETER_VERSION)
+        self.assertEqual(snapshot["cohort_date"], "20260712")
+        self.assertEqual(snapshot["observation_end_date"], "20260727")
+        self.assertEqual(snapshot["miniapp_exact_rows"], 40)
+        self.assertEqual(snapshot["miniapp_exact_available_rows"], 21)
+        self.assertEqual(snapshot["gzh_exact_rows"], 110)
+        self.assertEqual(snapshot["gzh_exact_available_rows"], 93)
+        self.assertAlmostEqual(snapshot["miniapp_channel_multiplier"], 2.608491, places=6)
+        self.assertAlmostEqual(snapshot["gzh_channel_multiplier"], 2.476153, places=6)
+
+    def test_miniapp_uses_exact_then_published_fallbacks(self):
+        exact = self.parameters.match(
+            "self",
+            package="泛人群",
+            optimize_goal="关键页面访问次数",
+        )
+        self.assertEqual(exact.match_level, MATCH_MINIAPP_EXACT)
+        self.assertAlmostEqual(exact.multiplier, 2.515898565120092)
+
+        missing_goal = self.parameters.match(
+            "self",
+            package="泛人群",
+            optimize_goal="",
+        )
+        self.assertEqual(missing_goal.match_level, MATCH_MINIAPP_PACKAGE)
+        self.assertAlmostEqual(missing_goal.multiplier, 2.5182863849765257)
+
+        insufficient_exact = self.parameters.match(
+            "self",
+            package="unexp*day*商业",
+            optimize_goal="关键页面访问次数",
+        )
+        self.assertEqual(insufficient_exact.match_level, MATCH_MINIAPP_GOAL)
+        self.assertAlmostEqual(insufficient_exact.multiplier, 2.610471, places=6)
+
+    def test_gzh_insufficient_exact_uses_partner_fallback(self):
+        exact = self.parameters.match(
+            "gzh", partner="szhx", official_account="尊闻"
+        )
+        self.assertEqual(exact.match_level, MATCH_GZH_EXACT)
+
+        fallback = self.parameters.match(
+            "gzh", partner="yy", official_account="异闻怪谈"
+        )
+        self.assertEqual(fallback.match_level, MATCH_GZH_PARTNER)
+        self.assertAlmostEqual(fallback.multiplier, 1.887225, places=6)
+
+    def test_qiwei_uses_reference_multiplier_without_control_semantics(self):
+        match = self.parameters.match("qiwei", partner="企微合作方")
+        self.assertEqual(match.match_level, MATCH_QIWEI_REFERENCE)
+        self.assertEqual(match.multiplier, 1.0)
+        self.assertIn("待补算", match.source)
+
+    def test_database_parameter_round_trip_preserves_release(self):
+        metadata = self.parameters.snapshot()
+        metadata["file_sha256"] = dict(self.parameters.release.file_sha256)
+        restored = parameters_from_database(
+            {
+                "version": self.parameters.release.version,
+                "cohort_date": date(2026, 7, 12),
+                "observation_end_date": date(2026, 7, 27),
+                "run_suffix": self.parameters.release.run_suffix,
+                "content_sha256": parameter_content_sha256(self.parameters),
+                "metadata_json": json.dumps(metadata, ensure_ascii=False),
+            },
+            parameter_values(self.parameters),
+        )
+        self.assertEqual(
+            parameter_content_sha256(restored),
+            parameter_content_sha256(self.parameters),
+        )
+        self.assertEqual(restored.snapshot(), self.parameters.snapshot())
+
+    def test_roi_formula_does_not_add_t0_twice(self):
+        frame = pd.DataFrame(
+            [
+                {
+                    "dt": "20260727",
+                    "entity_type": "self",
+                    "channel": "小程序投流-稳定",
+                    "代理名称": "",
+                    "账号id": "1",
+                    "账号名称": "测试账户",
+                    "广告id": "2",
+                    "广告名称": "测试广告",
+                    "包名": "泛人群",
+                    "广告优化目标": "关键页面访问次数",
+                    "创意id": "3",
+                    "合作方名": "",
+                    "公众号名": "",
+                    "首层UV": 100,
+                    "T0裂变数": 20,
+                    "成本": 100,
+                    "效率收入": 50,
+                    "多层裂变收入": 30,
+                }
+            ]
+        )
+        result = prepare_daily_metrics(frame, self.parameters).iloc[0]
+        expected_tail = 30 * (result[DISPLAY_MULTIPLIER_COLUMN] - 1)
+        expected_fission = 30 + expected_tail
+        self.assertAlmostEqual(result["T0实际裂变收入"], 30)
+        self.assertAlmostEqual(result["预测T1-T15裂变收入"], expected_tail)
+        self.assertAlmostEqual(result["预测T0-T15裂变收入"], expected_fission)
+        self.assertAlmostEqual(result["预测全链路效率收入"], 50 + expected_fission)
+        self.assertAlmostEqual(result["ROI"], (50 + expected_fission) / 100)
+        self.assertAlmostEqual(result["实际ROI"], 0.8)
+
+    def test_daily_sql_preserves_explicit_optimize_goal(self):
+        sql = build_daily_sql("20260725", "20260727")
+        self.assertIn("AS 广告优化目标", sql)
+        self.assertIn("广告优化目标='null'", sql)
+        self.assertIn("GROUP BY\n  dt, channel, 账号id, 广告id, 包名", sql)
+
+    def test_recompute_sql_matches_published_release_audit_sql(self):
+        audit_dir = (
+            PROJECT_DIR
+            / "roi_control"
+            / "sql"
+            / "fission_multiplier"
+            / DEFAULT_FISSION_PARAMETER_VERSION
+        )
+        expected_miniapp = (
+            audit_dir / "小程序人群包转化目标_A0-A15_20260712.sql"
+        ).read_text(encoding="utf-8").strip()
+        expected_gzh = (
+            audit_dir / "公众号合作即转_A0-A15_20260712.sql"
+        ).read_text(encoding="utf-8").strip()
+        self.assertEqual(
+            build_miniapp_activity_curve_sql("20260712"),
+            expected_miniapp,
+        )
+        self.assertEqual(
+            build_gzh_activity_curve_sql("20260712"),
+            expected_gzh,
+        )
+
+
+if __name__ == "__main__":
+    unittest.main()

+ 3 - 1
examples/tencent_realtime_control/.env.example

@@ -3,7 +3,7 @@ RTC_STOP_HOUR=21
 RTC_POLL_SECONDS=600
 RTC_HIGH_CPM=250
 RTC_LOW_CPM=190
-RTC_BID_UP_RATIO=1.25
+RTC_BID_UP_RATIO=1.05
 RTC_INVENTORY_REFRESH_MINUTES=60
 RTC_MAX_PARTITION_LAG_HOURS=2
 RTC_DB_LOCK_NAME=tencent_realtime_control
@@ -24,11 +24,13 @@ DAILY_ROI_HOUR=11
 DAILY_ROI_MINUTE=0
 DAILY_ROI_RUN_ON_STARTUP=0
 ROI_APPLY_ENABLED=0
+ROI_FISSION_PARAMETER_VERSION=20260712_A0-A15_v1
 ROI_APPROVAL_TTL_MINUTES=120
 ROI_SCALE_RATIO=1.10
 ROI_SCALE_COOLDOWN_DAYS=3
 ROI_MAX_BASE_RATIO=2.00
 ROI_FEISHU_CHAT_ID=
+FEISHU_OPERATOR_CHAT_ID=
 
 ODPS_ACCESS_ID=
 ODPS_ACCESS_SECRET=

+ 8 - 1
examples/tencent_realtime_control/README.md

@@ -18,7 +18,7 @@
 北京时间默认每天 `12:00-21:00` 每 10 分钟检查一次。广告自身投放时段
 仍由 `time_series` 管理,在实时调控开始前按基础出价正常投放:
 
-- `CPM > 250`:基础出价上调 25%。
+- `CPM > 250`:基础出价上调 5%。
 - `190 <= CPM <= 250`:恢复基础出价并恢复策略暂停的广告。
 - `CPM < 190`:恢复基础出价,将广告开始日期延后至次日;保持广告开启,次日
   进入 `time_series` 投放时段后由腾讯自动投放。
@@ -170,6 +170,13 @@ dry-run 切换步骤见
 CPM 调控共用 `RTC_DB_LOCK_NAME`,并在写入后回读验证。详细开关和分阶段上线
 步骤见统一部署文档。
 
+当前指标版本 `north_star_roi_t15_v3`、报表版本 `roi_report_v4` 消费 `ROI_FISSION_PARAMETER_VERSION` 指定的
+已发布传播裂变参数,默认 `20260712_A0-A15_v1`。T0 收入使用实际值,仅预测
+T1-T15 裂变增量。参数只影响日级 ROI 计算和建议,
+不参与实时 CPM 决策。正式参数由更新脚本发布到 MySQL,日级任务只读取数据库且
+不会现场重算或回退到镜像文件。ROI 在线表同时发送到 ROI 通知群和
+`FEISHU_OPERATOR_CHAT_ID`,重复群 ID 自动去重。
+
 ## ECS 首次迁移 ODPS 配置
 
 仅用于旧 `auto_put_ad_mini` 容器仍在运行、但 ECS 的

+ 2 - 2
examples/tencent_realtime_control/realtime_config.py

@@ -14,7 +14,7 @@ class RealtimeControlConfig:
     poll_seconds: int = 600
     high_cpm: Decimal = Decimal("250")
     low_cpm: Decimal = Decimal("190")
-    bid_up_ratio: Decimal = Decimal("1.25")
+    bid_up_ratio: Decimal = Decimal("1.05")
     inventory_refresh_minutes: int = 60
     max_partition_lag_hours: int = 2
     lock_name: str = "tencent_realtime_control"
@@ -27,7 +27,7 @@ class RealtimeControlConfig:
             poll_seconds=int(os.getenv("RTC_POLL_SECONDS", "600")),
             high_cpm=Decimal(os.getenv("RTC_HIGH_CPM", "250")),
             low_cpm=Decimal(os.getenv("RTC_LOW_CPM", "190")),
-            bid_up_ratio=Decimal(os.getenv("RTC_BID_UP_RATIO", "1.25")),
+            bid_up_ratio=Decimal(os.getenv("RTC_BID_UP_RATIO", "1.05")),
             inventory_refresh_minutes=int(
                 os.getenv("RTC_INVENTORY_REFRESH_MINUTES", "60")
             ),

+ 39 - 0
examples/tencent_realtime_control/schema.sql

@@ -44,6 +44,8 @@ CREATE TABLE IF NOT EXISTS roi_metric_run (
     run_key VARCHAR(128) NOT NULL,
     metric_version VARCHAR(64) NOT NULL,
     policy_version VARCHAR(64) NOT NULL,
+    fission_parameter_version VARCHAR(64) DEFAULT NULL,
+    fission_cohort_date DATE DEFAULT NULL,
     start_date DATE NOT NULL,
     end_date DATE NOT NULL,
     config_json LONGTEXT NOT NULL,
@@ -69,6 +71,33 @@ CREATE TABLE IF NOT EXISTS roi_metric_run (
     KEY idx_roi_run_end_date (end_date)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='版本化ROI计算与整批审批运行';
 
+CREATE TABLE IF NOT EXISTS roi_fission_parameter_release (
+    version VARCHAR(64) NOT NULL PRIMARY KEY,
+    cohort_date DATE NOT NULL,
+    observation_end_date DATE NOT NULL,
+    horizon_days INT NOT NULL,
+    run_suffix VARCHAR(32) NOT NULL,
+    content_sha256 CHAR(64) NOT NULL,
+    metadata_json LONGTEXT NOT NULL,
+    published_by VARCHAR(128) DEFAULT NULL,
+    published_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    UNIQUE KEY uk_roi_fission_parameter_content (content_sha256)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='ROI传播裂变系数发布版本';
+
+CREATE TABLE IF NOT EXISTS roi_fission_parameter_value (
+    id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+    version VARCHAR(64) NOT NULL,
+    entity_type VARCHAR(32) NOT NULL,
+    match_level VARCHAR(64) NOT NULL,
+    key_primary VARCHAR(255) NOT NULL DEFAULT '',
+    key_secondary VARCHAR(255) NOT NULL DEFAULT '',
+    multiplier DOUBLE NOT NULL,
+    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    UNIQUE KEY uk_roi_fission_parameter_value
+        (version, entity_type, match_level, key_primary, key_secondary),
+    KEY idx_roi_fission_parameter_version (version)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='ROI传播裂变系数匹配明细';
+
 CREATE TABLE IF NOT EXISTS roi_entity_snapshot (
     id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
     run_id VARCHAR(64) NOT NULL,
@@ -81,8 +110,14 @@ CREATE TABLE IF NOT EXISTS roi_entity_snapshot (
     adgroup_name VARCHAR(255) DEFAULT NULL,
     dynamic_creative_id BIGINT DEFAULT NULL,
     audience_name VARCHAR(255) DEFAULT NULL,
+    conversion_goal VARCHAR(255) DEFAULT NULL,
     partner_name VARCHAR(255) DEFAULT NULL,
     official_account_name VARCHAR(255) DEFAULT NULL,
+    fission_parameter_version VARCHAR(64) DEFAULT NULL,
+    fission_cohort_date VARCHAR(8) DEFAULT NULL,
+    fission_multiplier_vs_t0 DECIMAL(18,8) DEFAULT NULL,
+    fission_match_level VARCHAR(64) DEFAULT NULL,
+    fission_source VARCHAR(512) DEFAULT NULL,
     ad_age INT DEFAULT NULL,
     avg_first_uv DECIMAL(18,4) DEFAULT NULL,
     first_uv DECIMAL(18,4) DEFAULT NULL,
@@ -91,6 +126,10 @@ CREATE TABLE IF NOT EXISTS roi_entity_snapshot (
     cost DECIMAL(20,4) DEFAULT NULL,
     efficiency_revenue DECIMAL(20,4) DEFAULT NULL,
     fission_revenue DECIMAL(20,4) DEFAULT NULL,
+    actual_total_revenue DECIMAL(20,4) DEFAULT NULL,
+    actual_roi DECIMAL(18,8) DEFAULT NULL,
+    predicted_tail_revenue DECIMAL(20,4) DEFAULT NULL,
+    predicted_fission_revenue DECIMAL(20,4) DEFAULT NULL,
     total_revenue DECIMAL(20,4) DEFAULT NULL,
     roi DECIMAL(18,8) DEFAULT NULL,
     stop_threshold DECIMAL(18,8) DEFAULT NULL,

+ 37 - 0
examples/tencent_realtime_control/storage.py

@@ -97,6 +97,43 @@ def initialize_schema() -> None:
                         (operator_pause_mode, operator_resume_at)
                     """
                 )
+
+            roi_migrations = {
+                "roi_metric_run": {
+                    "fission_parameter_version": "VARCHAR(64) DEFAULT NULL",
+                    "fission_cohort_date": "DATE DEFAULT NULL",
+                },
+                "roi_entity_snapshot": {
+                    "conversion_goal": "VARCHAR(255) DEFAULT NULL",
+                    "fission_parameter_version": "VARCHAR(64) DEFAULT NULL",
+                    "fission_cohort_date": "VARCHAR(8) DEFAULT NULL",
+                    "fission_multiplier_vs_t0": "DECIMAL(18,8) DEFAULT NULL",
+                    "fission_match_level": "VARCHAR(64) DEFAULT NULL",
+                    "fission_source": "VARCHAR(512) DEFAULT NULL",
+                    "actual_total_revenue": "DECIMAL(20,4) DEFAULT NULL",
+                    "actual_roi": "DECIMAL(18,8) DEFAULT NULL",
+                    "predicted_tail_revenue": "DECIMAL(20,4) DEFAULT NULL",
+                    "predicted_fission_revenue": "DECIMAL(20,4) DEFAULT NULL",
+                },
+            }
+            for table_name, columns in roi_migrations.items():
+                cursor.execute(
+                    """
+                    SELECT COLUMN_NAME
+                    FROM information_schema.COLUMNS
+                    WHERE TABLE_SCHEMA=%s AND TABLE_NAME=%s
+                    """,
+                    (os.environ["DB_NAME"], table_name),
+                )
+                table_columns = {
+                    row["COLUMN_NAME"] for row in cursor.fetchall()
+                }
+                for column, definition in columns.items():
+                    if column not in table_columns:
+                        cursor.execute(
+                            f"ALTER TABLE {table_name} "
+                            f"ADD COLUMN {column} {definition}"
+                        )
     finally:
         connection.close()