# 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 — 价格本身已经是 CNY(price_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=市值+可用+冻结 |