# 预算约束下的智能出价调整系统 ## 概述 本系统实现了基于裂变效率的多维出价调整决策,用于腾讯广告小程序投放的预算控制。 **核心机制:** 通过调整 oCPM 出价(bid_amount)来控制消耗速度,而非设置日预算限制。 ## 业务背景 ### 场景 - 昨日消耗:173,765 元(216 个有效广告 + 79 个样本不足广告) - 今日预算:100,000 元 - **缩量幅度:-42%** ### 关键发现 1. **控制机制**:所有广告的 `day_amount=0`(不限日预算),实际通过调整 `bid_amount`(oCPM 出价)控制消耗 2. **决策维度**:多层次决策(账户层、广告层、创意层) 3. **数据来源**: - SQL 1:`creative_detail` 表 → 昨日效率数据(T0裂变系数、单用户成本) - SQL 2:`ad_put_tencent_ad` 表 → 当前广告状态(bid_amount、targeting、optimization_goal) - Python 合并:通过 ad_id 关联两个数据集 ## 核心指标 ### 效率分计算 ``` 效率分 = T0裂变系数 / 单用户成本 其中: - T0裂变系数 = 裂变0层回流数 / 首层小程序打开数 - 单用户成本 = cost / 首层小程序打开数 ``` ### 数据有效性 - **有效广告**:首层小程序打开数 >= 100 且有消耗 - **样本不足**:首层小程序打开数 < 100 或无消耗 ## 系统架构 ### 新增工具 #### 1. `get_ad_current_status` (data_query.py) 查询广告当前状态(出价、预算、定向等) ```python await get_ad_current_status( account_id=123456, ad_ids=[90397405754, 90397405755] # 可选 ) ``` **返回字段:** - `ad_id`, `ad_name`, `account_id` - `bid_amount`:当前出价(单位:分) - `day_amount`:日预算限制(0=不限) - `ad_status`:广告状态 - `optimization_goal`:转化目标 - `targeting`:定向配置(JSON) - `create_time`:创建时间 #### 2. `budget_calculate_from_data` (budget_calc.py) - 重构 基于昨日裂变效率数据计算今日出价调整方案 ```python result = await budget_calculate_from_data( account_id=123456, total_budget_yuan=100000, bizdate="20260406", # 默认 "yesterday" strategy="auto", # 自动判断缩量/扩量 tier1_ratio=0.15, # Tier 1 占比 tier2_ratio=0.35, # Tier 2 占比 min_bid_cents=10 # 最低出价(分) ) ``` **核心逻辑:** 1. 拉取昨日效率数据(`data_query`) 2. 拉取当前广告状态(`get_ad_current_status`) 3. 合并数据,按效率分分层 4. 计算出价调整方案 5. 输出详细调整说明 #### 3. `bid_adjustment_execute` (budget_calc.py) 执行出价调整方案 ```python result = await bid_adjustment_execute( adjustment_plan=plan["adjustment_plan"], account_id=123456 ) ``` **功能:** - 批量调整广告出价 - 暂停低效广告 - 返回执行结果统计 ## 决策算法 ### Step 1: 判断缩量/扩量场景 ```python scale_ratio = total_budget_yuan / yesterday_total if scale_ratio < 0.7: strategy = "aggressive_scale_down" # 大幅缩量(>30%) elif scale_ratio < 1.0: strategy = "moderate_scale_down" # 温和缩量 elif scale_ratio > 1.3: strategy = "scale_up" # 扩量 else: strategy = "maintain" # 基本持平 ``` ### Step 2: 按效率分分层 ```python # 按效率分降序排列 ads_sorted = sorted(ads_with_data, key=lambda x: x["efficiency"], reverse=True) # 动态分层 tier1_size = min(30, int(total_count * 0.15)) # Top 15%,最多30个 tier2_size = min(70, int(total_count * 0.35)) # 中部35%,最多70个 tier1 = ads_sorted[:tier1_size] # 核心广告 tier2 = ads_sorted[tier1_size:tier1_size+tier2_size] # 观察广告 tier3 = ads_sorted[tier1_size+tier2_size:] # 低效广告 ``` ### Step 3: 应用出价调整策略 #### 大幅缩量场景(aggressive_scale_down) | 层级 | 出价调整幅度 | 决策原则 | |------|-------------|---------| | Tier 1(核心) | -5% ~ 0% | 保护高效资产,轻微降价或不降 | | Tier 2(中部) | -10% ~ -15% | 适度降价 | | Tier 3(低效) | -20% ~ -30% | 大幅降价,低于最低出价则暂停 | | 样本不足 | - | 全部暂停 | #### 温和缩量场景(moderate_scale_down) | 层级 | 出价调整幅度 | |------|-------------| | Tier 1 | -3% | | Tier 2 | -8% | | Tier 3 | -15% | | 样本不足 | 暂停 | #### 扩量场景(scale_up) | 层级 | 出价调整幅度 | 决策原则 | |------|-------------|---------| | Tier 1 | +10% ~ +15% | 优先加码高效广告 | | Tier 2 | +5% ~ +10% | 适度增加 | | Tier 3 | 0% | 不调整 | | 样本不足 | - | 启动,出价设为中位数 | #### 持平场景(maintain) | 层级 | 出价调整幅度 | |------|-------------| | 所有层级 | ±3% 微调 | ### Step 4: 出价边界检查 ```python MIN_BID = 10 # 最低出价 0.10 元(10分) MAX_BID = 10000 # 最高出价 100 元(10000分) new_bid = int(current_bid * (1 + adjustment_ratio)) new_bid = max(MIN_BID, min(new_bid, MAX_BID)) if new_bid < MIN_BID: action = "pause" # 低于最低出价,暂停广告 ``` ## 使用流程 ### 1. 交互式使用 ```bash python examples/auto_put_ad/run.py > 账户 123456 今日预算 10 万,帮我调整出价 ``` **系统行为:** 1. Budget Agent 调用 `budget_calculate_from_data` 2. 输出分层出价调整方案 3. 等待用户确认 4. 用户确认后,调用 `bid_adjustment_execute` 5. 报告执行结果 ### 2. 程序化调用 ```python from examples.auto_put_ad.tools.budget_calc import ( budget_calculate_from_data, bid_adjustment_execute ) # 计算方案 result = await budget_calculate_from_data( account_id=123456, total_budget_yuan=100000 ) # 展示方案给用户 print(result.output) # 用户确认后执行 if user_confirms: exec_result = await bid_adjustment_execute( adjustment_plan=result.data["adjustment_plan"], account_id=123456 ) print(exec_result.output) ``` ## 输出示例 ``` 账户 123456 出价调整方案(缩量 42%,昨日消耗 173,765 元 → 今日预算 100,000 元) 策略:aggressive_scale_down(大幅缩量) 【Tier 1 核心广告 - 32个,保护资产,出价 -5%~0%】 ad_id: 90397405754 | 效率分: 8.93 | 昨日消耗: 3,100元 当前出价: 50分(0.50元) → 新出价: 48分(0.48元) | 动作: 调整 ad_id: 90397405755 | 效率分: 8.75 | 昨日消耗: 2,900元 当前出价: 52分(0.52元) → 新出价: 52分(0.52元) | 动作: 调整 【Tier 2 中部广告 - 76个,适度缩量,出价 -15%】 ad_id: 90397405800 | 效率分: 6.20 | 昨日消耗: 1,800元 当前出价: 45分(0.45元) → 新出价: 38分(0.38元) | 动作: 调整 【Tier 3 低效广告 - 108个,大幅削减,出价 -30%】 ad_id: 90397405900 | 效率分: 3.10 | 昨日消耗: 800元 当前出价: 40分(0.40元) → 新出价: 28分(0.28元) | 动作: 调整 【暂停广告 - 79个样本不足 + 15个出价过低】 ad_id: 90397406000 | 当前出价: 15分 → 低于最低出价 | 动作: 暂停 合计:预计消耗约 100,000 元(基于历史消耗和出价调整比例估算) ``` ## 测试 ### 运行单元测试 ```bash python3 examples/auto_put_ad/test_bid_adjustment_simple.py ``` **测试覆盖:** - ✓ 策略判断逻辑 - ✓ 分层逻辑 - ✓ 出价调整计算 - ✓ 数据合并 ### 测试结果示例 ``` ============================================================ 测试 1: 策略判断 ============================================================ ✓ 缩量 50%: scale_ratio=0.50 → aggressive_scale_down ✓ 缩量 25%: scale_ratio=0.75 → moderate_scale_down ✓ 持平: scale_ratio=1.00 → maintain ✓ 扩量 50%: scale_ratio=1.50 → scale_up ============================================================ 测试 2: 分层逻辑 ============================================================ 总广告数: 100 Tier 1 (Top 15%): 15 个,效率分范围 8.74 ~ 10.00 Tier 2 (中部 35%): 35 个,效率分范围 5.59 ~ 8.65 Tier 3 (尾部 50%): 50 个,效率分范围 1.09 ~ 5.50 ``` ## 技术要点 ### 1. 数据合并逻辑 ```python def _merge_efficiency_and_status(yesterday_data, current_status): """合并昨日效率数据和当前广告状态""" status_dict = {ad["ad_id"]: ad for ad in current_status} merged = [] for yd in yesterday_data: ad_id = yd["ad_id"] if ad_id in status_dict: merged.append({**yd, **status_dict[ad_id]}) return merged ``` ### 2. 出价计算 ```python # Tier 1: -5% ~ 0% for ad in tier1: max_efficiency = tier1[0].get("efficiency", 1.0) adj_ratio = -0.05 if ad.get("efficiency", 0) < max_efficiency * 0.8 else 0 new_bid = int(ad["bid_amount"] * (1 + adj_ratio)) new_bid = max(new_bid, MIN_BID) ``` ### 3. 批量执行 ```python for item in adjustment_plan: if item["action"] == "pause": await ad_update( account_id=account_id, adgroup_id=item["ad_id"], configured_status="AD_STATUS_SUSPEND" ) else: await ad_update( account_id=account_id, adgroup_id=item["ad_id"], bid_amount=item["new_bid"] ) ``` ## 配置参数 ### budget_calculate_from_data 参数 | 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | account_id | int | 必填 | 账户ID | | total_budget_yuan | float | 必填 | 今日总预算(元) | | bizdate | str | "yesterday" | 数据日期(YYYYMMDD) | | strategy | str | "auto" | 策略(auto/aggressive_scale_down/moderate_scale_down/scale_up/maintain) | | tier1_ratio | float | 0.15 | Tier 1 占比 | | tier2_ratio | float | 0.35 | Tier 2 占比 | | min_bid_cents | int | 10 | 最低出价(分) | ## 注意事项 ### 1. 调整节奏 - 单次调整后观察至少 2 小时再做下一次调整 - 避免频繁调整导致系统震荡 ### 2. 出价边界 - 最低出价:10分(0.10元) - 最高出价:10000分(100元) - 低于最低出价的广告直接暂停 ### 3. 样本量要求 - 有效数据门槛:首层小程序打开数 >= 100 - 样本不足的广告在缩量时暂停,扩量时启动 ### 4. API 限制 - 单账户 QPS 限制 10 - 批量操作单次最多 50 条 - 出价和预算单位:分(1元 = 100分) ## 文件清单 ### 核心文件 - `tools/data_query.py`:新增 `get_ad_current_status` 工具 - `tools/budget_calc.py`:重构 `budget_calculate_from_data`,新增 `bid_adjustment_execute` - `tools/ad_api.py`:复用 `ad_update` 更新出价 - `prompts/budget.prompt`:更新为出价调整流程 - `skills/budget_strategy.md`:更新为多维出价调整策略 ### 测试文件 - `test_bid_adjustment.py`:完整测试(需要 agent 框架) - `test_bid_adjustment_simple.py`:简化测试(独立运行) ### 文档 - `BID_ADJUSTMENT_README.md`:本文档 ## 未来扩展 ### 多维属性增强(可选) 根据广告的定向、人群、转化目标进行微调: ```python def parse_targeting(targeting_json): """解析定向配置,提取渠道、人群包类型""" channel = "unknown" if "SITE_SET_MOMENTS" in str(targeting_json): channel = "moments" # 朋友圈 elif "SITE_SET_WECHAT_OFFICIAL_ACCOUNT" in str(targeting_json): channel = "official_account" # 公众号 return channel # 在调整出价时考虑多维属性 for item in adjustment_plan: if item["action"] == "adjust": channel = parse_targeting(item.get("targeting")) optimization_goal = item.get("optimization_goal") # 高价值组合:朋友圈 + 关键页面浏览 if channel == "moments" and optimization_goal == "OPTIMIZATIONGOAL_PROMOTION_VIEW_KEY_PAGE": # 缩量时保护,调整幅度减半 item["adjustment_ratio"] *= 0.5 item["new_bid"] = int(item["current_bid"] * (1 + item["adjustment_ratio"])) ``` ## 版本历史 - **v1.0** (2026-04-07):初始实现 - 基于裂变效率的出价调整 - 多层级分层策略 - 自动缩量/扩量判断 - 批量执行功能 --- **维护者:** liulidong **最后更新:** 2026-04-07