# 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(老爸)。笑笑负责代码实现,测试完成后通知老爸验收。