docs: 新增 Tushare 接口参考文档 + 接口自检脚本(实测版,防再踩 daily_vip 不存在的坑)
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Tushare Pro 接口自检脚本
|
||||
=========================
|
||||
检查当前 token 对常用接口的可用性,避免改代码时用到不存在的接口名/无权限接口。
|
||||
|
||||
用法(在 quantitative_data/ 目录下运行,自动读取 .env 中的 token):
|
||||
/opt/quant-venv/bin/python tushare_api_check.py
|
||||
/opt/quant-venv/bin/python tushare_api_check.py --token 你的token
|
||||
|
||||
输出说明:
|
||||
✅ 可用 — 接口存在且有权限
|
||||
❌ 40101 — 接口名不存在(如 daily_vip),别用这个接口名
|
||||
❌ 40203 — 接口存在但当前 token 无权限(积分不够)
|
||||
❌ 其他 — 见错误码提示
|
||||
"""
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
import urllib.request
|
||||
|
||||
API_URL = "http://api.tushare.pro"
|
||||
|
||||
# 自检清单:接口名 -> 测试参数(用最小代价的参数)
|
||||
CHECK_LIST = {
|
||||
"stock_basic": {},
|
||||
"trade_cal": {"exchange": "SSE", "start_date": "20260101", "end_date": "20260131"},
|
||||
"daily": {"trade_date": "20260105"},
|
||||
"daily_vip": {"trade_date": "20260105"},
|
||||
"daily_basic": {"trade_date": "20260105"},
|
||||
"daily_basic_vip": {"trade_date": "20260105"},
|
||||
"adj_factor": {"trade_date": "20260105"},
|
||||
"adj_factor_vip": {"trade_date": "20260105"},
|
||||
"moneyflow": {"trade_date": "20260105"},
|
||||
"index_daily": {"ts_code": "000001.SH", "start_date": "20260105", "end_date": "20260105"},
|
||||
"income": {"ts_code": "000001.SZ", "period": "20251231"},
|
||||
"income_vip": {"ts_code": "000001.SZ", "period": "20251231"},
|
||||
"balancesheet": {"ts_code": "000001.SZ", "period": "20251231"},
|
||||
"balancesheet_vip": {"ts_code": "000001.SZ", "period": "20251231"},
|
||||
"cashflow": {"ts_code": "000001.SZ", "period": "20251231"},
|
||||
"cashflow_vip": {"ts_code": "000001.SZ", "period": "20251231"},
|
||||
"fina_indicator": {"ts_code": "000001.SZ", "period": "20251231"},
|
||||
"fina_indicator_vip": {"ts_code": "000001.SZ", "period": "20251231"},
|
||||
}
|
||||
|
||||
|
||||
def get_token(args_token):
|
||||
if args_token:
|
||||
return args_token.strip()
|
||||
try:
|
||||
from config import TUSHARE_TOKEN
|
||||
if TUSHARE_TOKEN:
|
||||
return TUSHARE_TOKEN.strip()
|
||||
except Exception:
|
||||
pass
|
||||
print("未找到 token:请加 --token 参数,或确认 .env 里 TUSHARE_TOKEN 已配置")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def call_api(token, api_name, params):
|
||||
body = json.dumps({
|
||||
"api_name": api_name,
|
||||
"token": token,
|
||||
"params": params,
|
||||
"fields": "",
|
||||
}).encode("utf-8")
|
||||
req = urllib.request.Request(API_URL, data=body, headers={"Content-Type": "application/json"})
|
||||
with urllib.request.urlopen(req, timeout=30) as resp:
|
||||
return json.loads(resp.read().decode("utf-8"))
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Tushare 接口自检")
|
||||
parser.add_argument("--token", default=None, help="Tushare token(默认读 .env)")
|
||||
args = parser.parse_args()
|
||||
|
||||
token = get_token(args.token)
|
||||
print("=" * 64)
|
||||
print(f"Tushare 接口自检 token前8位: {token[:8]}")
|
||||
print("=" * 64)
|
||||
|
||||
ok, fail = 0, 0
|
||||
for api_name, params in CHECK_LIST.items():
|
||||
try:
|
||||
result = call_api(token, api_name, params)
|
||||
code = result.get("code", -1)
|
||||
msg = result.get("msg", "")
|
||||
if code == 0:
|
||||
print(f" ✅ {api_name:24s} 可用")
|
||||
ok += 1
|
||||
else:
|
||||
print(f" ❌ {api_name:24s} code={code} {msg}")
|
||||
fail += 1
|
||||
except Exception as e:
|
||||
print(f" ❌ {api_name:24s} 请求异常: {e}")
|
||||
fail += 1
|
||||
|
||||
print("=" * 64)
|
||||
print(f"结果: {ok} 可用, {fail} 不可用")
|
||||
if fail:
|
||||
print("提示: 40101=接口名不存在(别用这个名) 40203=无权限(积分不够)")
|
||||
sys.exit(1 if fail else 0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user