Files
MoFin/docs/portfolio-data-model.md
T
知微 7d49470aeb 总资产公式修复+数据模型文档
bugfix: price_monitor写total_assets时漏算frozen_cash
  公式修正: total_assets = market_value + cash + frozen_cash
  影响: price_monitor两处公式 + stale_push_wlin fallback路径

docs: portfolio-data-model.md 新增
  数据模型字段说明
  现金流更新规则
  常见错误清单
2026-06-29 22:35:07 +08:00

116 lines
3.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# portfolio.json 数据模型
## 一句话
**总资产 = 持仓市值 + 可用现金 + 冻结资金**,三个数字必须全对,缺少任何一项数字就不对。
## 字段说明
```jsonc
{
// 持仓列表(price_monitor 每2分钟更新价格)
"holdings": [
{
"code": "01888", // 股票代码
"name": "建滔积层板", // 股票名称
"shares": 500, // 持股数
"price": 83.59, // 最新价(CNY!所有股票统一人民币计价)
"cost": 88.23, // 成本价(CNY
"market_value": 41795.0 // 市值 = shares × price
}
// ...
],
// 现金(从 Dad 截图来源更新,price_monitor 不碰!)
"cash": 92678.85, // 可用资金(人民币)
"frozen_cash": 39481.40, // 冻结资金(T+2未交收/挂单占用)
// 汇总(price_monitor 每2分钟自动重算)
"total_mv": 835552.6, // 持仓市值 = Σ(shares × price)
"total_assets": 967712.85, // 总资产 = total_mv + cash + frozen_cash
"position_pct": 86.3, // 仓位% = total_mv / total_assets × 100
// 元数据
"currency": "CNY", // 本文件所有价格均为人民币
"updated_at": "2026-06-29 22:33:00", // 最近一次更新
"source": "holding.xls / manual", // 持仓来源
"data_model_version": "2" // 数据模型版本(防止新旧数据混淆)
}
```
## 现金流
### 现金如何被更新?
| 渠道 | 操作 | 更新字段 | 频次 |
|------|------|---------|------|
| holding.xls 导入 | `import_holding_xls.py` | cash, frozen_cash | Dad更新后 |
| 成交截图 | 手动解析 + 对比旧数据计算变更 | cash(+/-), frozen_cash | Dad发送时 |
| price_monitor | 只更新价格,不动现金 | 不更新 | 每2分钟 |
| 手动修正 | Dad告知准确数字 | cash, frozen_cash | Dad告知时 |
### 现金变更追踪
portfolio.json 的 `cash_history` 数组记录了每次现金变更:
```jsonc
"cash_history": [
{
"time": "2026-06-29 22:23:47",
"cash": 92678.85, // 更新后的可用资金
"frozen": 39481.40, // 更新后的冻结资金
"source": "manual:post-法拉电子-sell", // 变更来源
"formula": "初始73758.85 + 法拉电子18920" // 计算过程
}
]
```
### 规则
1. **price_monitor 绝不能修改 cash / frozen_cash** — 它只更新 price 字段和 total_mv / total_assets
2. 现金变更只能来自 Dad 截图、holding.xls 导入、或 Dad 手动告知
3. 每次现金变更必须记录到 cash_history,注明来源和计算过程
4. 所有报告脚本读总资产时,从 `portfolio.json.total_assets` 取,不要自己算
## 币种
- portfolio.json 全部存 CNY(港股价格 × HK_RATE 转人民币)
- decisions.json 港股价格存 HKD 原值(带 `currency: "HKD"` 标记)
- price_monitor 比较 decisions.json 中的价格和止损时:同币种(都是 HKD),直接比较
- 报告输出港股价格时显示 HKD 并标注「(HKD)」
## 常见错误
### ❌ total_assets 漏了冻结资金
```python
# WRONG — 只加了可用现金,冻结资金漏了
total_assets = market_value + cash
# RIGHT — 可用 + 冻结
total_assets = market_value + cash + frozen_cash
```
### ❌ 港股硬编码 ×0.866
```python
# WRONG — 价格本身已经是 CNYprice_monitor在写入时就转了)
mv = shares * price * 0.866
# RIGHT — price 已经是 CNY
mv = shares * price
```
### ❌ LLM 报告自己算总资产
```
WRONG: 报告里写 "总资产 = 持仓市值 + 现金"
RIGHT: 报告里写 "总资产 = portfolio.json.total_assets"
```
## 版本记录
| 版本 | 日期 | 变更 |
|------|------|------|
| 1 | 2026-06-29以前 | 无规范,cash字段含义模糊 |
| 2 | 2026-06-29 | 明确 cash=可用, frozen_cash=冻结, total_assets=市值+可用+冻结 |