Python SDK

为量化研究员量身打造的高性能 Python 数据客户端

PyPI v0.4.4
$ pip install quantdb-sdk
统一数据入口 client.data DataFrame 一等公民 DuckDB 极速直读 V2 按日分区直取 断点续传 Cursor AsyncIO 异步支持

SDK 设计理念 Design Principles

quantdb-sdk 封装了 QuantDB 的全量 RESTful 与对象存储直连接口,提供同步(QuantDBClient)和异步(AsyncQuantDBClient)两种调用方式。所有查询与下载接口直接产出经过清洗和类型转换的标准 pandas DataFrame,无缝对接 NumPy、Polars、Backtrader、Qlib 与 LightGBM 等研究框架。

安装与依赖 Installation

Bash
pip install quantdb-sdk

开发或贡献源码时,可从本地仓库执行可编辑安装:

Bash
# 安装核心依赖与开发测试组件
pip install -e ".[dev]"
批量下载性能指南:批量拉取多标的或多日切片时,建议使用 8 个工作线程并发下载(concurrent.futures.ThreadPoolExecutor(max_workers=8) 或 asyncio.Semaphore(8))。实测 8 线程可跑满千兆带宽,同时维持极低的本地内存与连接开销。服务端接口不限频,连续拉取数千文件不会触发 429 限制。

初始化客户端 Authentication

方式一:API Key 鉴权(强烈推荐)

通过环境变量读取 API Key,杜绝密钥泄露风险:

Python
import os
from quantdb_sdk import QuantDBClient

# 从环境变量 QUANTDB_API_KEY 获取凭据
client = QuantDBClient(api_key=os.environ["QUANTDB_API_KEY"])

方式二:账户密码登录(获取 24h JWT Bearer Token)

Python
client = QuantDBClient(
    username="trader01",
    password="your_secure_password"
)

核心方法一览 Method Matrix

账户与用量查询 Account & Usage

Python
# 查询已用流量与当前订阅状态(套餐额度与流量包额度分开返回)
usage = client.get_usage()
print(f"套餐:   已用 {usage['plan_used_gb']:.2f} / {usage['plan_total_gb']:.2f} GB,剩余 {usage['plan_remaining_gb']:.2f} GB")
print(f"流量包: 已用 {usage['package_used_gb']:.2f} / {usage['package_total_gb']:.2f} GB,剩余 {usage['package_remaining_gb']:.2f} GB")
print(f"合计:   已用 {usage['used_gb']:.2f} / {usage['total_gb']:.2f} GB,剩余 {usage['remaining_gb']:.2f} GB")
print(f"订阅状态: {usage['subscription'].get('status')}")

API Key 管理 Key Management

专业版用户支持 1 个有效 API Key。API Key 永久有效,可随时重新生成:

Python
# 列出已有 Key
keys = client.list_api_keys()

# 创建新 Key
new_key = client.create_api_key(description="Quant Server 01")
print(new_key["key"])

订阅与在线支付 Subscription & Orders

SDK 原生支持列出套餐、创建订单并拉起支付宝网页支付:

Python
# 1. 列出可购买套餐
plans = client.list_plans()
for p in plans:
    print(p["id"], p["name"], p["amount_yuan"])

# 2. 创建专业版月付订单(¥99 / 月)
order = client.create_order(plan_id="pro-monthly")
print("支付链接:", order["pay_url"])

# 3. 校验订单状态
status = client.get_order(order_id=order["order_id"])
print(status["status"])

V1 / V2 物理数据布局 Storage Architecture

QuantDB 针对不同数据特征采用最优物理存储策略:

纯 V2 按日分区数据集列表

数据集sub_category日期范围更新状态
日线不复权daily_unadjusted2016-01-04 ~ 至今每日更新
日线前复权daily_forward2016-01-04 ~ 至今每日更新
日线后复权daily_backward2016-01-04 ~ 至今每日更新
指数日线index_daily2016-01-04 ~ 至今每日更新
1 分钟 K 线min1_kline2016-01-04 ~ 至今每日更新
5 分钟 K 线min5_kline2016-01-04 ~ 至今每日更新
Tick 逐笔tick_data2026-09-03 起(按日)每日更新
ETF 日 K 线etf_kline2006-04-24 ~ 至今每日更新
估值指标valuation2016-01-04 ~ 至今每日更新
技术指标technical_indicators2016-01-04 ~ 至今每日更新
盘口情绪market_sentiment2016-01-04 ~ 至今每日更新
日频特征features_daily2016-01-04 ~ 至今每日更新
L1 日频因子l1_factors2016-01-04 ~ 至今每日更新
融资融券margin_trading2016-01-04 ~ 至今每日更新
L2 高频因子l2_factors2023-01-01 ~ 至今每日更新
训练宽表(300+ 维)l1_l2_factors2023-01-01 ~ 至今每日更新

client.data — 统一数据入口 0.4.0

client.data 是跨分类的统一取数入口:只凭 dataset 名即可访问全部 6 大分类目录,无需再手填 category_id + sub_category。SDK 侧自动解析分类并路由,同时覆盖在线查询与本地零流量读取。异步客户端对应 client.data(方法统一 a_ 前缀,如 a_read_local())。

发现与元数据(零流量)

Python
# 列出全部数据集(可按分类 / 访问级别 / 关键词过滤)
print(client.data.datasets().head())
print(client.data.datasets(category="6"))          # ML 数据集分类
print(client.data.datasets(keyword="复权"))

# 数据集详情 + 云端元数据(覆盖区间 / 文件数 / 文件大小)
print(client.data.info("l1_factors"))

在线查询与本地零流量读取

Python
# 在线查询:按数据集名自动路由(日线 / ETF / Tick / V2 / V1)
df = client.data.query(
    "daily_forward", symbol="600519.SH",
    start_date="2026-09-01", end_date="2026-09-05"
)
tick = client.data.query("tick_data", symbol="600519.SH", trade_date="20260924")

# 本地零流量读取(root 缺省读 QUANTDB_DATA_DIR,可显式指定)
local = client.data.read_local("daily_forward", start_date="2026-09-01")
paths = client.data.local_files("balance", symbol="600519.SH")

# 本地优先,缺失时才显式回退在线(会消耗流量)
df2 = client.data.read("valuation", symbol="600519.SH", prefer="local")

# 其余映射:preview / load / download / sync / mount
client.data.preview("balance", symbol="600519.SH", limit=5)
零流量原则:datasets() / info() / local_files() / local_path() / read_local() 全程不发起下载;read() 默认本地优先,仅在本地缺失时才回退在线,避免静默消耗流量。

query_kline — K 线数据查询 Data Query

Python
# 查询贵州茅台前复权日线(返回 DataFrame)
df = client.query_kline(
    symbol="600519.SH",
    adj_type="forward",
    start_date="2026-01-01",
    end_date="2026-07-22"
)
print(df.head())

# 仅查询收盘价与成交量字段
df_mini = client.query_kline("000001.SZ", fields="close,volume", limit=20)

query_etf_kline — ETF 日 K 线查询 ETF Kline

查询分类 4 的 etf_kline(V2 按日分区,symbol 形如 510300.SH)。auto 优先 V2 日切片,日期范围覆盖不完整时回退 V1 逐股票文件。

Python
# 查询沪深 300 ETF 日 K 线
df_etf = client.query_etf_kline(
    symbol="510300.SH",
    start_date="2026-09-01",
    end_date="2026-09-03"
)
print(df_etf.head())

query_partition_size — 各子分类分区大小 0.3.5

查询各数据子分类的分区大小,用于估算下载流量与数据占用。返回分区数 file_count、总字节 file_size 与换算列 file_size_gb;缺省返回全部子分类,可传 sub_category 单查。异步版为 a_query_partition_size()。

Python
# 查询全部子分类的分区大小
df_sizes = client.query_partition_size()
print(df_sizes[["dimension", "file_count", "file_size_gb"]].to_string(index=False))

# 只查 daily_forward 一个子分类的字节数(用于评估该数据集下载流量)
df_one = client.query_partition_size(sub_category="daily_forward")
print(df_one)

query_tick — Tick 分笔高频数据 High Frequency

Python
# 下载平安银行指定交易日五档 Tick 数据
df_tick = client.query_tick(
    symbol="000001.SZ",
    trade_date="20260720",
    start_ts="09:30:00",
    end_ts="11:30:00"
)
print(df_tick.head())

sync_dataset — 本地增量同步 Incremental Sync

通过服务端的 Release Cursor 实现微秒级差异比对。支持断点续传、临时文件原子替换与本地 MD5 对账跳过:

Python
# 首次同步自动初始化本地 quantdb_sync.sqlite 元数据库
result = client.sync_dataset("daily_forward", save_dir="D:/quantdb-data")
print(f"已下载: {len(result['downloaded'])} 个, 对账跳过: {len(result['matched'])} 个")

# 财务表增量同步(支持断点重试)
financial = client.sync_dataset("balance", save_dir="D:/quantdb-data")

# ETF 日线增量同步(0.3.5 起支持)
etf = client.sync_dataset("etf_kline", save_dir="D:/quantdb-data")

DuckDBWarehouse — 本地极速 SQL 引擎 Local DuckDB Engine

将本地已同步的多个 Parquet 数据集注册为内存 DuckDB 视图,零流量毫秒级执行复杂多表关联(SQL JOIN):

Python
from quantdb_sdk import QuantDBClient, DuckDBWarehouse

client = QuantDBClient(api_key=os.environ["QUANTDB_API_KEY"])
wh = client.get_local_warehouse()

# 挂载日线行情与财务利润表为本地 View
wh.mount_dataset("1", "daily_unadjusted", symbol="600519.SH", view_name="kline")
wh.mount_dataset("3", "income", symbol="600519.SH", view_name="income")

# 零流量本地 SQL JOIN 查询
df_join = wh.query("""
    SELECT k.trade_date, k.close, i.net_profit_excl_min_int_inc 
    FROM kline k 
    LEFT JOIN income i ON k.trade_date = i.m_anntime
    ORDER BY k.trade_date DESC
    LIMIT 20
""")
print(df_join)

300+ 维 ML 特征宽表装载 AI / ML Training

Python
# 一键将 300+ 维预计算模型训练宽表装入内存
df_factors = client.load_as_df(category_id="6", sub_category="l1_l2_factors", symbol="train_factors_2026q1")
print(df_factors.shape)  # (175217 行, 367 列)

# 直接喂入 LightGBM 训练
import lightgbm as lgb
feature_cols = [c for c in df_factors.columns if c not in ["wind_code", "date", "target_5d"]]
train_data = lgb.Dataset(df_factors[feature_cols], label=df_factors["target_5d"])
model = lgb.train({}, train_data, num_boost_round=100)

AsyncQuantDBClient — 异步高并发 AsyncIO

Python
import asyncio
from quantdb_sdk import AsyncQuantDBClient

async def main():
    client = AsyncQuantDBClient(api_key=os.environ["QUANTDB_API_KEY"])

    # 异步并发请求多只股票日线
    tasks = [
        client.a_query_kline("600519.SH", adj_type="forward"),
        client.a_query_kline("000858.SZ", adj_type="forward"),
        client.a_query_stock_list(keyword="芯片"),
    ]
    results = await asyncio.gather(*tasks)
    for df in results:
        print(df.shape)

asyncio.run(main())

典型策略场景实战 Strategy Recipes

场景:双均线金叉策略回测

Python
import pandas as pd

df = client.query_kline("600519.SH", adj_type="forward", start_date="2025-01-01")
df["ma5"] = df["close"].rolling(5).mean()
df["ma20"] = df["close"].rolling(20).mean()

# 信号生成:MA5 上穿 MA20 买入,下穿卖出
df["signal"] = 0
df.loc[df["ma5"] > df["ma20"], "signal"] = 1
df.loc[df["ma5"] < df["ma20"], "signal"] = -1

df["strat_ret"] = df["signal"].shift(1) * df["close"].pct_change()
print(f"累计收益: {(1 + df['strat_ret']).cumprod().iloc[-1]:.2%}")