5D Library › 非遍历性财富动力学、凯利准则与波动率税 · English
第八章 实践与预注册试验
第一部分 四步生存与复利核查表
前七章可以归结为一份核查表,供家庭或小企业每年(或在重大决定之前)检查一次自己的现金流与配置。它不需要任何行情数据,只需要一张资产负债清单和过去一年的支出记录。
- 无收入存活月数。 如果收入明天停止,现有的流动资金能支付多少个月的刚性支出(房租或房贷、贷款、保险、学费;企业的工资、租金)?(第四章)
- 单一风险敞口占比。 最大的几项「单一风险」(一只股票、一个客户、一处房产、雇主的股份)各占净资产的多少?其中任何一项损失一半,会让你的净资产减少多少?(第三章、第六章)
- 再平衡纪律。 有没有写下来的目标比例?现在各部分是否偏离了目标超过事先规定的范围?(第五章)
- 参数高估折算。 你(或卖给你产品的人)假设的期望收益率是多少?把超额收益减半之后,按凯利公式算出的杠杆是多少?你现在实际使用的杠杆是否高于它?(第二章、第三章)
推导
核查表应用于两个虚构的案例:一个家庭和一家小企业。所有数字都是编造的。
# The four-step survival-and-compounding checklist applied to two FICTIONAL cases (every
# number invented). Amounts in thousands of any currency. Each position:
# (value, spread over many independent risks?).
H = dict(liquid=54, rigid_monthly=9, net_worth=600,
positions={"home equity": (250, False), "index fund": (150, True),
"bond fund": (40, True), "employer's shares": (100, False),
"cash": (54, True), "a friend's start-up": (6, False)},
targets={"index fund": 0.55, "bond fund": 0.20, "cash": 0.25}, band=0.05,
claimed_return=0.12, vol=0.18, rf=0.03, leverage_used=1.0)
F = dict(liquid=45, rigid_monthly=30, net_worth=400,
positions={"inventory": (120, True), "receivables, 40 customers": (100, True),
"one customer's contract": (160, False), "cash": (45, True)},
targets=None, band=None, claimed_return=0.25, vol=0.40, rf=0.03, leverage_used=2.0)
for name, c in (("household", H), ("small firm", F)):
print(f"== {name}")
nw = c["net_worth"]
# 1. months of rigid spending covered with zero income
months = c["liquid"] / c["rigid_monthly"]
print(f"1. survival without income: {months:.1f} months"
+ (" <- below 6, FLAG" if months < 6 else ""))
# 2. the largest exposures to a SINGLE risk, and what losing half would cost
single = sorted(((v[0], k) for k, v in c["positions"].items() if not v[1]), reverse=True)
for v, k in single[:2]:
print(f"2. single risk: {k}, {v / nw:.0%} of net worth;"
f" losing half costs {v / 2 / nw:.0%}")
# 3. rebalancing: is any sleeve outside its band?
if c["targets"]:
tot = sum(c["positions"][k][0] for k in c["targets"])
for k, t in c["targets"].items():
w = c["positions"][k][0] / tot
if abs(w - t) > c["band"]:
print(f"3. rebalance: {k} {w:.0%} vs target {t:.0%}"
f" (band +/-{c['band']:.0%})")
else:
print("3. rebalancing: no written target weights - write them down first")
# 4. haircut: halve the claimed excess return, then compare leverage with Kelly
ex = c["claimed_return"] - c["rf"]
k_full, k_cut = ex / c["vol"] ** 2, 0.5 * ex / c["vol"] ** 2
print(f"4. Kelly leverage: on the claim {k_full:.2f}; excess return halved {k_cut:.2f};"
f" half of that {0.5 * k_cut:.2f}")
print(f" leverage used {c['leverage_used']:.1f}"
+ (" <- above the haircut Kelly level, FLAG"
if c["leverage_used"] > k_cut else ""))
# == household
# 1. survival without income: 6.0 months
# 2. single risk: home equity, 42% of net worth; losing half costs 21%
# 2. single risk: employer's shares, 17% of net worth; losing half costs 8%
# 3. rebalance: index fund 61% vs target 55% (band +/-5%)
# 4. Kelly leverage: on the claim 2.78; excess return halved 1.39; half of that 0.69
# leverage used 1.0
# == small firm
# 1. survival without income: 1.5 months <- below 6, FLAG
# 2. single risk: one customer's contract, 40% of net worth; losing half costs 20%
# 3. rebalancing: no written target weights - write them down first
# 4. Kelly leverage: on the claim 1.37; excess return halved 0.69; half of that 0.34
# leverage used 2.0 <- above the haircut Kelly level, FLAG在这两个虚构的案例中,家庭有 6 个月的存活期,最大的单一风险是自住房产(占净资产 42%)与雇主的股份(17%:工作与股票押在同一家公司上,二者往往同时出问题);指数基金的比例比目标高出约 6.5 个百分点(61.5% 对 55%),超出了事先规定的范围;即使把假设的超额收益减半,它目前不加杠杆的配置也低于凯利水平。小企业则亮了两盏红灯:现金只够 1.5 个月的刚性成本,而且它的实际杠杆(2 倍)高于把假设收益减半之后的凯利水平(约 0.7 倍);最大的单一风险是一个客户的合同,占净资产 40%。
注
这份核查表不是投资建议,也不是评分工具。 「6 个月」「超额收益减半」「半凯利」这些数字是记录用的约定,不是经过验证的「最优值」;每个家庭和企业的收入稳定性、融资渠道和风险承受能力都不同。核查表的作用是在做决定之前,把最容易被忽视的问题列出来:你离吸收壁有多远,你的财富押在多少个独立的风险上,你的规则有没有写下来,你对收益的估计有多乐观。涉及具体的借贷、投资或保险决定,请咨询持牌的专业人士。
第二部分 一项预注册随机对照行为实验方案
问题
在一个重复的乘性投资任务中,把同一个风险资产用「算术期望收益与许多模拟玩家的平均最终财富」来描述,与用「中位数路径、时间平均增长率与最终低于起点的模拟玩家比例」来描述,是否会改变受试者选择的杠杆?
为什么做这个实验
第一章到第三章说明,在乘性的世界里,期望值高的选择未必是对一个人长期有利的选择。如果人们过度加杠杆的部分原因是展示方式让他们只看到了期望值,那么换一种同样准确、但强调时间平均的展示方式,就可能改变他们的选择。
证据
展示方式会改变风险选择。 贝纳茨与塞勒发现,让受试者看到股票收益在三十年期限上的分布、而不是一年期限上的分布,他们在退休账户中选择的股票比例明显更高 (Benartzi and Thaler 1999)。格尼兹与波特斯发现,在重复下注的实验中,让受试者更频繁地看到结果、更频繁地做决定,会降低他们承担的风险 (Gneezy and Potters 1997)。这些研究说明,同样的信息以不同的方式呈现,会改变人们的风险选择;方向取决于呈现的是什么。
设计
| 要素 | 规定 |
|---|---|
| 参与者 | 年满 21 岁的成年人,通过独立的在线调查样本库招募;不从作者企业的客户、合作伙伴或社群中招募;排除自报从事金融交易或投资顾问职业的人 |
| 任务 | 40 轮重复投资:每轮风险资产乘以 1.3 或 0.8,概率各一半;受试者每轮从 0 到 3 倍(每 0.25 一档)中选择杠杆,杠杆 L 使财富乘以 1 + 0.3L 或 1 − 0.2L;起始财富 100 点 |
| 激励 | 固定报酬加奖金,奖金与 40 轮后的最终财富成正比;在开始前明确告知 |
| 练习轮 | 正式任务前 5 轮练习,只展示两种结果及其概率,不展示任何汇总;练习轮的平均杠杆作为基线协变量 |
| 随机分组 | 1:1 随机分配,由平台自动完成。A 组(算术展示):资产的每轮期望收益,以及 10,000 名模拟玩家按受试者所选杠杆玩 40 轮后的平均最终财富。B 组(遍历展示):同一资产的每轮时间平均增长率,10,000 名模拟玩家的中位数最终财富与路径,以及最终低于起点的玩家比例。两组展示的都是同一组参数的正确计算结果,字数、版式与图表数量相同 |
| 盲法 | 参与者不知道存在两种展示方式和研究假设;任务全部由程序自动进行;分析者在分析完成前看不到组别标签 |
| 主要结局 | 40 轮正式任务中所选杠杆的平均值 |
| 次要结局 | 杠杆高于两倍凯利(约 1.67)的轮次比例;所选杠杆与凯利杠杆的距离 abs(L − L*),用来同时捕捉「过度谨慎」;最终财富 |
| 理解检查 | 两道关于任务规则的题目;未通过者按事先规定排除 |
| 分析 | 主要结局用线性回归,自变量为组别,协变量为练习轮基线杠杆;双侧 α = 0.05 |
关于激励需要特别说明:奖金与最终财富成正比时,一个只关心期望报酬的风险中性者应该每轮都选 3 倍杠杆(期望收益最高);一个关心典型结果的人应该选接近凯利的杠杆(约 0.83 倍)。所以这项实验不事先规定哪一种杠杆是「正确的」,它检验的是:同样准确的信息,换一种展示方式,是否会改变人们的选择。
推导
任务中不同杠杆的期望收益与时间平均增长率,以及事先写定的判定规则。
# The task and the decision rule, both fixed before data collection.
# Task: each round the asset's factor is 1.3 or 0.8 with equal probability; leverage L
# (0 to 3, in steps of 0.25) turns it into 1 + 0.3 L or 1 - 0.2 L.
import math
g = lambda L: 0.5 * math.log(1 + 0.3 * L) + 0.5 * math.log(1 - 0.2 * L)
grid = [i / 4 for i in range(13)]
print("leverage expected gain/round time-average growth/round")
for L in grid[::2]:
print(f"{L:8.2f} {5 * L:+19.1f} % {100 * (math.exp(g(L)) - 1):+24.2f} %")
best = max(grid, key=g)
print(f"best leverage on the grid: {best} (exact Kelly 5/6 = {5 / 6:.3f});"
f" expected gain rises up to L = 3")
# Share of players below their start after 40 rounds (exact, from the binomial count of
# up-rounds): what the ergodic display shows at each leverage.
for L in (5 / 6, 1.0, 2.0, 3.0):
below = sum(math.comb(40, k) for k in range(41)
if k * math.log(1 + 0.3 * L) + (40 - k) * math.log(1 - 0.2 * L) < 0) / 2 ** 40
print(f"L = {L:.2f}: {below:.1%} of players end the 40 rounds below their start")
# Decision rule. d = arm B (ergodic display) minus arm A (arithmetic display) in mean
# chosen leverage, standardised, with its 95 % CI. Lower leverage is the predicted way.
SESOI = 0.30
def verdict(d, lo, hi, comprehension_ok=True):
if not comprehension_ok:
return f"{d:+.2f}: NOT INTERPRETABLE - over 15 % failed comprehension in an arm"
if hi <= -SESOI: v = "B lowers leverage by at least the smallest effect of interest"
elif hi < 0: v = "B lowers leverage; size not shown to reach 0.30 SD"
elif lo > 0: v = "B RAISES leverage (opposite to prediction)"
elif lo >= -SESOI and hi <= SESOI: v = "no difference worth acting on"
else: v = "unclear"
return f"{d:+.2f} ({lo:+.2f} to {hi:+.2f}): {v}"
cases = ((-0.55, -0.73, -0.37), (-0.45, -0.63, -0.27), (-0.15, -0.33, 0.03),
(-0.20, -0.36, -0.04), (0.05, -0.13, 0.23), (0.25, 0.07, 0.43))
for case in cases:
print(verdict(*case))
print("Secondary, reported with intervals, never decisive: share of rounds above 2 x Kelly;")
print("distance |L - L*|, which also catches over-caution; final wealth.")
# leverage expected gain/round time-average growth/round
# 0.00 +0.0 % +0.00 %
# 0.50 +2.5 % +1.73 %
# 1.00 +5.0 % +1.98 %
# 1.50 +7.5 % +0.75 %
# 2.00 +10.0 % -2.02 %
# 2.50 +12.5 % -6.46 %
# 3.00 +15.0 % -12.82 %
# best leverage on the grid: 0.75 (exact Kelly 5/6 = 0.833); expected gain rises up to L = 3
# L = 0.83: 21.5% of players end the 40 rounds below their start
# L = 1.00: 31.8% of players end the 40 rounds below their start
# L = 2.00: 56.3% of players end the 40 rounds below their start
# L = 3.00: 86.6% of players end the 40 rounds below their start
# -0.55 (-0.73 to -0.37): B lowers leverage by at least the smallest effect of interest
# -0.45 (-0.63 to -0.27): B lowers leverage; size not shown to reach 0.30 SD
# -0.15 (-0.33 to +0.03): unclear
# -0.20 (-0.36 to -0.04): B lowers leverage; size not shown to reach 0.30 SD
# +0.05 (-0.13 to +0.23): no difference worth acting on
# +0.25 (+0.07 to +0.43): B RAISES leverage (opposite to prediction)
# Secondary, reported with intervals, never decisive: share of rounds above 2 x Kelly;
# distance |L - L*|, which also catches over-caution; final wealth.一个事先写明的反方向假设
遍历展示可能让受试者过度谨慎:看到高杠杆下(L ≥ 2)「过半的模拟玩家最终低于起点」之后(40 轮后,凯利杠杆下约 21.5% 低于起点,L = 1 约 32%,L = 2 约 56%,L = 3 约 87%),有人可能选择远低于凯利的杠杆,甚至完全不投资。本实验把「与凯利杠杆的距离」作为次要结局事先登记:如果 B 组的平均杠杆更低、但与凯利的距离并没有缩小(因为大量受试者从过度加杠杆变成了过度谨慎),报告必须同时写明这一点。
样本量
推导
# Sample size for the pre-registered randomised behavioural experiment. Participants play
# the same repeated multiplicative investment task (40 rounds; each round they choose a
# leverage from 0 to 3 on a risky asset; bonus proportional to final wealth). Arm A sees
# the asset described by its arithmetic expected return and the AVERAGE final wealth of
# many simulated players; arm B sees the same parameters as the MEDIAN path, the
# time-average growth rate and the share of simulated players ending below the start.
# Primary outcome: mean chosen leverage over the 40 rounds. Two-sided alpha 0.05.
import math
from statistics import NormalDist
N = NormalDist()
def n_per_arm(d, alpha=0.05, power=0.90):
# normal-approximation formula, rounded up, plus 1 to allow for using the t distribution
return math.ceil(2 * (N.inv_cdf(1 - alpha / 2) + N.inv_cdf(power)) ** 2 / d ** 2) + 1
for d in (0.20, 0.25, 0.30, 0.40):
print(f"standardised effect {d:.2f}: {n_per_arm(d, power=0.8):4d} per arm for 80 % power,"
f" {n_per_arm(d):4d} for 90 %")
n = n_per_arm(0.30)
recruit = math.ceil(n / 0.85)
print(f"chosen: 0.30 SD, 90 % power -> {n} analysable per arm")
print(f"recruit {recruit} per arm allowing 15 % exclusions (comprehension checks),"
f" {2 * recruit} in all")
# Baseline leverage (mean of 5 practice rounds, before any display appears) enters the
# analysis as a covariate. If it correlates r = 0.5 with the outcome, power rises; the
# sample is still sized without it, leaving a margin.
r = 0.5
pw = N.cdf(0.30 / math.sqrt(2 * (1 - r ** 2) / n) - N.inv_cdf(0.975))
print(f"with a baseline covariate correlating {r}: power for 0.30 SD at n = {n} is {pw:.3f}")
# standardised effect 0.20: 394 per arm for 80 % power, 527 for 90 %
# standardised effect 0.25: 253 per arm for 80 % power, 338 for 90 %
# standardised effect 0.30: 176 per arm for 80 % power, 235 for 90 %
# standardised effect 0.40: 100 per arm for 80 % power, 133 for 90 %
# chosen: 0.30 SD, 90 % power -> 235 analysable per arm
# recruit 277 per arm allowing 15 % exclusions (comprehension checks), 554 in all
# with a baseline covariate correlating 0.5: power for 0.30 SD at n = 235 is 0.964按最小关注效应 0.30 个标准差、双侧 α = 0.05、90% 把握度计算,每组需要 235 名可分析的参与者;考虑到约 15% 的参与者可能因未通过理解检查而被排除,每组招募 277 人,共 554 人。加入练习轮基线作为协变量后,如果它与主要结局的相关为 0.5,把握度会提高到约 96%;样本量仍按不使用协变量计算,留出余量。
这项实验不能说明什么
第一,这是一个实验室任务。参与者面对的是一个参数完全已知、每轮独立的两点赌局,奖金的数额也远小于真实的投资;他们在任务中的选择,不一定等于他们在真实账户中的行为。
第二,两种展示方式同时改变了几样东西(期望值还是中位数、平均财富还是低于起点的比例、数字还是路径图),阳性结果不能说明是哪一样起作用。
第三,实验不能说明哪一种杠杆是「对」的。正如上面所说,在与最终财富成正比的激励下,最大化期望报酬与最大化典型结果给出不同的答案;这正是本书讨论的问题,而不是实验能替人回答的问题。
第四,结果不论正负都会发表,代码与方案在数据收集之前公开登记。
利益披露
作者创办并经营 Asia Influencer X 与 Yafu Global,从事网红营销与数字营销业务,不持有任何金融服务牌照。本实验设计为由独立于作者企业的研究人员实施和分析,不从作者企业的客户、合作伙伴或社群中招募参与者;书中所有代码与方案均公开,供任何人检验。作者亦将本书及自用脚本(个人看盘学习用,不对外销售)作为其社群课程、升维牌卡(5D Ascension Cards)与 Yafu AI 知识库的方法论参考;作者不持有任何金融服务牌照,不提供任何投资顾问、代客理财或交易信号服务。
本章小结
全书的结论可以归结为四个问题:你离吸收壁有多远;你的财富押在多少个独立的风险上;你的再平衡规则有没有写下来;你对收益的估计有多乐观。本章用两个虚构的案例演示了这份核查表,并给出一项预注册的随机对照行为实验方案:比较算术展示与遍历展示对重复乘性投资任务中所选杠杆的影响,每组 235 人可分析、招募 277 人,判定规则与反方向假设都事先写定。
参考文献
Fan, Y. (2026). Non-Ergodic Wealth Dynamics, the Kelly Criterion and Volatility Drag: From Itô's Lemma on Geometric Brownian Motion and Ruin Barriers to Barbell Portfolios, Read Beside the Shiji's 'Biographies of the Money-Makers' [非遍历性财富动力学、凯利准则与波动率税] (Version 1.0.0). 5D Library. https://doi.org/10.5281/zenodo.23754709 · Licensed under Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0).