用 /v1/quote 查实时行情与日 K 收盘价
查一只股票"现在多少钱"只需一次 GET —— `/v1/quote` 免 Key、免注册,返回最近 30 个交易日的 OHLC(开/高/低/收)+ 成交量额 + 换手率,`data[0]` 就是最新一天。适合做行情展示、复盘取数、批量取收盘价的底座。
一、先看最常用的 5 行代码
`/v1/quote` 是免费端点(无需 Key、无需注册)。核心参数只有 `code`,返回统一信封 `{ ok, endpoint, tier, elapsed_ms, source, data }`,`data` 是从新到旧的日数组(默认 30 条),`data[0]` = 最近交易日。
import requests
r = requests.get(
"https://api.ashareapi.com/v1/quote",
params={"code": "sh600667"}, # 必须带市场前缀
timeout=10,
)
body = r.json()
if not body.get("ok"):
raise RuntimeError(body) # 失败时返回 ok=false + error
bar = body["data"][0] # 最近一个交易日
print(bar["date"], bar["last"], bar["turnover"])- `code` 必须带市场前缀:`sh600667`(沪)/ `sz000001`(深)/ `bj920002`(北交所)/ `hk00700`(港股)/ `usAAPL`(美股)—— 纯 6 位会返回空
- `data` 是数组(默认 30 条,`data[0]` 最新),不是单个对象
二、字段含义与单位(最关键,别搞错)
| 字段 | 含义 | 单位 / 注意 |
|---|---|---|
| date | 交易日 | YYYY-MM-DD,是数据日期不是查询日期 |
| open / high / low | 开 / 最高 / 最低 | 字符串形式的数字 |
| last | 收盘价(上一交易日) | 不是盘中实时价 —— 见第三节 |
| volume | 成交量 | 手(×100 = 股) |
| amount | 成交额 | 元(不是万、不是亿) |
| turnover | 换手率 | 百分数(4.92 = 4.92%) |
口径提醒:`volume` 是手、`amount` 是元、`turnover` 是百分数 —— 这三个单位是新手最常踩的坑(把 4.92 当成 4.92 元、把 volume 当成股)。同一字段在 `/v1/kline` 也是同名同值(口径一致,可放心混用)。
三、"实时价"还是"收盘价"?—— 数据日期语义
`/v1/quote` 的 `last` 是该交易日的收盘价,`date` 告诉你这是哪一天。盘中调用时 `data[0].date` 就是当天,`last` 是截至请求时刻的最新价(可视为当前价);盘后调用时则是当天收盘价。所以判断"是不是实时"看 `date` 是否等于今天即可。
这是设计使然:同一个端点既可当"实时行情"也可当"历史收盘价"用,靠 `date` 区分。想做纯展示(页面显示"现价"),先检查 `date` 是否是今天,避免把昨日收盘价当现价展示(这是最常见的误导)。
- 盘中:`date` = 今天 → `last` 是当前最新价
- 盘后 / 休市:`date` = 最近交易日 → `last` 是收盘价
- 判断方法:`bar["date"] == 今天`(或按交易日历判断)
四、批量取多只股票(并发 + 限流)
`/v1/quote` 每次只接收一个 `code`(不是逗号分隔)。要取多只,用线程池并发,并注意匿名限流:5 次/分钟。
from concurrent.futures import ThreadPoolExecutor
import requests
def q(code):
r = requests.get("https://api.ashareapi.com/v1/quote",
params={"code": code}, timeout=10)
j = r.json()
if not j.get("ok"): # 429 限流 / 401 也会走这里
return code, j.get("error")
return code, j["data"][0]["last"]
codes = ["sh600667", "sz000001", "sh600519"]
with ThreadPoolExecutor(max_workers=3) as ex:
for code, price in ex.map(q, codes):
print(code, price)- 匿名 5 次/分钟:超过会返回 429;需要更高频率 → 解一次 PoW 挑战提到 60 次/分钟(见第五节),或申请 Key
- 并发不要太高:3~5 个线程足够,太高只会更快撞限流
五、撞到 429 怎么办(免费提速)
匿名调用每秒/每分钟有配额,超了返回 `429 Too Many Requests`。`/v1/challenge` 是免费提速通道:取一个挑战(PoW),解出后用 `X-PoW` 头带回来,匿名配额从 5 次/分钟 → 60 次/分钟。
import requests
# 1) 取挑战(difficulty 只能调高不能调低)
ch = requests.get("https://api.ashareapi.com/v1/challenge", timeout=10).json()
# ch = {"challenge": ..., "difficulty": 18, ...}
# 2) 解 PoW:找一个 nonce 使 sha256(challenge+nonce) 前 difficulty 位为 0
# (细节见 /docs/errors;大多数场景直接申请 Key 更省事)
# 3) 带着 X-PoW 调用,配额提升
# r = requests.get("https://api.ashareapi.com/v1/quote",
# params={"code": "sh600667"},
# headers={"X-PoW": solved}, timeout=10)- 日常够用:单机展示/复盘 5 次/分钟通常够;批量任务建议直接申请 Key(见 /pricing)
- 429 不要死循环重试:退避几秒再试,或降低频率
六、quote 和 kline 有什么区别?
| /v1/quote | /v1/kline | |
|---|---|---|
| 用途 | 行情快照 + 最近 30 日 | 历史 K 线(可指定周期/条数) |
| 参数 | code | code / period / count |
| 默认返回 | 最近 30 个交易日 | 最近 30 根(count 最大 1212) |
| 复权 | 不复权语义(原始价) | 前复权(除权日不跳空) |
| 字段 | date/open/high/low/last/volume/amount/turnover | 同名同值 |
一句话:要"现在/最近几天的价"用 `quote`;要"完整历史走势、算指标、回测"用 `kline`(前复权)。两者字段口径一致,互相接得上。
常见问题
看 `data[0].date`:等于今天时 `last` 就是盘中最新价(可当现价用);等于历史日期时就是那天收盘价。这个端点设计上同时服务"实时快照"和"收盘价取数"两种用途,用 date 区分,避免把昨日收盘价当现价。
volume 单位是手(1 手 = 100 股),amount 单位是元,turnover 是百分数(4.92 表示 4.92%)。这三个是最容易搞错的单位,建议在代码里统一注释。
不能 —— `/v1/quote` 每次一个 code。批量请用线程池并发,并注意匿名限流(5 次/分钟);高频需求建议申请 Key 或用 /v1/challenge 解 PoW 提额到 60 次/分钟。
必须带市场前缀(sh600667 / sz000001 / bj920002 / hk00700 / usAAPL)。只传 6 位数字会返回空结果(不是报错),这是最常见的新手问题。
免费 —— 无需注册、无需 Key,匿名即可调用(限流 5 次/分钟)。更高额度见 /pricing。
最后更新: 2026-10-01
数据来自 ashareapi /v1/quote 线上实测(2026-10-01:600667 返回 30 条,data[0] date=2026-09-30 last=17.29 high=18.28 volume=1029096 amount=1804480000 turnover=4.92);字段与单位经线上响应核对。