编译产物反向工程 · asset-divergence-lab

老破小排序器

把「北京房产价值评估」的打分链路从压缩后的 JS 里完整还原,再用它自己公开的 8663 条小区数据跑一遍。结论:那个叫「决策价值分」的东西,和它宣称衡量的居住品质统计上无关

拆解对象 LiuLi4/asset-divergence-lab 数据 community-values.json · 8663 条 拆解日期 2026-08-20

公式全部还原完毕,我用 Python 重写后与它公开数据中的已有字段逐条对齐验证:流动性分 2769 条 100% 吻合,品质分四维加权 R²=0.78。

还原之后能看清一件事:「决策价值分」的排序,几乎完全由「比周边便宜多少」和「180 天成交几套」两个开关决定。品质分在其中被稀释到近乎不起作用——决策分 Top 100 的小区,品质分中位数是 79;全市中位数也是 79。

01

还原出的完整计算链路

五层,全部是确定性的线性加权,没有任何机器学习成分。前两层在数据管线里算好写进 JSON(私有仓库),后三层在浏览器里实时算。

01

品质分 · qualityScore

品质 = 职住 ×30% + 生活 ×20% + 交通 ×15% + 环境 ×20% + 户型 ×15% 职住 = 到最近的 7 个硬编码就业中心的大圆直线距离分段: ≤2km→75 ≤5km→69 ≤8km→62 ≤12km→54 ≤18km→45 ≤25km→36 >25km→25

就业中心是七个写死的经纬度点(金融街、国贸 CBD、中关村、上地/西二旗、望京、亦庄、运河商务区)。界面上这一项的说明写的是「高峰门到门时间、核心岗位密度、路线稳定性与新增供给压力」——实际实现里一个都没有,只有直线距离。作者在数据里老实标了「覆盖度 40%,仅作通勤弱代理」,但用户看不到。户型维度在小区层根本不评分。

02

流动性分 · liquidityScore

流动性 = min(40 + 5 × 近180天成交套数, 100)

就这一行。2769 个已评分小区百分之百吻合,我逐条比对过。不除以小区总户数、不看挂牌量、不看去化周期。成交满 12 套即封顶。结果是大盘天然满分、小院永远垫底。

03

价格机会分 · priceOpportunityScore

价格机会 = clamp(50 + 同质折价% × 3.5, 0, 100) 而 同质折价 本身已被硬夹在 ±30%

系数 3.5 意味着:折价只要超过 ±14.3%,分数就被压成 0 或 100。实测 2769 个已评分小区里,46.7% 落在这两个端点上(707 个 0 分、586 个 100 分)。这一层实际上被退化成了一个三值开关。

04

资产性分 & 砖头风险分

证据置信 = 市场置信 ×70% + 五维覆盖度 ×30% 资产性 = 品质 ×55% + 流动性 ×25% + 证据 ×20% − 风险扣分 砖头风险 = 100 − (品质 ×50% + 流动性 ×30% + 证据 ×20%) + 风险扣分 ×1.5

砖头风险几乎是资产性的镜像,两者共用同一批输入,只是权重和符号不同。全量数据上砖头风险最高只到 64——而判定「砖头型」的阈值是 65。

05

决策价值分 · purchaseValueScore

原始分 = 资产性 ×55% + 价格机会 ×30% + 流动性 ×10% + 证据 ×5% 若 证据置信 < 40 → 封顶 64 若 品质 ≤ 60 或 资产性 < 55 → 封顶 64 分档:≥80 强 / 65–79 观察 / <65 谨慎

这就是地图上每个点的颜色。展开看:品质分的实际权重是 55%×55% = 30.25%,而价格机会(30%)加流动性(55%×25% + 10% = 23.75%)合计 53.75%——已经过半。再叠加第 02、03 层的极端截断,品质那 30% 基本被淹没。

02

三个致命发现

系统性偏差

它把「体量大的老破小」评成了北京最值得买的房子

这不是抽样印象,是把全部 2769 个已评分小区跑完之后的分布事实。

按还原出的决策价值分排序,三组样本对照(单价单位:元/㎡,均为中位数)
样本组参考单价同质折价180天成交品质分单价/周边中位价
决策分 Top 10042,694+19.8%14790.88
全市 2769 个已评分54,904−0.1%3791.02
决策分 Bottom 10065,456−27.6%175
79 / 79
Top 100 的品质分中位数 / 全市品质分中位数——完全没有区分
56
品质分最高的 20 个小区,决策分中位数只有 56,落在「谨慎」档
77 / 61
Top 100 中价格机会满分的个数 / 流动性满分的个数

机制很清楚:大体量老小区 → 成交套数多 → 流动性 100房龄老 → 比周边次新便宜 → 折价 >14.3% → 价格机会 100。两个满分叠加,直接冲上全市榜首。而真正决定居住品质的那一层,权重只剩三成,且分布本身极度压缩(全市标准差仅 7.9,一半小区挤在 75–84 之间)。

它把「持续比周边同类便宜」读成了买入机会。但在真实的北京二手房市场上,同地段同类型长期折价通常意味着房子有具体问题——顶层、临街、朝向、房本、单位产权、无电梯。模型没有房龄、没有产权性质、没有学区,所以分不出「便宜是因为被低估」还是「便宜是因为有毛病」。

小红书评论区已经有人凭直觉指出来了:

为何海淀区评分高的小区大多数是老旧公房小区和回迁房小区?其实不太受市场欢迎 —— 小红书用户评论,2026-08-19

她说对了,而且原因就在上面那两行公式里。

还原出的全市决策价值分 Top 15。注意价格机会与流动性两列几乎全是满分
决策分小区品质价格机会流动性参考单价
94本家润园(C区)东城9110010079,690
94冠城名敦道(A区)东城8910010058,385
92上元君庭朝阳8310010062,754
92弘善家园朝阳8510010037,790
91芳城园(一区)丰台8010010045,996
91三环新城7号院丰台8110010043,993
91西罗园四区丰台8110010037,181
91汇锦苑丰台8010010037,046
91都会华庭朝阳859610051,699
91九龙花园朝阳8010010049,303
91怡美家园海淀799910067,192
91志新村小区海淀8110010067,660
91清上园海淀8010010059,068
91明光村小区海淀7910010075,607
91时尚街区西区通州8010010028,428
死代码

宣传的「三型判断」,有两型在全量数据上永远触发不了

小红书文案写的是「资产型看保值与流动性,收租型看净租金与抗空置,砖头型识别折旧和退出风险」。还原出判定逻辑后逐条验证:

  • 收租型 / 混合型——判定依赖 rentalEvidence(年租金、空置率、持有成本、租客需求)。公开数据 8663 条里 0 条有这个字段。界面永远显示「待补租金、空置与成本」。
  • 砖头型——需要砖头风险分 ≥ 65。全量数据上该分最高 64,已评分小区中触发数为 0
  • 实际只输出两种:资产型 1261 个、不确定 1508 个

宣称的三分类框架,三分之二是空转的。这一条我不认为是有意误导——更像是模型设计走在了数据前面,管线没跟上。但对着屏幕做决策的人分不出这个区别。

时效

成交数据落后整整一年,界面上标的却是「近 180 天」

把 2896 条带成交日期的记录全部拉出来:最新一笔 2025-08-01,最早 2025-02-07,集中在 2025 年 6–7 月。今天是 2026-08-20。

与此同时,OSM 那部分证据的采集时间戳是 2026-08-09,公积金和 LPR 政策更新到 2026-08-08——都是新鲜的。三套时间尺度差了一整年的数据被拼在同一张卡片上,界面不作区分。

更麻烦的是这个字段直接喂给了流动性分。所谓「近 180 天成交 14 套」,实际是一年前的那 180 天成交了 14 套。上游数据源 flowerwithoutbee/beijing-property-dashboard 最后推送于 2026 年 4 月,本身也已停更。

03

公平地说,它做对的部分

金融测算那一半是真下了功夫的,和空间评分不是一个水准:公积金与商贷分账、等额本息逐月摊还、买房与租房理财的双路径终值对比、用二分法反解「临界房价涨幅」、双变量压力测试。政策常量全部带来源和文号——京建发〔2026〕400 号、公积金中心业务问答、2026-07-20 的 LPR——还做了「超过 72 小时提示复核、超过 7 天标记过期」的机制。

数据自身的诚实度也高于行业平均:每个维度都带 coverage 字段(环境只标 25%、职住只标 40%),8663 个小区里 5894 个主动标为「证据不足,暂不评分」,界面反复写着「分数不是结论,只是下一步实地核验的顺序」。

问题出在传播层:这些边界写在 JSON 字段和小字里,而首页给出的是一张全北京彩色打分地图。普通用户拿走的是颜色,不是覆盖度。

04

自己复现

下面这段能完整重跑第 01–05 层。数据文件直接从它的公开仓库取,无需登录。

# 1. 取数据(仓库只有编译产物,源码在私有仓库,但数据是公开的)
git clone --depth 1 https://github.com/LiuLi4/asset-divergence-lab.git
cd asset-divergence-lab/site

# 2. 还原出的核心公式(Python)
import json, math

clamp = lambda v,lo,hi: min(hi, max(lo, v))

# 第 03 层:价格机会分(源码里的 Xf / Gc)
price_opp = lambda disc: clamp(50 + disc * 3.5, 0, 100)

# 第 04 层:资产性分(源码里的 cc)
def asset(q, liq, ev, risk):
    return round(clamp(q*.55 + liq*.25 + ev*.2 - max(risk or 0, 0), 0, 100))

# 第 04 层:砖头风险分(源码里的 vf)
def brick(q, liq, ev, risk):
    return round(clamp(100 - (q*.5 + liq*.3 + ev*.2) + max(risk or 0,0)*1.5, 0, 100))

# 第 05 层:决策价值分(源码里的 wf)
def purchase_value(q, po, liq, ev, risk):
    a = asset(q, liq, ev, risk)
    r = a*.55 + po*.3 + liq*.1 + ev*.05
    if ev < 40:            r = min(r, 64)
    if q <= 60 or a < 55:  r = min(r, 64)
    return round(clamp(r, 0, 100)), a

# 3. 验证「流动性 = 40 + 5×成交」这条(应输出 100%)
c = [x for x in json.load(open('data/community-values.json'))['communities']
     if x['dataStatus'] == 'scored']
ok = sum(x['liquidityScore'] == min(40 + 5*x['transactions180d'], 100) for x in c)
print(f'流动性公式吻合率 {ok/len(c):.1%}')   # → 100.0%

证据置信那一层还要叠一个五维覆盖度加权(证据 = 市场置信×70% + 覆盖度×30%),覆盖度按第 01 层同一组权重、用每个小区 qualityEvidence.coverage 里的实际值算。上面表格里的全部数字都是这样跑出来的。

05

对规划口的意思

这份拆解真正值钱的地方不在于挑出了毛病,而在于它演示了一件事:当空间品质的度量做不细时,它在综合评分里会被自动挤出去。

这里的品质分名义权重 55%,实际影响权重 30%,而且因为底层只有 OSM 邻近性、分布压缩在 20 分区间内,它在排序上几乎不产生位移。真正驱动排序的是两个能拉出满分差距的粗变量——便宜、好卖。模型不是不想看品质,是品质那一侧的信号太弱、太平,压不过另外两侧的极端值。

而「品质那一侧的信号」恰恰是规划口手里有、市面上没有的东西:真实路网的步行时间而非大圆距离、按格点算的岗位可达而非七个硬编码质心、进出站客流、房龄与产权性质、更新与征收预期、管控边界。把这些接进去,第 01 层的分布立刻能拉开,第 05 层的排序也就跟着变了。

换句话说,它现在的样子不是方法论选择,是数据约束的必然结果。