File size: 8,452 Bytes
72a9562
 
 
 
 
 
 
 
 
 
 
98c3a25
72a9562
23022b9
2a8a0f5
98c3a25
72a9562
 
 
2a8a0f5
 
 
23022b9
4a3dd5b
2a8a0f5
 
 
 
 
98c3a25
72a9562
98c3a25
 
 
 
 
 
 
 
72a9562
98c3a25
72a9562
98c3a25
72a9562
98c3a25
 
 
 
 
 
2a8a0f5
98c3a25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2a8a0f5
98c3a25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2a8a0f5
98c3a25
 
 
 
 
 
 
72a9562
 
 
2a8a0f5
98c3a25
72a9562
98c3a25
 
 
 
 
 
4a3dd5b
98c3a25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72a9562
 
 
98c3a25
 
 
 
 
 
 
 
72a9562
 
98c3a25
 
 
 
 
 
 
 
72a9562
 
 
 
98c3a25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72a9562
98c3a25
 
 
 
 
2a8a0f5
 
 
98c3a25
 
 
 
 
 
 
 
 
 
 
 
 
 
72a9562
 
 
98c3a25
72a9562
98c3a25
 
 
 
 
 
 
 
 
 
 
72a9562
 
 
98c3a25
 
 
 
 
 
72a9562
 
 
98c3a25
 
 
 
 
 
2a8a0f5
98c3a25
 
 
2a8a0f5
98c3a25
 
 
 
 
 
 
 
 
 
2a8a0f5
98c3a25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72a9562
 
 
 
 
 
 
98c3a25
 
 
 
 
4a3dd5b
 
98c3a25
 
 
 
 
 
 
 
 
 
 
2a8a0f5
98c3a25
 
 
 
 
 
 
 
 
 
 
 
2a8a0f5
 
 
 
23022b9
2a8a0f5
 
23022b9
 
2a8a0f5
 
 
 
 
 
 
 
 
 
 
98c3a25
 
 
 
 
 
72a9562
98c3a25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
---
title: Kronos Stock Predictor API
emoji: 📈
colorFrom: blue
colorTo: indigo
sdk: docker
pinned: false
---

# Kronos Stock Predictor API

基于[清华大学 Kronos 金融 K 线基础大模型](https://arxiv.org/abs/2508.02739)的 A 股概率预测 REST API。

- **数据源**:Tushare Pro A 股日线,前复权(qfq)
- **推理方式**:蒙特卡洛分批采样,输出预测方向、置信度及 95% 交易区间
- **异步任务**:POST 提交 → 返回 `task_id` → GET 轮询结果

---

## 更新说明(2026-03-16)

- 请求/响应主字段由 `ts_code` 统一为 `symbol`
- 数据源切换回 Tushare Pro(`pro_bar`,前复权 `qfq`- 方向概率 `direction.probability` 定义为“当前 `direction.signal` 的概率(0–1)”
- 推理路径改为分批采样(可通过 `MC_BATCH_SIZE` 调整批大小)
- 新增阶段耗时日志(`fetch/calendar/infer/build/cache/total`)

---

## 模型信息

| 项目 | 值 |
|---|---|
| 模型 | [NeoQuasar/Kronos-base](https://huggingface.co/NeoQuasar/Kronos-base) |
| 参数量 | 102.3M |
| 架构 | Decoder-only Transformer |
| 最大上下文 | 512 根 K 线 |
| 预训练数据 | 全球 45 个交易所,120 亿根 K 线 |
| 推理设备 | CUDA(若可用)/ CPU fallback |

---

## 快速开始

### 1. 提交预测任务

```bash
curl -X POST "https://yingfeng64-kronos-api.hf.space/api/v1/predict" \
  -H "Content-Type: application/json" \
  -d '{
    "symbol": "000063.SZ",
    "lookback": 512,
    "pred_len": 5,
    "sample_count": 30,
    "mode": "simple"
  }'
```

```json
{ "task_id": "550e8400-e29b-41d4-a716-446655440000" }
```

### 2. 轮询结果

```bash
curl "https://yingfeng64-kronos-api.hf.space/api/v1/predict/550e8400-e29b-41d4-a716-446655440000"
```

`status``"pending"` 时继续等待,变为 `"done"``"failed"` 后读取结果。

### Python 一键轮询版

```python
import time, requests

BASE = "https://yingfeng64-kronos-api.hf.space"

resp = requests.post(f"{BASE}/api/v1/predict", json={
    "symbol": "000063.SZ",
    "lookback": 512,
    "pred_len": 5,
    "sample_count": 30,
})
task_id = resp.json()["task_id"]

while True:
    r = requests.get(f"{BASE}/api/v1/predict/{task_id}").json()
    if r["status"] in ("done", "failed"):
        break
    time.sleep(10)

print(r["result"])
```

---

## API 文档

### `POST /api/v1/predict` — 提交单个预测任务

**请求体**

| 字段 | 类型 | 默认值 | 范围 | 说明 |
|---|---|---|---|---|
| `symbol` | string | — | — | A 股代码,支持 `"603777"``"000063.SZ"` |
| `lookback` | int | 512 | 20–512 | 回看历史 K 线根数 |
| `pred_len` | int | 5 | 1–60 | 预测未来交易日数(建议 ≤ 30) |
| `sample_count` | int | 30 | 1–100 | MC 蒙特卡洛采样次数 |
| `mode` | string | `"simple"` | `simple` / `advanced` | 返回字段详细程度 |
| `include_volume` | bool | false | — | `advanced` 模式下是否返回成交量预测 |

**响应(`mode=simple`)**

```json
{
  "symbol": "000063.SZ",
  "base_date": "2026-03-13",
  "pred_len": 5,
  "confidence": 95,
  "confidence_warning": false,
  "cached": false,
  "cache_expires_at": "2026-03-16 15:00:00 UTC+08:00",
  "direction": {
    "signal": "bearish",
    "probability": 0.5667
  },
  "summary": {
    "mean_close": 36.35,
    "range_low": 30.60,
    "range_high": 40.01,
    "range_width": 9.41
  },
  "bands": [
    {
      "date": "2026-03-16",
      "step": 1,
      "mean_close": 36.10,
      "trading_low": 34.46,
      "trading_high": 37.32,
      "uncertainty": 0.0785
    }
  ]
}
```

**`mode=advanced` 在每个 `bands` 条目中追加**

| 字段 | 说明 |
|---|---|
| `mean_open` / `mean_high` / `mean_low` | 预测开/高/低价均值 |
| `close_ci_low` / `close_ci_high` | 收盘价 95% 置信区间 |

当 `include_volume: true` 时额外返回顶层 `volume` 数组:

```json
"volume": [
  {
    "date": "2026-03-16",
    "mean_volume": 1050000,
    "volume_ci_low": 820000,
    "volume_ci_high": 1280000
  }
]
```

---

### `GET /api/v1/predict/{task_id}` — 查询单个任务结果

**响应**

| `status` | 含义 |
|---|---|
| `pending` | 正在计算 |
| `done` | 完成,`result` 字段包含预测数据 |
| `failed` | 失败,`error` 字段包含错误信息 |

---

### `POST /api/v1/predict/batch` — 批量提交

一次提交最多 20 个预测请求,所有子任务并发入队。每个子任务参数与单个预测相同。

```bash
curl -X POST "https://yingfeng64-kronos-api.hf.space/api/v1/predict/batch" \
  -H "Content-Type: application/json" \
  -d '{
    "requests": [
      {"symbol": "000063", "pred_len": 5, "sample_count": 30},
      {"symbol": "600900", "pred_len": 5, "sample_count": 30},
      {"symbol": "000001", "pred_len": 5, "sample_count": 30}
    ]
  }'
```

```json
{
  "batch_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "task_ids": ["aaa...", "bbb...", "ccc..."]
}
```

---

### `GET /api/v1/predict/batch/{batch_id}` — 查询批量进度

```json
{
  "batch_id": "xxxxxxxx-...",
  "status": "done",
  "total": 3,
  "done": 3,
  "failed": 0,
  "tasks": [
    {
      "task_id": "aaa...",
      "status": "done",
      "result": { ... },
      "error": null
    }
  ]
}
```

| `status` | 含义 |
|---|---|
| `pending` | 仍有子任务在计算 |
| `done` | 全部成功 |
| `partial` | 部分成功、部分失败 |
| `failed` | 全部失败 |

---

### `GET /api/v1/cache` — 查看缓存状态

列出有效缓存条目及剩余 TTL。

| 参数 | 说明 |
|---|---|
| `symbol`(可选) | 只返回该股票的缓存,不传则返回全部 |

```bash
# 查某只股票
curl "https://yingfeng64-kronos-api.hf.space/api/v1/cache?symbol=000063"

# 查全部
curl "https://yingfeng64-kronos-api.hf.space/api/v1/cache"
```

```json
{
  "count": 1,
  "entries": [
    {
      "symbol": "000063",
      "lookback": 512,
      "pred_len": 5,
      "sample_count": 30,
      "mode": "simple",
      "include_volume": false,
      "cached_at": "2026-03-16 10:23:00 UTC+08:00",
      "expires_at": "2026-03-16 15:00:00 UTC+08:00",
      "ttl_seconds": 17220
    }
  ]
}
```

---

### `GET /health` — 健康检查

```json
{ "status": "ok" }
```

---

## 响应字段说明

| 字段 | 含义 |
|---|---|
| `base_date` | 预测所基于的最后一个历史 K 线日期 |
| `direction.signal` | `"bullish"` / `"bearish"`,由内部看涨概率是否 >= 0.5 决定 |
| `direction.probability` | 当前 `direction.signal` 的概率(0–1) |
| `trading_low` | 该日预测最低价的 q2.5 分位数(95% 交易区间下沿) |
| `trading_high` | 该日预测最高价的 q97.5 分位数(95% 交易区间上沿) |
| `uncertainty` | `(trading_high − trading_low) / last_close`,无量纲不确定性 |
| `confidence_warning` | `pred_len > 30` 时为 `true`,表示预测不确定性较大 |
| `cached` | 结果是否来自缓存 |
| `cache_expires_at` | 缓存失效时间(北京时间) |

---

## 缓存机制

缓存 key 由 `(symbol, lookback, pred_len, sample_count, mode, include_volume)` 六元组构成,失效时机为下一个 A 股交易日收盘(15:00 CST)。

| 请求时间(CST) | 缓存过期时间 |
|---|---|
| 工作日 00:00–15:00 | 当日 15:00 CST |
| 工作日 15:00 后 | 次个工作日 15:00 CST |
| 周末 | 下周一 15:00 CST |
| 法定节假日 | 不特殊处理(节假日无新数据,缓存命中结果正确) |

缓存命中时响应时间 < 100ms,无需等待模型推理。

---

## 运行配置

| 环境变量 | 默认值 | 说明 |
|---|---|---|
| `TUSHARE_TOKEN` | — | Tushare 访问令牌(必填) |
| `KRONOS_DIR` | `/app/Kronos` | Kronos 源码目录 |
| `MC_BATCH_SIZE` | `8` | 蒙特卡洛分批采样大小(越大通常越快,但占用显存/内存更高) |
| `TS_RETRY_COUNT` | `3` | Tushare 请求重试次数 |
| `TS_RETRY_BASE_SLEEP` | `0.8` | Tushare 重试退避基准秒数(指数退避) |

---

## 可观测性

服务会在 `INFO` 日志输出预测阶段耗时,示例:

```text
Task <task_id> timing symbol=300065.SZ fetch=...ms calendar=...ms infer=...ms build=...ms cache=...ms total=...ms
```

## 性能参考

| 环境 | 单次采样 | 30 次 MC 总耗时 |
|---|---|---|
| RTX 3090 (CUDA) | ~230ms | ~7s |
| CPU only | ~3–5s | ~2–5min |

> 推荐选用 GPU 硬件以获得实用响应速度。首次冷启动需从 HuggingFace Hub 下载模型权重,约需 1–2 分钟。