用Python模拟霍特林博弈:从街头冰淇淋店到互联网产品定价的实战推演
想象一下,炎炎夏日里一条笔直的街道上,两家冰淇淋店分别位于两端。顾客们会根据价格和步行距离决定去哪家购买——这就是1929年Harold Hotelling提出的经典模型。但霍特林博弈的智慧远不止于此,从外卖平台的配送范围优化,到视频会员的差异化定价,再到共享单车的投放策略,这个看似简单的模型能解释无数现实商业现象。
本文将用Python带你亲手搭建霍特林模型的动态模拟系统。不同于静态的理论推导,我们将通过可交互的代码实验,直观观察空间竞争如何影响定价策略。无论你是想理解商业竞争本质的产品经理,还是希望用博弈论优化策略的数据分析师,这些代码都能成为你的决策实验室。
1. 环境搭建与基础模型
首先确保你的Python环境已安装以下库:
PYTHON
2
import matplotlib.pyplot as plt
3
from ipywidgets import interact, FloatSlider
1.1 线性城市的基本假设
我们构建一个长度为1的"线性城市",消费者均匀分布在[0,1]区间。假设两家商店分别位于a=0和b=1的位置,销售同质化产品。消费者选择商店时考虑:
- 商品价格(p1, p2)
- 单位距离旅行成本t(可理解为时间成本或运费)
需求函数推导的关键在于找到"无差异消费者位置"x*,即:
TEXT
1
U - t*x* - p1 = U - t*(1-x*) - p2
解得x* = (p2 - p1 + t)/(2t)。据此可编写基础需求函数:
PYTHON
1
def demand(p1, p2, t, a=0, b=1):
2
x_star = (p2 - p1 + t*(b-a)) / (2*t)
3
d1 = np.clip(x_star, 0, 1)
4
d2 = 1 - np.clip(x_star, 0, 1)
1.2 价格均衡的可视化
固定商店2价格p2=1.5,观察商店1价格变化如何影响市场份额:
PYTHON
3
p1_range = np.linspace(0.1, 3, 100)
4
d1_values = [demand(p1, p2, t)[0] for p1 in p1_range]
6
plt.figure(figsize=(10,6))
7
plt.plot(p1_range, d1_values, label='商店1需求')
8
plt.axvline(x=p2, color='r', linestyle='--', label='商店2价格')
当p1=p2时,市场份额平分;价格低于竞争者时获得更多客户——这与直觉完全一致。但真正的博弈在于双方会如何动态调整价格?
2. 动态博弈与纳什均衡
2.1 利润函数与最优响应
假设单位成本c=1,利润函数为:
PYTHON
1
def profit(p1, p2, t, c=1):
2
d1, _ = demand(p1, p2, t)
商店1在面对p2时会选择使利润最大化的p1。通过求导可得最优响应函数:
实现代码:
PYTHON
1
def best_response(p2, t, c=1):
2
return (p2 + t + c) / 2
2.2 均衡收敛模拟
通过迭代反应观察价格如何收敛到均衡:
PYTHON
1
def simulate_equilibrium(t=0.5, c=1, max_iter=20):
5
for _ in range(max_iter):
6
p1 = best_response(p2, t, c)
7
p2 = best_response(p1, t, c)
8
history.append((p1, p2))
10
return np.array(history)
绘制收敛过程:
PYTHON
1
history = simulate_equilibrium()
2
plt.plot(history[:,0], label='商店1价格')
3
plt.plot(history[:,1], label='商店2价格')
4
plt.axhline(y=1+0.5, color='k', linestyle='--', label='理论均衡')
2.3 旅行成本的影响
旅行成本t越大,产品差异化程度越高。我们观察不同t值下的均衡价格:
| t值 |
均衡价格 |
均衡利润 |
| 0.1 |
1.1 |
0.05 |
| 0.3 |
1.3 |
0.15 |
| 0.5 |
1.5 |
0.25 |
| 0.8 |
1.8 |
0.4 |
代码验证:
PYTHON
1
t_values = [0.1, 0.3, 0.5, 0.8]
2
equilibrium_prices = [1 + t for t in t_values]
3
profits = [t/2 for t in t_values]
3. 商店位置的内生决定
经典模型中商店位置是外生给定的,现实中企业会战略性地选择位置。我们扩展模型,让位置也成为决策变量。
3.1 位置-价格联合博弈
定义利润函数时加入位置参数:
PYTHON
1
def profit_full(p1, p2, a, b, t, c=1):
2
x_star = (p2 - p1 + t*(1-a-b)) / (2*t*(1-a-b)) + (1-b+a)/2
3
d1 = np.clip(x_star, 0, 1)
3.2 位置策略模拟
固定一家位置,观察另一家的最优响应:
PYTHON
1
a_values = np.linspace(0, 0.5, 50)
4
p1_eq = 1 + t*(1-a)*(3+a)/3
5
profit = profit_full(p1_eq, p1_eq, a, 1-a, t)
8
plt.plot(a_values, profits)
结果显示中间位置(最小差异化)反而是利润最低的,这与霍特林著名的"主街悖论"一致。
4. 互联网产品的差异化竞争
将空间差异转化为产品特性差异,模型可应用于:
4.1 视频会员定价案例
假设:
- "位置"代表内容偏好(0=电影爱好者,1=剧集爱好者)
- 旅行成本t代表用户对非偏好内容的容忍度
模拟代码:
PYTHON
1
def streaming_demand(p1, p2, t, a, b):
3
x_star = (p2 - p1 + t*(1-a-b)*(1+a-b)) / (2*t*(1-a-b))
4
return np.clip(x_star, 0, 1)
7
demand_A = streaming_demand(15, 18, 10, 0.2, 0.8)
4.2 可交互模拟器
创建Jupyter交互控件,实时观察参数影响:
PYTHON
6
def plot_streaming(t=10, a=0.2, b=0.8):
7
p_range = np.linspace(10, 30, 100)
8
demands = [streaming_demand(p, 20, t, a, b) for p in p_range]
9
plt.plot(p_range, demands)
5. 模型局限与扩展方向
虽然霍特林模型极具洞察力,但现实更复杂。可以考虑以下扩展:
- 多维差异化:同时考虑价格、质量、服务等多维度
PYTHON
2
def utility(distance, price, quality):
3
return quality - 0.5*distance - price
-
动态博弈:多期竞争与用户迁移成本
-
网络效应:用户选择受现有用户规模影响
-
数据驱动的参数估计:
PYTHON
2
from scipy.optimize import minimize
3
def calibrate_t(observed_share, prices, locations):
5
pred = demand(prices[0], prices[1], t, locations[0], locations[1])[0]
6
return (pred - observed_share)**2
7
return minimize(error, x0=0.5).x[0]
这些扩展方向都能在原有代码框架上实现,为商业决策提供更精细的模拟工具。