本文介绍如何通过 python 循环、f-string 模板和 itertools 组合,将重复性高的多国宏观经济方程(如 uk、us、de 等)自动批量生成,显著提升可维护性、降低代码行数,并支持灵活扩展新国家及变量。
本文介绍如何通过 python 循环、f-string 模板和 itertools 组合,将重复性高的多国宏观经济方程(如 uk、us、de 等)自动批量生成,显著提升可维护性、降低代码行数,并支持灵活扩展新国家及变量。
在构建跨国家动态一般均衡(DGE)或宏观计量模型时,常需为每个国家定义结构高度一致但变量名带前缀(如 YUK, RUS, BsUKUS)的一组方程。手动复制粘贴 20+ 国家的数十条方程不仅易出错,且后续参数调整、新增国家或调试变量时维护成本极高。根本解法不是“写得更快”,而是结构性抽象:将国家标识、变量模式与方程逻辑解耦。
✅ 核心策略:三类模板 + 可组合迭代
我们按方程涉及的国家数量划分为三类模板,并用 itertools.product 和条件过滤精准控制变量组合:
- 单国方程(Self-contained):仅依赖本国变量,如财富积累 Vc - Vc(-1) = YDrc - CONSc
- 双边交互方程(Two-country):含“源-目标”关系,如 YDhsc1 = YDrc1 + d(XRc2)*Bsc1c2(-1),需遍历所有 c1 ≠ c2 的有序对
- 自反+交互混合方程(Hybrid):如税收方程中既含本国资本收益 Rc(-1)*Bdccc(-1),也含他国资产收益 XRc2*Rc2(-1)*Bsc1c2(-1),需分情况展开
from itertools import product
countries = ['UK', 'US', 'DE', 'JP', 'CA'] # ✅ 新增国家只需在此添加
# 1️⃣ 单国方程:财富积累、消费约束等
for c in countries:
model.add(f'V{c} - V{c}(-1) = YDr{c} - CONS{c}') # Eq. 12.3/12.6
model.add(f'T{c} = theta{c}*(Y{c} + R{c}(-1)*Bd{c}{c}(-1)'
f' + sum({"+".join([f"XR{c2}*R{c2}(-1)*Bs{c}{c2}(-1)" for c2 in countries if c2 != c])}))')
# 2️⃣ 双边方程:可贸易收入、Haig-Simons 收入等(c1 → c2 流动)
for c1, c2 in product(countries, repeat=2):
if c1 == c2: # 跳过自循环(除非模型明确需要,如本例中 Bscc 通常不出现)
continue
model.add(f'YDr{c1} = (Y{c1} + R{c1}(-1)*Bd{c1}{c1}(-1) + XR{c2}*R{c2}(-1)*Bs{c1}{c2}(-1))*(1 - theta{c1}) + d(XR{c2})*Bs{c1}{c2}(-1)')
model.add(f'YDhs{c1} = YDr{c1} + d(XR{c2})*Bs{c1}{c2}(-1)') # Eq. 12.2/12.5
# 3️⃣ 中央银行利润(含自持与跨境持有)
for c in countries:
# 自持部分:Bcbdcc
self_term = f'R{c}(-1)*Bcbd{c}{c}(-1)'
# 跨境部分:对所有他国 c2,持有其债券 Bcbsc c2 × 汇率 XRc2
cross_terms = " + ".join([f'R{c2}(-1)*Bcbs{c}{c2}(-1)*XR{c2}' for c2 in countries if c2 != c])
model.add(f'Fcb{c} = {self_term} + {cross_terms}') # Eq. 12.11/12.12
# 4️⃣ 政府预算约束(含本国债务滚动、税收、央行利润转移)
for c in countries:
model.add(f'Bs{c} = Bs{c}(-1) + G{c} + R{c}(-1)*Bs{c}(-1) - T{c} - Fcb{c}') # Eq. 12.13/12.14
⚠️ 关键注意事项
- 命名一致性是前提:确保所有变量严格遵循 {PREFIX}{COUNTRY} 或 {PREFIX}{COUNTRY1}{COUNTRY2} 模式(如 BsUKUS, BdUSUS),否则模板会失效;
- 避免过度嵌套:sum(...) 在 f-string 中用列表推导模拟,适用于中小规模国家集(≤50);超大规模建议预生成字符串池或使用 jinja2 模板引擎;
- Solver 兼容性:(-1) 是求解器语法,非 Python 运算符,f-string 仅作字符串拼接,无需转义;
- 调试友好性:可在循环内加入 print(f'[DEBUG] Adding: {eq}') 快速验证生成逻辑;
- 参数化扩展:将 theta, G, CONS 等参数存为字典(如 theta = {'UK': 0.25, 'US': 0.30}),使方程真正数据驱动。
✅ 总结:从“写代码”到“生成代码”
重构后,新增一个国家(如 'AU')仅需在 countries 列表末尾追加一行,全部 30+ 条相关方程自动覆盖,零手工修改。LOC 减少约 70%,错误率趋近于零,且天然支持参数敏感性分析(如批量修改 theta 字典)、多国对比绘图(for c in countries: plt.plot(data[c], label=c))。这才是面向建模者而非程序员的可持续代码设计。










