|
@@ -360,9 +360,9 @@ async def get_ads_for_review(
|
|
|
|
|
|
|
|
# 全体 ROI 分布
|
|
# 全体 ROI 分布
|
|
|
roi_series = df["动态ROI_7日均值"].dropna()
|
|
roi_series = df["动态ROI_7日均值"].dropna()
|
|
|
- roi_mean = float(roi_series.median()) if len(roi_series) > 0 else 0.0
|
|
|
|
|
|
|
+ # channel_roi_p50 = 渠道P50(全体广告"动态ROI 7日均值"的中位数),决策基准
|
|
|
|
|
+ channel_roi_p50 = float(roi_series.median()) if len(roi_series) > 0 else 0.0
|
|
|
roi_p25 = float(roi_series.quantile(0.25)) if len(roi_series) > 0 else 0.0
|
|
roi_p25 = float(roi_series.quantile(0.25)) if len(roi_series) > 0 else 0.0
|
|
|
- roi_p50 = float(roi_series.quantile(0.50)) if len(roi_series) > 0 else 0.0
|
|
|
|
|
roi_p75 = float(roi_series.quantile(0.75)) if len(roi_series) > 0 else 0.0
|
|
roi_p75 = float(roi_series.quantile(0.75)) if len(roi_series) > 0 else 0.0
|
|
|
roi_p90 = float(roi_series.quantile(0.90)) if len(roi_series) > 0 else 0.0
|
|
roi_p90 = float(roi_series.quantile(0.90)) if len(roi_series) > 0 else 0.0
|
|
|
|
|
|
|
@@ -377,7 +377,7 @@ async def get_ads_for_review(
|
|
|
|
|
|
|
|
for _, row in df.iterrows():
|
|
for _, row in df.iterrows():
|
|
|
cost_7d_avg = float(row.get("cost_7d_avg", 0) or 0)
|
|
cost_7d_avg = float(row.get("cost_7d_avg", 0) or 0)
|
|
|
- f_roi = row.get("动态ROI_7日均值")
|
|
|
|
|
|
|
+ dynamic_roi_7d = row.get("动态ROI_7日均值")
|
|
|
ad_age = row.get("ad_age_days")
|
|
ad_age = row.get("ad_age_days")
|
|
|
bid_inc = bool(row.get("bid_increased_7d", False))
|
|
bid_inc = bool(row.get("bid_increased_7d", False))
|
|
|
creative_chg = bool(row.get("creative_changed_7d", False))
|
|
creative_chg = bool(row.get("creative_changed_7d", False))
|
|
@@ -422,8 +422,8 @@ async def get_ads_for_review(
|
|
|
# 待优化评估:ROI 偏低 或 衰退信号 或 出价调整候选(需要智能判断)
|
|
# 待优化评估:ROI 偏低 或 衰退信号 或 出价调整候选(需要智能判断)
|
|
|
# ★ 关停条件对齐投手经验2.4:需要昨日消耗≥300 且 广告年龄>3天
|
|
# ★ 关停条件对齐投手经验2.4:需要昨日消耗≥300 且 广告年龄>3天
|
|
|
roi_low = (
|
|
roi_low = (
|
|
|
- (not pd.isna(f_roi))
|
|
|
|
|
- and (f_roi < roi_mean * roi_review_factor)
|
|
|
|
|
|
|
+ (not pd.isna(dynamic_roi_7d))
|
|
|
|
|
+ and (dynamic_roi_7d < channel_roi_p50 * roi_review_factor)
|
|
|
and yesterday_cost >= ROI_LOW_MIN_YESTERDAY_COST # 昨日消耗≥300
|
|
and yesterday_cost >= ROI_LOW_MIN_YESTERDAY_COST # 昨日消耗≥300
|
|
|
and (ad_age is not None and ad_age > COLD_START_DAYS) # 广告年龄>3天
|
|
and (ad_age is not None and ad_age > COLD_START_DAYS) # 广告年龄>3天
|
|
|
)
|
|
)
|
|
@@ -468,8 +468,8 @@ async def get_ads_for_review(
|
|
|
# 3-7天 + 后端数据好 + 均值消耗 <1000 + ROI>渠道均值5% + 裂变>同类10% + CTR 正常 → 提价 5-10%
|
|
# 3-7天 + 后端数据好 + 均值消耗 <1000 + ROI>渠道均值5% + 裂变>同类10% + CTR 正常 → 提价 5-10%
|
|
|
# 含义:"数据已证明这条广告优质,提价拉更多量"
|
|
# 含义:"数据已证明这条广告优质,提价拉更多量"
|
|
|
bid_up_candidate_b = (
|
|
bid_up_candidate_b = (
|
|
|
- (not pd.isna(f_roi))
|
|
|
|
|
- and f_roi > roi_mean * params["BID_UP_ROI_FACTOR"] # ROI 高于渠道均值5%
|
|
|
|
|
|
|
+ (not pd.isna(dynamic_roi_7d))
|
|
|
|
|
+ and dynamic_roi_7d > channel_roi_p50 * params["BID_UP_ROI_FACTOR"] # ROI 高于渠道均值5%
|
|
|
and cost_7d_avg < BID_UP_MAX_SPEND # 消耗<1000(固定阈值)
|
|
and cost_7d_avg < BID_UP_MAX_SPEND # 消耗<1000(固定阈值)
|
|
|
and bid_amount > 0
|
|
and bid_amount > 0
|
|
|
and (ad_age is not None and ad_age <= EARLY_GROWTH_DAYS) # 仅4-7天可提价(≤3天已被冷启动排除)
|
|
and (ad_age is not None and ad_age <= EARLY_GROWTH_DAYS) # 仅4-7天可提价(≤3天已被冷启动排除)
|
|
@@ -484,9 +484,9 @@ async def get_ads_for_review(
|
|
|
|
|
|
|
|
# 降价:ROI低于渠道均值10% + 裂变低于同类10% + 消耗≥500元/天
|
|
# 降价:ROI低于渠道均值10% + 裂变低于同类10% + 消耗≥500元/天
|
|
|
bid_down_candidate = (
|
|
bid_down_candidate = (
|
|
|
- (not pd.isna(f_roi))
|
|
|
|
|
- and f_roi < roi_mean * params["BID_DOWN_ROI_FACTOR"] # ROI低于渠道均值10%
|
|
|
|
|
- and f_roi >= roi_mean * params["ROI_LOW_FACTOR"] # 但未达关停线
|
|
|
|
|
|
|
+ (not pd.isna(dynamic_roi_7d))
|
|
|
|
|
+ and dynamic_roi_7d < channel_roi_p50 * params["BID_DOWN_ROI_FACTOR"] # ROI低于渠道均值10%
|
|
|
|
|
+ and dynamic_roi_7d >= channel_roi_p50 * params["ROI_LOW_FACTOR"] # 但未达关停线
|
|
|
and cost_7d_avg >= BID_DOWN_MIN_SPEND # 消耗≥500元/天
|
|
and cost_7d_avg >= BID_DOWN_MIN_SPEND # 消耗≥500元/天
|
|
|
and bid_amount > 0
|
|
and bid_amount > 0
|
|
|
and (tier_fission_mean is None or ad_fission is None # 裂变低于同类均值10%(无数据时跳过)
|
|
and (tier_fission_mean is None or ad_fission is None # 裂变低于同类均值10%(无数据时跳过)
|
|
@@ -497,8 +497,8 @@ async def get_ads_for_review(
|
|
|
persistent_low_roi = False
|
|
persistent_low_roi = False
|
|
|
if (
|
|
if (
|
|
|
not roi_low # 当前未达关停线(ROI在0.75~0.90之间)
|
|
not roi_low # 当前未达关停线(ROI在0.75~0.90之间)
|
|
|
- and (not pd.isna(f_roi))
|
|
|
|
|
- and f_roi < roi_mean * params["BID_DOWN_ROI_FACTOR"] # ROI仍低于渠道均值10%
|
|
|
|
|
|
|
+ and (not pd.isna(dynamic_roi_7d))
|
|
|
|
|
+ and dynamic_roi_7d < channel_roi_p50 * params["BID_DOWN_ROI_FACTOR"] # ROI仍低于渠道均值10%
|
|
|
and yesterday_cost >= ROI_LOW_MIN_YESTERDAY_COST # 昨日消耗≥300
|
|
and yesterday_cost >= ROI_LOW_MIN_YESTERDAY_COST # 昨日消耗≥300
|
|
|
and (ad_age is not None and ad_age > COLD_START_DAYS) # 年龄>3天
|
|
and (ad_age is not None and ad_age > COLD_START_DAYS) # 年龄>3天
|
|
|
):
|
|
):
|
|
@@ -511,7 +511,7 @@ async def get_ads_for_review(
|
|
|
roi_low = True # 升级!
|
|
roi_low = True # 升级!
|
|
|
logger.info(
|
|
logger.info(
|
|
|
f"广告 {row['ad_id']} 降价后{days_since_bd}天ROI仍低"
|
|
f"广告 {row['ad_id']} 降价后{days_since_bd}天ROI仍低"
|
|
|
- f"({f_roi:.4f}<{roi_mean * params['BID_DOWN_ROI_FACTOR']:.4f}),升级为关停候选"
|
|
|
|
|
|
|
+ f"({dynamic_roi_7d:.4f}<{channel_roi_p50 * params['BID_DOWN_ROI_FACTOR']:.4f}),升级为关停候选"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
# 扩量候选:成熟期 + 消耗稳定 + 高消耗 + ROI正常(基于决策树)
|
|
# 扩量候选:成熟期 + 消耗稳定 + 高消耗 + ROI正常(基于决策树)
|
|
@@ -520,8 +520,8 @@ async def get_ads_for_review(
|
|
|
and ad_age > 7 # 成熟期(>7天)
|
|
and ad_age > 7 # 成熟期(>7天)
|
|
|
and stable_days >= 7 # 消耗稳定(≥7天)
|
|
and stable_days >= 7 # 消耗稳定(≥7天)
|
|
|
and cost_7d_avg > 1000 # 高消耗(>1000元/天)
|
|
and cost_7d_avg > 1000 # 高消耗(>1000元/天)
|
|
|
- and (not pd.isna(f_roi))
|
|
|
|
|
- and f_roi >= roi_mean * 0.9 # ROI正常(≥均值的90%)
|
|
|
|
|
|
|
+ and (not pd.isna(dynamic_roi_7d))
|
|
|
|
|
+ and dynamic_roi_7d >= channel_roi_p50 * 0.9 # ROI正常(≥均值的90%)
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
# ===== 消耗稳定性前置门控(决策树:成熟期+不稳定→observe)=====
|
|
# ===== 消耗稳定性前置门控(决策树:成熟期+不稳定→observe)=====
|
|
@@ -591,7 +591,7 @@ async def get_ads_for_review(
|
|
|
ad_dict = {
|
|
ad_dict = {
|
|
|
"ad_id": int(row["ad_id"]),
|
|
"ad_id": int(row["ad_id"]),
|
|
|
"ad_name": str(row.get("ad_name", "")),
|
|
"ad_name": str(row.get("ad_name", "")),
|
|
|
- "动态ROI_7日均值": round(float(f_roi), 4) if not pd.isna(f_roi) else None,
|
|
|
|
|
|
|
+ "动态ROI_7日均值": round(float(dynamic_roi_7d), 4) if not pd.isna(dynamic_roi_7d) else None,
|
|
|
"cost_7d_avg": round(cost_7d_avg, 2),
|
|
"cost_7d_avg": round(cost_7d_avg, 2),
|
|
|
"cost_7d_total": round(float(row.get("cost_7d_total", 0) or 0), 2),
|
|
"cost_7d_total": round(float(row.get("cost_7d_total", 0) or 0), 2),
|
|
|
"ad_age_days": int(ad_age) if ad_age is not None else None,
|
|
"ad_age_days": int(ad_age) if ad_age is not None else None,
|
|
@@ -615,7 +615,7 @@ async def get_ads_for_review(
|
|
|
tier = ad_dict.get("audience_tier", "default")
|
|
tier = ad_dict.get("audience_tier", "default")
|
|
|
tier_stats = by_tier_stats.get(tier, {})
|
|
tier_stats = by_tier_stats.get(tier, {})
|
|
|
|
|
|
|
|
- # ROI 对比走"渠道整体"(roi_mean),故此处不注入 tier_roi_* 字段
|
|
|
|
|
|
|
+ # ROI 对比走"渠道整体"(channel_roi_p50),故此处不注入 tier_roi_* 字段
|
|
|
|
|
|
|
|
# 裂变率同类对比数据(裂变必须对比同人群)
|
|
# 裂变率同类对比数据(裂变必须对比同人群)
|
|
|
ad_dict["tier_fission_mean"] = tier_stats.get("fission_mean")
|
|
ad_dict["tier_fission_mean"] = tier_stats.get("fission_mean")
|
|
@@ -632,20 +632,18 @@ async def get_ads_for_review(
|
|
|
ad_dict["bid_up_target_min"] = round(tier_bid_mean * 1.05, 4) if tier_bid_mean else None
|
|
ad_dict["bid_up_target_min"] = round(tier_bid_mean * 1.05, 4) if tier_bid_mean else None
|
|
|
ad_dict["bid_up_target_max"] = round(tier_bid_mean * 1.10, 4) if tier_bid_mean else None
|
|
ad_dict["bid_up_target_max"] = round(tier_bid_mean * 1.10, 4) if tier_bid_mean else None
|
|
|
|
|
|
|
|
- # ROI 阈值线:基于"渠道P50"(roi_mean,全体广告7日均值的中位数),严禁用同类
|
|
|
|
|
- channel_p50 = roi_mean
|
|
|
|
|
-
|
|
|
|
|
|
|
+ # ROI 阈值线:基于"渠道P50"(channel_roi_p50,全体广告7日均值的中位数),严禁用同类
|
|
|
# 关停线:渠道P50 的 70-75%(低于25-30%)
|
|
# 关停线:渠道P50 的 70-75%(低于25-30%)
|
|
|
- ad_dict["pause_line_min"] = round(channel_p50 * 0.70, 4) if channel_p50 else None
|
|
|
|
|
- ad_dict["pause_line_max"] = round(channel_p50 * 0.75, 4) if channel_p50 else None
|
|
|
|
|
|
|
+ ad_dict["pause_line_min"] = round(channel_roi_p50 * 0.70, 4) if channel_roi_p50 else None
|
|
|
|
|
+ ad_dict["pause_line_max"] = round(channel_roi_p50 * 0.75, 4) if channel_roi_p50 else None
|
|
|
|
|
|
|
|
# 降价线:渠道P50 的 85-90%(低于10-15%)
|
|
# 降价线:渠道P50 的 85-90%(低于10-15%)
|
|
|
- ad_dict["bid_down_line_min"] = round(channel_p50 * 0.85, 4) if channel_p50 else None
|
|
|
|
|
- ad_dict["bid_down_line_max"] = round(channel_p50 * 0.90, 4) if channel_p50 else None
|
|
|
|
|
|
|
+ ad_dict["bid_down_line_min"] = round(channel_roi_p50 * 0.85, 4) if channel_roi_p50 else None
|
|
|
|
|
+ ad_dict["bid_down_line_max"] = round(channel_roi_p50 * 0.90, 4) if channel_roi_p50 else None
|
|
|
|
|
|
|
|
# 提价线:渠道P50 的 105-110%(高于5-10%)
|
|
# 提价线:渠道P50 的 105-110%(高于5-10%)
|
|
|
- ad_dict["bid_up_line_min"] = round(channel_p50 * 1.05, 4) if channel_p50 else None
|
|
|
|
|
- ad_dict["bid_up_line_max"] = round(channel_p50 * 1.10, 4) if channel_p50 else None
|
|
|
|
|
|
|
+ ad_dict["bid_up_line_min"] = round(channel_roi_p50 * 1.05, 4) if channel_roi_p50 else None
|
|
|
|
|
+ ad_dict["bid_up_line_max"] = round(channel_roi_p50 * 1.10, 4) if channel_roi_p50 else None
|
|
|
|
|
|
|
|
# ===== 新增:年龄分段标签(基于决策树图片)=====
|
|
# ===== 新增:年龄分段标签(基于决策树图片)=====
|
|
|
if ad_age is not None:
|
|
if ad_age is not None:
|
|
@@ -731,16 +729,16 @@ async def get_ads_for_review(
|
|
|
"max_batch_size": max((b["count"] for b in tier_batches), default=0),
|
|
"max_batch_size": max((b["count"] for b in tier_batches), default=0),
|
|
|
},
|
|
},
|
|
|
"distribution": {
|
|
"distribution": {
|
|
|
- "roi_mean": round(roi_mean, 4),
|
|
|
|
|
|
|
+ "channel_roi_p50": round(channel_roi_p50, 4),
|
|
|
"p25": round(roi_p25, 4),
|
|
"p25": round(roi_p25, 4),
|
|
|
- "p50": round(roi_p50, 4),
|
|
|
|
|
|
|
+ "p50": round(channel_roi_p50, 4),
|
|
|
"p75": round(roi_p75, 4),
|
|
"p75": round(roi_p75, 4),
|
|
|
"p90": round(roi_p90, 4),
|
|
"p90": round(roi_p90, 4),
|
|
|
},
|
|
},
|
|
|
"bid_adjustment": {
|
|
"bid_adjustment": {
|
|
|
"enabled": BID_ADJUSTMENT_ENABLED,
|
|
"enabled": BID_ADJUSTMENT_ENABLED,
|
|
|
- "bid_down_line": round(roi_mean * params["BID_DOWN_ROI_FACTOR"], 4),
|
|
|
|
|
- "bid_up_line": round(roi_mean * params["BID_UP_ROI_FACTOR"], 4),
|
|
|
|
|
|
|
+ "bid_down_line": round(channel_roi_p50 * params["BID_DOWN_ROI_FACTOR"], 4),
|
|
|
|
|
+ "bid_up_line": round(channel_roi_p50 * params["BID_UP_ROI_FACTOR"], 4),
|
|
|
"bid_up_max_spend": BID_UP_MAX_SPEND,
|
|
"bid_up_max_spend": BID_UP_MAX_SPEND,
|
|
|
"roi_low_min_yesterday_cost": ROI_LOW_MIN_YESTERDAY_COST,
|
|
"roi_low_min_yesterday_cost": ROI_LOW_MIN_YESTERDAY_COST,
|
|
|
},
|
|
},
|
|
@@ -750,10 +748,10 @@ async def get_ads_for_review(
|
|
|
"BID_UP_ROI_FACTOR": params["BID_UP_ROI_FACTOR"],
|
|
"BID_UP_ROI_FACTOR": params["BID_UP_ROI_FACTOR"],
|
|
|
"BID_UP_MAX_SPEND": BID_UP_MAX_SPEND,
|
|
"BID_UP_MAX_SPEND": BID_UP_MAX_SPEND,
|
|
|
"ROI_LOW_MIN_YESTERDAY_COST": ROI_LOW_MIN_YESTERDAY_COST,
|
|
"ROI_LOW_MIN_YESTERDAY_COST": ROI_LOW_MIN_YESTERDAY_COST,
|
|
|
- "roi_mean": round(roi_mean, 4),
|
|
|
|
|
- "pause_line": round(roi_mean * params["ROI_LOW_FACTOR"], 4),
|
|
|
|
|
- "bid_down_line": round(roi_mean * params["BID_DOWN_ROI_FACTOR"], 4),
|
|
|
|
|
- "bid_up_line": round(roi_mean * params["BID_UP_ROI_FACTOR"], 4),
|
|
|
|
|
|
|
+ "channel_roi_p50": round(channel_roi_p50, 4),
|
|
|
|
|
+ "pause_line": round(channel_roi_p50 * params["ROI_LOW_FACTOR"], 4),
|
|
|
|
|
+ "bid_down_line": round(channel_roi_p50 * params["BID_DOWN_ROI_FACTOR"], 4),
|
|
|
|
|
+ "bid_up_line": round(channel_roi_p50 * params["BID_UP_ROI_FACTOR"], 4),
|
|
|
},
|
|
},
|
|
|
# 零消耗广告由规则全自动处理,LLM 无需逐条决策
|
|
# 零消耗广告由规则全自动处理,LLM 无需逐条决策
|
|
|
# 仅传入规模 + 10 条样本(供 LLM 追溯形态,避免 1000+ 条名单挤占 context)
|
|
# 仅传入规模 + 10 条样本(供 LLM 追溯形态,避免 1000+ 条名单挤占 context)
|
|
@@ -779,7 +777,7 @@ async def get_ads_for_review(
|
|
|
"need_review_ads": len(need_review_ads),
|
|
"need_review_ads": len(need_review_ads),
|
|
|
"normal_ads": normal_ads_count,
|
|
"normal_ads": normal_ads_count,
|
|
|
"tier_groups": len(review_by_tier),
|
|
"tier_groups": len(review_by_tier),
|
|
|
- "roi_mean": roi_mean,
|
|
|
|
|
|
|
+ "channel_roi_p50": channel_roi_p50,
|
|
|
"end_date": end_date,
|
|
"end_date": end_date,
|
|
|
},
|
|
},
|
|
|
)
|
|
)
|
|
@@ -938,12 +936,12 @@ async def apply_decisions(
|
|
|
ad_id = int(row["ad_id"])
|
|
ad_id = int(row["ad_id"])
|
|
|
if ad_id not in zero_spend_ad_ids and ad_id not in need_review_ad_ids:
|
|
if ad_id not in zero_spend_ad_ids and ad_id not in need_review_ad_ids:
|
|
|
cost_7d_avg = float(row.get("cost_7d_avg", 0) or 0)
|
|
cost_7d_avg = float(row.get("cost_7d_avg", 0) or 0)
|
|
|
- f_roi = row.get("动态ROI_7日均值")
|
|
|
|
|
|
|
+ dynamic_roi_7d = row.get("动态ROI_7日均值")
|
|
|
ad_age_days = row.get("ad_age_days")
|
|
ad_age_days = row.get("ad_age_days")
|
|
|
|
|
|
|
|
# 冷启动保护:广告年龄 ≤ 3天(基于决策树)
|
|
# 冷启动保护:广告年龄 ≤ 3天(基于决策树)
|
|
|
if ad_age_days is not None and ad_age_days <= COLD_START_DAYS:
|
|
if ad_age_days is not None and ad_age_days <= COLD_START_DAYS:
|
|
|
- roi_str = f"{f_roi:.2f}" if not pd.isna(f_roi) else "数据不足"
|
|
|
|
|
|
|
+ roi_str = f"{dynamic_roi_7d:.2f}" if not pd.isna(dynamic_roi_7d) else "数据不足"
|
|
|
normal_running_rows.append({
|
|
normal_running_rows.append({
|
|
|
"ad_id": ad_id,
|
|
"ad_id": ad_id,
|
|
|
"action": "hold",
|
|
"action": "hold",
|
|
@@ -955,7 +953,7 @@ async def apply_decisions(
|
|
|
})
|
|
})
|
|
|
else:
|
|
else:
|
|
|
# 正常运行
|
|
# 正常运行
|
|
|
- roi_str = f"{f_roi:.2f}" if not pd.isna(f_roi) else "数据不足"
|
|
|
|
|
|
|
+ roi_str = f"{dynamic_roi_7d:.2f}" if not pd.isna(dynamic_roi_7d) else "数据不足"
|
|
|
normal_running_rows.append({
|
|
normal_running_rows.append({
|
|
|
"ad_id": ad_id,
|
|
"ad_id": ad_id,
|
|
|
"action": "hold",
|
|
"action": "hold",
|
|
@@ -1167,19 +1165,19 @@ async def query_ad_detail(
|
|
|
|
|
|
|
|
# 全局 ROI 分布(使用中位数作为基准,避免被少数高ROI广告拉高)
|
|
# 全局 ROI 分布(使用中位数作为基准,避免被少数高ROI广告拉高)
|
|
|
roi_series = df["动态ROI_7日均值"].dropna()
|
|
roi_series = df["动态ROI_7日均值"].dropna()
|
|
|
- roi_mean = float(roi_series.median()) if len(roi_series) > 0 else 0.0
|
|
|
|
|
|
|
+ channel_roi_p50 = float(roi_series.median()) if len(roi_series) > 0 else 0.0
|
|
|
|
|
|
|
|
- roi_low_line = roi_mean * ROI_LOW_FACTOR
|
|
|
|
|
- bid_down_line = roi_mean * BID_DOWN_ROI_FACTOR
|
|
|
|
|
- bid_up_line = roi_mean * BID_UP_ROI_FACTOR
|
|
|
|
|
|
|
+ roi_low_line = channel_roi_p50 * ROI_LOW_FACTOR
|
|
|
|
|
+ bid_down_line = channel_roi_p50 * BID_DOWN_ROI_FACTOR
|
|
|
|
|
+ bid_up_line = channel_roi_p50 * BID_UP_ROI_FACTOR
|
|
|
|
|
|
|
|
# 构建广告详情
|
|
# 构建广告详情
|
|
|
- f_roi = row.get("动态ROI_7日均值")
|
|
|
|
|
|
|
+ dynamic_roi_7d = row.get("动态ROI_7日均值")
|
|
|
ad_detail = {
|
|
ad_detail = {
|
|
|
"ad_id": ad_id_int,
|
|
"ad_id": ad_id_int,
|
|
|
"ad_name": str(row.get("ad_name", "")),
|
|
"ad_name": str(row.get("ad_name", "")),
|
|
|
"bid_amount": round(float(row.get("bid_amount", 0) or 0), 2),
|
|
"bid_amount": round(float(row.get("bid_amount", 0) or 0), 2),
|
|
|
- "动态ROI_7日均值": round(float(f_roi), 4) if not pd.isna(f_roi) else None,
|
|
|
|
|
|
|
+ "动态ROI_7日均值": round(float(dynamic_roi_7d), 4) if not pd.isna(dynamic_roi_7d) else None,
|
|
|
"cost_7d_avg": round(float(row.get("cost_7d_avg", 0) or 0), 2),
|
|
"cost_7d_avg": round(float(row.get("cost_7d_avg", 0) or 0), 2),
|
|
|
"cost_7d_total": round(float(row.get("cost_7d_total", 0) or 0), 2),
|
|
"cost_7d_total": round(float(row.get("cost_7d_total", 0) or 0), 2),
|
|
|
"ad_age_days": ad_age_days,
|
|
"ad_age_days": ad_age_days,
|
|
@@ -1206,7 +1204,7 @@ async def query_ad_detail(
|
|
|
|
|
|
|
|
# 全局上下文
|
|
# 全局上下文
|
|
|
global_context = {
|
|
global_context = {
|
|
|
- "全体动态ROI基准(中位数)": round(roi_mean, 4),
|
|
|
|
|
|
|
+ "全体动态ROI基准(中位数)": round(channel_roi_p50, 4),
|
|
|
"ROI关停线": round(roi_low_line, 4),
|
|
"ROI关停线": round(roi_low_line, 4),
|
|
|
"ROI降价线": round(bid_down_line, 4),
|
|
"ROI降价线": round(bid_down_line, 4),
|
|
|
"ROI提价线": round(bid_up_line, 4),
|
|
"ROI提价线": round(bid_up_line, 4),
|