Code review · 2026-08-17

三层不是竞品。
硬并会毁边界。

x-margin 是真钱账本,Harvest 是公开数据湖,OHLC 是研究与纸面交易台。这份报告把 x-margin 的账本缺陷放回整条投资栈里看。

0仓库 / 三层分工
0x-margin 已核实问题
0安全边际实现
SQLite真钱唯一落点
UI 已经收敛,账本还没有。x-margin 不是「小而美、补补文档就行」。它是这条链上唯一真实资金路径,却没有备份、没有 schema 迁移、卖超仓只 clamp。

GitHub 简介写「quantifies your margin of safety」。代码里没有内在价值、没有安全边际、没有估值字段。现在是净值 + XIRR + 退休投影。

三层分工

Supply

Harvest

把公开市场与另类数据采进 Mongo / ClickHouse。运维用,不是投资产品。

Judgment

OHLC

选股、回测、信号、A 股纸面账户。行情来自网关 + 只读 Harvest。

Book

x-margin

记你的真钱。离线、手工价、本地 SQLite。不读湖。

flowchart TB M[公开市场与披露] -->|抓取| H[Harvest
Mongo SoT + CH 时序] H -->|只读契约| O[OHLC
PG SoT + CH 副本] O -->|纸面买卖 T+1| P[Paper Account
不是真钱] U[券商流水 / 手工价] -->|手录| X[x-margin SQLite] X --> N[净值 · XIRR · 退休] X -.->|不要接| H O -.->|不要混域| X

图:数据只从湖流向研究台。真钱账本独立。虚线是禁止的耦合。

读懂 x-margin

个人真实资金净值账本。单页 dashboard,无路由。模态录入 → createServerFnbetter-sqlite3 → hook 全量重算。

文件职责
实体src/lib/db-schemas.ts现金账户、存取转、持仓、买卖/分红/拆股/费用、价格快照、退休设置
账本position-state / portfolio / xirr / retirement持仓状态、现金、XIRR、退休投影
写入src/server/*几乎无业务校验的 CRUD;删账户 CASCADE 买卖流水
展示src/routes/index.tsx账户 / 流水 / 组合 / 持仓 / 退休

阅读顺序:db-schemas.tsdb.tsposition-state.tsportfolio.tsuse-portfolio-history.tsindex.tsx

它不问市场现在多少钱,只记你说买了什么、你报的价。这是设计,不是缺口。

对照表

维度x-marginHarvestOHLC
一句话记我的真钱把公开数据采进湖用湖做研究 / 模拟
用户投资者运维研究员
钱是真的吗是。现金 + 持仓由流水推导否。公募披露持仓、价快照否。Paper Account,T+1
价格从哪来手工 price_snapshotsYahoo / 通达信 / 巨潮 / 东财…PG 日线 + 网关;港美日线主源是 Harvest CH
持久化单机 SQLiteMongo SoT + CH + RedisPG SoT + CH 副本;跨库只读 Harvest
在线刻意离线生产常驻计算/存储分离同拓扑;CLI / Web / GraphQL / bots
备份每日 mongodump 滚动保留PG dump;CH 可重建
领域模型无 CONTEXT.md源 / 类别 / 跨仓契约10 个 bounded context + ADR
成熟度0.0.1,无 CI生产在跑,有 CI0.75.1,NO GREEN NO MERGE
依赖另外两个被 OHLC 只读硬依赖 Harvest(ADR-0037 / 0044)

OHLC 的 ohlc portfolio / avgCost 是模拟盘或市场筹码分布,不是税基。Harvest 的 fund_holdings 是基金公司持仓披露。

成熟度雷达

主观评分,只用来对照工程纪律,不是产品分。x-margin 的 UI 分高,账本与运维分低。

x-margin:已核实的账本问题

审计对象 XFreeCoder/x-marginHEAD 2b6d827。未跑测试(仓库无安装)。未启动桌面壳。

#问题影响工作量
1 历史曲线漏掉分红和费用 use-portfolio-history 把分红/费用写死成 0。Analytics 累计收益画错。 S
2 卖超仓只 clamp 持仓变 0,卖出金额全进卖出所得,投入成本不动。卖出表单不看持仓。 S
3 删现金账户 CASCADE 买卖流水 对话框只报 cash record 数。算了 txCount 没用。持仓成本 silently 变。 S
4 XIRR 失败显示 +0.00% 牛顿法不收敛或现金流同号时,主面板年化收益看起来是零。 S
5 positive() 拒绝 0 免佣、0% 通胀、0 储蓄存不进去。设置文案还说开支按通胀增长,实现是 Fisher 折现。 S
6 生产 mapRow 不跑 Zod 只在 DEV safeParse,然后 as T。坏行进 Decimal / UI。 S
7 没有 schema migration 只有 CREATE IF NOT EXISTS。现有用户库加列是空操作。 M
8 写路径零测试 四个 lib 单测。XIRR / 退休大量 not.toBeNull()。上面 1–4 都漏了。 M
9 无 CI;TanStack 钉 latest 脚本在,没人跑。八个 @tanstack/* 是浮动版本。 S
10 文档与代码相反 README 写 localStorage;AGENTS 写 server functions unused;mock-data 指向已删脚本。 S

看过、否掉

  • getDb 并发竞态 — 同步函数,JS 单线程。
  • 未鉴权 server fn = 漏洞 — 本地单用户,没有证据绑了非 loopback。
  • 全表 SELECT * / 历史 O(dates×positions) — 个人账本量级,现在优化是投机。
  • 把 14 个 create/update 收成 factory — 刚按类型拆开。
  • tsconfig.exclude: ["server"] 跳过 src/server — 排除的是仓库根 server/

不该做的事

  1. 不要把真钱账本塞进 OHLC。 会和 Paper Account 混域,且 OHLC 是在线多服务,违背离线前提。
  2. 不要让 Harvest 存个人持仓。 它是湖,不是 PMS。
  3. 现在不要给 x-margin 接行情。 产品写明手工价。真要接,只读 OHLC / Harvest,当填价助手,别当账本源。

唯一真重叠:两边都有「账户 + 流水推持仓 + 均价」。差在 OHLC 是 A 股 T+1、印花税、收盘价结算;x-margin 是多品种、手工价、XIRR、退休。

下一步

对照另外两个,x-margin 缺的是账本正确性和备份,不是再做一个迷你 OHLC。

  1. 先写钱路径的表征测试(含历史分红、超卖、级联删除)。
  2. 修 #1–#4:历史收益、超卖拒绝、删账户、XIRR 空值。
  3. 加 schema version,再谈任何表结构变更。
  4. 导出 / 导入 / 显示数据库路径。Harvest 有滚动备份,x-margin 重装即清盘。
  5. Deno Desktop × better-sqlite3 先实证再谈发布。
依赖:测试必须先于改历史计算和改删除语义。没有 migration 就不要改 schema。

方法与限度

  • 对象:x-margin(克隆审读)+ Harvest + OHLC 本地仓库。
  • 方法:README / CONTEXT / AGENTS / ADR + 源码交叉检索。无 Understand-Anything 图谱。
  • 未做:三仓都没在本轮启动;x-margin 未跑 typecheck / test(无 node_modules)。
  • 脱敏:本页不含内网地址、凭据、SSH、数据库连接串。

结论强度:架构与缺陷来自源码对照。三层应保持分离是推断。Deno Desktop 能否加载 native SQLite 未实测。