@tushare/sdk
v1.2.0
Published
Tushare Pro SDK
Downloads
55
Maintainers
Readme
@tushare/sdk
Tushare Pro 门面聚合 SDK(严格类型、零 any,Node 18+ / 浏览器)
@tushare/sdk 基于 @tushare/core 的通用能力(固定窗口限流、指数退避重试、内存缓存、同构 fetch),通过“注册表 + 工厂”自动生成强类型方法,免去手写样板代码,专注业务调用。
- 强类型:字段选择按字面量数组收窄,返回值自动
Pick<> - 通用能力:重试/限流/缓存/超时,统一可配
- 同构:Node 18+ 和浏览器均可使用(浏览器建议经后端代理)
- 轻量:按需导入类型;运行时仅保留必要元信息
安装
# 使用 pnpm(推荐)
pnpm add @tushare/sdk
# 或 npm
npm i @tushare/sdk
# 或 yarn
yarn add @tushare/sdk快速上手
// 中文注释:引入门面类并初始化(请使用你的 Tushare token)
import { Tushare } from '@tushare/sdk';
// 中文注释:可选配置,均有合理默认值
const sdk = new Tushare('YOUR_TUSHARE_TOKEN', {
baseUrl: 'https://api.tushare.pro', // 中文注释:基础地址
defaults: {
transform: 'object', // 中文注释:将表格转换为对象数组;'raw' 则返回原始二维表
cacheTtlMs: 10_000, // 中文注释:内存缓存时长(毫秒);0 表示关闭
timeoutMs: 20_000, // 中文注释:请求超时(毫秒)
},
rateLimit: {
windowMs: 1000, // 中文注释:固定窗口(毫秒)
maxRequests: 80, // 中文注释:每窗口最大请求数
},
maxRetries: 3, // 中文注释:最大重试次数
backoffBaseMs: 200, // 中文注释:退避初始毫秒
backoffFactor: 2, // 中文注释:退避倍率
backoffJitter: true, // 中文注释:是否加入抖动
});
// 中文注释:通过自动模块/方法调用 API;字段选择将收窄返回类型
const rows = await sdk.auto.getStockBasic(
{ limit: 1 }, // 中文注释:参数对象(类型安全)
['ts_code', 'name'] as const // 中文注释:字段选择(字面量数组)
);
// rows: Array<{ ts_code: string; name: string }>
console.log(rows);API 结构与命名
- 模块来自注册表
registry的分节(section)。常用分节之一为auto。 - 每个方法名称通常以
getXxx命名,对应 Tushare 的api_name(例如stock_basic→getStockBasic)。 - 统一方法签名:
sdk[section][method](params, fields?)params:严格类型化的参数对象fields:可选的字段字面量数组(传入则返回值自动收窄为Pick<TEntity, K[number]>[])
你也可以在编辑器中查看自动生成的类型:
import type { ... } from '@tushare/sdk'。
错误处理
import { TushareError } from '@tushare/core';
try {
const rows = await sdk.auto.getStockBasic({ limit: 1 }, ['ts_code'] as const);
console.log(rows);
} catch (e) {
// 中文注释:业务错误(code != 0)或 HTTP 错误都会抛出 TushareError
if (e instanceof TushareError) {
console.error('API 出错', {
name: e.name, // 'TushareError'
api: e.apiName, // 中文注释:接口名(如 'stock_basic')
code: e.code, // 中文注释:业务码(非 0)
httpStatus: e.httpStatus,
params: e.params,
message: e.message,
});
} else {
console.error(e);
}
}性能与可靠性
- 限流:固定窗口(
windowMs/maxRequests) - 重试:支持最大次数与指数退避(可抖动)
- 缓存:内存缓存(TTL + 简易 LRU)
- 超时:请求级超时控制
以上能力由
@tushare/core提供,在本 SDK 中通过TushareClientOptions统一配置。
分页与大数据处理
SDK 不内置自动分页:
@tushare/sdk方法一次只执行一次 API 调用。你可以手动使用limit/offset分页;或推荐使用@tushare/mcp的sdk_call顺序分页(含重试/退避)。手动分页示例(TS):
// 中文注释:手动 limit/offset 循环(仅示例,生产建议改用 MCP 顺序分页)
import { Tushare } from '@tushare/sdk';
const sdk = new Tushare('TOKEN');
const pageSize = 5000; // 中文注释:单页条数
let offset = 0; // 中文注释:偏移量
const all: Array<{ ts_code: string; trade_date: string; close: number }> = [];
while (true) {
const rows = await sdk.auto.getDaily(
{ ts_code: '000001.SZ', start_date: '20240101', limit: pageSize, offset },
['ts_code', 'trade_date', 'close'] as const
);
if (!rows.length) break;
all.push(...rows);
offset += rows.length;
if (rows.length < pageSize) break; // 中文注释:已到最后一页
}
console.log('total rows:', all.length);- 使用 MCP 顺序分页(推荐):
{
"name": "sdk_call",
"arguments": {
"api_name": "daily",
"params": { "ts_code": "000001.SZ", "start_date": "20240101" },
"paginate": true,
"limit": 5000,
"max_rows": 20000,
"fields_preset": "basic",
"transform": "object"
}
}提示:MCP 的
paginate=true为顺序分页,带有指数退避与重试,更适合大数据抓取与限流环境。
在浏览器中使用
- SDK 为 ESM 包,可在现代打包器中直接使用。
- 出于安全考虑,请勿在前端直接暴露 Tushare Token。推荐通过后端代理转发请求;或为浏览器环境单独申请受限 token。
TypeScript 支持
- 项目默认严格类型检查(
no any)。 - 字段选择使用字面量数组(
as const)实现返回值的编译期收窄。 - 所有实体与参数类型来自代码生成(
src/generated),会随着接口的扩展而自动更新。
运行环境
- Node.js >= 18(内置 fetch)
- 或现代浏览器(通过打包器)
示例:更多选项
import { Tushare } from '@tushare/sdk';
const sdk = new Tushare('TOKEN', {
baseUrl: 'https://api.tushare.pro',
defaults: { transform: 'raw', cacheTtlMs: 0, timeoutMs: 10_000 }, // 中文注释:返回原始二维表
rateLimit: { windowMs: 1000, maxRequests: 60 }, // 中文注释:更保守的限流
maxRetries: 5,
backoffBaseMs: 100,
backoffFactor: 2,
backoffJitter: true,
});
const table = await sdk.auto.getStockBasic({ market: '主板', limit: 5 });
console.log(table);常见问题(FAQ)
- 字段名在哪里查?
- 参见 Tushare 官方文档;本包暴露的类型也可在编辑器悬浮查看。
- 返回值为什么有时是对象数组、有时是二维表?
- 由
defaults.transform或单次调用时的 transform 决定。'object'返回对象数组,'raw'返回原始表格。
- 由
- 为什么我的请求没有发送?
- 可能被内存缓存命中(TTL 内相同请求体只调用一次)。设置
cacheTtlMs: 0可禁用。
- 可能被内存缓存命中(TTL 内相同请求体只调用一次)。设置
