docs: update CHANGELOG + data model + mark decisions migration complete
This commit is contained in:
+162
-159
@@ -1,159 +1,162 @@
|
||||
# decisions.json → SQLite 数据库迁移需求
|
||||
|
||||
## 背景
|
||||
|
||||
当前系统所有策略数据存在 `/home/hmo/web-dashboard/data/decisions.json`,一个约 50~60 条策略的 JSON 文件。
|
||||
|
||||
## 现状痛点
|
||||
|
||||
| 问题 | 举例 |
|
||||
|------|------|
|
||||
| 没有写入锁,并发写会损坏 | price_monitor + per_stock_reassess 同时写,JSON 截断 |
|
||||
| 币种字段不统一 | 港股 price 曾经存 HKD 也存过 CNY,修了几轮才用 currency 标记 |
|
||||
| 缺乏 schema 校验 | 空字段、类型错误(str 写成了 int)无声失败 |
|
||||
| 无 changelog 审计 | 谁在什么时候改了哪个字段,查不了 |
|
||||
| 没有事务回滚 | 写一半 crash,整个文件废了 |
|
||||
| 只能全量读 | 50 条策略每次全部加载,浪费 token |
|
||||
| 各脚本自拉价格 | stale_detector 拉一次腾讯 API,per_stock_reassess 又拉一次 |
|
||||
|
||||
## 需求目标
|
||||
|
||||
**单线程写入 / 多线程安全读**。
|
||||
将 decisions.json 迁移到 `mofin.db`(已有该数据库),建 `strategies` 表。
|
||||
|
||||
## 表结构
|
||||
|
||||
```sql
|
||||
CREATE TABLE strategies (
|
||||
code TEXT PRIMARY KEY, -- 股票代码,如 "00700"
|
||||
name TEXT NOT NULL, -- 股票名称
|
||||
type TEXT DEFAULT '自选策略', -- 持仓策略 / 自选策略
|
||||
status TEXT DEFAULT 'active', -- active / updated / stale
|
||||
currency TEXT DEFAULT 'CNY', -- CNY / HKD。港股固定 HKD
|
||||
|
||||
-- 价格与仓位
|
||||
price REAL, -- 最新价格(原始币种,港股=HKD,A股=CNY)
|
||||
price_cny REAL, -- 折算为人民币的价格(统一口径用)
|
||||
cost REAL, -- 持仓成本(有持仓时)
|
||||
shares INTEGER, -- 持仓股数
|
||||
share INTEGER, -- 同 shares,历史遗留字段
|
||||
|
||||
-- 策略参数
|
||||
entry_low REAL, -- 买入区间下沿(原始币种)
|
||||
entry_high REAL, -- 买入区间上沿(原始币种)
|
||||
stop_loss REAL, -- 止损价
|
||||
take_profit REAL, -- 止盈/目标价
|
||||
stop_loss_cny REAL, -- 止损(人民币,统一口径用)
|
||||
take_profit_cny REAL, -- 止盈(人民币)
|
||||
rr_ratio REAL, -- 盈亏比
|
||||
timing_signal TEXT, -- 短词信号:买入/加仓/持有/观望/冷却中
|
||||
|
||||
-- 来源与状态
|
||||
trigger_reason TEXT, -- 策略生成原由
|
||||
created_at TEXT, -- ISO时间
|
||||
updated_at TEXT, -- 最后更新时间
|
||||
reassessed_at TEXT, -- 最近一次重评时间
|
||||
action TEXT, -- 最新操作摘要文本
|
||||
|
||||
-- JSON 嵌套字段(存为 TEXT,应用层 JSON parse)
|
||||
analysis TEXT, -- JSON: 分析详情
|
||||
trigger TEXT, -- JSON: 触发条件
|
||||
changelog TEXT, -- JSON: 变更历史数组
|
||||
signal_factors TEXT, -- JSON: 因子列表
|
||||
tech_snapshot TEXT, -- JSON: 技术面快照
|
||||
action_note TEXT, -- 长文本动作说明
|
||||
sector_context TEXT -- 行业上下文
|
||||
);
|
||||
```
|
||||
|
||||
### 为什么不全部展开成列
|
||||
|
||||
analysis 和 trigger 有嵌套结构且未来可能加字段。存 JSON 字符串,应用层 parse。查询止损/止盈用 `json_extract()`。
|
||||
|
||||
## 读写接口需求
|
||||
|
||||
### 写操作(高频,每 2 分钟)
|
||||
|
||||
price_monitor 每轮更新所有持仓 + 自选的价格:
|
||||
|
||||
```sql
|
||||
INSERT INTO strategies (code, price, price_cny, currency, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
ON CONFLICT(code) DO UPDATE SET
|
||||
price = excluded.price,
|
||||
price_cny = excluded.price_cny,
|
||||
updated_at = excluded.updated_at;
|
||||
```
|
||||
|
||||
价格更新不涉及其他字段。港股:price=HKD,price_cny=HKD×汇率。
|
||||
A股:price=price_cny。
|
||||
|
||||
### 写操作(低频,策略重评时)
|
||||
|
||||
per_stock_reassess 跑完单股重评后更新全部策略参数:
|
||||
|
||||
```sql
|
||||
UPDATE strategies SET
|
||||
entry_low = ?, entry_high = ?, stop_loss = ?,
|
||||
take_profit = ?, rr_ratio = ?, timing_signal = ?,
|
||||
stop_loss_cny = ?, take_profit_cny = ?,
|
||||
currency = ?,
|
||||
analysis = ?,
|
||||
trigger = ?,
|
||||
reassessed_at = ?,
|
||||
changelog = json_insert(changelog, '$[#]', ?)
|
||||
WHERE code = ?;
|
||||
```
|
||||
|
||||
### 读操作(各报告脚本)
|
||||
|
||||
所有 LLM cron、no_agent 脚本统一从 `strategies` 表读,不再拉腾讯 API:
|
||||
|
||||
```sql
|
||||
SELECT * FROM strategies WHERE status = 'active' ORDER BY code;
|
||||
```
|
||||
|
||||
按币种过滤:
|
||||
```sql
|
||||
SELECT * FROM strategies WHERE currency = 'HKD';
|
||||
```
|
||||
|
||||
读某只具体股票:
|
||||
```sql
|
||||
SELECT * FROM strategies WHERE code = '00700';
|
||||
```
|
||||
|
||||
## 不变的输出
|
||||
|
||||
1. **保留 decisions.json 同步输出**(过渡期 2 周)。每次写 DB 后,同步写一份 decisions.json 给旧脚本兼容。
|
||||
2. **输出格式不做大改**。JSON decode analysis/trigger 后保持现有字段名。
|
||||
|
||||
## 不允许的行为
|
||||
|
||||
1. ❌ 各脚本自行拉腾讯 API 获取价格。价格入口只有 price_monitor。
|
||||
2. ❌ 直接写 decisions.json。全部走 DB。
|
||||
3. ❌ 变更 decisions.json 的输出字段名/格式(过渡期兼容)。
|
||||
|
||||
## 验收标准
|
||||
|
||||
1. `strategies` 表有数据,decisions.json 和 `SELECT * FROM strategies` 内容一致
|
||||
2. price_monitor 跑一轮后 DB 里的 price 更新正确(港股 HKD,A 股 CNY)
|
||||
3. per_stock_reassess 跑完单股后 DB 里对应股票策略更新
|
||||
4. stale_detector 从 DB 读数据,输出和从 JSON 读一样
|
||||
5. 并发读写(price_monitor 2min + stale_detector 同时跑)不损坏数据
|
||||
6. 迁移后旧 decisions.json 仍同步更新
|
||||
|
||||
## 相关文件路径
|
||||
|
||||
| 文件 | 说明 |
|
||||
|------|------|
|
||||
| `/home/hmo/MoFin/price_monitor.py` | 价格监控,每2分钟写price |
|
||||
| `/home/hmo/MoFin/scripts/strategy_lifecycle.py` | 策略生命周期,reassess_strategy() |
|
||||
| `/home/hmo/MoFin/scripts/per_stock_reassess.py` | 单股重评入口 |
|
||||
| `/home/hmo/MoFin/scripts/stale_push_wlin.py` | 自选买入提醒 |
|
||||
| `/home/hmo/web-dashboard/data/decisions.json` | 当前JSON文件 |
|
||||
| `/home/hmo/MoFin/data/mofin.db` | 目标数据库(已有market/trend等表) |
|
||||
|
||||
## 联系人
|
||||
|
||||
有问题问 hmo(老爸)。笑笑负责代码实现,测试完成后通知老爸验收。
|
||||
# decisions.json → SQLite 数据库迁移需求
|
||||
|
||||
> **✅ 已完成 (2026-07-03)** — 全部迁移到 `holding_strategies` 表。
|
||||
> decisions.json 不再被任何代码读写。详见 CHANGELOG.md。
|
||||
|
||||
## 背景
|
||||
|
||||
当前系统所有策略数据存在 `/home/hmo/web-dashboard/data/decisions.json`,一个约 50~60 条策略的 JSON 文件。
|
||||
|
||||
## 现状痛点
|
||||
|
||||
| 问题 | 举例 |
|
||||
|------|------|
|
||||
| 没有写入锁,并发写会损坏 | price_monitor + per_stock_reassess 同时写,JSON 截断 |
|
||||
| 币种字段不统一 | 港股 price 曾经存 HKD 也存过 CNY,修了几轮才用 currency 标记 |
|
||||
| 缺乏 schema 校验 | 空字段、类型错误(str 写成了 int)无声失败 |
|
||||
| 无 changelog 审计 | 谁在什么时候改了哪个字段,查不了 |
|
||||
| 没有事务回滚 | 写一半 crash,整个文件废了 |
|
||||
| 只能全量读 | 50 条策略每次全部加载,浪费 token |
|
||||
| 各脚本自拉价格 | stale_detector 拉一次腾讯 API,per_stock_reassess 又拉一次 |
|
||||
|
||||
## 需求目标
|
||||
|
||||
**单线程写入 / 多线程安全读**。
|
||||
将 decisions.json 迁移到 `mofin.db`(已有该数据库),建 `strategies` 表。
|
||||
|
||||
## 表结构
|
||||
|
||||
```sql
|
||||
CREATE TABLE strategies (
|
||||
code TEXT PRIMARY KEY, -- 股票代码,如 "00700"
|
||||
name TEXT NOT NULL, -- 股票名称
|
||||
type TEXT DEFAULT '自选策略', -- 持仓策略 / 自选策略
|
||||
status TEXT DEFAULT 'active', -- active / updated / stale
|
||||
currency TEXT DEFAULT 'CNY', -- CNY / HKD。港股固定 HKD
|
||||
|
||||
-- 价格与仓位
|
||||
price REAL, -- 最新价格(原始币种,港股=HKD,A股=CNY)
|
||||
price_cny REAL, -- 折算为人民币的价格(统一口径用)
|
||||
cost REAL, -- 持仓成本(有持仓时)
|
||||
shares INTEGER, -- 持仓股数
|
||||
share INTEGER, -- 同 shares,历史遗留字段
|
||||
|
||||
-- 策略参数
|
||||
entry_low REAL, -- 买入区间下沿(原始币种)
|
||||
entry_high REAL, -- 买入区间上沿(原始币种)
|
||||
stop_loss REAL, -- 止损价
|
||||
take_profit REAL, -- 止盈/目标价
|
||||
stop_loss_cny REAL, -- 止损(人民币,统一口径用)
|
||||
take_profit_cny REAL, -- 止盈(人民币)
|
||||
rr_ratio REAL, -- 盈亏比
|
||||
timing_signal TEXT, -- 短词信号:买入/加仓/持有/观望/冷却中
|
||||
|
||||
-- 来源与状态
|
||||
trigger_reason TEXT, -- 策略生成原由
|
||||
created_at TEXT, -- ISO时间
|
||||
updated_at TEXT, -- 最后更新时间
|
||||
reassessed_at TEXT, -- 最近一次重评时间
|
||||
action TEXT, -- 最新操作摘要文本
|
||||
|
||||
-- JSON 嵌套字段(存为 TEXT,应用层 JSON parse)
|
||||
analysis TEXT, -- JSON: 分析详情
|
||||
trigger TEXT, -- JSON: 触发条件
|
||||
changelog TEXT, -- JSON: 变更历史数组
|
||||
signal_factors TEXT, -- JSON: 因子列表
|
||||
tech_snapshot TEXT, -- JSON: 技术面快照
|
||||
action_note TEXT, -- 长文本动作说明
|
||||
sector_context TEXT -- 行业上下文
|
||||
);
|
||||
```
|
||||
|
||||
### 为什么不全部展开成列
|
||||
|
||||
analysis 和 trigger 有嵌套结构且未来可能加字段。存 JSON 字符串,应用层 parse。查询止损/止盈用 `json_extract()`。
|
||||
|
||||
## 读写接口需求
|
||||
|
||||
### 写操作(高频,每 2 分钟)
|
||||
|
||||
price_monitor 每轮更新所有持仓 + 自选的价格:
|
||||
|
||||
```sql
|
||||
INSERT INTO strategies (code, price, price_cny, currency, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
ON CONFLICT(code) DO UPDATE SET
|
||||
price = excluded.price,
|
||||
price_cny = excluded.price_cny,
|
||||
updated_at = excluded.updated_at;
|
||||
```
|
||||
|
||||
价格更新不涉及其他字段。港股:price=HKD,price_cny=HKD×汇率。
|
||||
A股:price=price_cny。
|
||||
|
||||
### 写操作(低频,策略重评时)
|
||||
|
||||
per_stock_reassess 跑完单股重评后更新全部策略参数:
|
||||
|
||||
```sql
|
||||
UPDATE strategies SET
|
||||
entry_low = ?, entry_high = ?, stop_loss = ?,
|
||||
take_profit = ?, rr_ratio = ?, timing_signal = ?,
|
||||
stop_loss_cny = ?, take_profit_cny = ?,
|
||||
currency = ?,
|
||||
analysis = ?,
|
||||
trigger = ?,
|
||||
reassessed_at = ?,
|
||||
changelog = json_insert(changelog, '$[#]', ?)
|
||||
WHERE code = ?;
|
||||
```
|
||||
|
||||
### 读操作(各报告脚本)
|
||||
|
||||
所有 LLM cron、no_agent 脚本统一从 `strategies` 表读,不再拉腾讯 API:
|
||||
|
||||
```sql
|
||||
SELECT * FROM strategies WHERE status = 'active' ORDER BY code;
|
||||
```
|
||||
|
||||
按币种过滤:
|
||||
```sql
|
||||
SELECT * FROM strategies WHERE currency = 'HKD';
|
||||
```
|
||||
|
||||
读某只具体股票:
|
||||
```sql
|
||||
SELECT * FROM strategies WHERE code = '00700';
|
||||
```
|
||||
|
||||
## 不变的输出
|
||||
|
||||
1. **保留 decisions.json 同步输出**(过渡期 2 周)。每次写 DB 后,同步写一份 decisions.json 给旧脚本兼容。
|
||||
2. **输出格式不做大改**。JSON decode analysis/trigger 后保持现有字段名。
|
||||
|
||||
## 不允许的行为
|
||||
|
||||
1. ❌ 各脚本自行拉腾讯 API 获取价格。价格入口只有 price_monitor。
|
||||
2. ❌ 直接写 decisions.json。全部走 DB。
|
||||
3. ❌ 变更 decisions.json 的输出字段名/格式(过渡期兼容)。
|
||||
|
||||
## 验收标准
|
||||
|
||||
1. `strategies` 表有数据,decisions.json 和 `SELECT * FROM strategies` 内容一致
|
||||
2. price_monitor 跑一轮后 DB 里的 price 更新正确(港股 HKD,A 股 CNY)
|
||||
3. per_stock_reassess 跑完单股后 DB 里对应股票策略更新
|
||||
4. stale_detector 从 DB 读数据,输出和从 JSON 读一样
|
||||
5. 并发读写(price_monitor 2min + stale_detector 同时跑)不损坏数据
|
||||
6. 迁移后旧 decisions.json 仍同步更新
|
||||
|
||||
## 相关文件路径
|
||||
|
||||
| 文件 | 说明 |
|
||||
|------|------|
|
||||
| `/home/hmo/MoFin/price_monitor.py` | 价格监控,每2分钟写price |
|
||||
| `/home/hmo/MoFin/scripts/strategy_lifecycle.py` | 策略生命周期,reassess_strategy() |
|
||||
| `/home/hmo/MoFin/scripts/per_stock_reassess.py` | 单股重评入口 |
|
||||
| `/home/hmo/MoFin/scripts/stale_push_wlin.py` | 自选买入提醒 |
|
||||
| `/home/hmo/web-dashboard/data/decisions.json` | 当前JSON文件 |
|
||||
| `/home/hmo/MoFin/data/mofin.db` | 目标数据库(已有market/trend等表) |
|
||||
|
||||
## 联系人
|
||||
|
||||
有问题问 hmo(老爸)。笑笑负责代码实现,测试完成后通知老爸验收。
|
||||
|
||||
@@ -1,115 +1,114 @@
|
||||
# portfolio.json 数据模型
|
||||
# MoFin 数据模型
|
||||
|
||||
## 一句话
|
||||
> 数据已从 JSON 迁移到 SQLite。portfolio.json / decisions.json / watchlist.json 不再使用。
|
||||
|
||||
**总资产 = 持仓市值 + 可用现金 + 冻结资金**,三个数字必须全对,缺少任何一项数字就不对。
|
||||
## 核心表
|
||||
|
||||
## 字段说明
|
||||
| 表 | 对应旧 JSON | 用途 |
|
||||
|----|-----------|------|
|
||||
| `holdings` + `portfolio_summary` | portfolio.json | 持仓 + 汇总 |
|
||||
| `holding_strategies` | decisions.json | 策略/决策 |
|
||||
| `watchlist_stocks` | watchlist.json | 自选股 |
|
||||
| `live_prices` | live_prices.json | 实时价格快照 |
|
||||
| `mtf_cache` | multi_tf_cache.json | 多周期缓存 |
|
||||
| `market_snapshots` | market.json | 大盘数据 |
|
||||
| `capital_flow_cache` | capital_flow_cache.json | 资金流缓存 |
|
||||
| `cash_log` | 无 | 现金变更日志 |
|
||||
|
||||
```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未交收/挂单占用)
|
||||
**总资产 = 持仓总市值(CNY) + 可用现金 + 冻结资金**
|
||||
|
||||
// 汇总(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` 取,不要自己算
|
||||
`calc_total_assets()` (mo_models.py) 是唯一正确公式。
|
||||
|
||||
## 币种
|
||||
|
||||
- portfolio.json 全部存 CNY(港股价格 × HK_RATE 转人民币)
|
||||
- decisions.json 港股价格存 HKD 原值(带 `currency: "HKD"` 标记)
|
||||
- price_monitor 比较 decisions.json 中的价格和止损时:同币种(都是 HKD),直接比较
|
||||
- 报告输出港股价格时显示 HKD 并标注「(HKD)」
|
||||
### 个股层面
|
||||
|
||||
| 品种 | price | cost | currency | 说明 |
|
||||
|------|-------|------|----------|------|
|
||||
| 港股 | **HKD** | **HKD** | `HKD` | 跟股软显示一致,方便操作 |
|
||||
| A股 | **CNY** | **CNY** | `CNY` | |
|
||||
|
||||
技术位(stop_loss / take_profit / entry_low / entry_high)与 price 同币种。
|
||||
|
||||
### 汇总层面
|
||||
|
||||
`calc_total_mv()` / `calc_total_assets()` 汇总时自动将港股 HKD × `HK_RATE`(实时 API)转为 CNY。
|
||||
|
||||
```python
|
||||
# 个股 P&L:港股用 HKD 算,A股用 CNY 算
|
||||
profit_pct = (price - cost) / cost * 100 # 同币种,无需转换
|
||||
|
||||
# 总资产:港股市值自动转 CNY
|
||||
total_assets = calc_total_assets(pf) # 已处理 HKD→CNY
|
||||
```
|
||||
|
||||
### 禁止
|
||||
|
||||
- ❌ 港股 price(HKD) 和 A 股 price(CNY) 直接比较/相加
|
||||
- ❌ 港股 cost(HKD) 和 CNY price 混算 P&L
|
||||
- ❌ 硬编码汇率(`calc_total_mv` 内部调 `get_hk_rate()` 走实时 API)
|
||||
|
||||
## 数据流
|
||||
|
||||
```
|
||||
price_monitor (cron: */2 9-16)
|
||||
→ 东财/腾讯拉价格
|
||||
→ write_holdings_batch() → holdings 表 (price 更新)
|
||||
→ write_portfolio_summary() → portfolio_summary (total_mv/total_assets 重算)
|
||||
|
||||
regenerate_all (cron: 手动/定时)
|
||||
→ batch_fetch_prices() → 从 DB 读价格
|
||||
→ 技术分析 → 止损/止盈/买入区
|
||||
→ write_holding_strategy() → holding_strategies 表
|
||||
|
||||
server.py API
|
||||
→ 写端点: _save_portfolio / _save_decision / _save_watchlist → DB
|
||||
→ 读端点: mo_data.read_*() → DB
|
||||
```
|
||||
|
||||
## 现金
|
||||
|
||||
- `price_monitor` 只更新价格和汇总,不动现金
|
||||
- 现金变更通过截图导入 / holding.xls 导入 / 手动调整
|
||||
- `cash_log` 表记录每次变更(来源、before/after、备注)
|
||||
|
||||
## 常见错误
|
||||
|
||||
### ❌ total_assets 漏了冻结资金
|
||||
|
||||
### ❌ 港股价格转 CNY 再存
|
||||
```python
|
||||
# WRONG — 只加了可用现金,冻结资金漏了
|
||||
total_assets = market_value + cash
|
||||
# WRONG — 港股个股存 CNY 后股软对不上
|
||||
if is_hk_stock(code):
|
||||
price = price * HK_RATE
|
||||
|
||||
# RIGHT — 可用 + 冻结
|
||||
total_assets = market_value + cash + frozen_cash
|
||||
# RIGHT — 存 HKD 原值,汇总时由 calc_total_assets 转 CNY
|
||||
if is_hk_stock(code):
|
||||
currency = 'HKD'
|
||||
```
|
||||
|
||||
### ❌ 港股硬编码 ×0.866
|
||||
|
||||
### ❌ 混币计算
|
||||
```python
|
||||
# WRONG — 价格本身已经是 CNY(price_monitor在写入时就转了)
|
||||
mv = shares * price * 0.866
|
||||
# WRONG — price 是 HKD,cost 是 CNY,算出来没意义
|
||||
pnl = (price_hkd - cost_cny) / cost_cny
|
||||
|
||||
# RIGHT — price 已经是 CNY
|
||||
mv = shares * price
|
||||
# RIGHT — 同币种比较
|
||||
pnl = (price_hkd - cost_hkd) / cost_hkd
|
||||
```
|
||||
|
||||
### ❌ LLM 报告自己算总资产
|
||||
### ❌ 硬编码汇率
|
||||
```python
|
||||
# WRONG
|
||||
mv = shares * price * 0.87
|
||||
|
||||
```
|
||||
WRONG: 报告里写 "总资产 = 持仓市值 + 现金"
|
||||
RIGHT: 报告里写 "总资产 = portfolio.json.total_assets"
|
||||
# RIGHT — 用 calc_total_assets(内部调实时汇率)
|
||||
mv = calc_total_mv(holdings)
|
||||
```
|
||||
|
||||
## 版本记录
|
||||
## 版本
|
||||
|
||||
| 版本 | 日期 | 变更 |
|
||||
|------|------|------|
|
||||
| 1 | 2026-06-29以前 | 无规范,cash字段含义模糊 |
|
||||
| 2 | 2026-06-29 | 明确 cash=可用, frozen_cash=冻结, total_assets=市值+可用+冻结 |
|
||||
| 3 | 2026-07-03 | JSON→DB 迁移完成。港股个股存 HKD,汇总时转 CNY。 |
|
||||
| 2 | 2026-06-29 | 明确 cash/frozen_cash 字段含义 |
|
||||
| 1 | - | 无规范 |
|
||||
|
||||
Reference in New Issue
Block a user