ai_member_xiaoxi/scripts/june_revenue_forecast.py
2026-06-02 08:00:01 +08:00

159 lines
6.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""基于修正后退费数据重新预估6月端内营收"""
import math
# ---- 修正后的月度数据 ----
monthly = [
('2025-09', 4, 6096, 6096, 1529, 3.99),
('2025-10', 25, 30375, 30355, 2412, 12.58),
('2025-11', 24, 30676, 30676, 2971, 10.33),
('2025-12', 19, 19781, 19775, 3523, 5.61),
('2026-01', 42, 49358, 49314, 1937, 25.46),
('2026-02', 21, 30279, 30253, 1743, 17.36),
('2026-03', 65, 85431, 82234, 4166, 19.74), # 修正
('2026-04', 90, 112906, 106810, 5667, 18.85), # 修正
('2026-05', 50, 71740, 69142, 3300, 20.95), # 修正
]
# 5月每日新增
may_daily_new = [
('2026-05-01', 63), ('2026-05-02', 60), ('2026-05-03', 60), ('2026-05-04', 52),
('2026-05-05', 70), ('2026-05-06', 98), ('2026-05-07', 133), ('2026-05-08', 86),
('2026-05-09', 89), ('2026-05-10', 106), ('2026-05-11', 98), ('2026-05-12', 82),
('2026-05-13', 99), ('2026-05-14', 98), ('2026-05-15', 166), ('2026-05-16', 116),
('2026-05-17', 123), ('2026-05-18', 88), ('2026-05-19', 115), ('2026-05-20', 132),
('2026-05-21', 130), ('2026-05-22', 127), ('2026-05-23', 200), ('2026-05-24', 121),
('2026-05-25', 67), ('2026-05-26', 104), ('2026-05-27', 99), ('2026-05-28', 112),
('2026-05-29', 107), ('2026-05-30', 121), ('2026-05-31', 178),
]
print("=" * 70)
print("端内营收预估分析(修正退费数据后)")
print("=" * 70)
# ---- 月度汇总 ----
print("\n## 月度汇总2025-09 ~ 2026-05")
print(f"{'月份':<10} {'订单':>5} {'GMV':>10} {'GSV':>10} {'新增':>7} {'GSV/新增':>9}")
print("-" * 58)
for m in monthly:
print(f"{m[0]:<10} {m[1]:>5} {m[2]:>10,.0f} {m[3]:>10,.0f} {m[4]:>7,} {m[5]:>9.2f}")
# ---- 3/4/5月核心指标 ----
print("\n## 3/4/5月核心指标")
m345 = [m for m in monthly if m[0] >= '2026-03']
gsv_per_new_vals = [m[5] for m in m345]
avg_gsv_per_new = sum(gsv_per_new_vals) / len(gsv_per_new_vals)
for m in m345:
print(f" {m[0]}: GSV={m[3]:,.0f}元, 新增={m[4]:,}人, GSV/新增={m[5]:.2f}元, 订单={m[1]}")
print(f"\n GSV/新增用户均值: {avg_gsv_per_new:.2f}")
print(f" 范围: {min(gsv_per_new_vals):.2f} ~ {max(gsv_per_new_vals):.2f}")
cv = math.sqrt(sum((x-avg_gsv_per_new)**2 for x in gsv_per_new_vals)/len(gsv_per_new_vals))/avg_gsv_per_new*100
print(f" CV(变异系数): {cv:.1f}%")
# ---- 5月每日新增趋势 ----
print("\n## 5月每日新增注册趋势")
may_total = sum(nu for _, nu in may_daily_new)
may_avg = may_total / len(may_daily_new)
may_late = [(dt, nu) for dt, nu in may_daily_new if dt >= '2026-05-16']
may_late_avg = sum(nu for _, nu in may_late) / len(may_late)
may_early = [(dt, nu) for dt, nu in may_daily_new if dt < '2026-05-16']
may_early_avg = sum(nu for _, nu in may_early) / len(may_early)
print(f" 5月总新增: {may_total} 人, 日均: {may_avg:.0f}")
print(f" 上半月(1-15日)日均: {may_early_avg:.0f}")
print(f" 下半月(16-31日)日均: {may_late_avg:.0f}")
# 按周
from datetime import date
weeks = {}
for dt, nu in may_daily_new:
d = date.fromisoformat(dt)
wk = d.isocalendar()[1]
if wk not in weeks:
weeks[wk] = {'total': 0, 'days': 0}
weeks[wk]['total'] += nu
weeks[wk]['days'] += 1
for wk in sorted(weeks):
w = weeks[wk]
print(f"{wk}周: 日均{w['total']/w['days']:.0f}人, 合计{w['total']}")
# ---- 预估模型 ----
print("\n" + "=" * 70)
print("## 6月营收预估6月共30天")
print("=" * 70)
# 场景
scenarios = {
'乐观': may_late_avg * 1.10,
'基准': may_avg,
'保守': may_late_avg,
'悲观': may_late_avg * 0.85,
}
# 模型1: GSV/新增用户均值法
print("\n### 模型1: GSV/新增用户均值法")
print(f" 公式: 6月GSV = 6月预估新增 × {avg_gsv_per_new:.2f}")
for label, daily_new in scenarios.items():
jun_new = daily_new * 30
jun_gsv = jun_new * avg_gsv_per_new
print(f" {label}: 日均新增{daily_new:.0f}人 → 月新增{jun_new:.0f}人 → GSV≈{jun_gsv:,.0f}")
# 模型2: 线性回归
print("\n### 模型2: 月度新增→GSV线性回归")
xs = [m[4] for m in m345]
ys = [m[3] for m in m345]
n = len(xs)
x_mean = sum(xs) / n
y_mean = sum(ys) / n
slope = sum((xs[i]-x_mean)*(ys[i]-y_mean) for i in range(n)) / sum((x-x_mean)**2 for x in xs)
intercept = y_mean - slope * x_mean
r2 = 1 - sum((ys[i]-(slope*xs[i]+intercept))**2 for i in range(n)) / sum((y-y_mean)**2 for y in ys)
print(f" 回归: GSV = {slope:.2f} × 新增 + {intercept:.0f} (R²={r2:.4f})")
for label, daily_new in scenarios.items():
jun_new = daily_new * 30
jun_gsv = slope * jun_new + intercept
print(f" {label}: 新增{jun_new:.0f}人 → GSV≈{jun_gsv:,.0f}")
# 综合预估
print("\n" + "=" * 70)
print("## 综合预估")
print("=" * 70)
print(f"\n{'场景':<8} {'日均新增':>8} {'月新增':>8} {'模型1 GSV':>12} {'模型2 GSV':>12} {'综合GSV':>12}")
print("-" * 58)
for label, daily_new in scenarios.items():
jun_new = daily_new * 30
gsv1 = jun_new * avg_gsv_per_new
gsv2 = slope * jun_new + intercept
gsv_avg = (gsv1 + gsv2) / 2
print(f"{label:<8} {daily_new:>8.0f} {jun_new:>8.0f} {gsv1:>12,.0f} {gsv2:>12,.0f} {gsv_avg:>12,.0f}")
# 推荐区间
jun_new_base = may_avg * 30
gsv_base = (jun_new_base * avg_gsv_per_new + slope * jun_new_base + intercept) / 2
jun_new_conservative = may_late_avg * 30
gsv_conservative = (jun_new_conservative * avg_gsv_per_new + slope * jun_new_conservative + intercept) / 2
jun_new_optimistic = may_late_avg * 1.10 * 30
gsv_optimistic = (jun_new_optimistic * avg_gsv_per_new + slope * jun_new_optimistic + intercept) / 2
print(f"\n### 推荐预估区间")
print(f" 基准预估: 6月GSV ≈ {gsv_base:,.0f} 元(日均新增{may_avg:.0f}人)")
print(f" 保守预估: 6月GSV ≈ {gsv_conservative:,.0f} 元(日均新增{may_late_avg:.0f}人)")
print(f" 乐观预估: 6月GSV ≈ {gsv_optimistic:,.0f} 元(日均新增{may_late_avg*1.1:.0f}人)")
print(f" 预估区间: {gsv_conservative:,.0f} ~ {gsv_optimistic:,.0f}")
print("\n### 与修正前对比")
print(f" 修正前 GSV/新增均值: 20.71 → 修正后: {avg_gsv_per_new:.2f}")
print(f" 修正前基准预估: ~67,720 → 修正后: ~{gsv_base:,.0f}")
print("\n### 关键假设与风险")
print(f" 1. GSV/新增用户指标 CV={cv:.1f}%稳定性好假设6月延续")
print(f" 2. 5月新增3,300人较4月(5,667)下降42%")
print(f" 3. 5月下半月日均{may_late_avg:.0f}人,略高于上半月({may_early_avg:.0f}人)")
print(f" 4. 转化率逐月下降(1.87%→1.29%→0.79%),但客单价上升抵消了影响")
print(f" 5. 建议6月第1周结束后用实际新增数据回测修正")