docs: 文档治理第二波——更新8份保留文档(QUICKSTART/DEPLOY/DASHBOARD/HEALTH-PIPELINE/portfolio-data-model/morning-health-check/SELF_GROWTH/lifecycle),归档cron-catalog+system-audit

This commit is contained in:
hmo
2026-08-11 04:04:04 +08:00
parent a5a0a46fe9
commit 6929720d47
11 changed files with 111 additions and 84 deletions
+6 -4
View File
@@ -8,7 +8,7 @@
``` ```
MoFin Dashboard MoFin Dashboard
├── Services — 服务状态总览(MoFin API / Dashboard / 知微 Gateway / ejabberd / DB ├── Services — 服务状态总览(MoFin API+Dashboard / 知微 Gateway / ejabberd / DB,共4项
└── 开发原则 └── 开发原则
├── G 规范 — 开发规范 + Spec 文档 ├── G 规范 — 开发规范 + Spec 文档
└── F 健康 — 系统健康监控(Tier1/Tier2 └── F 健康 — 系统健康监控(Tier1/Tier2
@@ -50,7 +50,7 @@ MoFin Dashboard
"detail": "HTTP 200" "detail": "HTTP 200"
} }
], ],
"summary": {"ok": 5, "total": 5} "summary": {"ok": 4, "total": 4}
} }
``` ```
@@ -60,14 +60,16 @@ MoFin Dashboard
"tasks": [ "tasks": [
{"name": "agents-health-check", "status": "cron_ok"}, {"name": "agents-health-check", "status": "cron_ok"},
{"name": "agents-daily-health", "status": "not_deployed"}, {"name": "agents-daily-health", "status": "not_deployed"},
{"name": "dashboard", "status": "running", "detail": "services: 5/5"} {"name": "dashboard", "status": "running", "detail": "services: 4/4"}
], ],
"tier1": {"summary": {"ok": 5, "total": 5}, "services": [...]}, "tier1": {"summary": {"ok": 4, "total": 4}, "services": [...]},
"tier2": {"summary": {"ok": 0, "total": 0}, "services": []}, "tier2": {"summary": {"ok": 0, "total": 0}, "services": []},
"generated_at": "2026-07-19 10:00:00" "generated_at": "2026-07-19 10:00:00"
} }
``` ```
> 注:实际服务 4 项(mofin_api / zhiwei_gateway / ejabberd / mofin_db)。Dashboard 服务已并入 mofin_api:8899 一体)。
--- ---
## 前端架构 ## 前端架构
+48 -44
View File
@@ -1,6 +1,6 @@
# MoFin — 部署指南 # MoFin — 部署指南
> 版本: v1.0 | 部署目标: Linux 192.168.1.246 > 版本: v2.0 | 部署目标: Linux 192.168.1.246 | 更新: 2026-08-11
--- ---
@@ -8,92 +8,96 @@
| 组件 | 守护方式 | 端口 | 说明 | | 组件 | 守护方式 | 端口 | 说明 |
|------|---------|------|------| |------|---------|------|------|
| **server.py** | systemd `mofin-api` | 8899 | 持仓情报 API(已有,不动) | | **server.py**API+Dashboard 一体)| systemd `mofin-dashboard` | 8899 | 持仓情报 API + 管理门户(2026-07-19 合并)|
| **dashboard.py** | systemd `mofin-dashboard` | 8899 | 管理门户(新增) | | **hermes gateway**(知微)| systemd `hermes-gateway-zhiwei` | 8643 | 知微 Bot 网关 |
| **health_check** | crontab `*/5 * * * *` | — | Tier1 健康检查(新增) | | **hermes gateway**mohe| systemd `hermes-gateway@mohe` | 8646 | mohe Bot 网关 |
| **Tier1 健康检查** | crontab `*/5 * * * *` | — | agents_health_check.py |
> ⚠️ 无独立 `mofin-api` 服务——API 与 Dashboard 合并为 `mofin-dashboard.service`。
--- ---
## 1. Dashboard 部署 ## 1. 部署流程(正确工作流)
### 1.1 创建 systemd 服务 > **本地开发 → push Gitea → 246 pull 部署**。不直接在 246 上改代码,否则被 deploy_guard 回滚。
```bash ```bash
sudo tee /etc/systemd/system/mofin-dashboard.service << 'EOF' # 1. 本地开发环境(D:\...\projects\MoFin)提交并推送
[Unit] git add . && git commit -m '说明'
Description=MoFin Dashboard git push origin master # 推送到 Gitea (git.yoin.fun)
After=network.target
[Service] # 2. 246 部署:从 Gitea 拉取
Type=simple ssh hmo@192.168.1.246 "cd ~/MoFin && git pull --rebase"
User=hmo
WorkingDirectory=/home/hmo/MoFin
Environment=MOFIN_ROOT=/home/hmo/MoFin
ExecStart=/usr/bin/python3 /home/hmo/MoFin/dashboard.py
Restart=always
RestartSec=10
[Install] # 3. 同步脚本硬链接(如有脚本变更)
WantedBy=multi-user.target ssh hmo@192.168.1.246 "cd ~/MoFin && bash deploy/profile-scripts/sync_profile_scripts.sh"
EOF
# 4. 重启受影响服务
ssh hmo@192.168.1.246 "sudo systemctl restart mofin-dashboard"
# 5. 验证
ssh hmo@192.168.1.246 "curl -s http://127.0.0.1:8899/api/health"
``` ```
### 1.2 启动 ---
## 2. 服务管理
```bash ```bash
sudo systemctl daemon-reload # 状态/重启(API+Dashboard 一体)
sudo systemctl enable --now mofin-dashboard
sudo systemctl status mofin-dashboard sudo systemctl status mofin-dashboard
``` sudo systemctl restart mofin-dashboard
### 1.3 验证 # 日志(journald
sudo journalctl -u mofin-dashboard -n 50
```bash # 知微/amohe 网关
curl http://127.0.0.1:8899/api/health sudo systemctl restart hermes-gateway-zhiwei
curl http://127.0.0.1:8899/api/services | python3 -m json.tool sudo systemctl restart hermes-gateway@mohe
# 浏览器访问: http://192.168.1.246:8899
``` ```
--- ---
## 2. 健康管线部署 ## 3. 健康管线
```bash ```bash
# 添加到 crontab # Tier1 已在 crontab*/5 分钟)
(crontab -l 2>/dev/null; echo '# MoFin health pipeline'; echo '*/5 * * * * cd /home/hmo/MoFin && /usr/bin/python3 agents_health_check.py >> gateway/logs/health_check_cron.log 2>&1') | crontab -
# 验证
crontab -l | grep health crontab -l | grep health
# 手动运行(无输出 = 全正常)
cd ~/MoFin && python3 agents_health_check.py
# 最近报告
cat ~/MoFin/gateway/temp/last_health_check.json | python3 -m json.tool
``` ```
--- ---
## 3. 防火墙 ## 4. 防火墙
```bash ```bash
sudo ufw status | grep -E '8899|8899' sudo ufw status | grep 8899
# 如果未开放: # 如果未开放:
# sudo ufw allow 8899/tcp # sudo ufw allow 8899/tcp
``` ```
--- ---
## 4. 部署后验证清单 ## 5. 部署后验证清单
- [ ] `curl http://127.0.0.1:8899/api/health``{"status":"ok"}` - [ ] `curl http://127.0.0.1:8899/api/health``{"status":"ok"}`
- [ ] `curl http://127.0.0.1:8899/api/services` → 返回 5 个服务状态 - [ ] `curl http://127.0.0.1:8899/api/services` → 返回 4 个服务状态
- [ ] 浏览器打开 `http://192.168.1.246:8899` → Services Tab 显示服务状态 - [ ] 浏览器打开 `http://192.168.1.246:8899` → Services Tab 显示服务状态
- [ ] Dashboard F 健康 Tab → 定时任务状态显示正常 - [ ] Dashboard F 健康 Tab → 定时任务状态显示正常
- [ ] 点击各模块 ?§ 按钮 → 弹出 spec 帮助内容
- [ ] `python3 agents_health_check.py` → 无输出(全正常) - [ ] `python3 agents_health_check.py` → 无输出(全正常)
--- ---
## 5. 故障恢复 ## 6. 故障恢复
| 问题 | 命令 | | 问题 | 命令 |
|------|------| |------|------|
| Dashboard 挂了 | `ssh hmo@246 'sudo systemctl restart mofin-dashboard'` | | Dashboard/API 挂了 | `ssh hmo@246 'sudo systemctl restart mofin-dashboard'` |
| 健康检查不运行 | `ssh hmo@246 'crontab -l \| grep health'` | | 健康检查不运行 | `ssh hmo@246 'crontab -l \| grep health'` |
| MoFin API 挂了 | `ssh hmo@246 'sudo systemctl restart mofin-api'` | | 知微 Gateway 挂了 | `ssh hmo@246 'sudo systemctl restart hermes-gateway-zhiwei'` |
| 知微 Gateway 挂了 | `ssh hmo@246 'sudo systemctl restart hermes-gateway@zhiwei'` | | deploy_guard 回滚了改动 | 说明改动未提交——先在本地 commit + push,再 246 pull |
+6 -6
View File
@@ -22,7 +22,7 @@
└──────────┘ └──────────┘ └──────────┘ └──────────┘
│ │ │ │
agents_health_check agents_daily_health agents_health_check agents_daily_health
│ (规划中) │ (已部署 8/06)
┌────▼─────┐ ┌────▼─────┐
│ TODO 文件 │ │ TODO 文件 │
│ .jsonl │ │ .jsonl │
@@ -51,19 +51,19 @@
--- ---
## Tier 2: 每日全面检查(规划中 ## Tier 2: 每日全面检查(已部署
**计划脚本**: `agents_daily_health.py` **脚本**: `agents_daily_health.py`(位于 `/home/hmo/AgentsMeeting/gateway/scripts/`
**计划调度**: `crontab: 0 8 * * * 1-5`交易日 8:00 **调度**: `crontab: 0 8 * * *`日 8:002026-08-06 部署
**计划检查内容**: **检查内容**:
- 在 Tier 1 基础上增加: - 在 Tier 1 基础上增加:
- 磁盘空间检查(阈值 10G 警告 / 2G 严重) - 磁盘空间检查(阈值 10G 警告 / 2G 严重)
- crontab 存活检查(验证关键定时任务) - crontab 存活检查(验证关键定时任务)
- MoFin DB 大小和新鲜度检查 - MoFin DB 大小和新鲜度检查
- 生成结构化 JSON 报告 - 生成结构化 JSON 报告
**注意**: MoFin 已有 `system_health_check.py`9:00)和 `morning_health_check.py`(交易日 8:008层48项),Tier2 将与现有检查互补,不重复。 **注意**: MoFin 已有 `morning_health_check.py`交易8:008 类 40 项,历史存 `health_check_log`),Tier2 与其互补,不重复。
--- ---
+20 -12
View File
@@ -25,20 +25,22 @@ ssh hmo@192.168.1.246 "sudo systemctl status mofin-dashboard"
# 重启 # 重启
ssh hmo@192.168.1.246 "sudo systemctl restart mofin-dashboard" ssh hmo@192.168.1.246 "sudo systemctl restart mofin-dashboard"
# 查看日志 # 查看日志API+Dashboard 一体,日志走 journald
ssh hmo@192.168.1.246 "tail -50 ~/MoFin/gateway/logs/dashboard.log" ssh hmo@192.168.1.246 "sudo journalctl -u mofin-dashboard -n 50"
``` ```
--- ---
## MoFin API ## MoFin API
```bash > ⚠️ API 与 Dashboard 已合并为 `mofin-dashboard.service`:8899),无独立 mofin-api 服务。
# 查看状态
ssh hmo@192.168.1.246 "sudo systemctl status mofin-api"
# 重启 ```bash
ssh hmo@192.168.1.246 "sudo systemctl restart mofin-api" # 查看状态(用 mofin-dashboard
ssh hmo@192.168.1.246 "sudo systemctl status mofin-dashboard"
# 重启(用 mofin-dashboard
ssh hmo@192.168.1.246 "sudo systemctl restart mofin-dashboard"
# 测试 API # 测试 API
curl http://192.168.1.246:8899/api/portfolio curl http://192.168.1.246:8899/api/portfolio
@@ -63,14 +65,20 @@ ssh hmo@192.168.1.246 "cat ~/MoFin/gateway/temp/last_health_check.json | python3
## 部署更新 ## 部署更新
> 正确工作流:**本地开发 → push Gitea → 246 pull 部署**(不直接在 246 上改代码,避免 deploy_guard 拦截)
```bash ```bash
# 1. 拉代码 # 1. 本地开发环境提交并推送(D:\...\projects\MoFin
git add . && git commit -m '说明'
git push origin master
# 2. 246 部署:拉取最新代码
ssh hmo@192.168.1.246 "cd ~/MoFin && git pull --rebase" ssh hmo@192.168.1.246 "cd ~/MoFin && git pull --rebase"
# 2. 重启受影响的服务 # 3. 重启受影响的服务
ssh hmo@192.168.1.246 "sudo systemctl restart mofin-dashboard" ssh hmo@192.168.1.246 "sudo systemctl restart mofin-dashboard"
# 3. 验证 # 4. 验证
ssh hmo@192.168.1.246 "curl -s http://127.0.0.1:8899/api/health" ssh hmo@192.168.1.246 "curl -s http://127.0.0.1:8899/api/health"
``` ```
@@ -82,5 +90,5 @@ ssh hmo@192.168.1.246 "curl -s http://127.0.0.1:8899/api/health"
|------|------| |------|------|
| Dashboard 不响应 | `ssh hmo@246 sudo systemctl restart mofin-dashboard` | | Dashboard 不响应 | `ssh hmo@246 sudo systemctl restart mofin-dashboard` |
| F Tab 定时任务显示"未部署" | `ssh hmo@246 crontab -l \| grep health` 确认 | | F Tab 定时任务显示"未部署" | `ssh hmo@246 crontab -l \| grep health` 确认 |
| MoFin API 不响应 | `ssh hmo@246 sudo systemctl restart mofin-api` | | MoFin API 不响应 | `ssh hmo@246 sudo systemctl restart mofin-dashboard`API+Dashboard 一体)|
| 数据库查询失败 | `ssh hmo@246 'ls -la /home/hmo/web-dashboard/data/mofin.db'` | | 数据库查询失败 | `ssh hmo@246 'ls -la /home/hmo/MoFin/data/mofin.db'` |
+3 -1
View File
@@ -30,12 +30,14 @@
| 文档 | 内容 | | 文档 | 内容 |
|------|------| |------|------|
| [cron-review-poversold-20260811.md](cron-review-poversold-20260811.md) | **Cron 梳理报告**(对照 p_oversold 部署,停8/保持30/调整8/新增2)| | [cron-review-poversold-20260811.md](cron-review-poversold-20260811.md) | **Cron 梳理报告**(对照 p_oversold 部署,停8/保持30/调整8/新增2)|
| [cron-catalog.md](cron-catalog.md) | Cron 任务清单(⚠️ 6/27 版,过时待重建)|
| [QUICKSTART.md](QUICKSTART.md) | 快速操作手册 | | [QUICKSTART.md](QUICKSTART.md) | 快速操作手册 |
| [DEPLOY.md](DEPLOY.md) | 部署指南(本地→Gitea→246 工作流)|
| [DASHBOARD.md](DASHBOARD.md) | Dashboard API 参考 | | [DASHBOARD.md](DASHBOARD.md) | Dashboard API 参考 |
| [HEALTH-PIPELINE.md](HEALTH-PIPELINE.md) | 健康监控管线 | | [HEALTH-PIPELINE.md](HEALTH-PIPELINE.md) | 健康监控管线 |
| [doc-audit-20260811.md](doc-audit-20260811.md) | **文档治理核实报告**15 份文档对照系统实际)| | [doc-audit-20260811.md](doc-audit-20260811.md) | **文档治理核实报告**15 份文档对照系统实际)|
> ⚠️ cron-catalog.md6/27 版)已归档至 archive/——当前 cron 清单以 cron-review-poversold-20260811.md 为准。
### 📈 策略研究(2026-08 起,小小莫维护) ### 📈 策略研究(2026-08 起,小小莫维护)
| 文档 | 内容 | | 文档 | 内容 |
+11 -2
View File
@@ -1,7 +1,16 @@
# MoFin 自成长系统设计文档 # MoFin 自成长系统设计文档
> 状态:设计文档 | 最后更新:2026-06-23 | 维护人:知微 > 状态:设计文档(部分调度已变更,见下方"现状更新")| 最后更新:2026-06-23 | 维护人:知微
> 当前架构见 [SYSTEM_ARCHITECTURE.md](SYSTEM_ARCHITECTURE.md) | 开发规范见 [DEVELOPMENT_STANDARDS.md](DEVELOPMENT_STANDARDS.md) > 当前架构见 [DEVELOPMENT_STANDARDS.md](DEVELOPMENT_STANDARDS.md) | 开发规范见 [DEVELOPMENT_STANDARDS.md](DEVELOPMENT_STANDARDS.md)
## 现状更新(2026-08-11 核实)
-**分支自成长/元自成长/硬编码扫描** 仍在 jobs.json 运行
- ⚠️ **调度变更**branch_scanner 实际 `15,30,45,00 9-15`(每15分);分支剪枝实际 **每日 21:00**(非周六6:00
-**xiaoguo_scanner 已退役**(7/20 归档)——SENSE 层不再有小果扫描
- ⚠️ **market_watch 已恢复运行**(文档称"暂停被小果替代"已过时)
- ⚠️ **stale_push_wlin 未调度**(现由 per_stock_reassess / watchlist_12d_backfill 承接)
-**per_stock_reassess 已暂停**8/10 22:43,由 watchlist_12d_backfill 承接)
--- ---
+7 -6
View File
@@ -41,7 +41,8 @@
## 二、对象一:信号(Signal) ## 二、对象一:信号(Signal)
### 定义 ### 定义
xiaoguo_scanner 或 trend_detector 产出的原始信号,表示一只股票在某方面有异常。 宏观/背离/行业等数据源产出的原始信号(如 macro_watch / divergence_detector,表示一只股票或市场在某方面有异常。
> 现状更新(2026-08-11):xiaoguo_scanner 已退役(7/20 归档),信号来源改为 macro_watch / divergence_detector 等。
### 状态流转 ### 状态流转
``` ```
@@ -49,7 +50,7 @@ source写入(signal_news表)
┌──────┐ ┌──────┐
│ 未处理 │ ←─ source='xiaoguo' 或 'xiaoguo_risk' 或 'trend' │ 未处理 │ ←─ source='macro_watch' 或 'divergence_watch' 等
└──┬───┘ └──┬───┘
│ 知微(盯盘cron)读取并评估 │ 知微(盯盘cron)读取并评估
├──────────────────────────────────────┐ ├──────────────────────────────────────┐
@@ -61,17 +62,17 @@ source写入(signal_news表)
``` ```
### 处理流程 ### 处理流程
1. **写入**xiaoguo_scanner(每5min) / trend_detector(每25min) → INSERT INTO signal_news 1. **写入**macro_context_collector / divergence_detector → INSERT INTO signal_news
2. **读取**:盯盘cron(每15-25min) → SELECT FROM signal_news WHERE source LIKE 'xiaoguo%' ORDER BY id DESC 2. **读取**:盯盘cron → SELECT FROM signal_news WHERE processed=0
3. **评估**:五维全面分析(大盘→行业→个股,消息+基本面+技术面) 3. **评估**:五维全面分析(大盘→行业→个股,消息+基本面+技术面)
4. **分流** 4. **分流**
- 采纳 → 加入自选(watchlist) + 生成策略(decisions.json) - 采纳 → 加入自选(watchlist) + 生成策略(holding_strategies)
- 关注 → 加入关注列表(watchlist status=watching) - 关注 → 加入关注列表(watchlist status=watching)
- 忽略 → 不处理 - 忽略 → 不处理
### 当前缺口 ### 当前缺口
- [x] signal_news 缺 processed 标记 → 已修复(6/22): 加processed列,cron处理完后UPDATE标记 - [x] signal_news 缺 processed 标记 → 已修复(6/22): 加processed列,cron处理完后UPDATE标记
- [x] xiaoguo_risk 信号已接入(cron prompt处理) - [x] xiaoguo_risk 信号已接入(cron prompt处理)→ 小果已退役(7/20),此条已失效
### 修复方案 ### 修复方案
为 signal_news 表新增 `processed` 字段(0=未处理, 1=已处理),cron处理完后 UPDATE 标记。 为 signal_news 表新增 `processed` 字段(0=未处理, 1=已处理),cron处理完后 UPDATE 标记。
+7 -7
View File
@@ -15,7 +15,7 @@ trigger: 交易日 8:00 AM 自动运行
1. **health_checklist.json** — 可动态维护的检查清单(新增功能自动加入) 1. **health_checklist.json** — 可动态维护的检查清单(新增功能自动加入)
2. **morning_health_check.py** — 每日8:00开盘前运行,逐项比对 2. **morning_health_check.py** — 每日8:00开盘前运行,逐项比对
3. **self_discovery()** — 自动发现新增cron任务并追加到检查清单 3. **self_discovery()** — 自动发现新增cron任务并追加到检查清单
4. **历史追踪** — health_check_history.json 保留90天体检记录 4. **历史追踪** `health_check_log` 表(SQLite,替代原 health_check_history.json
## 架构 ## 架构
@@ -24,13 +24,13 @@ morning_health_check.py (no_agent, 8:00 Cron)
health_checklist.json (检查清单) health_checklist.json (检查清单)
分层检查 (8) 分层检查 (8)
基础设施 XMPP/Gateway/Dashboard/API/磁盘 基础设施 XMPP/Gateway/Dashboard/API/磁盘
SENSE price_monitor/xiaoguo/宏观/汇率/板块 SENSE price_monitor/宏观/汇率/板块
RESPOND 推送cron/价格事件/信号积压 RESPOND 推送cron/价格事件/信号积压
ADAPT 策略重评/策略树/时效性 ADAPT 策略重评/策略树/时效性
IMPROVE 知识萃取/硬编码/审计/剪枝/元成长 IMPROVE 知识萃取/硬编码/审计/剪枝/元成长
数据文件 全部关键JSON/DB文件新鲜度 数据库健康度 关键表新鲜度/死锁检查
管道完整性 cron异常/误暂停/delivery目标/信号桥/cron全局审计 管道完整性 cron异常/误暂停/delivery目标/信号桥/cron全局审计
元自检 昨日体检完成/checklist覆盖/cron调度 元自检 昨日体检完成/checklist覆盖/cron调度
@@ -47,7 +47,7 @@ morning_health_check.py (no_agent, 8:00 Cron)
位于 `/home/hmo/MoFin/data/health_checklist.json` 位于 `/home/hmo/MoFin/data/health_checklist.json`
累计8类48项检查。项目定期检查:盘中自检每15分钟,每日早检8:00,每周深度审计。 累计 **8类40项** 检查(2026-08-10 清理小果残留项后:48→40)。项目定期检查:盘中自检每15分钟,每日早检8:00,每周深度审计。
检查清单位于 `/home/hmo/MoFin/data/health_checklist.json` 检查清单位于 `/home/hmo/MoFin/data/health_checklist.json`
- id/description: 唯一标识和描述 - id/description: 唯一标识和描述
@@ -114,6 +114,6 @@ MoFin 系统体检 | 2026-06-25 周四 | 08:00
## 历史记录 ## 历史记录
保存在 `/home/hmo/MoFin/data/health_check_history.json` 保存在 `health_check_log` 表(mofin.db,替代原 `health_check_history.json`
- 每次运行记录时间戳、各等级计数、耗时 - 每次运行记录时间戳、各等级计数、耗时
- 保留最近90条(约3个月) - 每行一条体检结果,长期保留
+3 -2
View File
@@ -1,6 +1,7 @@
# MoFin 数据模型 # MoFin 数据模型
> 数据已从 JSON 迁移到 SQLite。portfolio.json / decisions.json / watchlist.json 不再使用。 > 数据已从 JSON 迁移到 SQLite。**decisions.json / watchlist.json 已移除**
> ⚠️ **portfolio.json 仍在用**update_data.py 写、stock_profile.py 读,2026-08-11 核实)。
## 核心表 ## 核心表
@@ -58,7 +59,7 @@ price_monitor (cron: */2 9-16)
→ write_holdings_batch() → holdings 表 (price 更新) → write_holdings_batch() → holdings 表 (price 更新)
→ write_portfolio_summary() → portfolio_summary (total_mv/total_assets 重算) → write_portfolio_summary() → portfolio_summary (total_mv/total_assets 重算)
regenerate_all (cron: 手动/定时) regenerate_strategies.py (cron: 盘前 8:10 premarket_full_review)
→ batch_fetch_prices() → 从 DB 读价格 → batch_fetch_prices() → 从 DB 读价格
→ 技术分析 → 止损/止盈/买入区 → 技术分析 → 止损/止盈/买入区
→ write_holding_strategy() → holding_strategies 表 → write_holding_strategy() → holding_strategies 表