最近做了一个记账项目,叫 SquirrelFin,小松鼠。它是一款安卓优先、本地保存的个人财富记录工具,界面里有一句话:“把财富,慢慢攒好。”
除了记录每天的收入和支出,我还把现金、投资、负债和贵重物品放进了同一本账里,并加了一组叫“生命能量”的功能:一笔消费相当于多少劳动投入,手里的钱按现在的支出速度大约能支撑多久。
这篇文章介绍一下它现在能做什么,以及这些功能背后的设计取舍。
项目地址:tyrantqiao/SquirrelFin。本文按本地源码 0.1.33 整理,后续变化以仓库说明为准。
从记收支,到看清自己的财富
记账最直接的问题是“这个月花了多少钱”,但把时间拉长,还会遇到另外一些问题:
- 钱分别放在哪里?现金、投资和欠款加起来,还剩多少?
- 投资账户余额涨了,是赚到了钱,还是刚刚又转进去一笔本金?
- 买过的贵重物品,如果出售,大概能收回多少钱?
- 一笔消费对应多少工作时间?如果暂时没有收入,现有资金能维持多久?
SquirrelFin 围绕这些问题,把日常流水、资产盘点和时间换算连在一起。首页负责展示财富概况与今日收支,具体账户和估值记录则进入资产页查看。
先让“记一笔”足够轻便
日常记账入口使用大号金额和数字键盘,支出用途可以点选图标,账户、日期等信息按需展开,保存后可以继续记下一笔。备注也能检索本地历史内容,减少重复输入。
分类上,我把“花在哪里”和“属于什么性质”分开了。例如,午饭和聚餐都可以属于餐饮,但一笔是日常开销,另一笔可能是偶发消费;房租属于居住,同时也是固定支出。这样看月度支出时,既能按用途分析,也能理解开支结构。
对房租、会员等经常出现的开支,可以保存常用模板,保留账户、金额、分类和每月或每年的标记。模板需要手工确认才生成流水,不会自动扣款或在后台悄悄记一笔。
如果之前已经在文本里记过账,也可以粘贴文字,或者选择 UTF-8 的 TXT、Markdown 文件导入。导入先展示预览,提示错误行和疑似重复,再由用户核对账户、确认追加,不直接把整份文本写到账本里。
把资产放在一起,但保留它们的区别
小松鼠支持登记现金、投资、贵重物品和负债,也可以记录存放位置与手工风险标签。
这里有两个需要分清的数字:
金融净资产 = 现金 + 投资 − 负债
含实物估值净资产 = 金融净资产 + 贵重物品预计变现净额
例如,相机的购入成本和现在预计能卖出的金额是两回事。实物残值由用户自己估计,不是平台报价,也不等于可以立即取用的现金。出售后,残值归零,到账资金另外留下流水,避免同一件东西被重复计入财富。
同样,从现金账户转钱到投资账户,只是钱换了一个位置,不应该让总财富凭空增长。内部转账也不会被算成日常消费。
余额增加,不一定是投资收益
投资记录里,我比较在意的一点是:不能只用账户余额的变化来判断赚了多少。
假设期初有 10,000 元,期间追加了 2,000 元,期末变成 12,500 元。余额增加了 2,500 元,但收益金额是:
收益 = 期末估值 − 期初估值 − 区间净投入
= 12,500 − 10,000 − 2,000
= 500 元
SquirrelFin 可以更新资产估值、保留历史记录,并核对期间追加、取出和分红等资金进出。没有现金流时展示持有期收益率;存在不规则现金流时,使用 XIRR 计算历史年化收益率。
不过,计算有前提:相关现金流需要先确认完整。补录或删除历史交易,会撤销受影响估值的核验状态;数据不足、无解或发现多解时,也不会给出一个确定的收益率。
估值本身还有日期边界:初始金额视为登记当天后续流水发生前的余额,后续估值视为当日日末余额,已经包含当日交易。收益只计算到最后一次估值日期,避免把旧估值误当成实时资产价格。
“生命能量”:用时间重新理解钱
这是小松鼠里我想重点介绍的部分。它把两种时间分开处理:为一笔消费投入的劳动时间,以及现有资产能够覆盖的生活时间。
一笔消费,需要多少劳动投入
只拿月工资除以工作时间,可以得到工资时薪。但工作往往还有额外成本,也会占用通勤和恢复时间。所以应用另外提供了一个可选的“真实时薪”:
真实时薪 =(税后劳动收入 − 工作附加成本)
÷(工作时间 + 通勤时间 + 额外恢复时间)
工作成本只填写因工作额外发生、个人承担且未获报销的部分;恢复时间也只填写工作额外带来的部分,几项时间不能重叠。
用一组假设数字举例:税后月收入 12,000 元,工作附加成本 1,000 元,每月工作 176 小时、通勤 22 小时、额外恢复 22 小时,真实时薪就是 50 元。一笔 300 元的消费,对应约 6 小时的劳动投入。
这个换算提供的是另一个观察角度,不替人判断消费是否值得,也不代表真的能少工作 6 小时。用户可以随时关闭换算,账务金额不会改变。
工资和工作成本可以从明确标记的流水汇总,也支持手工填写。时薪档案有生效日期,历史消费按交易日期匹配档案,避免所有旧流水都套用今天的工资水平。
手里的钱,能覆盖多久的生活
资产续航使用另一套分母:已记消费的平均支出速度。
支出时薪 = 区间已记消费 ÷(自然日数 × 24)
可支撑时长 = 资产余额 ÷ 支出时薪
例如,一个完整的 30 天里记了 6,000 元消费,平均每天花 200 元。如果现金余额是 30,000 元,按同样的支出速度,大约能覆盖 150 天。
这里不需要先设置工资档案。它回答的是现有资金能覆盖多久的开支,而真实时薪回答的是消费对应多少劳动投入,两者不能混用。
资产页默认看现金,还可以展开金融净资产、含实物估值净资产全部变现的情景。支出基准可选本月截至今日、上个完整月或近三个完整月。
这些都是静态估算:假设不再有收入、支出速度不变,不计未来收益。现金情景未一次性扣清全部负债,其他情景则假设资产能按登记估值变现并清偿负债。漏记支出会高估续航;没有正值支出记录时,应用不会显示“无限续航”。
本地保存,也把备份责任交给自己
目前的版本没有登录、账本服务器和广告。安卓账本保存在应用私有目录,浏览器预览版使用 localStorage,两边的数据独立保存。
应用的联网用途是检测 GitHub Release 更新和下载安装包,账本不会上传。金额防窥可以隐藏界面上的金额及相关换算结果,完整账本则支持 JSON 导出与恢复。
本地保存需要配合备份使用:卸载应用或清除数据可能丢失记录。导出的 JSON 是明文,当前也没有应用锁或额外数据库加密,因此需要自己妥善保存备份文件。
实现上保持简单
界面采用暖灰背景、鼠尾草绿和简约卡片,希望让每天打开、记一笔的过程轻一些。代码结构也比较直接:
| 部分 | 实现 |
|---|---|
| 界面与交互 | HTML、CSS、JavaScript |
| 账务计算 | 独立的 engine.js,供浏览器与 Node.js 使用 |
| 安卓端 | Java WebView 外壳,本地原子文件写入与系统文件选择器 |
| 电脑预览 | Node.js 本地服务,无第三方运行依赖 |
金额以整数分存储,财务计算与界面代码分开。项目的自动化测试覆盖本金与收益区分、内部转账、XIRR、估值日期边界和备份关联校验等规则。对这个工具来说,先把一笔钱的来源、去向和统计口径算清楚,再展示结果,是很重要的基础。
如何试用
安卓试用入口在 GitHub Releases,具体安装包和校验文件以发布页为准。当前源码版要求 Android 8.0 及以上,使用开发签名,仍属于试用性质。
如果想先在电脑上看看,可以克隆源码并启动预览:
git clone https://github.com/tyrantqiao/SquirrelFin.git
cd SquirrelFin
npm start
然后打开 http://127.0.0.1:4173。默认是空账本,也可以选择明确标注的示例数据体验。浏览器预览与 APK 共用界面和计算模块,但浏览器表现不能替代安卓真机验证;当前项目文档仍将真机运行、软键盘和覆盖安装列为未验证事项。
我希望小松鼠能让记下来的数字多一点用途:既知道这个月花了什么,也知道钱现在在哪里、资产变化来自哪里,以及这些钱和自己的时间有什么关系。
源码、使用说明与版本记录都放在 SquirrelFin 仓库,欢迎试用和反馈。