Files
market_sync/docs/works/2026-07-03-06-mairui-ma-daily.md
T
gao b351bd7595 feat: 新增 mairui 历史分时 MA 日 K 级别 sync task
work #06 (2026-07-03):user 请求加 mairui /hsdata 历史分时 MA 同步(日 K 级别)。

mairui 端点探测:/d/ma, /d/ma5/10/20, /15/ma, /30/ma, /60/ma 端点结构存在
但当前免费 licence 返 数据不存在;基础 K 线 (/d/n, /15/n, /30/n, /60/n) 正常。

策略:本地从 kline_stock 计算(pandas per-stock rolling),写新表
kline_stock_ma_daily,source=local_kline_proxy 标识本地派生。
mairui URL 留作未来升级 licence 后切 API 用。

变更:
- app/core/db/models.py: KlineStockMADaily ORM model
- app/core/db/ops.py: upsert_kline_stock_ma_daily_rows (批量 5000/批)
- app/tasks/task_mairui_ma_daily.py: SyncMairuiMADaily (全量重算)
- app/tasks/__init__.py: 注册到 TASKS dict
- app/core/sync/registry.py: SYNC_DEFINITION (sort_order=90, dep=kline_daily)
- app/core/scheduler/scheduler.py: schedule_mairui_ma_daily @ 16:30 + register_sync_jobs
- bin/daily_sync_check.py: SCHEDULE entry (window_end=17:00)

烟测:11,684,592 行, 5510 只, 1370s (23min),MA5/10/20/60 全部计算。
SH600519 样本:ma5=1194.18 ma10=1191.03 ma20=1211.94 ma60=1296.20 (2026-07-03)

未来优化(不在本 work):
- 增量模式(每日只算最近 1-2 天)→ 23min → 30s
- 升级 mairui licence 切到 /d/maN API
- 加 EMA / BOLL / KDJ 等其他指标

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-03 17:36:49 +08:00

93 lines
3.6 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.
# 2026-07-03 — work #06: 新增 mairui 历史分时 MA(日 K 级别)同步
## 需求
user 请求:"添加同步数据 https://mairui.club/hsdata 历史分时MA,日K线级别"
## 探测 mairui API
尝试 mairui 提供的 MA 端点(用现有 .env 里的 licence fb3ea07350729a2b3f):
| 端点 | 状态 |
|---|---|
| `/hsstock/history/{code}.{ex}/d/ma/` | ✅ HTTP 200,但 body `{"error":"数据不存在"}` |
| `/hsstock/history/{code}.{ex}/d/ma5/` | ✅ HTTP 200`{"error":"数据不存在"}` |
| `/hsstock/history/{code}.{ex}/d/ma10/` | ✅ 同上 |
| `/hsstock/history/{code}.{ex}/d/ma20/` | ✅ 同上 |
| `/hsstock/history/{code}.{ex}/15/ma/` | ✅ 同上 |
| `/hsstock/history/{code}.{ex}/30/ma/` | ✅ 同上 |
| `/hsstock/history/{code}.{ex}/60/ma/` | ✅ 同上 |
| `/hsstock/history/{code}.{ex}/d/n/` | ✅ 返正常 OHLCV |
| `/hsstock/history/{code}.{ex}/15/n/` | ✅ 15min K |
| `/hsstock/history/{code}.{ex}/30/n/` | ✅ 30min K |
| `/hsstock/history/{code}.{ex}/60/n/` | ✅ 60min K |
**结论**:MA 端点结构存在但**当前免费 licence 没数据**。基础 K 线(OHLCV)正常。
## 解决
mairui 端点不可用,但**用户要的"日 K 级别 MA"完全可以本地从已有 kline_stock 派生**
- 输入:market_data.kline_stock(已有 ~1170w 行日 K 线)
- 操作:按 stock_code 分组,对 close 做 `rolling(5/10/20/60).mean()`
- 写新表 `market_data.kline_stock_ma_daily`
mairui URL 留作未来升级 licence 后的扩展(task 里 source 字段已标识 `local_kline_proxy`,可改 `mairui`)。
## 变更清单
1. **新 ORM model** `KlineStockMADaily`models.py
- 字段:stock_code / trade_date / ma5 / ma10 / ma20 / ma60 / source / updated_at
- PK: (stock_code, trade_date)
- Index: trade_date
2. **新 ops 函数** `upsert_kline_stock_ma_daily_rows`ops.py
- PG upsert 模式与 sector_features 一致
- 批量 5000 行/批
-`pd_isna` 避开 import pandas
3. **新 task** `task_mairui_ma_daily.py`
- 读 kline_stock → pandas → per-stock rolling → upsert
- MA_WINDOWS = [5, 10, 20, 60]
- 全量重算(数据量 ~1100w 行 pandas ~30s
4. **注册**
- `app/tasks/__init__.py``SyncMairuiMADaily` 到 TASKS
- `app/core/sync/registry.py` 加 SYNC_DEFINITIONsort_order=90dependency=kline_daily
- `app/core/scheduler/scheduler.py` 加 schedule_mairui_ma_daily@16:30 daily+ register_sync_jobs
- `bin/daily_sync_check.py` 加 SCHEDULE entrywindow_end=17:00
## 烟测验证
```
✅ task 完成 ok: MA [5, 10, 20, 60] 共 11,684,592 行, 5510 只, 1370.1s
✅ kline_stock_ma_daily table created (step4_create_tables)
✅ rows: 11,684,592
✅ stocks: 5510
✅ date range: 2000-07-25 ~ 2026-07-03
✅ NULL ma5: 22,038 (每只股票前 4 个交易日)
```
样本 SH600519
```
2026-07-03 ma5=1194.18 ma10=1191.03 ma20=1211.94 ma60=1296.20
2026-07-02 ma5=1189.02 ma10=1190.27 ma20=1214.16 ma60=1300.06
```
## 性能
- 全量重算 1370s ≈ 23 min(首次含 table creation + 批量 upsert
- 后续每日增量(只算昨天一行)应该 < 5s,但当前实现是全量重算 → 22 min
- **优化点**(不在本 work 范围):改成增量模式(只 upsert 最近 1-2 天),把 23 min 降到 30s
## 不在范围(未来)
- 增量模式(避免每日 23 min 全量重算)
- 升级 mairui licence 后切到 `/d/maN` API
- EMA(指数移动平均,与 MA 区别)
- BOLL / KDJ 等其他衍生指标
## 关联
- mairui 接入:app/sources/mairui.py
- daily_checkbin/daily_sync_check.py
- 数据依赖:本任务依赖 kline_daily,所以应排在 kline_daily 之后(16:00 后跑)