dragon-quant 0.1.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.
- dragon_quant-0.1.0/LICENSE +21 -0
- dragon_quant-0.1.0/PKG-INFO +520 -0
- dragon_quant-0.1.0/README.md +502 -0
- dragon_quant-0.1.0/dragon_quant/__init__.py +17 -0
- dragon_quant-0.1.0/dragon_quant/__main__.py +5 -0
- dragon_quant-0.1.0/dragon_quant/analyze.py +113 -0
- dragon_quant-0.1.0/dragon_quant/cache/__init__.py +0 -0
- dragon_quant-0.1.0/dragon_quant/cache/data_cache.py +171 -0
- dragon_quant-0.1.0/dragon_quant/cli.py +301 -0
- dragon_quant-0.1.0/dragon_quant/data.py +222 -0
- dragon_quant-0.1.0/dragon_quant/logging/__init__.py +2 -0
- dragon_quant-0.1.0/dragon_quant/logging/logger.py +189 -0
- dragon_quant-0.1.0/dragon_quant/logging/query.py +236 -0
- dragon_quant-0.1.0/dragon_quant/logging/reporter.py +331 -0
- dragon_quant-0.1.0/dragon_quant/models/__init__.py +0 -0
- dragon_quant-0.1.0/dragon_quant/models/types.py +88 -0
- dragon_quant-0.1.0/dragon_quant/orchestrator.py +476 -0
- dragon_quant-0.1.0/dragon_quant/providers/__init__.py +23 -0
- dragon_quant-0.1.0/dragon_quant/providers/base.py +62 -0
- dragon_quant-0.1.0/dragon_quant/providers/cookie.py +92 -0
- dragon_quant-0.1.0/dragon_quant/providers/eastmoney.py +283 -0
- dragon_quant-0.1.0/dragon_quant/providers/tencent.py +201 -0
- dragon_quant-0.1.0/dragon_quant/providers/xueqiu.py +179 -0
- dragon_quant-0.1.0/dragon_quant/rate_limit.py +103 -0
- dragon_quant-0.1.0/dragon_quant/scorers/__init__.py +11 -0
- dragon_quant-0.1.0/dragon_quant/scorers/absorption.py +297 -0
- dragon_quant-0.1.0/dragon_quant/scorers/anti_drop.py +206 -0
- dragon_quant-0.1.0/dragon_quant/scorers/drive.py +406 -0
- dragon_quant-0.1.0/dragon_quant/scorers/leadership.py +225 -0
- dragon_quant-0.1.0/dragon_quant/storage/__init__.py +0 -0
- dragon_quant-0.1.0/dragon_quant/storage/manager.py +109 -0
- dragon_quant-0.1.0/dragon_quant/storage/paths.py +43 -0
- dragon_quant-0.1.0/dragon_quant/utils/__init__.py +0 -0
- dragon_quant-0.1.0/dragon_quant.egg-info/PKG-INFO +520 -0
- dragon_quant-0.1.0/dragon_quant.egg-info/SOURCES.txt +38 -0
- dragon_quant-0.1.0/dragon_quant.egg-info/dependency_links.txt +1 -0
- dragon_quant-0.1.0/dragon_quant.egg-info/entry_points.txt +2 -0
- dragon_quant-0.1.0/dragon_quant.egg-info/top_level.txt +1 -0
- dragon_quant-0.1.0/pyproject.toml +31 -0
- dragon_quant-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 gitBingxu
|
|
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,520 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dragon-quant
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: 龙头战法四维量化筛选系统 — A股涨停板龙头识别工具
|
|
5
|
+
Author: gitBingxu
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: repository, https://github.com/gitBingxu/dragon-quant
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
14
|
+
Requires-Python: >=3.8
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
19
|
+
# dragon-quant 🐉
|
|
20
|
+
|
|
21
|
+
**龙头战法四维量化筛选系统** — A 股涨停板龙头识别工具
|
|
22
|
+
|
|
23
|
+
基于东方财富、雪球、腾讯三大公开数据源,对涨停候选股进行四维量化评分,自动识别市场龙头。
|
|
24
|
+
|
|
25
|
+
## 安装
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip install dragon-quant
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
或从源码安装:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
git clone https://github.com/gitBingxu/dragon-quant.git
|
|
35
|
+
cd dragon-quant
|
|
36
|
+
pip install -e .
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 快速开始
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# 扫榜 — 找 top5 龙头
|
|
43
|
+
dragon-quant scan --top 5
|
|
44
|
+
|
|
45
|
+
# 完整扫榜
|
|
46
|
+
dragon-quant scan --top 25 --candidates 5 --workers 2
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## CLI 命令大全
|
|
50
|
+
|
|
51
|
+
### `scan` — 扫榜
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
dragon-quant scan [--top 25] [--candidates 5] [--workers 2]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
| 参数 | 默认 | 说明 |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| `--top` | 25 | 最终输出的候选股数量 |
|
|
60
|
+
| `--candidates` | 5 | 每个板块取前 N 只 |
|
|
61
|
+
| `--workers` | 2 | 并发线程数 |
|
|
62
|
+
|
|
63
|
+
输出包含:板块排行、候选股列表、四维评分表格、自然语言详细报告,同时自动持久化日志和结果到 `~/Library/Application Support/dragon-quant/`。
|
|
64
|
+
|
|
65
|
+
### `logs` — 日志查询
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# 查看最近 20 条日志
|
|
69
|
+
dragon-quant logs tail [-n 20]
|
|
70
|
+
|
|
71
|
+
# 按条件查询
|
|
72
|
+
dragon-quant logs query [--date 20260513] [--category scorer:drive] [--level error] [--code 600172]
|
|
73
|
+
|
|
74
|
+
# 查看最新扫描摘要(API 统计、错误数等)
|
|
75
|
+
dragon-quant logs summary
|
|
76
|
+
|
|
77
|
+
# 列出所有日志文件
|
|
78
|
+
dragon-quant logs list
|
|
79
|
+
|
|
80
|
+
# 清除 7 天前的日志
|
|
81
|
+
dragon-quant logs clear --days 7
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### `data` — 原子数据查询
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# 板块排行榜
|
|
88
|
+
dragon-quant data sector # 涨幅榜
|
|
89
|
+
dragon-quant data sector --asc # 跌幅榜
|
|
90
|
+
|
|
91
|
+
# 板块成分股
|
|
92
|
+
dragon-quant data components --sector BK0487
|
|
93
|
+
|
|
94
|
+
# 个股日 K 线
|
|
95
|
+
dragon-quant data kline --code 600172 [--source xueqiu] [--days 20]
|
|
96
|
+
|
|
97
|
+
# 个股 1 分钟 K 线(分时)
|
|
98
|
+
dragon-quant data minute --code 600172
|
|
99
|
+
|
|
100
|
+
# 实时行情
|
|
101
|
+
dragon-quant data quote --code 600172
|
|
102
|
+
dragon-quant data batch-quote --codes 600172,000001,002409
|
|
103
|
+
|
|
104
|
+
# Cookie 管理
|
|
105
|
+
dragon-quant data cookie-status # 查看 Cookie 状态
|
|
106
|
+
dragon-quant data cookie-fetch # 刷新全部 Cookie
|
|
107
|
+
dragon-quant data cookie-fetch --source xueqiu # 只刷新雪球
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### `storage` — 数据管理
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
dragon-quant storage status # 查看存储状态
|
|
114
|
+
dragon-quant storage size # 磁盘占用
|
|
115
|
+
dragon-quant storage clear --all # 清理全部数据
|
|
116
|
+
dragon-quant storage clear --logs --days 3 # 清理 3 天前的日志
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Programmtic API
|
|
120
|
+
|
|
121
|
+
### 编排器 — 完整扫描
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
import dragon_quant
|
|
125
|
+
|
|
126
|
+
result = dragon_quant.scan(top_n=5, candidates_n=5, workers=2)
|
|
127
|
+
# 返回 dict:
|
|
128
|
+
# {
|
|
129
|
+
# "timestamp": "20260513_160000",
|
|
130
|
+
# "elapsed_s": 38.2,
|
|
131
|
+
# "sectors": {"up": [...], "down": [...]},
|
|
132
|
+
# "ranking": [
|
|
133
|
+
# {
|
|
134
|
+
# "code": "600172", "name": "黄河旋风",
|
|
135
|
+
# "concepts": ["培育钻石"], "board_count": 3,
|
|
136
|
+
# "composite_score": 71.8,
|
|
137
|
+
# "dimensions": {
|
|
138
|
+
# "drive": {"score": 99.0, "weight": 0.35, "details": {...}},
|
|
139
|
+
# "anti_drop": {"score": 61.0, "weight": 0.15, "details": {...}},
|
|
140
|
+
# "leadership": {"score": 50.0, "weight": 0.25, "details": {...}},
|
|
141
|
+
# "absorption": {"score": 62.0, "weight": 0.25, "details": {...}},
|
|
142
|
+
# }
|
|
143
|
+
# },
|
|
144
|
+
# ...
|
|
145
|
+
# ],
|
|
146
|
+
# "api_stats": {...},
|
|
147
|
+
# "report_text": "黄河旋风(600172)——培育钻石——3连板-71.8分-强票\n..."
|
|
148
|
+
# }
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### 原子数据查询
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
from dragon_quant.data import (
|
|
155
|
+
get_sector_ranking, get_sector_components, get_sector_5min_kline,
|
|
156
|
+
get_kline, get_minute_kline, get_quote, batch_get_quotes,
|
|
157
|
+
cookie_status, fetch_cookies,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
# 板块
|
|
161
|
+
sectors = get_sector_ranking() # 涨幅榜
|
|
162
|
+
stocks = get_sector_components("BK0487") # 成分股
|
|
163
|
+
skline = get_sector_5min_kline("BK0487") # 板块 5 分 K
|
|
164
|
+
|
|
165
|
+
# 个股
|
|
166
|
+
kline = get_kline("600172", source="xueqiu", days=30)
|
|
167
|
+
mline = get_minute_kline("600172") # 1 分 K
|
|
168
|
+
quote = get_quote("600172") # 实时行情
|
|
169
|
+
quotes = batch_get_quotes(["600172", "000001", "002409"])
|
|
170
|
+
|
|
171
|
+
# Cookie 管理
|
|
172
|
+
status = cookie_status() # 查看 Cookie 是否有效
|
|
173
|
+
fetch_cookies() # 刷新全部 Cookie
|
|
174
|
+
fetch_cookies(source="xueqiu") # 只刷新雪球 Cookie
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### 日志查询
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
from dragon_quant.logging.query import (
|
|
181
|
+
tail_logs, query_logs, clear_logs, list_logs, log_summary,
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
# 最近 20 条
|
|
185
|
+
entries = tail_logs(20)
|
|
186
|
+
|
|
187
|
+
# 按条件查
|
|
188
|
+
errors = query_logs(level="error")
|
|
189
|
+
drive = query_logs(category="scorer:drive", code="600172")
|
|
190
|
+
|
|
191
|
+
# 扫描摘要
|
|
192
|
+
s = log_summary() # {"api_stats": {...}, "error_count": 0, "phases": {...}}
|
|
193
|
+
|
|
194
|
+
# 列出日志文件
|
|
195
|
+
files = list_logs()
|
|
196
|
+
|
|
197
|
+
# 清除 7 天前
|
|
198
|
+
result = clear_logs(days=7) # {"cleared": 3, "kept": 2, "files_removed": [...]}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## 四维评分体系
|
|
202
|
+
|
|
203
|
+
### 一、带动性(权重 35%)— "你是带头大哥吗?"
|
|
204
|
+
|
|
205
|
+
评估这只股票涨停后对同板块其他股票的带动效应。
|
|
206
|
+
|
|
207
|
+
- **板块共鸣(30%)**:同板块涨停股占比
|
|
208
|
+
- **跟风力度(30%)**:同板块非涨停股中涨幅 >3% 的比例
|
|
209
|
+
- **封板决策力(40%)**:封板时间早晚、在板块内的封板排名、小弟跟进紧密度
|
|
210
|
+
- 每多一连板额外 +5 分(封顶 100)
|
|
211
|
+
|
|
212
|
+
### 二、抗跌性(权重 15%)— "大盘崩了你扛得住吗?"
|
|
213
|
+
|
|
214
|
+
分析近期大盘跳水日(单日跌幅 < -0.7%)中个股表现。
|
|
215
|
+
|
|
216
|
+
- **相对回撤(40%)**:个股涨跌幅 vs 大盘涨跌幅
|
|
217
|
+
- **日内承接(30%)**:下影线比例 + 收盘位置
|
|
218
|
+
- **反弹弹性(30%)**:次日超额收益
|
|
219
|
+
|
|
220
|
+
### 三、领涨性(权重 25%)— "平时你在行业里排老几?"
|
|
221
|
+
|
|
222
|
+
不看涨停日,评估该股在同行业中的日常排名。
|
|
223
|
+
|
|
224
|
+
- **当日真实排名**:在行业成分股中的确切分位
|
|
225
|
+
- **历史估算排名**:近 5 个非涨停日的正态分布近似排位
|
|
226
|
+
- 偏离度加成:比行业中位数高出几个标准差
|
|
227
|
+
|
|
228
|
+
### 四、资金承接性(权重 25%)— "钱从别的板块跑你这来了吗?"
|
|
229
|
+
|
|
230
|
+
检测市场恐慌时跨板块的资金虹吸效应。
|
|
231
|
+
|
|
232
|
+
- 多板块 5 分 K 滑动窗口检测(≥2 个板块跌 >1% & 目标板块涨 >0.3%)
|
|
233
|
+
- **虹吸强度(40%)**:板块涨幅 / 窗口振幅
|
|
234
|
+
- **广度(20%)**:被抽血的板块数量
|
|
235
|
+
- **持续性(40%)**:尾盘回撤控制
|
|
236
|
+
|
|
237
|
+
## 数据源
|
|
238
|
+
|
|
239
|
+
| 数据源 | 用途 | 接口数 |
|
|
240
|
+
|---|---|---|
|
|
241
|
+
| 东方财富 | 板块排行、成分股、板块 5 分 K | 3 |
|
|
242
|
+
| 雪球 | 日 K 线、1 分 K 线 | 2 |
|
|
243
|
+
| 腾讯 | 实时行情、批量行情 | 2 |
|
|
244
|
+
|
|
245
|
+
## 设计思想
|
|
246
|
+
|
|
247
|
+
### 分层架构
|
|
248
|
+
|
|
249
|
+
```
|
|
250
|
+
┌─────────────────────────────────┐
|
|
251
|
+
│ CLI / Programmtic API │ ← cli.py / __init__.py
|
|
252
|
+
├─────────────────────────────────┤
|
|
253
|
+
│ Orchestrator(编排器) │ ← Phase A→F 全流程
|
|
254
|
+
├──────────┬──────────────────────┤
|
|
255
|
+
│ Scorers │ Logger & Reporter │ ← 四维评分 / 结构化日志
|
|
256
|
+
├──────────┴──────────────────────┤
|
|
257
|
+
│ DataCache + RateLimiter │ ← 内存/本地双缓存 + 限流
|
|
258
|
+
├─────────────────────────────────┤
|
|
259
|
+
│ Provider 适配层 │ ← 东财 / 雪球 / 腾讯
|
|
260
|
+
└─────────────────────────────────┘
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### 核心设计原则
|
|
264
|
+
|
|
265
|
+
1. **Provider 抽象**:所有数据源实现 `StockProvider` 接口,评分器只依赖接口不依赖具体实现,可无缝切换/新增数据源
|
|
266
|
+
2. **并发与限流**:`RateLimiter` 按 `(provider, endpoint)` 维度串行,不同 key 并发,控制 API 请求频率
|
|
267
|
+
3. **结构化日志**:`ScanLogger` 全链路打点,记录每次 API 调用、每项评分、每个阶段。支持按类别/级别/股票代码查询,方便排查问题
|
|
268
|
+
4. **结果持久化**:每次扫描自动保存 JSONL 日志、JSON 结果、文本报告三份文件,保留最新快照供 Agent 随时读取
|
|
269
|
+
5. **懒加载 Provider**:`data.py` 中 Provider 单例延迟初始化,模块 import 不触发网络请求
|
|
270
|
+
|
|
271
|
+
## 目录结构
|
|
272
|
+
|
|
273
|
+
```
|
|
274
|
+
dragon_quant/
|
|
275
|
+
├── __init__.py # 公共 API 导出
|
|
276
|
+
├── __main__.py # python -m 入口
|
|
277
|
+
├── cli.py # CLI 命令(scan/logs/data/storage)
|
|
278
|
+
├── orchestrator.py # 编排器(Phase A→F)
|
|
279
|
+
├── data.py # 原子数据查询 API
|
|
280
|
+
├── providers/ # 数据源适配器
|
|
281
|
+
│ ├── base.py # StockProvider 抽象接口
|
|
282
|
+
│ ├── eastmoney.py # 东方财富
|
|
283
|
+
│ ├── xueqiu.py # 雪球
|
|
284
|
+
│ ├── tencent.py # 腾讯
|
|
285
|
+
│ └── cookie.py # Cookie 管理
|
|
286
|
+
├── scorers/ # 四维评分器
|
|
287
|
+
│ ├── drive.py # 带动性
|
|
288
|
+
│ ├── anti_drop.py # 抗跌性
|
|
289
|
+
│ ├── leadership.py # 领涨性
|
|
290
|
+
│ └── absorption.py # 资金承接
|
|
291
|
+
├── models/
|
|
292
|
+
│ └── types.py # 数据模型(KBar, Quote, ScoreResult...)
|
|
293
|
+
├── cache/
|
|
294
|
+
│ └── data_cache.py # 内存+本地双缓存
|
|
295
|
+
├── logging/
|
|
296
|
+
│ ├── logger.py # ScanLogger 结构化日志
|
|
297
|
+
│ ├── reporter.py # ReportBuilder 自然语言报告
|
|
298
|
+
│ └── query.py # 日志查询 API
|
|
299
|
+
├── storage/
|
|
300
|
+
│ ├── paths.py # 数据目录管理
|
|
301
|
+
│ └── manager.py # StorageManager
|
|
302
|
+
├── rate_limit.py # 并发限流器
|
|
303
|
+
└── utils/
|
|
304
|
+
└── __init__.py
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## Agent 集成指南
|
|
308
|
+
|
|
309
|
+
本节展示 AI Agent 如何通过 Python API 调用 dragon-quant 完成常见任务。
|
|
310
|
+
|
|
311
|
+
### 场景 1:今日龙头扫榜 + 输出报告
|
|
312
|
+
|
|
313
|
+
```python
|
|
314
|
+
import dragon_quant
|
|
315
|
+
|
|
316
|
+
# 扫榜取 top5
|
|
317
|
+
result = dragon_quant.scan(top_n=5, candidates_n=5, workers=2)
|
|
318
|
+
|
|
319
|
+
print(f"🐉 今日龙头 TOP5 | 耗时 {result['elapsed_s']}s")
|
|
320
|
+
print()
|
|
321
|
+
print(f"{'排名':4s} {'代码':8s} {'名称':8s} {'综合':>6s} {'带动':>6s} {'抗跌':>6s} {'领涨':>6s} {'承接':>6s}")
|
|
322
|
+
print("-" * 56)
|
|
323
|
+
for i, r in enumerate(result["ranking"], 1):
|
|
324
|
+
dims = r.get("dimensions", {})
|
|
325
|
+
print(f"{i:4d} {r['code']:8s} {r['name']:8s} "
|
|
326
|
+
f"{r['composite_score']:6.1f} "
|
|
327
|
+
f"{dims.get('drive',{}).get('score',0):6.1f} "
|
|
328
|
+
f"{dims.get('anti_drop',{}).get('score',0):6.1f} "
|
|
329
|
+
f"{dims.get('leadership',{}).get('score',0):6.1f} "
|
|
330
|
+
f"{dims.get('absorption',{}).get('score',0):6.1f}")
|
|
331
|
+
|
|
332
|
+
# 输出自然语言报告(可直接发给用户)
|
|
333
|
+
print()
|
|
334
|
+
print(result["report_text"])
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### 场景 2:只取龙头排行数据,不打印(Agent 内部消费)
|
|
338
|
+
|
|
339
|
+
```python
|
|
340
|
+
import dragon_quant
|
|
341
|
+
|
|
342
|
+
result = dragon_quant.scan(top_n=10, verbose=False)
|
|
343
|
+
|
|
344
|
+
# 提取关键信息
|
|
345
|
+
for r in result["ranking"]:
|
|
346
|
+
code = r["code"]
|
|
347
|
+
name = r["name"]
|
|
348
|
+
score = r["composite_score"]
|
|
349
|
+
concepts = r.get("concepts", [])
|
|
350
|
+
boards = r.get("board_count", 0)
|
|
351
|
+
# 判断等级
|
|
352
|
+
if score >= 80:
|
|
353
|
+
grade = "🐲 龙头"
|
|
354
|
+
elif score >= 65:
|
|
355
|
+
grade = "🔥 强票"
|
|
356
|
+
else:
|
|
357
|
+
grade = "📊 一般"
|
|
358
|
+
print(f"{grade} {code} {name} | {boards}连板 | {', '.join(concepts)} | 综合{score}")
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### 场景 3:查某只股票的 K 线和实时行情
|
|
362
|
+
|
|
363
|
+
```python
|
|
364
|
+
from dragon_quant.data import get_kline, get_minute_kline, get_quote
|
|
365
|
+
|
|
366
|
+
code = "600172"
|
|
367
|
+
|
|
368
|
+
# 日K线
|
|
369
|
+
kline = get_kline(code, days=30)
|
|
370
|
+
print(f"{code} 最近 30 日 K 线:")
|
|
371
|
+
for k in kline[-5:]: # 最近5天
|
|
372
|
+
print(f" {getattr(k, 'time', '?')} | "
|
|
373
|
+
f"开{getattr(k, 'open', 0):.2f} 收{getattr(k, 'close', 0):.2f} "
|
|
374
|
+
f"涨{getattr(k, 'pct', 0):.2f}%")
|
|
375
|
+
|
|
376
|
+
# 实时行情
|
|
377
|
+
quote = get_quote(code)
|
|
378
|
+
if quote:
|
|
379
|
+
print(f"当前价: {quote.price} | 涨跌幅: {quote.pct}% | 换手率: {getattr(quote, 'turnover', 0):.2f}%")
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### 场景 4:API 返回 400/空数据 → 刷新 Cookie
|
|
383
|
+
|
|
384
|
+
当 scan() 或数据查询返回 400 错误、空数据时,通常是 Cookie 过期了。刷新后重试即可。
|
|
385
|
+
|
|
386
|
+
```python
|
|
387
|
+
from dragon_quant.data import cookie_status, fetch_cookies
|
|
388
|
+
|
|
389
|
+
# 先查看状态
|
|
390
|
+
status = cookie_status()
|
|
391
|
+
for source, info in status.items():
|
|
392
|
+
print(f"{source}: {'✅ 有效' if info['ok'] else '❌ 过期'} ({info['length']}字符)")
|
|
393
|
+
|
|
394
|
+
# 如果东财或雪球过期,刷新
|
|
395
|
+
if not status["eastmoney"]["ok"] or not status["xueqiu"]["ok"]:
|
|
396
|
+
print("Cookie 过期,正在刷新...")
|
|
397
|
+
fetch_cookies()
|
|
398
|
+
# 刷新后重新检查
|
|
399
|
+
new_status = cookie_status()
|
|
400
|
+
for source, info in new_status.items():
|
|
401
|
+
print(f" {source}: {'✅' if info['ok'] else '❌'} ({info['length']}字符)")
|
|
402
|
+
|
|
403
|
+
# 刷新后重试 scan
|
|
404
|
+
import dragon_quant
|
|
405
|
+
result = dragon_quant.scan(top_n=5)
|
|
406
|
+
print(f"扫描成功,{len(result['ranking'])} 只候选")
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### 场景 5:查板块热度(哪个方向最强)
|
|
410
|
+
|
|
411
|
+
```python
|
|
412
|
+
from dragon_quant.data import get_sector_ranking, get_sector_components
|
|
413
|
+
|
|
414
|
+
# 今日涨幅榜 top5 板块
|
|
415
|
+
sectors = get_sector_ranking(asc=False)[:5]
|
|
416
|
+
print("今日最强板块:")
|
|
417
|
+
for s in sectors:
|
|
418
|
+
print(f" {s.name} ({s.code}) | +{s.pct:.2f}%")
|
|
419
|
+
|
|
420
|
+
# 看龙头板块的涨停分布
|
|
421
|
+
if sectors:
|
|
422
|
+
stocks = get_sector_components(sectors[0].code)
|
|
423
|
+
up_limit = [s for s in stocks if s.pct and s.pct >= 9.9]
|
|
424
|
+
print(f"\n{sectors[0].name} 涨停股 ({len(up_limit)} 只):")
|
|
425
|
+
for s in up_limit:
|
|
426
|
+
print(f" {s.code} {s.name} | +{s.pct:.2f}%")
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### 场景 6:排查问题 — 查看扫描日志
|
|
430
|
+
|
|
431
|
+
```python
|
|
432
|
+
from dragon_quant.logging.query import list_logs, tail_logs, query_logs, log_summary, clear_logs
|
|
433
|
+
|
|
434
|
+
# 列出所有日志文件
|
|
435
|
+
files = list_logs()
|
|
436
|
+
print(f"共 {len(files)} 个日志文件")
|
|
437
|
+
for f in files[:5]:
|
|
438
|
+
print(f" {f['name']} | {f['size']} | {f['lines']} 行")
|
|
439
|
+
|
|
440
|
+
# 查看最新扫描的摘要
|
|
441
|
+
summary = log_summary()
|
|
442
|
+
print(f"\n最新扫描: {summary['file']}")
|
|
443
|
+
print(f" 阶段: {list(summary['phases'].keys())}")
|
|
444
|
+
print(f" API 调用: {summary['api_stats']['total']} 次 | 成功 {summary['api_stats']['ok']} | 失败 {summary['api_stats']['error']}")
|
|
445
|
+
print(f" 评分: {summary['scorer_count']} 次")
|
|
446
|
+
print(f" 错误: {summary['error_count']} 条")
|
|
447
|
+
|
|
448
|
+
# 如果有很多错误,查具体原因
|
|
449
|
+
if summary['error_count'] > 0:
|
|
450
|
+
errors = query_logs(level="error", tail=10)
|
|
451
|
+
print(f"\n最近 10 条错误:")
|
|
452
|
+
for e in errors:
|
|
453
|
+
print(f" [{e.get('category', '')}] {e.get('message', '')}")
|
|
454
|
+
if e.get('data', {}).get('exception'):
|
|
455
|
+
print(f" exception: {e['data']['exception'][:120]}")
|
|
456
|
+
|
|
457
|
+
# 查某只股票的评分细节
|
|
458
|
+
entries = query_logs(category="scorer", code="600172")
|
|
459
|
+
for e in entries:
|
|
460
|
+
print(f" {e['category']} → score={e.get('data',{}).get('score',0)}")
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
### 场景 7:清理日志
|
|
464
|
+
|
|
465
|
+
```python
|
|
466
|
+
from dragon_quant.logging.query import clear_logs, list_logs
|
|
467
|
+
|
|
468
|
+
# 清理前
|
|
469
|
+
before = list_logs()
|
|
470
|
+
print(f"清理前: {len(before)} 个日志文件")
|
|
471
|
+
|
|
472
|
+
# 保留最近 3 天
|
|
473
|
+
result = clear_logs(days=3)
|
|
474
|
+
print(f"删除了 {result['cleared']} 个文件 | 保留 {result['kept']} 个")
|
|
475
|
+
for f in result.get("files_removed", []):
|
|
476
|
+
print(f" - {f}")
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
### 场景 8:拿上一次扫描结果(无需重新跑)
|
|
480
|
+
|
|
481
|
+
```python
|
|
482
|
+
import json
|
|
483
|
+
from pathlib import Path
|
|
484
|
+
|
|
485
|
+
# macOS 默认路径
|
|
486
|
+
latest_path = Path.home() / "Library" / "Application Support" / "dragon-quant" / "results" / "latest.json"
|
|
487
|
+
|
|
488
|
+
if latest_path.exists():
|
|
489
|
+
with open(latest_path) as f:
|
|
490
|
+
data = json.load(f)
|
|
491
|
+
|
|
492
|
+
print(f"上次扫描: {data['timestamp']} | 耗时 {data['elapsed_s']}s")
|
|
493
|
+
for r in data["ranking"]:
|
|
494
|
+
print(f" {r['code']} {r['name']} — {r['composite_score']}分 — {r.get('board_count', 0)}连板")
|
|
495
|
+
else:
|
|
496
|
+
print("暂无扫描缓存,运行一次 scan() 即可生成")
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
### 场景 9:批量获取多只票的行情对比
|
|
500
|
+
|
|
501
|
+
```python
|
|
502
|
+
from dragon_quant.data import batch_get_quotes
|
|
503
|
+
|
|
504
|
+
codes = ["600172", "605589", "603052", "603203", "603126"]
|
|
505
|
+
quotes = batch_get_quotes(codes)
|
|
506
|
+
|
|
507
|
+
print(f"{'代码':8s} {'价格':>8s} {'涨跌幅':>8s} {'换手率':>8s} {'量比':>6s}")
|
|
508
|
+
print("-" * 44)
|
|
509
|
+
for q in quotes:
|
|
510
|
+
if q:
|
|
511
|
+
price = getattr(q, 'price', 0)
|
|
512
|
+
pct = getattr(q, 'pct', 0)
|
|
513
|
+
turnover = getattr(q, 'turnover', 0)
|
|
514
|
+
volume_ratio = getattr(q, 'volume_ratio', 0)
|
|
515
|
+
print(f"{q.code:8s} {price:8.2f} {pct:+7.2f}% {turnover:7.2f}% {volume_ratio:6.2f}")
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
## License
|
|
519
|
+
|
|
520
|
+
MIT
|