Skip to content

Commit da7b176

Browse files
authored
🔄 resync kesten_processes.md (#190)
1 parent 965ad3e commit da7b176

2 files changed

Lines changed: 111 additions & 82 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
source-sha: 13d27c47397e0b1c36175078683e7cbdd528ff0c
2+
synced-at: "2026-07-21"
3+
model: claude-sonnet-5
4+
mode: RESYNC
5+
section-count: 5
6+
tool-version: 0.20.0

lectures/kesten_processes.md

Lines changed: 105 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,23 @@ kernelspec:
77
display_name: Python 3
88
language: python
99
name: python3
10+
translation:
11+
title: Kesten过程与企业动态
12+
headings:
13+
Overview: 概述
14+
Kesten processes: Kesten过程
15+
'Kesten processes::Example: GARCH volatility': 示例:GARCH波动率
16+
'Kesten processes::Example: wealth dynamics': 示例:财富动态
17+
Kesten processes::Stationarity: 平稳性
18+
Kesten processes::Cross-sectional interpretation: 横截面解释
19+
Kesten processes::Conditions for stationarity: 平稳性条件
20+
Heavy tails: 重尾
21+
Heavy tails::The Kesten--Goldie theorem: Kesten--Goldie定理
22+
Heavy tails::Intuition: 直觉解释
23+
'Application: firm dynamics': 应用:企业动态
24+
'Application: firm dynamics::Gibrat''s law': Gibrat定律
25+
'Application: firm dynamics::Heavy tails': 重尾
26+
Exercises: 练习
1027
---
1128

1229
```{raw} jupyter
@@ -26,14 +43,15 @@ kernelspec:
2643
:depth: 2
2744
```
2845

46+
```{include} _admonition/gpu.md
47+
```
48+
2949
除了Anaconda中包含的内容外,本讲座还需要以下库:
3050

31-
```{code-cell} ipython
32-
---
33-
tags: [hide-output]
34-
---
35-
!pip install quantecon
36-
!pip install --upgrade yfinance
51+
```{code-cell} ipython3
52+
:tags: [hide-output]
53+
54+
!pip install --upgrade quantecon yfinance
3755
```
3856

3957
## 概述
@@ -47,29 +65,17 @@ tags: [hide-output]
4765
虽然Kesten过程的数学形式看起来很简单,但它们在经济学中非常重要,主要有两个原因:
4866

4967
1. 很多关键的经济过程可以用Kesten过程来描述。
50-
2. Kesten过程能够产生复杂的动态行为,尤其是在某些条件下,它们可以生成带有"重尾"特征的横截面分布,这与我们在现实经济数据中观察到的情况相符
68+
2. Kesten过程能够产生复杂的动态行为,尤其是在某些条件下,它们可以生成带有"重尾"特征的横截面分布。
5169

5270
我们接下来会讨论这些问题。
5371

5472
现在我们从一些导入开始:
5573

56-
```{code-cell} ipython
74+
```{code-cell} ipython3
5775
import matplotlib.pyplot as plt
58-
import matplotlib as mpl
59-
FONTPATH = "fonts/SourceHanSerifSC-SemiBold.otf"
60-
mpl.font_manager.fontManager.addfont(FONTPATH)
61-
plt.rcParams['font.family'] = ['Source Han Serif SC']
62-
63-
plt.rcParams["figure.figsize"] = (11, 5) #设置默认图形大小
6476
import numpy as np
6577
import quantecon as qe
66-
```
67-
68-
以下两行仅用于避免pandas和matplotlib之间的兼容性问题导致的`FutureWarning`
69-
70-
```{code-cell} ipython
71-
from pandas.plotting import register_matplotlib_converters
72-
register_matplotlib_converters()
78+
import yfinance as yf
7379
```
7480

7581
关于本讲座的更多技术细节,读者可以参考{cite}`buraczewski2016stochastic`这本专著。
@@ -106,19 +112,18 @@ GARCH模型在金融应用中很常见,其中时间序列(如资产收益)
106112
例如,考虑以下纳斯达克综合指数从2006年1月1日到2019年11月1日的日收益率图。
107113

108114
(ndcode)=
109-
```{code-cell} python3
110-
import yfinance as yf
111115

112-
s = yf.download('^IXIC', '2006-1-1', '2019-11-1', auto_adjust=False)['Adj Close']
116+
```{code-cell} ipython3
117+
s = yf.download(
118+
"^IXIC", "2006-1-1", "2019-11-1", auto_adjust=False
119+
)["Adj Close"]
113120
114121
r = s.pct_change()
115122
116123
fig, ax = plt.subplots()
117-
118124
ax.plot(r, alpha=0.7)
119-
120-
ax.set_ylabel('收益率', fontsize=12)
121-
ax.set_xlabel('日期', fontsize=12)
125+
ax.set_ylabel("收益率", fontsize=12)
126+
ax.set_xlabel("日期", fontsize=12)
122127
123128
plt.show()
124129
```
@@ -262,7 +267,7 @@ Kesten过程$X_{t+1} = a_{t+1} X_t + \eta_{t+1}$并不总是具有平稳分布
262267

263268
在某些条件下,Kesten过程的平稳分布具有帕累托尾。
264269

265-
(参见我们{doc}`之前关于重尾分布的讲座 <intro:heavy_tails>`。)
270+
(参见我们{doc}`关于重尾的讲座 <intro:heavy_tails>`以了解背景。)
266271

267272
这个事实对经济学很重要,因为帕累托尾分布在经济现象中广泛存在。
268273

@@ -299,7 +304,7 @@ $$
299304

300305
### 直觉解释
301306

302-
稍后我们将通过绘秩-规模图来直观地验证Kesten--Goldie定理的结论。
307+
稍后我们将通过秩-规模图来直观地验证Kesten--Goldie定理的结论。
303308

304309
在此之前,我们可以对定理条件进行以下直觉性解释。
305310

@@ -323,23 +328,23 @@ $$
323328
μ = -0.5
324329
σ = 1.0
325330
326-
def kesten_ts(ts_length=100):
331+
def kesten_ts(rng, ts_length=100):
327332
x = np.zeros(ts_length)
328-
for t in range(ts_length-1):
329-
a = np.exp(μ + σ * np.random.randn())
330-
b = np.exp(np.random.randn())
333+
for t in range(ts_length - 1):
334+
a = np.exp(μ + σ * rng.standard_normal())
335+
b = np.exp(rng.standard_normal())
331336
x[t+1] = a * x[t] + b
332337
return x
333338
334339
fig, ax = plt.subplots()
335340
336341
num_paths = 10
337-
np.random.seed(12)
342+
rng = np.random.default_rng(12)
338343
339344
for i in range(num_paths):
340-
ax.plot(kesten_ts())
345+
ax.plot(kesten_ts(rng))
341346
342-
ax.set(xlabel='时间', ylabel='$X_t$')
347+
ax.set(xlabel="时间", ylabel="$X_t$")
343348
plt.show()
344349
```
345350

@@ -386,7 +391,7 @@ s_{t+1} = a_{t+1} s_t + b_{t+1}
386391

387392
其中$\{a_t\}$和$\{b_t\}$都是独立同分布的,且相互独立。
388393

389-
在练习中,你需要证明{eq}`firm_dynam`中的Gibrat定律比{eq}`firm_dynam_gb`中的更符合上述实证结果
394+
在练习中,你需要证明{eq}`firm_dynam`{eq}`firm_dynam_gb`中的Gibrat定律更符合上述实证结果
390395

391396
### 重尾
392397

@@ -431,22 +436,22 @@ s_{t+1} = a_{t+1} s_t + b_{t+1}
431436
years = 15
432437
days = years * 250
433438
434-
def garch_ts(ts_length=days):
439+
def garch_ts(rng, ts_length=days):
435440
σ2 = 0
436441
r = np.zeros(ts_length)
437-
for t in range(ts_length-1):
438-
ξ = np.random.randn()
442+
for t in range(ts_length - 1):
443+
ξ = rng.standard_normal()
439444
σ2 = α_0 + σ2 * (α_1 * ξ**2 + β)
440-
r[t] = np.sqrt(σ2) * np.random.randn()
445+
r[t] = np.sqrt(σ2) * rng.standard_normal()
441446
return r
442447
443448
fig, ax = plt.subplots()
444449
445-
np.random.seed(12)
450+
rng = np.random.default_rng(12)
446451
447-
ax.plot(garch_ts(), alpha=0.7)
452+
ax.plot(garch_ts(rng), alpha=0.7)
448453
449-
ax.set(xlabel='时间', ylabel='$\\sigma_t^2$')
454+
ax.set(xlabel="时间", ylabel="$\\sigma_t^2$")
450455
plt.show()
451456
```
452457

@@ -549,7 +554,7 @@ $$
549554
:label: kp_ex4
550555
```
551556

552-
在如{eq}`firm_dynam`中所述的企业动态模型中,的一个不现实方面是它忽略了企业的进入和退出
557+
在如{eq}`firm_dynam`中所述的企业动态模型中,一个不现实的方面是它忽略了企业的进入和退出
553558

554559
在任何时期和任何市场中,我们都能观察到大量企业进入和退出市场。
555560

@@ -622,42 +627,60 @@ s_init = 1.0 # 每个企业的初始条件
622627
:class: dropdown
623628
```
624629

625-
这是一种答案。
626-
首先生成观测值:
630+
这是一种解答。
631+
632+
我们需要模拟一个大规模的企业横截面,因此这是使用JAX的一个很好的应用场景。
633+
634+
我们将企业参数存储在一个`NamedTuple`中,并将单个企业的更新规则{eq}`firm_dynam_ee`写成一个纯函数。
635+
636+
```{code-cell} ipython3
637+
import jax
638+
import jax.numpy as jnp
639+
from functools import partial
640+
from typing import NamedTuple
641+
642+
643+
class Firm(NamedTuple):
644+
μ_a: float
645+
σ_a: float
646+
μ_b: float
647+
σ_b: float
648+
μ_e: float
649+
σ_e: float
650+
s_bar: float
651+
652+
653+
def update(s, key, firm):
654+
"在给定一个新的随机密钥的情况下,更新单个企业的规模s。"
655+
a_key, b_key, e_key = jax.random.split(key, 3)
656+
a = jnp.exp(firm.μ_a + firm.σ_a * jax.random.normal(a_key))
657+
b = jnp.exp(firm.μ_b + firm.σ_b * jax.random.normal(b_key))
658+
e = jnp.exp(firm.μ_e + firm.σ_e * jax.random.normal(e_key))
659+
return jnp.where(s < firm.s_bar, e, a * s + b)
660+
```
661+
662+
我们使用`lax.scan`对一个企业模拟`T`期,然后使用`vmap`并行运行所有`M`个企业。
663+
664+
```{code-cell} ipython3
665+
@partial(jax.jit, static_argnames=("T", "M"))
666+
def generate_draws(firm, s_init=1.0, T=500, M=1_000_000, seed=0):
667+
keys = jax.random.split(jax.random.PRNGKey(seed), M)
668+
669+
def sim_firm(key):
670+
step_keys = jax.random.split(key, T)
671+
s_final, _ = jax.lax.scan(
672+
lambda s, k: (update(s, k, firm), None), s_init, step_keys
673+
)
674+
return s_final
675+
676+
return jax.vmap(sim_firm)(keys)
677+
```
678+
679+
现在我们根据上面的参数构建企业,并生成样本。
627680

628681
```{code-cell} ipython3
629-
from numba import jit, prange
630-
from numpy.random import randn
631-
632-
633-
@jit(parallel=True)
634-
def generate_draws(μ_a=-0.5,
635-
σ_a=0.1,
636-
μ_b=0.0,
637-
σ_b=0.5,
638-
μ_e=0.0,
639-
σ_e=0.5,
640-
s_bar=1.0,
641-
T=500,
642-
M=1_000_000,
643-
s_init=1.0):
644-
645-
draws = np.empty(M)
646-
for m in prange(M):
647-
s = s_init
648-
for t in range(T):
649-
if s < s_bar:
650-
new_s = np.exp(μ_e + σ_e * randn())
651-
else:
652-
a = np.exp(μ_a + σ_a * randn())
653-
b = np.exp(μ_b + σ_b * randn())
654-
new_s = a * s + b
655-
s = new_s
656-
draws[m] = s
657-
658-
return draws
659-
660-
data = generate_draws()
682+
firm = Firm(μ_a, σ_a, μ_b, σ_b, μ_e, σ_e, s_bar)
683+
data = generate_draws(firm, s_init=s_init, T=T, M=M)
661684
```
662685

663686
现在来生成秩-规模图:
@@ -666,7 +689,7 @@ data = generate_draws()
666689
fig, ax = plt.subplots()
667690
668691
rank_data, size_data = qe.rank_size(data, c=0.01)
669-
ax.loglog(rank_data, size_data, 'o', markersize=3.0, alpha=0.5)
692+
ax.loglog(rank_data, size_data, "o", markersize=3.0, alpha=0.5)
670693
ax.set_xlabel("对数秩")
671694
ax.set_ylabel("对数规模")
672695
@@ -676,4 +699,4 @@ plt.show()
676699
该图呈现出一条直线,符合帕累托尾的特性。
677700

678701
```{solution-end}
679-
```
702+
```

0 commit comments

Comments
 (0)