From 012475ff7150c7fcfa8c6b4f2fd640d159b5c227 Mon Sep 17 00:00:00 2001 From: blueming3 <1016769622@qq.com> Date: Wed, 30 Sep 2026 20:35:31 +0800 Subject: [PATCH] docs(launch-watch): add 89109-1 and the launch-time lessons Sync from SW-ads-global: six benchmark accounts through 89109-1 (2026-09-30), playbook and watch.py thresholds updated to match. Co-Authored-By: Claude Opus 5.5 (1M context) --- skills/swads-minis-launch-watch/SKILL.md | 5 +- .../references/benchmarks.json | 398 ++++++++++-------- .../references/playbook.md | 23 +- .../swads-minis-launch-watch/scripts/watch.py | 15 +- 4 files changed, 238 insertions(+), 203 deletions(-) diff --git a/skills/swads-minis-launch-watch/SKILL.md b/skills/swads-minis-launch-watch/SKILL.md index 6e40969..d09775c 100644 --- a/skills/swads-minis-launch-watch/SKILL.md +++ b/skills/swads-minis-launch-watch/SKILL.md @@ -42,7 +42,7 @@ python3 /scripts/watch.py --account --start "YYYY-MM-DD HH:MM - 状态行里有「按天数据落后」:以 TikTok 小时数为准,不要按旧数下结论,更不要报停量。 - `‼ 建议暂停关户` 开头的:放在最前面,说清是哪条健康度规则、现在亏多少,问运营关不关。 - 运营问「怎么办 / 哪些该留」:按最近 30 分钟每条广告的 ROAS 分成「留」(≥ 1)和「关」(< 0.8 且消耗 ≥ 10), - 并按当前 ROAS 算出回到 0.9、回本各需要再花多少钱、大概几点,超过 18 点的直接说不现实。 + 并按当前 ROAS 算出回到 0.9、回本各需要再花多少钱、大概几点;超过这个户「起量后 6 小时」的直接说不现实。 ## 写平台:只在运营点名后 @@ -52,7 +52,8 @@ python3 /scripts/watch.py --account --start "YYYY-MM-DD HH:MM | 关这个计划 / 关户 | `campaign_set_delivery(campaign_id, status="stopped", external_account_id)`,关户就逐个关所有在投计划 | `account_sync` 后读回计划状态 | | 加预算到 N | `campaign_set_budget(campaign_id, daily_budget=N, external_account_id)` | 看 `changed`、`previous_daily_budget` | -- 加预算每次都单独确认金额;17 点后要加,先把 playbook 里「18 点后加预算没赚到」告诉运营。 +- 加预算每次都单独确认金额;起量已满 5 小时还要加,先把 playbook 里「起量满 5 小时后加预算没赚到」告诉运营。 +- 所有阶段都按这个户自己的开投、起量时间顺延,不套别的户的钟点(晚开的户不能按 18 点判衰退)。 - 批量关(「亏的都关」)先列出清单(广告名、id、消耗、ROAS)让运营点「好」。 - 每次写平台后,在工作目录的 `events.jsonl` 追加一行(`kind` 用 关广告 / 关计划 / 加预算 / 停投 / 方案), 写清是谁确认的、当时的数。运营定下的止损或收尾方案也记一行 `方案`。 diff --git a/skills/swads-minis-launch-watch/references/benchmarks.json b/skills/swads-minis-launch-watch/references/benchmarks.json index 2a6767d..34d0e42 100644 --- a/skills/swads-minis-launch-watch/references/benchmarks.json +++ b/skills/swads-minis-launch-watch/references/benchmarks.json @@ -1,187 +1,213 @@ { - "note": "每小时消耗与 D0 回收(USD),账户报表时区。新户关户后把它追加进来:outcome 写结果,lesson 写一句教训。", - "accounts": [ - { - "short": "88775-5", - "date": "2026-09-27", - "kind": "good", - "enabled": "10:55", - "outcome": "消耗 1676.64 / 回收 2095.31 / ROAS 1.25,赚 419,未被罚,约 21:00 手动关", - "lesson": "起量第一个整点 1.29;每计划 1 条主力 CTR ≥ 23%;前期预警都自己回升;16-17 点最赚,18 点起衰退", - "hourly": { - "11": [ - 0.68, - 0.38 - ], - "12": [ - 82.44, - 106.38 - ], - "13": [ - 336.33, - 453.4 - ], - "14": [ - 365.39, - 396.63 - ], - "15": [ - 184.6, - 242.2 - ], - "16": [ - 108.13, - 200.48 - ], - "17": [ - 191.26, - 289.46 - ], - "18": [ - 212.82, - 211.89 - ], - "19": [ - 106.92, - 118.26 - ], - "20": [ - 78.03, - 73.49 - ], - "21": [ - 7.05, - 4.93 - ], - "22": [ - 2.08, - 2.9 - ], - "23": [ - 0.91, - 0.7 - ] - } - }, - { - "short": "88794-9", - "date": "2026-09-29", - "kind": "bad", - "enabled": "10:08", - "outcome": "消耗 218.97 / 回收 201.70 / ROAS 0.92,亏 17,未被罚,19:00 手动关", - "lesson": "起量就 0.86;CTR 全 20%+ 仍亏;按 ROAS 关 5 条后该段 1.12;跨 18 点冲回本反而回吐", - "hourly": { - "11": [ - 2.43, - 1.88 - ], - "12": [ - 85.49, - 73.76 - ], - "13": [ - 81.31, - 71.89 - ], - "14": [ - 7.15, - 10.63 - ], - "15": [ - 7.89, - 10.8 - ], - "16": [ - 30.43, - 28.81 - ], - "17": [ - 3.55, - 3.63 - ], - "18": [ - 0.84, - 0.47 - ], - "19": [ - 0.01, - 0.0 - ] - } - }, - { - "short": "88775-9", - "date": "2026-09-26", - "kind": "punished", - "enabled": "13:37(重开)", - "outcome": "消耗 280.69 / ROAS 1.84,约 15:00 ADVERTISER_ACCOUNT_PUNISH", - "lesson": "与剧无关猎奇图 + 性暗示;前一天开投约 4 小时被整体停用未查原因就重开;ROAS 高也被罚", - "hourly": { - "13": [ - 0.06, - 1.03 - ], - "14": [ - 280.63, - 522.34 - ] - } - }, - { - "short": "88775-7", - "date": "2026-09-26", - "kind": "punished", - "enabled": "约 17:00", - "outcome": "消耗 1041.71 / ROAS 0.79,约 21:27 ADVERTISER_ACCOUNT_PUNISH", - "lesson": "晚上开投撞衰退时段;20 点一小时花 644 仍在亏;猎奇素材且检测 502 无人检查", - "hourly": { - "17": [ - 0.06, - 0.0 - ], - "18": [ - 85.11, - 74.36 - ], - "19": [ - 204.46, - 192.82 - ], - "20": [ - 644.45, - 486.49 - ], - "21": [ - 107.63, - 72.95 - ] - } - }, - { - "short": "88776-1", - "date": "2026-09-30", - "kind": "bad", - "enabled": "09:59", - "outcome": "停时消耗 38.11 / 回收 24.93 / ROAS 0.65,亏约 13,未被罚,13:13 按运营「亏损不超 20」全停", - "lesson": "20 张与剧无关猎奇图;CPM 约 0.1、CTR 20-30% 但回收差,4 部剧全在 0.5-0.75;起量第一个整点 0.64,SilverWing 在本户也亏(前两户 >1.1)", - "hourly": { - "10": [ - 0.04, - 0.0 - ], - "11": [ - 8.23, - 4.88 - ], - "12": [ - 25.11, - 16.07 - ], - "13": [ - 4.73, - 3.98 - ] - } - } - ] -} \ No newline at end of file + "note": "每小时消耗与 D0 回收(USD),账户报表时区。新户关户后把它追加进来:outcome 写结果,lesson 写一句教训。", + "accounts": [ + { + "short": "88775-5", + "date": "2026-09-27", + "kind": "good", + "enabled": "10:55", + "outcome": "消耗 1676.64 / 回收 2095.31 / ROAS 1.25,赚 419,未被罚,约 21:00 手动关", + "lesson": "起量第一个整点 1.29;每计划 1 条主力 CTR ≥ 23%;前期预警都自己回升;16-17 点最赚,18 点起衰退", + "hourly": { + "11": [ + 0.68, + 0.38 + ], + "12": [ + 82.44, + 106.38 + ], + "13": [ + 336.33, + 453.4 + ], + "14": [ + 365.39, + 396.63 + ], + "15": [ + 184.6, + 242.2 + ], + "16": [ + 108.13, + 200.48 + ], + "17": [ + 191.26, + 289.46 + ], + "18": [ + 212.82, + 211.89 + ], + "19": [ + 106.92, + 118.26 + ], + "20": [ + 78.03, + 73.49 + ], + "21": [ + 7.05, + 4.93 + ], + "22": [ + 2.08, + 2.9 + ], + "23": [ + 0.91, + 0.7 + ] + } + }, + { + "short": "88794-9", + "date": "2026-09-29", + "kind": "bad", + "enabled": "10:08", + "outcome": "消耗 218.97 / 回收 201.70 / ROAS 0.92,亏 17,未被罚,19:00 手动关", + "lesson": "起量就 0.86;CTR 全 20%+ 仍亏;按 ROAS 关 5 条后该段 1.12;跨 18 点冲回本反而回吐", + "hourly": { + "11": [ + 2.43, + 1.88 + ], + "12": [ + 85.49, + 73.76 + ], + "13": [ + 81.31, + 71.89 + ], + "14": [ + 7.15, + 10.63 + ], + "15": [ + 7.89, + 10.8 + ], + "16": [ + 30.43, + 28.81 + ], + "17": [ + 3.55, + 3.63 + ], + "18": [ + 0.84, + 0.47 + ], + "19": [ + 0.01, + 0.0 + ] + } + }, + { + "short": "88775-9", + "date": "2026-09-26", + "kind": "punished", + "enabled": "13:37(重开)", + "outcome": "消耗 280.69 / ROAS 1.84,约 15:00 ADVERTISER_ACCOUNT_PUNISH", + "lesson": "与剧无关猎奇图 + 性暗示;前一天开投约 4 小时被整体停用未查原因就重开;ROAS 高也被罚", + "hourly": { + "13": [ + 0.06, + 1.03 + ], + "14": [ + 280.63, + 522.34 + ] + } + }, + { + "short": "88775-7", + "date": "2026-09-26", + "kind": "punished", + "enabled": "约 17:00", + "outcome": "消耗 1041.71 / ROAS 0.79,约 21:27 ADVERTISER_ACCOUNT_PUNISH", + "lesson": "晚上开投撞衰退时段;20 点一小时花 644 仍在亏;猎奇素材且检测 502 无人检查", + "hourly": { + "17": [ + 0.06, + 0.0 + ], + "18": [ + 85.11, + 74.36 + ], + "19": [ + 204.46, + 192.82 + ], + "20": [ + 644.45, + 486.49 + ], + "21": [ + 107.63, + 72.95 + ] + } + }, + { + "short": "88776-1", + "date": "2026-09-30", + "kind": "bad", + "enabled": "09:59", + "outcome": "停时消耗 38.11 / 回收 24.93 / ROAS 0.65,亏约 13,未被罚,13:13 按运营「亏损不超 20」全停", + "lesson": "20 张与剧无关猎奇图;CPM 约 0.1、CTR 20-30% 但回收差,4 部剧全在 0.5-0.75;起量第一个整点 0.64,SilverWing 在本户也亏(前两户 >1.1)", + "hourly": { + "10": [ + 0.04, + 0.0 + ], + "11": [ + 8.23, + 4.88 + ], + "12": [ + 25.11, + 16.07 + ], + "13": [ + 4.73, + 3.98 + ] + } + }, + { + "short": "89109-1", + "date": "2026-09-30", + "kind": "bad", + "enabled": "15:28", + "outcome": "停时消耗 81.02 / 回收 47.52 / ROAS 0.59,亏约 33.5,未被罚,19:14 运营全停", + "lesson": "下午 15:28 开投,约 16:12 过审,17 点才有曝光,18 点起量时已进衰退时段:18 点一小时花 68.85 ROAS 0.59;30 张与剧无关猎奇图,10 部剧只有 5 部有量且全 <0.7;单条 Ad 吃掉一半消耗(CTR 26% ROAS 0.67);关户预警 18:42 起连报,运营 19:14 才回,多亏约 15", + "hourly": { + "16": [ + 0.0, + 0.0 + ], + "17": [ + 5.11, + 2.51 + ], + "18": [ + 68.85, + 40.56 + ], + "19": [ + 7.06, + 4.45 + ] + } + } + ] +} diff --git a/skills/swads-minis-launch-watch/references/playbook.md b/skills/swads-minis-launch-watch/references/playbook.md index 5aeb3cb..6f2d2c1 100644 --- a/skills/swads-minis-launch-watch/references/playbook.md +++ b/skills/swads-minis-launch-watch/references/playbook.md @@ -1,7 +1,7 @@ # 判断点手册 来自 2026-09-25 至 09-30 五个 WISH 图文户(`benchmarks.json`)。ROAS 一律是 D0 广告变现 ÷ 消耗, -时间一律是账户报表时区。`scripts/watch.py` 里的阈值和这里一一对应,改一边就改另一边。 +时间一律是账户报表时区。**阶段一律按这个户自己的开投、起量时间顺延,不按钟点**(运营 2026-09-30:晚开的户不能套上午户的 18 点)。钟点效应还没被证实或排除,见下方「待验证」。`scripts/watch.py` 里的阈值和这里一一对应,改一边就改另一边。 样本只有 5 户,出现反例就改阈值并在 `benchmarks.json` 追加那个户。 ## 六句话 @@ -10,8 +10,8 @@ 2. 起量后第一个整点看好坏:≥ 1.2 好户,< 0.9 差户(88775-5 是 1.29,88794-9 是 0.86);< 0.7 直接提示可以提前止损(88776-1 是 0.64)。 3. 关广告看 ROAS,不看 CTR(88794-9 的 20 条广告 CTR 全在 20% 以上,照样亏)。 4. 前 3 小时的小样本预警多半自己回来;单条消耗 < 5 美元不下结论。 -5. 18 点是分界线,两个健康户都是 18 点后每小时 ROAS 掉到 1 附近。 -6. 不跨 18 点冲回本,不在 18 点后加预算。 +5. 阶段按这个户自己的起量时间顺延,不按钟点:两个健康户都是起量后约 6 小时开始衰退(12 点起量、18 点衰退),晚开的户衰退也跟着往后推。 +6. 不在起量满 6 小时后冲回本,不在起量满 5 小时后加预算。 ## 阶段 @@ -20,8 +20,8 @@ | 开投前 | 建计划当天 | 素材过红线;核对账户 id/小程序/身份/剧集页;视频转 1080×1920;推送后先不启用,核对表确认后再开 | 不用被罚户的素材,不改图「去重」 | | 等量期 | 开投后 0–1.5h | 只看过审、曝光、有没有被整体停用;满 2h 仍 0 消耗再同步查审核 | 不关、不加 | | 判断期 | 起量后 1–3h | 看起量后第一个整点 ROAS;找每个计划的主力广告(通常 1 条吃掉 70–90% 消耗) | 小样本不关;后台和系统数对不上时不关 | -| 放量期 | 开投 3–7h,约 13–18 点 | 盯主力的 ROAS 和 CTR;好户 17 点前可以加预算;差户进入止损 | 不因为 CTR 高就留住亏损广告 | -| 收尾期 | 18 点后或开投满 7–8h | 最近 30 分钟 ROAS < 1 就收 | 不加预算,不冲回本 | +| 放量期 | 起量后 3–6h | 盯主力的 ROAS 和 CTR;好户起量后 5 小时内可以加预算;差户进入止损 | 不因为 CTR 高就留住亏损广告 | +| 收尾期 | 起量后满 6h,或开投满 8h | 最近 30 分钟 ROAS < 1 就收 | 不加预算,不冲回本 | ## 判断点速查 @@ -37,8 +37,8 @@ | 关计划 | 峰值 ROAS > 1 后,连续两个 10 分钟窗口回收 < 消耗 | 别把早上赚的吐回去 | | 等一手 | 前 3h 计划 ROAS < 0.8 但单条消耗 < 5 美元 | 88775-5 前期几次预警全部回升 | | 等一手 | 后台 ROAS 与系统数对不上,或按天数据没更新 | D0 回收晚 10–20 分钟补齐(0.48 → 0.93) | -| 加预算 | 预算用到 80%,ROAS > 1.3,17 点前 | 18 点后加的 200 美元只跑出约 1.0 | -| 收尾 | 18 点后或开投满 8h,最近 30 分钟 ROAS < 1 | 两个健康户都在 18 点起衰退 | +| 加预算 | 预算用到 80%,ROAS > 1.3,起量后 5 小时内 | 88775-5 起量后约 6.7 小时加的 200 美元只跑出约 1.0 | +| 收尾 | 起量后满 6h 或开投满 8h,最近 30 分钟 ROAS < 1 | 两个健康户都在起量后约 6 小时开始衰退 | ## 做了什么,ROAS 会回来 @@ -47,8 +47,8 @@ | 按 ROAS 关掉亏损主力 | 88794-9:下一段 ROAS 0.76 → 1.12,亏损 24.4 → 16 | 用,最有效的止损 | | 等回收补齐 | SilverWing Ad 1:0.48 → 10 分钟后 0.93 | 用,小样本和数据延迟时 | | 好户前期预警不关 | 88775-5 的几个计划从 0.5–0.7 回到全天 1.1–1.3 | 用 | -| 18 点后加预算 | 88775-5:加完两段 1.16、0.84,基本保本 | 不用 | -| 跨 18 点冲回本 | 88794-9:亏 15.99 → 17.27 | 不用 | +| 起量满 5 小时后加预算 | 88775-5:加完两段 1.16、0.84,基本保本 | 不用 | +| 起量满 6 小时后冲回本 | 88794-9:亏 15.99 → 17.27 | 不用 | | 换户继续用被罚户的素材 | 88775-9 第一天整体停用,第二天处罚 | 不用,也不改图规避 | ## 素材红线 @@ -57,3 +57,8 @@ 价签商品、钱和奖品);明星、名人、政要的脸,包括恶搞表情包;别人社交帖的整屏截图(带点赞图标或水印); 烟酒、危险行为、儿童;被罚户用过的素材。系统检测只查性内容和诈骗诱饵图,检测返回 502 等于没检查。 优先用剧本身的画面:剧照、剧集截图、剧集视频片段。 + +## 待验证 + +- **衰退跟钟点走,还是跟生命周期走?** 两个上午户都是 12 点起量、18 点衰退,分不开。晚开户(89109-2,15:48 开)按生命周期顺延来判;它哪个时点开始衰退,能区分这两种解释。 +- **开投时间本身的影响**:上午开 vs 下午开,样本见运营记忆里的开投时间假设。 diff --git a/skills/swads-minis-launch-watch/scripts/watch.py b/skills/swads-minis-launch-watch/scripts/watch.py index 25bfdc5..7dc5da6 100644 --- a/skills/swads-minis-launch-watch/scripts/watch.py +++ b/skills/swads-minis-launch-watch/scripts/watch.py @@ -203,6 +203,10 @@ if prev and prev.get("fresh") != fresh_iso and prev.get("day") == today: alerts.append(f"先赚后亏 {short(name)}({camps[name]['external_campaign_id']}):最近 10 分钟 {ds:.2f}/{dr:.2f},连续 {streak[name]} 个窗口亏;今天 {sp:.2f} ROAS {rv / sp:.2f},峰值 {peak[name]:.2f} → 建议关这个计划") st["snap"] = {"fresh": fresh_iso, "day": today, "camps": {n: v for n, v in agg.items()}} +# ---- lifecycle clock: stages follow this account's own ramp, not the wall clock (operator 2026-09-30) ---- +ramp = [h for h in sorted(hsum) if hsum[h][0] >= 20 and h < now.hour] +since_ramp = (now.hour + now.minute / 60 - ramp[0]) if ramp else None # hours since the first >= 20 USD hour began + # ---- rule: budget 80% / 95% while profitable; say whether adding still makes sense ---- for name, (sp, rv) in agg.items(): c = camps[name]; bud = f(c.get("budget")); ro = rv / sp if sp else 0.0 @@ -212,13 +216,12 @@ for name, (sp, rv) in agg.items(): key = f"budget{pct}|{c['external_campaign_id']}|{bud}" if key not in rep: rep[key] = {"sp": sp, "ro": ro} - late = now.hour >= 17 - hint = "已过 17 点,手册建议不加" if late else ("ROAS > 1.3,可以加" if ro > 1.3 else "ROAS 不到 1.3,加不加看你") + late = since_ramp is not None and since_ramp >= 5 + hint = "起量已满 5 小时,手册建议不加" if late else ("ROAS > 1.3,可以加" if ro > 1.3 else "ROAS 不到 1.3,加不加看你") alerts.append(f"预算快用完 {short(name)}:今天 {sp:.0f}/{bud:.0f}({sp / bud * 100:.0f}%)ROAS {ro:.2f} → {hint}") break # ---- judgement: first full hours after the account starts spending ---- -ramp = [h for h in sorted(hsum) if hsum[h][0] >= 20 and h < now.hour] if ramp and "judge" not in lc: h0 = ramp[0]; r0 = hsum[h0][1] / hsum[h0][0] verdict = "好户" if r0 >= 1.2 else ("观察" if r0 >= 0.9 else "差户信号") @@ -274,8 +277,8 @@ if hours_in >= 4 and tsp >= 50 and cum < 0.90 and w30 and w30[2] < 0.90: H.append(f"开投 {hours_in:.1f} 小时累计 ROAS {cum:.2f} < 0.90,最近 30 分钟 {w30[2]:.2f} 也 < 0.90") if w30 and w30[0] >= 30 and w30[2] < 0.80: H.append(f"最近 30 分钟放量 {w30[0]:.2f} USD 但 ROAS 只有 {w30[2]:.2f} < 0.80") -if (now.hour >= 18 or hours_in >= 8) and w30 and w30[0] >= 3 and w30[2] < 1.0: - H.append(f"进入收尾期(18 点后或开投满 8 小时),最近 30 分钟 ROAS {w30[2]:.2f} < 1") +if ((since_ramp is not None and since_ramp >= 6) or hours_in >= 8) and w30 and w30[0] >= 3 and w30[2] < 1.0: + H.append(f"进入收尾期(起量后满 6 小时或开投满 8 小时),最近 30 分钟 ROAS {w30[2]:.2f} < 1") if tsp >= 50 and cum >= 1.0 and lc.get("was_below_1") and "breakeven" not in lc: lc["breakeven"] = now.strftime("%H:%M") H.append(f"累计 ROAS 回到 1 以上({cum:.2f}),可以考虑收尾锁住") @@ -345,7 +348,7 @@ except (OSError, ValueError, KeyError): print("\n".join(alerts) if alerts else "一轮无异常") top = sorted(agg.items(), key=lambda kv: -kv[1][0])[:3] -stage = "等量期" if not lc.get("had_spend") and hours_in < 2 else ("判断期" if hours_in < 3 else ("放量期" if now.hour < 18 and hours_in < 8 else "收尾期")) +stage = ("等量期" if not ramp else ("判断期" if since_ramp < 3 else ("放量期" if since_ramp < 6 and hours_in < 8 else "收尾期"))) if hours_in < 8 else "收尾期" w30t = f";最近 30 分钟 {w30[0]:.2f}/{w30[1]:.2f} ROAS {w30[2]:.2f}" if w30 else "" lag = f";按天数据落后,TikTok 小时数合计 {h_total:.2f}" if h_total - tsp > 2 else "" print(f"[{stage} {hours_in:.1f}h|{len(camps)} 个在投计划 今天 {tsp:.2f}/{trv:.2f} ROAS {cum:.2f}{w30t};"