""" 营销策略模拟模块 """ import numpy as np import pandas as pd from .utils import ensure_native_type from .lifecycle_analyzer_service import enhanced_data_preprocessing def simulate_marketing_strategy(revenue_series, quantity_series, date_series, stages_map, stage_statistics, strategy_type, strategy_params): """模拟营销策略对SKU生命周期的影响""" # 转换为可修改的列表 simulated_revenue = list(revenue_series) simulated_quantity = list(quantity_series) # 解析策略参数 start_date = strategy_params.get('start_date') end_date = strategy_params.get('end_date') intensity = float(strategy_params.get('intensity', 0.5)) price_change = float(strategy_params.get('price_change', 0)) # 找到策略作用的日期范围索引 start_idx = None end_idx = None for i, date_str in enumerate(date_series): if start_date and date_str == start_date: start_idx = i if end_date and date_str == end_date: end_idx = i # 如果未找到精确匹配,尝试模糊匹配 if start_idx is None and start_date: for i, date_str in enumerate(date_series): if start_date in date_str: start_idx = i break if end_idx is None and end_date: for i, date_str in enumerate(date_series): if end_date in date_str: end_idx = i break # 默认范围 if start_idx is None: start_idx = 0 if end_idx is None: end_idx = len(simulated_revenue) - 1 # 确保范围有效 start_idx = max(0, min(start_idx, len(simulated_revenue) - 1)) end_idx = max(start_idx, min(end_idx, len(simulated_revenue) - 1)) # 根据策略类型应用不同的影响 strategy_effects = { 'promotion': { # 促销活动 'quantity_boost': 1.3 + (intensity * 0.5), 'revenue_boost': 1.15 + (intensity * 0.25), }, 'advertising': { # 广告宣传 'quantity_boost': 1.2 + (intensity * 0.6), 'revenue_boost': 1.25 + (intensity * 0.6), }, 'price_cut': { # 降价 'quantity_boost': 1.4 + (abs(price_change) / 100 * 1.5), 'revenue_boost': 1.0 + (price_change / 100), }, 'price_increase': { # 涨价 'quantity_boost': 1.0 - (price_change / 100 * 0.3), 'revenue_boost': 1.0 + (price_change / 100), }, } effect = strategy_effects.get(strategy_type, {'quantity_boost': 1.0, 'revenue_boost': 1.0}) # 应用策略影响(考虑渐进式影响和衰减) for i in range(start_idx, end_idx + 1): progress = (i - start_idx) / max(1, end_idx - start_idx) # 使用钟形曲线模拟影响强度 impact_factor = np.exp(-((progress - 0.5) ** 2) / 0.1) # 应用影响 quantity_multiplier = 1.0 + (effect['quantity_boost'] - 1.0) * impact_factor revenue_multiplier = 1.0 + (effect['revenue_boost'] - 1.0) * impact_factor simulated_quantity[i] *= quantity_multiplier simulated_revenue[i] *= revenue_multiplier # 计算策略影响的后续效应 carryover_length = min(20, (end_idx - start_idx) // 2) for i in range(end_idx + 1, min(end_idx + 1 + carryover_length, len(simulated_revenue))): decay_factor = 1.0 - ((i - end_idx) / carryover_length) carryover_boost = 0.1 * intensity * decay_factor simulated_quantity[i] *= (1.0 + carryover_boost) simulated_revenue[i] *= (1.0 + carryover_boost * 0.5) # 平滑处理 smoothed_simulated_revenue, smoothed_simulated_quantity = enhanced_data_preprocessing( pd.Series(simulated_revenue), pd.Series(simulated_quantity) ) # 计算对比指标 original_total_revenue = sum(revenue_series) original_total_quantity = sum(quantity_series) simulated_total_revenue = sum(simulated_revenue) simulated_total_quantity = sum(simulated_quantity) revenue_increase = simulated_total_revenue - original_total_revenue quantity_increase = simulated_total_quantity - original_total_quantity revenue_increase_pct = (revenue_increase / original_total_revenue * 100) if original_total_revenue > 0 else 0 quantity_increase_pct = (quantity_increase / original_total_quantity * 100) if original_total_quantity > 0 else 0 # 计算策略期间的增量 strategy_period_original_revenue = sum(revenue_series[start_idx:end_idx + 1]) strategy_period_simulated_revenue = sum(simulated_revenue[start_idx:end_idx + 1]) strategy_period_revenue_increase = strategy_period_simulated_revenue - strategy_period_original_revenue strategy_period_revenue_increase_pct = ( (strategy_period_revenue_increase / strategy_period_original_revenue * 100) if strategy_period_original_revenue > 0 else 0 ) return { 'simulated_revenue': [ensure_native_type(v, decimal_places=2) for v in simulated_revenue], 'simulated_quantity': [ensure_native_type(v, decimal_places=2) for v in simulated_quantity], 'smoothed_simulated_revenue': [ensure_native_type(v, decimal_places=2) for v in smoothed_simulated_revenue.tolist()], 'smoothed_simulated_quantity': [ensure_native_type(v, decimal_places=2) for v in smoothed_simulated_quantity.tolist()], 'comparison': { 'original_total_revenue': ensure_native_type(original_total_revenue, decimal_places=2), 'simulated_total_revenue': ensure_native_type(simulated_total_revenue, decimal_places=2), 'revenue_increase': ensure_native_type(revenue_increase, decimal_places=2), 'revenue_increase_pct': ensure_native_type(revenue_increase_pct, decimal_places=2), 'original_total_quantity': ensure_native_type(original_total_quantity, decimal_places=2), 'simulated_total_quantity': ensure_native_type(simulated_total_quantity, decimal_places=2), 'quantity_increase': ensure_native_type(quantity_increase, decimal_places=2), 'quantity_increase_pct': ensure_native_type(quantity_increase_pct, decimal_places=2), 'strategy_period_revenue_increase': ensure_native_type(strategy_period_revenue_increase, decimal_places=2), 'strategy_period_revenue_increase_pct': ensure_native_type(strategy_period_revenue_increase_pct, decimal_places=2), }, 'strategy_range': { 'start_idx': start_idx, 'end_idx': end_idx, 'start_date': date_series[start_idx], 'end_date': date_series[end_idx], } }