xtquant-duck 0.1.20260702.2__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.
- xtquant_duck-0.1.20260702.2/.gitignore +25 -0
- xtquant_duck-0.1.20260702.2/LICENSE +21 -0
- xtquant_duck-0.1.20260702.2/PKG-INFO +93 -0
- xtquant_duck-0.1.20260702.2/README.md +68 -0
- xtquant_duck-0.1.20260702.2/docs/MOCK_XTQUANT_API.md +310 -0
- xtquant_duck-0.1.20260702.2/pyproject.toml +55 -0
- xtquant_duck-0.1.20260702.2/qmt_data_layer/__init__.py +5 -0
- xtquant_duck-0.1.20260702.2/qmt_data_layer/duckdb_data.py +608 -0
- xtquant_duck-0.1.20260702.2/scripts/build_duckdb.py +575 -0
- xtquant_duck-0.1.20260702.2/scripts/compare_recent_tick_qmt.py +358 -0
- xtquant_duck-0.1.20260702.2/scripts/import_a50_2026.py +471 -0
- xtquant_duck-0.1.20260702.2/scripts/import_qmt_index_daily.py +146 -0
- xtquant_duck-0.1.20260702.2/scripts/validate_duckdb.py +347 -0
- xtquant_duck-0.1.20260702.2/scripts/validate_qmt_daily_alignment.py +136 -0
- xtquant_duck-0.1.20260702.2/test/README.md +9 -0
- xtquant_duck-0.1.20260702.2/test/test_duckdb_data.py +229 -0
- xtquant_duck-0.1.20260702.2/test/test_mock_xtquant_api.py +124 -0
- xtquant_duck-0.1.20260702.2/xtquant/__init__.py +3 -0
- xtquant_duck-0.1.20260702.2/xtquant/xtconstant.py +4 -0
- xtquant_duck-0.1.20260702.2/xtquant/xtdata.py +131 -0
- xtquant_duck-0.1.20260702.2/xtquant/xttrader.py +38 -0
- xtquant_duck-0.1.20260702.2/xtquant/xttype.py +4 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
.venv/
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.pyo
|
|
5
|
+
*.pyd
|
|
6
|
+
*.egg-info/
|
|
7
|
+
dist/
|
|
8
|
+
build/
|
|
9
|
+
.pytest_cache/
|
|
10
|
+
.mypy_cache/
|
|
11
|
+
.ruff_cache/
|
|
12
|
+
.coverage
|
|
13
|
+
htmlcov/
|
|
14
|
+
|
|
15
|
+
reports/
|
|
16
|
+
*.duckdb
|
|
17
|
+
*.duckdb.wal
|
|
18
|
+
*.parquet
|
|
19
|
+
*.csv
|
|
20
|
+
*.log
|
|
21
|
+
*.tmp
|
|
22
|
+
|
|
23
|
+
.env
|
|
24
|
+
.env.*
|
|
25
|
+
!.env.example
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 drunkpig
|
|
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,93 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: xtquant-duck
|
|
3
|
+
Version: 0.1.20260702.2
|
|
4
|
+
Summary: DuckDB-backed local mock implementation of selected xtquant APIs.
|
|
5
|
+
Project-URL: Homepage, https://github.com/drunkpig/xtquant-duck
|
|
6
|
+
Project-URL: Repository, https://github.com/drunkpig/xtquant-duck
|
|
7
|
+
Project-URL: Issues, https://github.com/drunkpig/xtquant-duck/issues
|
|
8
|
+
Author: drunkpig
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: duckdb,mock,qmt,quant,xtquant
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Requires-Dist: duckdb>=1.0
|
|
21
|
+
Requires-Dist: numpy>=1.24
|
|
22
|
+
Requires-Dist: pandas>=2.0
|
|
23
|
+
Requires-Dist: pyarrow>=14.0
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# xtquant-duck
|
|
27
|
+
|
|
28
|
+
DuckDB-backed local mock implementation of selected `xtquant` APIs.
|
|
29
|
+
|
|
30
|
+
The goal is to let research code switch between real QMT `xtquant.xtdata` and a
|
|
31
|
+
local DuckDB-backed mock without changing strategy logic. QMT semantics are the
|
|
32
|
+
canonical reference; unsupported mock behavior raises `NotImplementedError`
|
|
33
|
+
instead of silently returning placeholder data.
|
|
34
|
+
|
|
35
|
+
## Install
|
|
36
|
+
|
|
37
|
+
```powershell
|
|
38
|
+
uv pip install xtquant-duck
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
For local development:
|
|
42
|
+
|
|
43
|
+
```powershell
|
|
44
|
+
git clone git@github.com:drunkpig/xtquant-duck.git
|
|
45
|
+
cd xtquant-duck
|
|
46
|
+
uv sync --all-extras --dev
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Basic Usage
|
|
50
|
+
|
|
51
|
+
Set the DuckDB database path:
|
|
52
|
+
|
|
53
|
+
```powershell
|
|
54
|
+
$env:QMT_MOCK_DUCKDB = "C:\data-tick\duckdb\qmt_mock.duckdb"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Use the mock `xtquant` package directly:
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from xtquant import xtdata
|
|
61
|
+
|
|
62
|
+
data = xtdata.get_market_data_ex(
|
|
63
|
+
field_list=["time", "open", "high", "low", "close", "volume"],
|
|
64
|
+
stock_list=["600036.SH"],
|
|
65
|
+
period="1d",
|
|
66
|
+
start_time="20220101",
|
|
67
|
+
end_time="20251231",
|
|
68
|
+
dividend_type="back_ratio",
|
|
69
|
+
)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Lower-level DuckDB access is available through:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from qmt_data_layer import DuckDbMarketData
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Default database path is `C:\data-tick\duckdb\qmt_mock.duckdb`; override it with
|
|
79
|
+
`QMT_MOCK_DUCKDB`.
|
|
80
|
+
|
|
81
|
+
## Documentation
|
|
82
|
+
|
|
83
|
+
See [docs/MOCK_XTQUANT_API.md](docs/MOCK_XTQUANT_API.md) for supported APIs,
|
|
84
|
+
parameters, return shapes, and strict unsupported behavior.
|
|
85
|
+
|
|
86
|
+
## Tests
|
|
87
|
+
|
|
88
|
+
```powershell
|
|
89
|
+
uv run python -m unittest discover -s test -v
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The unit tests build a temporary DuckDB database and do not read or write the
|
|
93
|
+
default production database.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# xtquant-duck
|
|
2
|
+
|
|
3
|
+
DuckDB-backed local mock implementation of selected `xtquant` APIs.
|
|
4
|
+
|
|
5
|
+
The goal is to let research code switch between real QMT `xtquant.xtdata` and a
|
|
6
|
+
local DuckDB-backed mock without changing strategy logic. QMT semantics are the
|
|
7
|
+
canonical reference; unsupported mock behavior raises `NotImplementedError`
|
|
8
|
+
instead of silently returning placeholder data.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```powershell
|
|
13
|
+
uv pip install xtquant-duck
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
For local development:
|
|
17
|
+
|
|
18
|
+
```powershell
|
|
19
|
+
git clone git@github.com:drunkpig/xtquant-duck.git
|
|
20
|
+
cd xtquant-duck
|
|
21
|
+
uv sync --all-extras --dev
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Basic Usage
|
|
25
|
+
|
|
26
|
+
Set the DuckDB database path:
|
|
27
|
+
|
|
28
|
+
```powershell
|
|
29
|
+
$env:QMT_MOCK_DUCKDB = "C:\data-tick\duckdb\qmt_mock.duckdb"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Use the mock `xtquant` package directly:
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from xtquant import xtdata
|
|
36
|
+
|
|
37
|
+
data = xtdata.get_market_data_ex(
|
|
38
|
+
field_list=["time", "open", "high", "low", "close", "volume"],
|
|
39
|
+
stock_list=["600036.SH"],
|
|
40
|
+
period="1d",
|
|
41
|
+
start_time="20220101",
|
|
42
|
+
end_time="20251231",
|
|
43
|
+
dividend_type="back_ratio",
|
|
44
|
+
)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Lower-level DuckDB access is available through:
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from qmt_data_layer import DuckDbMarketData
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Default database path is `C:\data-tick\duckdb\qmt_mock.duckdb`; override it with
|
|
54
|
+
`QMT_MOCK_DUCKDB`.
|
|
55
|
+
|
|
56
|
+
## Documentation
|
|
57
|
+
|
|
58
|
+
See [docs/MOCK_XTQUANT_API.md](docs/MOCK_XTQUANT_API.md) for supported APIs,
|
|
59
|
+
parameters, return shapes, and strict unsupported behavior.
|
|
60
|
+
|
|
61
|
+
## Tests
|
|
62
|
+
|
|
63
|
+
```powershell
|
|
64
|
+
uv run python -m unittest discover -s test -v
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The unit tests build a temporary DuckDB database and do not read or write the
|
|
68
|
+
default production database.
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
# Mock xtquant API
|
|
2
|
+
|
|
3
|
+
This document describes the DuckDB-backed mock package installed as:
|
|
4
|
+
|
|
5
|
+
`xtquant`
|
|
6
|
+
|
|
7
|
+
Install `xtquant-duck` or place `C:\workspace\xtquant-duck` before the real QMT package on `PYTHONPATH`.
|
|
8
|
+
|
|
9
|
+
The mock is intentionally strict. Unsupported semantics raise `NotImplementedError`; missing local data raises `FileNotFoundError`. It must not silently return placeholder market data.
|
|
10
|
+
|
|
11
|
+
## Environment
|
|
12
|
+
|
|
13
|
+
| variable | default | meaning |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| `QMT_MOCK_DUCKDB` | `C:\data-tick\duckdb\qmt_mock.duckdb` | DuckDB database path |
|
|
16
|
+
| `QMT_MOCK_NOW` | current local time | default clock for `get_full_tick` if `set_mock_now()` is not used |
|
|
17
|
+
|
|
18
|
+
## Time And Code Rules
|
|
19
|
+
|
|
20
|
+
Stock codes are normalized to QMT format, for example:
|
|
21
|
+
|
|
22
|
+
- `sh600000` -> `600000.SH`
|
|
23
|
+
- `600000.SH` -> `600000.SH`
|
|
24
|
+
- `000001` -> `000001.SZ`
|
|
25
|
+
|
|
26
|
+
Time parameters accept the formats handled by `parse_qmt_time()`:
|
|
27
|
+
|
|
28
|
+
- `YYYYMMDD`
|
|
29
|
+
- `YYYYMMDDHHMMSS`
|
|
30
|
+
- pandas-compatible datetime strings
|
|
31
|
+
- Unix seconds or milliseconds as integers
|
|
32
|
+
|
|
33
|
+
Returned `time` values use QMT-style local-time milliseconds since Unix epoch.
|
|
34
|
+
|
|
35
|
+
## `xtquant.xtdata`
|
|
36
|
+
|
|
37
|
+
### `download_history_data(stock_code, period, start_time="", end_time="", incrementally=False, **kwargs) -> bool`
|
|
38
|
+
|
|
39
|
+
Validates that local DuckDB already has data for the requested code, period, and time range.
|
|
40
|
+
|
|
41
|
+
Supported parameters:
|
|
42
|
+
|
|
43
|
+
| parameter | supported value |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| `stock_code` | QMT-style or normalizable stock code |
|
|
46
|
+
| `period` | `tick`, `1m`, `1min`, `60m`, `60min`, `1h`, `1d`, `day`, `d` |
|
|
47
|
+
| `start_time`, `end_time` | optional QMT-style time strings |
|
|
48
|
+
| `incrementally` | only `False` |
|
|
49
|
+
|
|
50
|
+
Returns `True` when local data exists.
|
|
51
|
+
|
|
52
|
+
Raises:
|
|
53
|
+
|
|
54
|
+
- `FileNotFoundError` if DuckDB has no matching local data.
|
|
55
|
+
- `NotImplementedError` for unsupported period, `incrementally=True`, or extra keyword arguments.
|
|
56
|
+
|
|
57
|
+
### `download_history_data2(stock_list, period, start_time="", end_time="", incrementally=False, **kwargs) -> bool`
|
|
58
|
+
|
|
59
|
+
Calls `download_history_data()` for every stock in `stock_list`.
|
|
60
|
+
|
|
61
|
+
Returns `True` only when every stock has matching local data.
|
|
62
|
+
|
|
63
|
+
Raises the same exceptions as `download_history_data()`.
|
|
64
|
+
|
|
65
|
+
### `get_market_data_ex(field_list=None, stock_list=None, period="1d", start_time="", end_time="", count=-1, fill_data=False, dividend_type=None, **kwargs) -> dict[str, pandas.DataFrame]`
|
|
66
|
+
|
|
67
|
+
Main historical market-data API.
|
|
68
|
+
|
|
69
|
+
Supported parameters:
|
|
70
|
+
|
|
71
|
+
| parameter | supported value |
|
|
72
|
+
| --- | --- |
|
|
73
|
+
| `field_list` | `None`, empty list, or implemented field names for the requested period |
|
|
74
|
+
| `stock_list` | list of QMT-style or normalizable stock codes |
|
|
75
|
+
| `period` | `tick`, `1m`, `1min`, `60m`, `60min`, `1h`, `1d`, `day`, `d` |
|
|
76
|
+
| `start_time`, `end_time` | optional QMT-style time strings |
|
|
77
|
+
| `count` | `-1`/`0` for all rows, positive integer for tail rows |
|
|
78
|
+
| `fill_data` | only `False` |
|
|
79
|
+
| `dividend_type` | see period-specific rules below |
|
|
80
|
+
|
|
81
|
+
Return value is a dict keyed by normalized QMT code. Each value is a pandas DataFrame sorted by time.
|
|
82
|
+
|
|
83
|
+
When `field_list` is provided, only those fields are returned. If the DataFrame has a `time` column and `time` was not requested, `time` is still prepended to match strategy expectations. Requesting an unimplemented field raises `NotImplementedError`.
|
|
84
|
+
|
|
85
|
+
#### Period `tick`
|
|
86
|
+
|
|
87
|
+
Source: `raw_tick_v3`.
|
|
88
|
+
|
|
89
|
+
Price domain: raw, never adjusted.
|
|
90
|
+
|
|
91
|
+
Supported `dividend_type`: `None`, `""`, `none`.
|
|
92
|
+
|
|
93
|
+
Fields:
|
|
94
|
+
|
|
95
|
+
| field | meaning |
|
|
96
|
+
| --- | --- |
|
|
97
|
+
| `time` | QMT-style millisecond timestamp |
|
|
98
|
+
| `ts` | pandas timestamp |
|
|
99
|
+
| `lastPrice` | latest raw tick price |
|
|
100
|
+
| `volume` | cumulative trading-day volume in lots up to this tick |
|
|
101
|
+
| `amount` | cumulative trading-day amount up to this tick |
|
|
102
|
+
| `open` | first valid tick price of the trading day up to this tick |
|
|
103
|
+
| `askPrice`, `bidPrice` | 5-level price lists |
|
|
104
|
+
| `askVol`, `bidVol` | 5-level volume lists |
|
|
105
|
+
|
|
106
|
+
`dividend_type` other than empty/`none` raises `NotImplementedError`.
|
|
107
|
+
|
|
108
|
+
#### Period `1m` / `1min`
|
|
109
|
+
|
|
110
|
+
Source: dynamic aggregation from `raw_tick_v3`.
|
|
111
|
+
|
|
112
|
+
Raw bar rules:
|
|
113
|
+
|
|
114
|
+
- `09:30` bar is the opening auction bar from `09:25` ticks.
|
|
115
|
+
- Continuous auction bars are right-labeled.
|
|
116
|
+
- `15:00` closing auction tick is labeled `15:00`.
|
|
117
|
+
- `volume` is per-bar volume in lots.
|
|
118
|
+
- `amount` is per-bar traded amount.
|
|
119
|
+
|
|
120
|
+
Supported `dividend_type`:
|
|
121
|
+
|
|
122
|
+
| value | behavior |
|
|
123
|
+
| --- | --- |
|
|
124
|
+
| `None`, `""`, `none` | raw 1m bars |
|
|
125
|
+
| `front_ratio`, `front` | dynamic front-adjusted 1m bars |
|
|
126
|
+
|
|
127
|
+
Base fields:
|
|
128
|
+
|
|
129
|
+
| field | meaning |
|
|
130
|
+
| --- | --- |
|
|
131
|
+
| `time`, `ts` | bar label time |
|
|
132
|
+
| `open`, `high`, `low`, `close` | raw or front-adjusted price depending on `dividend_type` |
|
|
133
|
+
| `volume`, `amount` | raw per-bar volume/amount, not adjusted |
|
|
134
|
+
| `preClose` | currently `NaN` for raw intraday bars |
|
|
135
|
+
|
|
136
|
+
Additional fields for `front_ratio`/`front`:
|
|
137
|
+
|
|
138
|
+
| field | meaning |
|
|
139
|
+
| --- | --- |
|
|
140
|
+
| `raw_open`, `raw_high`, `raw_low`, `raw_close`, `raw_preClose` | raw price fields before adjustment |
|
|
141
|
+
| `foreAdjustFactor` | BaoStock factor as of the bar date |
|
|
142
|
+
| `anchor_factor` | BaoStock factor as of the latest bar date in the requested result set |
|
|
143
|
+
|
|
144
|
+
Formula:
|
|
145
|
+
|
|
146
|
+
`adjusted_price = raw_price * foreAdjustFactor(bar_date) / foreAdjustFactor(anchor_date)`
|
|
147
|
+
|
|
148
|
+
`back_ratio`/`back` raises `NotImplementedError`.
|
|
149
|
+
|
|
150
|
+
#### Period `60m` / `60min` / `1h`
|
|
151
|
+
|
|
152
|
+
Source: dynamic aggregation from `raw_tick_v3`, not from 1m bars.
|
|
153
|
+
|
|
154
|
+
Raw bar boundaries:
|
|
155
|
+
|
|
156
|
+
- `10:30`: `[09:30, 10:30)`
|
|
157
|
+
- `11:30`: `[10:30, 11:30)`
|
|
158
|
+
- `14:00`: `[13:00, 14:00)`
|
|
159
|
+
- `15:00`: `[14:00, 15:00:59]`
|
|
160
|
+
|
|
161
|
+
Fields and `dividend_type` behavior are the same as `1m`.
|
|
162
|
+
|
|
163
|
+
The current strategy requests raw 60m bars.
|
|
164
|
+
|
|
165
|
+
#### Period `1d` / `day` / `d`
|
|
166
|
+
|
|
167
|
+
Source: `raw_daily_v1`.
|
|
168
|
+
|
|
169
|
+
Supported `dividend_type`:
|
|
170
|
+
|
|
171
|
+
| value | behavior |
|
|
172
|
+
| --- | --- |
|
|
173
|
+
| `None`, `""`, `none` | raw daily bars |
|
|
174
|
+
| `front_ratio`, `front` | dynamic front-adjusted daily bars |
|
|
175
|
+
| `back_ratio`, `back` | BaoStock back-adjusted daily bars |
|
|
176
|
+
|
|
177
|
+
Raw fields:
|
|
178
|
+
|
|
179
|
+
| field | meaning |
|
|
180
|
+
| --- | --- |
|
|
181
|
+
| `time`, `ts` | trading date |
|
|
182
|
+
| `open`, `high`, `low`, `close` | raw OHLC |
|
|
183
|
+
| `volume` | daily volume in lots |
|
|
184
|
+
| `amount` | daily traded amount |
|
|
185
|
+
| `preClose` | previous raw close within the returned source sequence |
|
|
186
|
+
|
|
187
|
+
Additional fields for `front_ratio`/`front`:
|
|
188
|
+
|
|
189
|
+
| field | meaning |
|
|
190
|
+
| --- | --- |
|
|
191
|
+
| `raw_open`, `raw_high`, `raw_low`, `raw_close`, `raw_preClose` | raw daily fields before adjustment |
|
|
192
|
+
| `foreAdjustFactor` | BaoStock factor as of the trading date |
|
|
193
|
+
| `anchor_factor` | BaoStock factor as of the latest trading date in the requested result set |
|
|
194
|
+
|
|
195
|
+
Formula:
|
|
196
|
+
|
|
197
|
+
`adjusted_price = raw_price * foreAdjustFactor(date) / foreAdjustFactor(anchor_date)`
|
|
198
|
+
|
|
199
|
+
Additional fields for `back_ratio`/`back`:
|
|
200
|
+
|
|
201
|
+
| field | meaning |
|
|
202
|
+
| --- | --- |
|
|
203
|
+
| `raw_open`, `raw_high`, `raw_low`, `raw_close`, `raw_preClose` | raw daily fields before adjustment |
|
|
204
|
+
| `backAdjustFactor` | BaoStock back-adjust factor as of the trading date |
|
|
205
|
+
|
|
206
|
+
Formula:
|
|
207
|
+
|
|
208
|
+
`adjusted_price = raw_price * backAdjustFactor(date)`
|
|
209
|
+
|
|
210
|
+
### `get_full_tick(stock_list) -> dict[str, dict]`
|
|
211
|
+
|
|
212
|
+
Returns the latest raw tick for each stock at the mock clock.
|
|
213
|
+
|
|
214
|
+
Clock source:
|
|
215
|
+
|
|
216
|
+
1. `set_mock_now(value)` if called.
|
|
217
|
+
2. `QMT_MOCK_NOW` environment variable.
|
|
218
|
+
3. current local time.
|
|
219
|
+
|
|
220
|
+
Returned dict fields match the tick fields used by the strategy:
|
|
221
|
+
|
|
222
|
+
| field | meaning |
|
|
223
|
+
| --- | --- |
|
|
224
|
+
| `time`, `ts` | tick time |
|
|
225
|
+
| `lastPrice` | latest raw tick price |
|
|
226
|
+
| `volume` | cumulative trading-day volume in lots up to the tick |
|
|
227
|
+
| `amount` | cumulative trading-day amount up to the tick |
|
|
228
|
+
| `open` | first valid tick price of the trading day up to the tick |
|
|
229
|
+
| `askPrice`, `bidPrice`, `askVol`, `bidVol` | 5-level lists |
|
|
230
|
+
|
|
231
|
+
Stocks with no tick at or before the mock clock for that day are omitted from the returned dict.
|
|
232
|
+
|
|
233
|
+
### `set_mock_now(value) -> None`
|
|
234
|
+
|
|
235
|
+
Sets the process-local mock clock used by `get_full_tick()`.
|
|
236
|
+
|
|
237
|
+
### `get_mock_now() -> pandas.Timestamp | None`
|
|
238
|
+
|
|
239
|
+
Returns the process-local mock clock, or `None` if unset.
|
|
240
|
+
|
|
241
|
+
### `close() -> None`
|
|
242
|
+
|
|
243
|
+
Closes the cached DuckDB connection used by the mock module.
|
|
244
|
+
|
|
245
|
+
### Unsupported push APIs
|
|
246
|
+
|
|
247
|
+
These APIs are declared only so imports resolve, but push subscriptions are not implemented:
|
|
248
|
+
|
|
249
|
+
- `subscribe_quote(...)`
|
|
250
|
+
- `subscribe_whole_quote(...)`
|
|
251
|
+
- `unsubscribe_quote(...)`
|
|
252
|
+
- `run()`
|
|
253
|
+
|
|
254
|
+
All raise `NotImplementedError`.
|
|
255
|
+
|
|
256
|
+
## `xtquant.xttrader`
|
|
257
|
+
|
|
258
|
+
The mock package provides import-compatible stubs:
|
|
259
|
+
|
|
260
|
+
- `XtQuantTraderCallback`
|
|
261
|
+
- `XtQuantTrader`
|
|
262
|
+
|
|
263
|
+
`XtQuantTrader.register_callback(callback)` stores the callback object only.
|
|
264
|
+
|
|
265
|
+
The following trading/account methods are not implemented and raise `NotImplementedError`:
|
|
266
|
+
|
|
267
|
+
- `start()`
|
|
268
|
+
- `connect()`
|
|
269
|
+
- `subscribe(account)`
|
|
270
|
+
- `query_stock_asset(account)`
|
|
271
|
+
- `query_stock_positions(account)`
|
|
272
|
+
- `query_stock_orders(account, cancelable_only=False)`
|
|
273
|
+
- `query_stock_trades(account)`
|
|
274
|
+
|
|
275
|
+
This prevents mock backtests from accidentally treating placeholder account data as real trading state.
|
|
276
|
+
|
|
277
|
+
## `xtquant.xttype`
|
|
278
|
+
|
|
279
|
+
### `StockAccount(account_id: str, account_type: str = "STOCK")`
|
|
280
|
+
|
|
281
|
+
Simple data holder with attributes:
|
|
282
|
+
|
|
283
|
+
- `account_id`
|
|
284
|
+
- `account_type`
|
|
285
|
+
|
|
286
|
+
## `xtquant.xtconstant`
|
|
287
|
+
|
|
288
|
+
Defined constants:
|
|
289
|
+
|
|
290
|
+
| name | value |
|
|
291
|
+
| --- | --- |
|
|
292
|
+
| `STOCK_BUY` | `23` |
|
|
293
|
+
| `STOCK_SELL` | `24` |
|
|
294
|
+
| `FIX_PRICE` | `11` |
|
|
295
|
+
| `LATEST_PRICE` | `5` |
|
|
296
|
+
|
|
297
|
+
## Tests
|
|
298
|
+
|
|
299
|
+
Run:
|
|
300
|
+
|
|
301
|
+
```powershell
|
|
302
|
+
uv run python -m unittest discover -s test -v
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
The tests build a temporary DuckDB database and verify:
|
|
306
|
+
|
|
307
|
+
- raw tick cumulative fields.
|
|
308
|
+
- dynamic front-adjusted 1m and daily data.
|
|
309
|
+
- strict `NotImplementedError` behavior.
|
|
310
|
+
- mock `download_history_data`, `get_market_data_ex`, `get_full_tick`, and trader stubs.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "xtquant-duck"
|
|
3
|
+
version = "0.1.20260702.2"
|
|
4
|
+
description = "DuckDB-backed local mock implementation of selected xtquant APIs."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
license = { text = "MIT" }
|
|
8
|
+
authors = [
|
|
9
|
+
{ name = "drunkpig" }
|
|
10
|
+
]
|
|
11
|
+
keywords = ["xtquant", "qmt", "duckdb", "quant", "mock"]
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Development Status :: 3 - Alpha",
|
|
14
|
+
"Intended Audience :: Developers",
|
|
15
|
+
"License :: OSI Approved :: MIT License",
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Programming Language :: Python :: 3.10",
|
|
18
|
+
"Programming Language :: Python :: 3.11",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"duckdb>=1.0",
|
|
23
|
+
"numpy>=1.24",
|
|
24
|
+
"pandas>=2.0",
|
|
25
|
+
"pyarrow>=14.0",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://github.com/drunkpig/xtquant-duck"
|
|
30
|
+
Repository = "https://github.com/drunkpig/xtquant-duck"
|
|
31
|
+
Issues = "https://github.com/drunkpig/xtquant-duck/issues"
|
|
32
|
+
|
|
33
|
+
[dependency-groups]
|
|
34
|
+
dev = [
|
|
35
|
+
"build>=1.2",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[build-system]
|
|
39
|
+
requires = ["hatchling>=1.25"]
|
|
40
|
+
build-backend = "hatchling.build"
|
|
41
|
+
|
|
42
|
+
[tool.hatch.build.targets.wheel]
|
|
43
|
+
packages = ["qmt_data_layer", "xtquant"]
|
|
44
|
+
|
|
45
|
+
[tool.hatch.build.targets.sdist]
|
|
46
|
+
include = [
|
|
47
|
+
"qmt_data_layer",
|
|
48
|
+
"xtquant",
|
|
49
|
+
"scripts",
|
|
50
|
+
"docs",
|
|
51
|
+
"test",
|
|
52
|
+
"README.md",
|
|
53
|
+
"LICENSE",
|
|
54
|
+
"pyproject.toml",
|
|
55
|
+
]
|