data-backtest-live-common 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data_backtest_live_common-0.2.0/LICENSE +21 -0
- data_backtest_live_common-0.2.0/PKG-INFO +143 -0
- data_backtest_live_common-0.2.0/README.md +92 -0
- data_backtest_live_common-0.2.0/data_backtest_live_common.egg-info/PKG-INFO +143 -0
- data_backtest_live_common-0.2.0/data_backtest_live_common.egg-info/SOURCES.txt +31 -0
- data_backtest_live_common-0.2.0/data_backtest_live_common.egg-info/dependency_links.txt +1 -0
- data_backtest_live_common-0.2.0/data_backtest_live_common.egg-info/requires.txt +6 -0
- data_backtest_live_common-0.2.0/data_backtest_live_common.egg-info/top_level.txt +1 -0
- data_backtest_live_common-0.2.0/dbl_common/__init__.py +93 -0
- data_backtest_live_common-0.2.0/dbl_common/adjust.py +74 -0
- data_backtest_live_common-0.2.0/dbl_common/boards.py +162 -0
- data_backtest_live_common-0.2.0/dbl_common/circuit_breaker.py +82 -0
- data_backtest_live_common-0.2.0/dbl_common/corporate_actions.py +177 -0
- data_backtest_live_common-0.2.0/dbl_common/fees.py +171 -0
- data_backtest_live_common-0.2.0/dbl_common/halts.py +182 -0
- data_backtest_live_common-0.2.0/dbl_common/io_utils.py +70 -0
- data_backtest_live_common-0.2.0/dbl_common/lots.py +110 -0
- data_backtest_live_common-0.2.0/dbl_common/price_limit.py +326 -0
- data_backtest_live_common-0.2.0/dbl_common/proc.py +130 -0
- data_backtest_live_common-0.2.0/dbl_common/settlement.py +108 -0
- data_backtest_live_common-0.2.0/dbl_common/ticks.py +57 -0
- data_backtest_live_common-0.2.0/dbl_common/trade_calendar.py +128 -0
- data_backtest_live_common-0.2.0/dbl_common/trading_calendar.py +202 -0
- data_backtest_live_common-0.2.0/dbl_common/trading_hours.py +159 -0
- data_backtest_live_common-0.2.0/dbl_common/vec.py +134 -0
- data_backtest_live_common-0.2.0/pyproject.toml +41 -0
- data_backtest_live_common-0.2.0/setup.cfg +4 -0
- data_backtest_live_common-0.2.0/tests/test_adjust.py +95 -0
- data_backtest_live_common-0.2.0/tests/test_io_utils.py +48 -0
- data_backtest_live_common-0.2.0/tests/test_price_limit.py +137 -0
- data_backtest_live_common-0.2.0/tests/test_proc.py +58 -0
- data_backtest_live_common-0.2.0/tests/test_trade_calendar.py +124 -0
- data_backtest_live_common-0.2.0/tests/test_trading_rules.py +560 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 data-backtest-live-common contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: data-backtest-live-common
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: 数据(Data)/回测(Backtest)/实盘(Live)三系统公共库:复权、A股交易规则全集(涨跌幅/时段/费用/交收/熔断/除权)、交易日历、原子写、无黑窗子进程
|
|
5
|
+
Author: dbl_common maintainers
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 data-backtest-live-common contributors
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Keywords: quant,data,backtest,live-trading,a-share,tushare,akshare
|
|
29
|
+
Classifier: Development Status :: 4 - Beta
|
|
30
|
+
Classifier: Intended Audience :: Developers
|
|
31
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
32
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
33
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
34
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
35
|
+
Classifier: Programming Language :: Python :: 3
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
41
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
42
|
+
Requires-Python: >=3.10
|
|
43
|
+
Description-Content-Type: text/markdown
|
|
44
|
+
License-File: LICENSE
|
|
45
|
+
Requires-Dist: pandas
|
|
46
|
+
Requires-Dist: numpy
|
|
47
|
+
Requires-Dist: duckdb
|
|
48
|
+
Provides-Extra: test
|
|
49
|
+
Requires-Dist: pytest; extra == "test"
|
|
50
|
+
Dynamic: license-file
|
|
51
|
+
|
|
52
|
+
# data-backtest-live-common(导入名 `dbl_common`)
|
|
53
|
+
|
|
54
|
+
数据(Data)/ 回测(Backtest)/ 实盘(Live Trading)三个系统**共用**的公共库。
|
|
55
|
+
独立项目,像 akshare 一样 pip 安装后直接 import 使用。
|
|
56
|
+
|
|
57
|
+
- **发行名(pip 名)**:`data-backtest-live-common` —— 数据/回测/实盘三个英文单词 + common(用户 2026-09-26 指定口径)
|
|
58
|
+
- **导入名**:`dbl_common` —— 三词首字母 + common(对齐 `beautifulsoup4 → import bs4` 的短名惯例,免得每次 import 敲 24 个字符)
|
|
59
|
+
- **版本**:0.2.0 —— 2026-09-26 从 `quant_data_center/common` 抽出独立成库;**2026-09-27 并入原 `market_common`(A 股交易规则库)两库合一**,`f:/code/finance/market_common` 内容已全部迁入本库并停止维护(原目录删除被环境安全删除守卫拦截,只剩弃用标记,可随时人工删除)
|
|
60
|
+
|
|
61
|
+
## 收录标准(硬规则)
|
|
62
|
+
|
|
63
|
+
只收「**数据、回测、实盘三个系统都会用到**」的代码。
|
|
64
|
+
单系统专属的公共代码放回各系统自己的 common 包
|
|
65
|
+
(例如 quant_data_center 的 throttle 限频 / pagination 翻页是采集专属,留在那边)。
|
|
66
|
+
|
|
67
|
+
## 模块清单
|
|
68
|
+
|
|
69
|
+
| 模块 | 干什么 | 三系统各自的用途 |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| `adjust` | 本地复权引擎(hfq = raw×adj_factor 锚定上市日;qfq 锚定最新) | 数据:清洗层标准化;回测:价格连续序列;实盘:指标口径 |
|
|
72
|
+
| `boards` | 证券代码规范化 / 品种识别 / 板块判定(规则库最底层,纯函数零依赖) | 所有系统问「这代码是什么品种、哪个板块」 |
|
|
73
|
+
| `price_limit` | 涨跌停**规则全集**(主板/科创/创业/北交/ST/ETF/转债/B股/新股首日非对称档,含历史制度变更,返回 `LimitSpec` 值对象) | 数据:审核规则;回测:判板;实盘:委托价边界 |
|
|
74
|
+
| `vec` | 涨跌停**向量化引擎唯一实现**(`limit_prices`/`flags_from_bars`/`board_flags`/`hfq_ret_on`,spec 驱动,支持 ETF 三位报价) | 回测全市场判板(5000+ 只 × 数千日) |
|
|
75
|
+
| `trade_calendar` | 交易日历读取(Tushare cal Parquet;`cal_glob` 必传,不绑定任何系统路径) | 三系统同一套日历口径 |
|
|
76
|
+
| `trading_calendar` | 交易日历**注入契约**(`InjectedCalendar`:BaoStock CSV / QDC raw 层 Parquet,三态诚实) | 回测/实盘注入自己的日历数据源 |
|
|
77
|
+
| `trading_hours` | 交易时段(集合竞价/连续竞价/收盘集合竞价,`Phase` 枚举) | 实盘下单时段校验;回测撮合时点 |
|
|
78
|
+
| `settlement` | 交收制度(T+1/T+0/T+3,`STOCK_T1_START`) | 实盘可卖判断;回测成交约束 |
|
|
79
|
+
| `lots` / `ticks` | 申报单位(手数)/ 最小变动价位(含 snap/校验) | 实盘委托合法性;回测撮合精度 |
|
|
80
|
+
| `fees` | 交易费用(印花税/过户费**时间线**,佣金必显式传) | 回测净收益;实盘成本预估 |
|
|
81
|
+
| `circuit_breaker` | 2016 熔断制度(历史触发记录) | 回测跨 2016-01 必须剔除熔断时段 |
|
|
82
|
+
| `halts` | 盘中临时停牌(新股/转债临停规则与复牌时间) | 回测撮合跳过临停;实盘委托拦截 |
|
|
83
|
+
| `corporate_actions` | 除权除息参考价官方公式 + 理论因子跳变 + 数据中心核验入口(容差 0.5%;B股/转债拒答) | 数据:dividend 对账;回测:复权核验 |
|
|
84
|
+
| `proc` | 子进程无黑窗(`no_window`/`no_window_if_detached`/`pid_alive`,Windows) | 任何会起子进程的系统(调度/并行网格/网关进程) |
|
|
85
|
+
| `io_utils` | 原子写文件(tmp + os.replace + WinError5 重试) | 任何写「会被并发读」的状态/数据文件的系统 |
|
|
86
|
+
|
|
87
|
+
依赖:`pandas` / `numpy` / `duckdb`(pip install 自动拉齐;已有这些包的系统可加 `--no-deps`)。
|
|
88
|
+
|
|
89
|
+
## 安装(三种姿势)
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# ① 开发期(editable:改源码立即生效,无需重装)
|
|
93
|
+
"D:\Program Files\Python314\python.exe" -m pip install -e f:/code/finance/data-backtest-live-common --no-deps
|
|
94
|
+
|
|
95
|
+
# ② 正式(打 wheel 安装)
|
|
96
|
+
python -m pip wheel . --no-deps -w dist
|
|
97
|
+
python -m pip install dist/data_backtest_live_common-0.2.0-py3-none-any.whl
|
|
98
|
+
|
|
99
|
+
# ③ 未来发布 PyPI 后(像 akshare 一样)
|
|
100
|
+
pip install data-backtest-live-common
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
quant_data_center 当前用姿势 ①(editable,装在 `D:\Program Files\Python314` 解释器上,
|
|
104
|
+
tests / uvicorn / scheduler 子进程全部可见)。
|
|
105
|
+
|
|
106
|
+
## 开发与测试
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# 需要解释器里有 pandas / numpy / duckdb / pytest(vendor PYTHONPATH 或已 pip 安装)
|
|
110
|
+
$env:PYTHONPATH = "F:\code\finance\quant_data_center\vendor"
|
|
111
|
+
"D:\Program Files\Python314\python.exe" -m pytest tests -q
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## 诚实边界
|
|
115
|
+
|
|
116
|
+
- `trade_calendar` 只读「已经落盘的日历 Parquet」,不联网、不猜测:文件缺失返回 `[]` 由调用方降级;**参数(cal_glob)缺失直接 ValueError**(程序员错误必须响亮);
|
|
117
|
+
- `price_limit` 的 ST 判定只有当前名单、没有逐日历史 → 5% 档用「恰好贴板」精确判定(详见模块 docstring 的血泪教训:用 `≥` 会把普通涨超 5% 的交易日成片误判);
|
|
118
|
+
- `adjust` 的 hfq 锚定上市日(历史行永不变,适合增量落盘),qfq 锚定最新(历史随分红改写,只适合展示);
|
|
119
|
+
- 1996-12-16 之前 A 股无涨跌停制度,`vec.flags_from_bars` 一律不判;
|
|
120
|
+
- `corporate_actions` 对 B 股(需当日汇率折算,属运行期数据非规则)与可转债(不除权)显式 raise 拒答,不猜;
|
|
121
|
+
- 新股「首 N 日不设涨跌幅」没有交易日序号时按自然日近似,`reason` 里如实标注「近似」。
|
|
122
|
+
|
|
123
|
+
## 与兄弟项目的关系(互不 import)
|
|
124
|
+
|
|
125
|
+
| 项目 | 定位 | 关系 |
|
|
126
|
+
|---|---|---|
|
|
127
|
+
| `quant_data_center` | 数据系统 | 本库母体;现为 pip 依赖 `dbl_common` |
|
|
128
|
+
| 回测 / 实盘系统(未来) | — | 直接 `pip install` 本库即可(原需另装 market_common,2026-09-27 已并入) |
|
|
129
|
+
|
|
130
|
+
> **两库合一记录(2026-09-27)**:用户对比本库与 `market_common` 后指令「如有重复删除
|
|
131
|
+
> market」。实测仅 `price_limit` 领域同源重复(本库=引擎+简化规则,market=规则全集),
|
|
132
|
+
> 其余 10 个交易规则模块是独有内容 → **整体并入**:`price_limit` 取超集版(含
|
|
133
|
+
> `round_half_up` 浮点修正),向量化引擎统一进 `vec.py`(spec 驱动签名),83 项守卫
|
|
134
|
+
> 测试随迁为 `tests/test_trading_rules.py`,原 market_common 目录弃用(AI 删除时被环境
|
|
135
|
+
> 安全删除守卫拦截,内容已 100% 迁入本库并经测试验证,该目录可随时人工删除)。
|
|
136
|
+
|
|
137
|
+
## 怎么加新模块(给 AI 的守则)
|
|
138
|
+
|
|
139
|
+
1. 先判定「三个系统都用到吗」——不是就放回各系统自己的 common,别塞进来;
|
|
140
|
+
2. 纯函数优先、零系统路径耦合(需要路径/配置就做成必传参数,参照 `trade_calendar.cal_glob`);
|
|
141
|
+
3. 配 `tests/` 用例,锚点用真实制度事实(如创业板 2020-08-24 改 20%、round_half_up(2.675)=2.68);
|
|
142
|
+
4. 版本号 +1(`pyproject.toml` 与 `dbl_common/__init__.py` 同步改),更新本 README 模块表;
|
|
143
|
+
5. Windows 环境跑命令一律后台无窗(`Start-Process -WindowStyle Hidden`)。
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# data-backtest-live-common(导入名 `dbl_common`)
|
|
2
|
+
|
|
3
|
+
数据(Data)/ 回测(Backtest)/ 实盘(Live Trading)三个系统**共用**的公共库。
|
|
4
|
+
独立项目,像 akshare 一样 pip 安装后直接 import 使用。
|
|
5
|
+
|
|
6
|
+
- **发行名(pip 名)**:`data-backtest-live-common` —— 数据/回测/实盘三个英文单词 + common(用户 2026-09-26 指定口径)
|
|
7
|
+
- **导入名**:`dbl_common` —— 三词首字母 + common(对齐 `beautifulsoup4 → import bs4` 的短名惯例,免得每次 import 敲 24 个字符)
|
|
8
|
+
- **版本**:0.2.0 —— 2026-09-26 从 `quant_data_center/common` 抽出独立成库;**2026-09-27 并入原 `market_common`(A 股交易规则库)两库合一**,`f:/code/finance/market_common` 内容已全部迁入本库并停止维护(原目录删除被环境安全删除守卫拦截,只剩弃用标记,可随时人工删除)
|
|
9
|
+
|
|
10
|
+
## 收录标准(硬规则)
|
|
11
|
+
|
|
12
|
+
只收「**数据、回测、实盘三个系统都会用到**」的代码。
|
|
13
|
+
单系统专属的公共代码放回各系统自己的 common 包
|
|
14
|
+
(例如 quant_data_center 的 throttle 限频 / pagination 翻页是采集专属,留在那边)。
|
|
15
|
+
|
|
16
|
+
## 模块清单
|
|
17
|
+
|
|
18
|
+
| 模块 | 干什么 | 三系统各自的用途 |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| `adjust` | 本地复权引擎(hfq = raw×adj_factor 锚定上市日;qfq 锚定最新) | 数据:清洗层标准化;回测:价格连续序列;实盘:指标口径 |
|
|
21
|
+
| `boards` | 证券代码规范化 / 品种识别 / 板块判定(规则库最底层,纯函数零依赖) | 所有系统问「这代码是什么品种、哪个板块」 |
|
|
22
|
+
| `price_limit` | 涨跌停**规则全集**(主板/科创/创业/北交/ST/ETF/转债/B股/新股首日非对称档,含历史制度变更,返回 `LimitSpec` 值对象) | 数据:审核规则;回测:判板;实盘:委托价边界 |
|
|
23
|
+
| `vec` | 涨跌停**向量化引擎唯一实现**(`limit_prices`/`flags_from_bars`/`board_flags`/`hfq_ret_on`,spec 驱动,支持 ETF 三位报价) | 回测全市场判板(5000+ 只 × 数千日) |
|
|
24
|
+
| `trade_calendar` | 交易日历读取(Tushare cal Parquet;`cal_glob` 必传,不绑定任何系统路径) | 三系统同一套日历口径 |
|
|
25
|
+
| `trading_calendar` | 交易日历**注入契约**(`InjectedCalendar`:BaoStock CSV / QDC raw 层 Parquet,三态诚实) | 回测/实盘注入自己的日历数据源 |
|
|
26
|
+
| `trading_hours` | 交易时段(集合竞价/连续竞价/收盘集合竞价,`Phase` 枚举) | 实盘下单时段校验;回测撮合时点 |
|
|
27
|
+
| `settlement` | 交收制度(T+1/T+0/T+3,`STOCK_T1_START`) | 实盘可卖判断;回测成交约束 |
|
|
28
|
+
| `lots` / `ticks` | 申报单位(手数)/ 最小变动价位(含 snap/校验) | 实盘委托合法性;回测撮合精度 |
|
|
29
|
+
| `fees` | 交易费用(印花税/过户费**时间线**,佣金必显式传) | 回测净收益;实盘成本预估 |
|
|
30
|
+
| `circuit_breaker` | 2016 熔断制度(历史触发记录) | 回测跨 2016-01 必须剔除熔断时段 |
|
|
31
|
+
| `halts` | 盘中临时停牌(新股/转债临停规则与复牌时间) | 回测撮合跳过临停;实盘委托拦截 |
|
|
32
|
+
| `corporate_actions` | 除权除息参考价官方公式 + 理论因子跳变 + 数据中心核验入口(容差 0.5%;B股/转债拒答) | 数据:dividend 对账;回测:复权核验 |
|
|
33
|
+
| `proc` | 子进程无黑窗(`no_window`/`no_window_if_detached`/`pid_alive`,Windows) | 任何会起子进程的系统(调度/并行网格/网关进程) |
|
|
34
|
+
| `io_utils` | 原子写文件(tmp + os.replace + WinError5 重试) | 任何写「会被并发读」的状态/数据文件的系统 |
|
|
35
|
+
|
|
36
|
+
依赖:`pandas` / `numpy` / `duckdb`(pip install 自动拉齐;已有这些包的系统可加 `--no-deps`)。
|
|
37
|
+
|
|
38
|
+
## 安装(三种姿势)
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# ① 开发期(editable:改源码立即生效,无需重装)
|
|
42
|
+
"D:\Program Files\Python314\python.exe" -m pip install -e f:/code/finance/data-backtest-live-common --no-deps
|
|
43
|
+
|
|
44
|
+
# ② 正式(打 wheel 安装)
|
|
45
|
+
python -m pip wheel . --no-deps -w dist
|
|
46
|
+
python -m pip install dist/data_backtest_live_common-0.2.0-py3-none-any.whl
|
|
47
|
+
|
|
48
|
+
# ③ 未来发布 PyPI 后(像 akshare 一样)
|
|
49
|
+
pip install data-backtest-live-common
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
quant_data_center 当前用姿势 ①(editable,装在 `D:\Program Files\Python314` 解释器上,
|
|
53
|
+
tests / uvicorn / scheduler 子进程全部可见)。
|
|
54
|
+
|
|
55
|
+
## 开发与测试
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# 需要解释器里有 pandas / numpy / duckdb / pytest(vendor PYTHONPATH 或已 pip 安装)
|
|
59
|
+
$env:PYTHONPATH = "F:\code\finance\quant_data_center\vendor"
|
|
60
|
+
"D:\Program Files\Python314\python.exe" -m pytest tests -q
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## 诚实边界
|
|
64
|
+
|
|
65
|
+
- `trade_calendar` 只读「已经落盘的日历 Parquet」,不联网、不猜测:文件缺失返回 `[]` 由调用方降级;**参数(cal_glob)缺失直接 ValueError**(程序员错误必须响亮);
|
|
66
|
+
- `price_limit` 的 ST 判定只有当前名单、没有逐日历史 → 5% 档用「恰好贴板」精确判定(详见模块 docstring 的血泪教训:用 `≥` 会把普通涨超 5% 的交易日成片误判);
|
|
67
|
+
- `adjust` 的 hfq 锚定上市日(历史行永不变,适合增量落盘),qfq 锚定最新(历史随分红改写,只适合展示);
|
|
68
|
+
- 1996-12-16 之前 A 股无涨跌停制度,`vec.flags_from_bars` 一律不判;
|
|
69
|
+
- `corporate_actions` 对 B 股(需当日汇率折算,属运行期数据非规则)与可转债(不除权)显式 raise 拒答,不猜;
|
|
70
|
+
- 新股「首 N 日不设涨跌幅」没有交易日序号时按自然日近似,`reason` 里如实标注「近似」。
|
|
71
|
+
|
|
72
|
+
## 与兄弟项目的关系(互不 import)
|
|
73
|
+
|
|
74
|
+
| 项目 | 定位 | 关系 |
|
|
75
|
+
|---|---|---|
|
|
76
|
+
| `quant_data_center` | 数据系统 | 本库母体;现为 pip 依赖 `dbl_common` |
|
|
77
|
+
| 回测 / 实盘系统(未来) | — | 直接 `pip install` 本库即可(原需另装 market_common,2026-09-27 已并入) |
|
|
78
|
+
|
|
79
|
+
> **两库合一记录(2026-09-27)**:用户对比本库与 `market_common` 后指令「如有重复删除
|
|
80
|
+
> market」。实测仅 `price_limit` 领域同源重复(本库=引擎+简化规则,market=规则全集),
|
|
81
|
+
> 其余 10 个交易规则模块是独有内容 → **整体并入**:`price_limit` 取超集版(含
|
|
82
|
+
> `round_half_up` 浮点修正),向量化引擎统一进 `vec.py`(spec 驱动签名),83 项守卫
|
|
83
|
+
> 测试随迁为 `tests/test_trading_rules.py`,原 market_common 目录弃用(AI 删除时被环境
|
|
84
|
+
> 安全删除守卫拦截,内容已 100% 迁入本库并经测试验证,该目录可随时人工删除)。
|
|
85
|
+
|
|
86
|
+
## 怎么加新模块(给 AI 的守则)
|
|
87
|
+
|
|
88
|
+
1. 先判定「三个系统都用到吗」——不是就放回各系统自己的 common,别塞进来;
|
|
89
|
+
2. 纯函数优先、零系统路径耦合(需要路径/配置就做成必传参数,参照 `trade_calendar.cal_glob`);
|
|
90
|
+
3. 配 `tests/` 用例,锚点用真实制度事实(如创业板 2020-08-24 改 20%、round_half_up(2.675)=2.68);
|
|
91
|
+
4. 版本号 +1(`pyproject.toml` 与 `dbl_common/__init__.py` 同步改),更新本 README 模块表;
|
|
92
|
+
5. Windows 环境跑命令一律后台无窗(`Start-Process -WindowStyle Hidden`)。
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: data-backtest-live-common
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: 数据(Data)/回测(Backtest)/实盘(Live)三系统公共库:复权、A股交易规则全集(涨跌幅/时段/费用/交收/熔断/除权)、交易日历、原子写、无黑窗子进程
|
|
5
|
+
Author: dbl_common maintainers
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 data-backtest-live-common contributors
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Keywords: quant,data,backtest,live-trading,a-share,tushare,akshare
|
|
29
|
+
Classifier: Development Status :: 4 - Beta
|
|
30
|
+
Classifier: Intended Audience :: Developers
|
|
31
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
32
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
33
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
34
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
35
|
+
Classifier: Programming Language :: Python :: 3
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
41
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
42
|
+
Requires-Python: >=3.10
|
|
43
|
+
Description-Content-Type: text/markdown
|
|
44
|
+
License-File: LICENSE
|
|
45
|
+
Requires-Dist: pandas
|
|
46
|
+
Requires-Dist: numpy
|
|
47
|
+
Requires-Dist: duckdb
|
|
48
|
+
Provides-Extra: test
|
|
49
|
+
Requires-Dist: pytest; extra == "test"
|
|
50
|
+
Dynamic: license-file
|
|
51
|
+
|
|
52
|
+
# data-backtest-live-common(导入名 `dbl_common`)
|
|
53
|
+
|
|
54
|
+
数据(Data)/ 回测(Backtest)/ 实盘(Live Trading)三个系统**共用**的公共库。
|
|
55
|
+
独立项目,像 akshare 一样 pip 安装后直接 import 使用。
|
|
56
|
+
|
|
57
|
+
- **发行名(pip 名)**:`data-backtest-live-common` —— 数据/回测/实盘三个英文单词 + common(用户 2026-09-26 指定口径)
|
|
58
|
+
- **导入名**:`dbl_common` —— 三词首字母 + common(对齐 `beautifulsoup4 → import bs4` 的短名惯例,免得每次 import 敲 24 个字符)
|
|
59
|
+
- **版本**:0.2.0 —— 2026-09-26 从 `quant_data_center/common` 抽出独立成库;**2026-09-27 并入原 `market_common`(A 股交易规则库)两库合一**,`f:/code/finance/market_common` 内容已全部迁入本库并停止维护(原目录删除被环境安全删除守卫拦截,只剩弃用标记,可随时人工删除)
|
|
60
|
+
|
|
61
|
+
## 收录标准(硬规则)
|
|
62
|
+
|
|
63
|
+
只收「**数据、回测、实盘三个系统都会用到**」的代码。
|
|
64
|
+
单系统专属的公共代码放回各系统自己的 common 包
|
|
65
|
+
(例如 quant_data_center 的 throttle 限频 / pagination 翻页是采集专属,留在那边)。
|
|
66
|
+
|
|
67
|
+
## 模块清单
|
|
68
|
+
|
|
69
|
+
| 模块 | 干什么 | 三系统各自的用途 |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| `adjust` | 本地复权引擎(hfq = raw×adj_factor 锚定上市日;qfq 锚定最新) | 数据:清洗层标准化;回测:价格连续序列;实盘:指标口径 |
|
|
72
|
+
| `boards` | 证券代码规范化 / 品种识别 / 板块判定(规则库最底层,纯函数零依赖) | 所有系统问「这代码是什么品种、哪个板块」 |
|
|
73
|
+
| `price_limit` | 涨跌停**规则全集**(主板/科创/创业/北交/ST/ETF/转债/B股/新股首日非对称档,含历史制度变更,返回 `LimitSpec` 值对象) | 数据:审核规则;回测:判板;实盘:委托价边界 |
|
|
74
|
+
| `vec` | 涨跌停**向量化引擎唯一实现**(`limit_prices`/`flags_from_bars`/`board_flags`/`hfq_ret_on`,spec 驱动,支持 ETF 三位报价) | 回测全市场判板(5000+ 只 × 数千日) |
|
|
75
|
+
| `trade_calendar` | 交易日历读取(Tushare cal Parquet;`cal_glob` 必传,不绑定任何系统路径) | 三系统同一套日历口径 |
|
|
76
|
+
| `trading_calendar` | 交易日历**注入契约**(`InjectedCalendar`:BaoStock CSV / QDC raw 层 Parquet,三态诚实) | 回测/实盘注入自己的日历数据源 |
|
|
77
|
+
| `trading_hours` | 交易时段(集合竞价/连续竞价/收盘集合竞价,`Phase` 枚举) | 实盘下单时段校验;回测撮合时点 |
|
|
78
|
+
| `settlement` | 交收制度(T+1/T+0/T+3,`STOCK_T1_START`) | 实盘可卖判断;回测成交约束 |
|
|
79
|
+
| `lots` / `ticks` | 申报单位(手数)/ 最小变动价位(含 snap/校验) | 实盘委托合法性;回测撮合精度 |
|
|
80
|
+
| `fees` | 交易费用(印花税/过户费**时间线**,佣金必显式传) | 回测净收益;实盘成本预估 |
|
|
81
|
+
| `circuit_breaker` | 2016 熔断制度(历史触发记录) | 回测跨 2016-01 必须剔除熔断时段 |
|
|
82
|
+
| `halts` | 盘中临时停牌(新股/转债临停规则与复牌时间) | 回测撮合跳过临停;实盘委托拦截 |
|
|
83
|
+
| `corporate_actions` | 除权除息参考价官方公式 + 理论因子跳变 + 数据中心核验入口(容差 0.5%;B股/转债拒答) | 数据:dividend 对账;回测:复权核验 |
|
|
84
|
+
| `proc` | 子进程无黑窗(`no_window`/`no_window_if_detached`/`pid_alive`,Windows) | 任何会起子进程的系统(调度/并行网格/网关进程) |
|
|
85
|
+
| `io_utils` | 原子写文件(tmp + os.replace + WinError5 重试) | 任何写「会被并发读」的状态/数据文件的系统 |
|
|
86
|
+
|
|
87
|
+
依赖:`pandas` / `numpy` / `duckdb`(pip install 自动拉齐;已有这些包的系统可加 `--no-deps`)。
|
|
88
|
+
|
|
89
|
+
## 安装(三种姿势)
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# ① 开发期(editable:改源码立即生效,无需重装)
|
|
93
|
+
"D:\Program Files\Python314\python.exe" -m pip install -e f:/code/finance/data-backtest-live-common --no-deps
|
|
94
|
+
|
|
95
|
+
# ② 正式(打 wheel 安装)
|
|
96
|
+
python -m pip wheel . --no-deps -w dist
|
|
97
|
+
python -m pip install dist/data_backtest_live_common-0.2.0-py3-none-any.whl
|
|
98
|
+
|
|
99
|
+
# ③ 未来发布 PyPI 后(像 akshare 一样)
|
|
100
|
+
pip install data-backtest-live-common
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
quant_data_center 当前用姿势 ①(editable,装在 `D:\Program Files\Python314` 解释器上,
|
|
104
|
+
tests / uvicorn / scheduler 子进程全部可见)。
|
|
105
|
+
|
|
106
|
+
## 开发与测试
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# 需要解释器里有 pandas / numpy / duckdb / pytest(vendor PYTHONPATH 或已 pip 安装)
|
|
110
|
+
$env:PYTHONPATH = "F:\code\finance\quant_data_center\vendor"
|
|
111
|
+
"D:\Program Files\Python314\python.exe" -m pytest tests -q
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## 诚实边界
|
|
115
|
+
|
|
116
|
+
- `trade_calendar` 只读「已经落盘的日历 Parquet」,不联网、不猜测:文件缺失返回 `[]` 由调用方降级;**参数(cal_glob)缺失直接 ValueError**(程序员错误必须响亮);
|
|
117
|
+
- `price_limit` 的 ST 判定只有当前名单、没有逐日历史 → 5% 档用「恰好贴板」精确判定(详见模块 docstring 的血泪教训:用 `≥` 会把普通涨超 5% 的交易日成片误判);
|
|
118
|
+
- `adjust` 的 hfq 锚定上市日(历史行永不变,适合增量落盘),qfq 锚定最新(历史随分红改写,只适合展示);
|
|
119
|
+
- 1996-12-16 之前 A 股无涨跌停制度,`vec.flags_from_bars` 一律不判;
|
|
120
|
+
- `corporate_actions` 对 B 股(需当日汇率折算,属运行期数据非规则)与可转债(不除权)显式 raise 拒答,不猜;
|
|
121
|
+
- 新股「首 N 日不设涨跌幅」没有交易日序号时按自然日近似,`reason` 里如实标注「近似」。
|
|
122
|
+
|
|
123
|
+
## 与兄弟项目的关系(互不 import)
|
|
124
|
+
|
|
125
|
+
| 项目 | 定位 | 关系 |
|
|
126
|
+
|---|---|---|
|
|
127
|
+
| `quant_data_center` | 数据系统 | 本库母体;现为 pip 依赖 `dbl_common` |
|
|
128
|
+
| 回测 / 实盘系统(未来) | — | 直接 `pip install` 本库即可(原需另装 market_common,2026-09-27 已并入) |
|
|
129
|
+
|
|
130
|
+
> **两库合一记录(2026-09-27)**:用户对比本库与 `market_common` 后指令「如有重复删除
|
|
131
|
+
> market」。实测仅 `price_limit` 领域同源重复(本库=引擎+简化规则,market=规则全集),
|
|
132
|
+
> 其余 10 个交易规则模块是独有内容 → **整体并入**:`price_limit` 取超集版(含
|
|
133
|
+
> `round_half_up` 浮点修正),向量化引擎统一进 `vec.py`(spec 驱动签名),83 项守卫
|
|
134
|
+
> 测试随迁为 `tests/test_trading_rules.py`,原 market_common 目录弃用(AI 删除时被环境
|
|
135
|
+
> 安全删除守卫拦截,内容已 100% 迁入本库并经测试验证,该目录可随时人工删除)。
|
|
136
|
+
|
|
137
|
+
## 怎么加新模块(给 AI 的守则)
|
|
138
|
+
|
|
139
|
+
1. 先判定「三个系统都用到吗」——不是就放回各系统自己的 common,别塞进来;
|
|
140
|
+
2. 纯函数优先、零系统路径耦合(需要路径/配置就做成必传参数,参照 `trade_calendar.cal_glob`);
|
|
141
|
+
3. 配 `tests/` 用例,锚点用真实制度事实(如创业板 2020-08-24 改 20%、round_half_up(2.675)=2.68);
|
|
142
|
+
4. 版本号 +1(`pyproject.toml` 与 `dbl_common/__init__.py` 同步改),更新本 README 模块表;
|
|
143
|
+
5. Windows 环境跑命令一律后台无窗(`Start-Process -WindowStyle Hidden`)。
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
data_backtest_live_common.egg-info/PKG-INFO
|
|
5
|
+
data_backtest_live_common.egg-info/SOURCES.txt
|
|
6
|
+
data_backtest_live_common.egg-info/dependency_links.txt
|
|
7
|
+
data_backtest_live_common.egg-info/requires.txt
|
|
8
|
+
data_backtest_live_common.egg-info/top_level.txt
|
|
9
|
+
dbl_common/__init__.py
|
|
10
|
+
dbl_common/adjust.py
|
|
11
|
+
dbl_common/boards.py
|
|
12
|
+
dbl_common/circuit_breaker.py
|
|
13
|
+
dbl_common/corporate_actions.py
|
|
14
|
+
dbl_common/fees.py
|
|
15
|
+
dbl_common/halts.py
|
|
16
|
+
dbl_common/io_utils.py
|
|
17
|
+
dbl_common/lots.py
|
|
18
|
+
dbl_common/price_limit.py
|
|
19
|
+
dbl_common/proc.py
|
|
20
|
+
dbl_common/settlement.py
|
|
21
|
+
dbl_common/ticks.py
|
|
22
|
+
dbl_common/trade_calendar.py
|
|
23
|
+
dbl_common/trading_calendar.py
|
|
24
|
+
dbl_common/trading_hours.py
|
|
25
|
+
dbl_common/vec.py
|
|
26
|
+
tests/test_adjust.py
|
|
27
|
+
tests/test_io_utils.py
|
|
28
|
+
tests/test_price_limit.py
|
|
29
|
+
tests/test_proc.py
|
|
30
|
+
tests/test_trade_calendar.py
|
|
31
|
+
tests/test_trading_rules.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
dbl_common
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""dbl_common — 数据 / 回测 / 实盘 三系统公共库(Data Backtest Live Common)
|
|
3
|
+
|
|
4
|
+
命名口径(用户 2026-09-26 指定):
|
|
5
|
+
· 发行名(pip 名)= 数据/回测/实盘三个英文单词 + common → ``data-backtest-live-common``;
|
|
6
|
+
· 导入名 = 三词首字母 + common → ``dbl_common``(对齐 beautifulsoup4 → ``import bs4``
|
|
7
|
+
的短名惯例,避免每次 import 敲 24 个字符)。
|
|
8
|
+
|
|
9
|
+
收录标准(硬规则):**只收「数据、回测、实盘三个系统都会用到」的代码**;
|
|
10
|
+
单系统专属的公共代码放回各系统自己的 common 包(如 quant_data_center 的
|
|
11
|
+
throttle 限频 / pagination 翻页是采集专属,留在那边,不进本库)。
|
|
12
|
+
|
|
13
|
+
模块清单(2026-09-27 起 = 原 market_common 交易规则库整体并入,两库合一):
|
|
14
|
+
- adjust : 本地复权引擎(hfq = raw × adj_factor,锚定上市日,增量追加安全)
|
|
15
|
+
- boards : 证券代码规范化 / 品种识别 / 板块判定(规则库最底层,纯函数零依赖)
|
|
16
|
+
- price_limit : 涨跌停规则全集(主板/科创/创业/北交/ST/ETF/转债/B股/新股首日,含历史制度变更)
|
|
17
|
+
- vec : numpy 向量化涨跌停引擎(limit_prices / flags_from_bars / board_flags / hfq_ret_on)
|
|
18
|
+
- trade_calendar : 交易日历(Tushare cal Parquet 读取;cal_glob 必传,不绑定任何系统路径)
|
|
19
|
+
- trading_calendar : 交易日历注入契约(InjectedCalendar:BaoStock CSV / QDC raw 层 Parquet)
|
|
20
|
+
- trading_hours : 交易时段(集合竞价 / 连续竞价 / 收盘集合竞价)
|
|
21
|
+
- settlement : 交收制度(T+1 / T+0 / T+3)
|
|
22
|
+
- lots / ticks : 申报单位(手数)/ 价位(最小变动价位)
|
|
23
|
+
- fees : 交易费用(印花税 / 过户费时间线;佣金必显式传)
|
|
24
|
+
- circuit_breaker : 2016 熔断制度
|
|
25
|
+
- halts : 盘中临时停牌(新股 / 转债临停)
|
|
26
|
+
- corporate_actions: 除权除息参考价官方公式 + 理论因子跳变 + 数据中心核验入口
|
|
27
|
+
- proc : 子进程无黑窗唯一实现(no_window / no_window_if_detached / pid_alive)
|
|
28
|
+
- io_utils : 原子写文件(atomic_write_text / atomic_write_bytes,tmp+os.replace+重试)
|
|
29
|
+
|
|
30
|
+
历史:
|
|
31
|
+
· 2026-09-26 从 quant_data_center/common 抽出独立成库(adjust/price_limit/
|
|
32
|
+
trade_calendar/proc/io_utils 五模块);
|
|
33
|
+
· 2026-09-27 用户指令「两库如有重复则删除 market」→ 实测仅 price_limit 领域
|
|
34
|
+
同源重复(规则超集 + 引擎),其余 10 个交易规则模块为本库没有的独有内容 →
|
|
35
|
+
**整体并入**(price_limit 取超集版 + round_half_up 浮点修正;引擎统一进
|
|
36
|
+
vec.py;83 项守卫测试随迁为 tests/test_trading_rules.py),market_common
|
|
37
|
+
目录删除。再往前溯源是 global_market_dashboard 的成熟代码「复制适配」。
|
|
38
|
+
"""
|
|
39
|
+
from .boards import Board, BOARD_LABEL, SecurityType, board_of, exchange_of, \
|
|
40
|
+
normalize_code, security_type
|
|
41
|
+
from .price_limit import LimitSpec, limit_spec, round_half_up, \
|
|
42
|
+
limit_up_price, limit_down_price, price_decimals, candidates_of, \
|
|
43
|
+
LIMIT_ERA_START, ST_5PCT_START, GEM_20PCT_START, MAIN_REG_START, \
|
|
44
|
+
MAIN_IPO_4436_START, CB_20PCT_START, CENT_TOL, EPS
|
|
45
|
+
from .trading_hours import Phase, PHASE_LABEL, phase_at, is_auction, \
|
|
46
|
+
is_continuous, can_cancel
|
|
47
|
+
from .settlement import settle_rule, can_sell_today, STOCK_T1_START
|
|
48
|
+
from .lots import lot_rule, validate_qty
|
|
49
|
+
from .ticks import tick_size, snap_to_tick, is_valid_price
|
|
50
|
+
from .fees import FeeResult, calc_fees, stamp_tax, transfer_fee_rate, \
|
|
51
|
+
commission_cap, stamp_tax_timeline
|
|
52
|
+
from .circuit_breaker import is_active as cb_is_active, market_state as cb_state, \
|
|
53
|
+
CB_START, CB_END, LEVEL1, LEVEL2, HISTORICAL_TRIGGERS
|
|
54
|
+
from .halts import HaltRule, intraday_halt_rule, resume_time, halt_price
|
|
55
|
+
from .trading_calendar import InjectedCalendar, from_baostock_csv, \
|
|
56
|
+
from_parquet_dataset, weekend_is_trading_day, weekend_next_trading_day, \
|
|
57
|
+
weekend_prev_trading_day
|
|
58
|
+
from .corporate_actions import CorporateAction, from_per_ten, \
|
|
59
|
+
ex_right_price, factor_jump, validate_against_factor, check_applicable
|
|
60
|
+
|
|
61
|
+
__version__ = "0.2.0"
|
|
62
|
+
|
|
63
|
+
__all__ = [
|
|
64
|
+
# boards
|
|
65
|
+
"Board", "BOARD_LABEL", "SecurityType", "board_of", "exchange_of",
|
|
66
|
+
"normalize_code", "security_type",
|
|
67
|
+
# price_limit
|
|
68
|
+
"LimitSpec", "limit_spec", "round_half_up", "limit_up_price",
|
|
69
|
+
"limit_down_price", "price_decimals", "candidates_of",
|
|
70
|
+
"LIMIT_ERA_START", "ST_5PCT_START", "GEM_20PCT_START", "MAIN_REG_START",
|
|
71
|
+
"MAIN_IPO_4436_START", "CB_20PCT_START", "CENT_TOL", "EPS",
|
|
72
|
+
# trading_hours
|
|
73
|
+
"Phase", "PHASE_LABEL", "phase_at", "is_auction", "is_continuous", "can_cancel",
|
|
74
|
+
# settlement
|
|
75
|
+
"settle_rule", "can_sell_today", "STOCK_T1_START",
|
|
76
|
+
# lots / ticks
|
|
77
|
+
"lot_rule", "validate_qty", "tick_size", "snap_to_tick", "is_valid_price",
|
|
78
|
+
# fees
|
|
79
|
+
"FeeResult", "calc_fees", "stamp_tax", "transfer_fee_rate",
|
|
80
|
+
"commission_cap", "stamp_tax_timeline",
|
|
81
|
+
# circuit breaker
|
|
82
|
+
"cb_is_active", "cb_state", "CB_START", "CB_END", "LEVEL1", "LEVEL2",
|
|
83
|
+
"HISTORICAL_TRIGGERS",
|
|
84
|
+
# halts(盘中临时停牌)
|
|
85
|
+
"HaltRule", "intraday_halt_rule", "resume_time", "halt_price",
|
|
86
|
+
# calendar(注入契约;Tushare cal Parquet 读取见 dbl_common.trade_calendar)
|
|
87
|
+
"InjectedCalendar", "from_baostock_csv", "from_parquet_dataset",
|
|
88
|
+
"weekend_is_trading_day", "weekend_next_trading_day",
|
|
89
|
+
"weekend_prev_trading_day",
|
|
90
|
+
# corporate actions(除权除息参考价)
|
|
91
|
+
"CorporateAction", "from_per_ten", "ex_right_price", "factor_jump",
|
|
92
|
+
"validate_against_factor", "check_applicable",
|
|
93
|
+
]
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""dbl_common.adjust — 本地复权引擎(数据/回测/实盘共用)
|
|
3
|
+
|
|
4
|
+
溯源:global_market_dashboard tushare_fetcher.compute_hfq →
|
|
5
|
+
quant_data_center/common/adjust.py → 2026-09-26 抽入本独立库(内容不变)。
|
|
6
|
+
|
|
7
|
+
核心设计(为什么锚定上市日、而不是「÷ 最新因子」锚定最新):
|
|
8
|
+
adj_factor 的历史值**永不回改**(新分红只抬高未来行的因子),
|
|
9
|
+
所以 hfq 的历史行也永不变 —— 增量追加天然安全。
|
|
10
|
+
若锚定最新,每次分红都会改写全部历史,合并接缝处必出人工断崖。
|
|
11
|
+
|
|
12
|
+
连续性保证:除权日 raw 跳空、因子同幅度反向跳变,乘积天然连续 ——
|
|
13
|
+
这就是 92 只 known-list 断崖(sina/腾讯因子基准漂移)的治本项。
|
|
14
|
+
"""
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import pandas as pd
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def compute_hfq(daily_df: pd.DataFrame, factor_df: pd.DataFrame) -> pd.DataFrame:
|
|
21
|
+
"""本地后复权引擎:**hfq = raw × adj_factor**(锚定上市日)。
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
daily_df: 日线表,需含 date + OHLC 列
|
|
25
|
+
factor_df: 复权因子表,需含 date + adj_factor 列
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
合并后的 DataFrame,OHLC 已乘上 adj_factor(后复权);
|
|
29
|
+
因子缺失/非法(≤0)的行 OHLC 置 NaN 如实缺失(不冒充数据),
|
|
30
|
+
该行仍保留(volume/amount 是真实成交,不因价格缺失而丢)。
|
|
31
|
+
"""
|
|
32
|
+
if daily_df is None or daily_df.empty:
|
|
33
|
+
return daily_df
|
|
34
|
+
m = daily_df.copy()
|
|
35
|
+
if factor_df is None or factor_df.empty:
|
|
36
|
+
for c in ("open", "high", "low", "close"):
|
|
37
|
+
if c in m.columns:
|
|
38
|
+
m[c] = float("nan")
|
|
39
|
+
m["adj_factor"] = float("nan")
|
|
40
|
+
return m
|
|
41
|
+
f = factor_df[["date", "adj_factor"]].copy()
|
|
42
|
+
f["adj_factor"] = pd.to_numeric(f["adj_factor"], errors="coerce")
|
|
43
|
+
m = m.merge(f, on="date", how="left").sort_values(
|
|
44
|
+
"date", kind="stable").reset_index(drop=True)
|
|
45
|
+
# 因子与日线同为逐交易日行,merge 应 1:1;个别日期缺因子时用前一交易日
|
|
46
|
+
# 因子兜底(因子在除权日之间保持不变,ffill 语义正确)。
|
|
47
|
+
m["adj_factor"] = m["adj_factor"].ffill()
|
|
48
|
+
bad = m["adj_factor"].isna() | (m["adj_factor"] <= 0)
|
|
49
|
+
for c in ("open", "high", "low", "close"):
|
|
50
|
+
if c in m.columns:
|
|
51
|
+
v = pd.to_numeric(m[c], errors="coerce") * m["adj_factor"]
|
|
52
|
+
m[c] = v.mask(bad)
|
|
53
|
+
return m
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def compute_qfq(daily_df: pd.DataFrame, factor_df: pd.DataFrame) -> pd.DataFrame:
|
|
57
|
+
"""本地前复权引擎:**qfq = raw × adj_factor ÷ 最新 adj_factor**(锚定最新价)。
|
|
58
|
+
|
|
59
|
+
与 hfq 的区别:锚定最新价,历史行会随新分红而改写。
|
|
60
|
+
适合「按最新价看历史」的展示场景,不适合增量落盘(接缝会断)。
|
|
61
|
+
"""
|
|
62
|
+
m = compute_hfq(daily_df, factor_df)
|
|
63
|
+
if m is None or m.empty or "adj_factor" not in m.columns:
|
|
64
|
+
return m
|
|
65
|
+
valid = m["adj_factor"].dropna()
|
|
66
|
+
if valid.empty:
|
|
67
|
+
return m
|
|
68
|
+
latest = valid.iloc[-1]
|
|
69
|
+
if latest <= 0:
|
|
70
|
+
return m
|
|
71
|
+
for c in ("open", "high", "low", "close"):
|
|
72
|
+
if c in m.columns:
|
|
73
|
+
m[c] = pd.to_numeric(m[c], errors="coerce") / latest
|
|
74
|
+
return m
|