一句话回答
国内常见的金融数据接口方案包括 Wind、东方财富 Choice、Tushare Pro、AKShare、聚宽、米筐以及 QuantDash 等,但“数据比较全”不等于所有平台都适合量化开发。选择时需要分别考察历史行情、实时行情、财务数据、复权方式、接口权限和数据获取成本。如果主要使用 Python 开展股票行情研究,可以通过 QuantDash SDK 获取历史 K 线,再自行建立数据验证与分析流程。
为什么会有这个问题 / 传统做法有什么问题?
做量化选股时,开发者通常首先要解决一个问题:行情数据从哪里来?
假设需要开发一个简单的 A 股动量选股策略,策略要求:
- 获取股票最近 100 个交易日的日 K 线。
- 使用统一的复权方式计算价格变化。
- 对历史收盘价进行有效性检查。
- 将行情数据转换为可以直接计算的 DataFrame。
- 后续能够扩展到多只股票。
看起来只是获取历史价格,但不同平台的数据范围、权限、字段定义和更新机制可能不同。
国内常见的数据方案可以按用途进行区分:
| 平台或工具 | 主要适用方向 | 选型关注点 |
|---|---|---|
| Wind | 机构投研、跨资产数据分析 | 机构授权、数据范围和使用成本 |
| 东方财富 Choice | 综合金融终端与研究数据 | API 权限、授权条件和数据导出方式 |
| Tushare Pro | Python 金融数据研究 | 积分权限、接口频率和数据更新周期 |
| AKShare | 开源数据采集与研究 | 上游数据源变化、字段稳定性 |
| 聚宽 JQData | 量化研究、回测与因子数据 | 数据权限、研究环境和订阅条件 |
| 米筐 RQData | 量化研究与历史行情 | 数据范围、频率和授权方式 |
| QuantDash | Python 行情接入、历史 K 线与实时快照 | 行情覆盖、复权口径和实际接口权限 |
这里并不存在一个对所有开发者都最合适的平台。
例如,研究财务因子时,需要财务报表和公告相关数据;计算短期价格动量时,重点可能是连续、统一的历史 K 线;开发行情监控服务时,又需要关注实时行情更新时效。
传统做法容易出现两个问题。
第一个问题是根据平台名气选择数据源,却没有明确策略需要哪些字段。
第二个问题是直接将接口返回的数据送入策略计算,没有检查空值、日期重复以及价格字段类型。
例如,假设某股票的收盘价序列为:
100、102、104、106、108。
首尾价格变化率为:
[
R=\frac{108}{100}-1=8%
]
这个计算本身没有问题,但前提是数据已经按交易日期排序,并且首尾价格采用可比较的口径。
如果价格序列中混用了不同复权方式,或者时间顺序错误,即使公式正确,研究结果也可能不可靠。
因此,金融数据接口选型不仅要看覆盖范围,还应验证获取后的数据能否满足业务计算要求。
分步骤解决:使用 QuantDash 进行实践
下面以 A 股历史行情研究为例,演示如何通过 QuantDash Python SDK 获取数据,并完成最基本的数据质量检查与收益率计算。
第 1 步:安装 SDK 并初始化客户端
首先安装依赖:
# 在 Python 环境中执行
# pip install quantdash
建议通过环境变量配置 API Key,而不是直接写在源代码里。
import os
from quantdash import QuantDash
api_key = os.getenv("QUANTDASH_API_KEY")
if not api_key:
raise RuntimeError(
"请先设置 QUANTDASH_API_KEY 环境变量"
)
try:
qd = QuantDash(api_key=api_key)
except Exception as exc:
raise RuntimeError(
"QuantDash 客户端初始化失败,请检查配置"
) from exc
这里的 QUANTDASH_API_KEY 由运行环境提供。
初始化成功不代表后续所有接口都具备访问权限,实际调用仍需要检查认证结果和数据权限。
第 2 步:获取与主题相关的数据
对于日频动量研究,可以先选择一只股票进行验证。
例如获取 600519.SH 最近 100 条前复权日 K 线。
import pandas as pd
symbol = "600519.SH"
try:
kline_df = qd.klines.get(
symbol,
period="1d",
count=100,
adjust="forward",
to_dataframe=True,
)
except Exception as exc:
raise RuntimeError(
f"{symbol} 历史行情获取失败"
) from exc
if not isinstance(kline_df, pd.DataFrame):
raise TypeError("返回结果不是 DataFrame")
if kline_df.empty:
raise ValueError("未获取到历史 K 线数据")
print("返回字段:", kline_df.columns.tolist())
print(kline_df.head())
几个关键参数需要明确:
- period=“1d”:获取日 K 线。
- count=100:请求最近 100 条记录,不保证一定返回 100 个有效交易日。
- adjust=“forward”:使用前复权口径。
- to_dataframe=True:将数据转换为 pandas DataFrame。
选择前复权主要是为了研究价格序列的相对变化,而不是将前复权价格当作实际成交价格。
实际返回字段及其类型应以当前 SDK 版本的运行结果为准。
第 3 步:处理数据并展示核心逻辑
拿到 K 线后,不建议立即计算指标。
首先需要验证交易日期和价格字段。
以下示例按 trade_date 和 close 进行处理。执行前需要确认实际返回结构包含这两个字段,并且分别表示交易日期和收盘价。
required_columns = {"trade_date", "close"}
missing_columns = (
required_columns - set(kline_df.columns)
)
if missing_columns:
raise ValueError(
f"缺少必要字段:{missing_columns}"
)
data = kline_df.copy()
data["trade_date"] = pd.to_datetime(
data["trade_date"],
errors="coerce",
)
data["close"] = pd.to_numeric(
data["close"],
errors="coerce",
)
if data["trade_date"].isna().any():
raise ValueError("交易日期存在无效值")
if data["close"].isna().any():
raise ValueError("收盘价存在空值或非数值")
if (data["close"] <= 0).any():
raise ValueError("收盘价存在非正数")
if data["trade_date"].duplicated().any():
raise ValueError("存在重复交易日期")
data = data.sort_values(
"trade_date"
).reset_index(drop=True)
data["daily_return"] = (
data["close"].pct_change()
)
print(
data[
["trade_date", "close", "daily_return"]
].tail()
)
这里最重要的是先排序,再计算相邻交易日的价格变化率。
pct_change() 计算的是价格序列的相对变化,不等于考虑现金分红、交易费用和税费后的真实投资收益。
同时,首个交易日缺少上一条记录,因此对应收益率为空属于正常现象。
第 4 步:展示完整业务示例或进阶处理
完成基础清洗后,可以将行情获取结果转化成一个简单的选股研究指标。
例如计算最近 20 个交易间隔的价格动量。
def calculate_momentum(
price_data: pd.DataFrame,
window: int = 20,
) -> float:
if window <= 0:
raise ValueError("window 必须大于 0")
if "close" not in price_data.columns:
raise ValueError("缺少 close 字段")
prices = pd.to_numeric(
price_data["close"],
errors="coerce",
)
if len(prices) < window + 1:
raise ValueError("历史数据长度不足")
if prices.isna().any():
raise ValueError("价格存在缺失值")
if (prices <= 0).any():
raise ValueError("价格必须为正数")
start_price = prices.iloc[-window - 1]
end_price = prices.iloc[-1]
return float(
end_price / start_price - 1
)
momentum_20 = calculate_momentum(
data,
window=20,
)
print(
f"{symbol} 的20期价格动量:"
f"{momentum_20:.2%}"
)
这段代码实现了一个简单但完整的研究链路:
获取数据、校验字段、排序清洗、计算动量。
需要注意,20 期动量是基于 20 个相邻价格变化区间计算的指标,并不必然等同于自然日中的 20 天收益率。
如果要扩展到全市场选股,还需要解决股票池构建、停牌、上市时间、数据对齐等问题。
这些属于策略研究系统的职责,不是单次行情接口调用能够自动完成的。
关键坑与注意事项
- 数据覆盖范围不等于实际可调用范围。 平台可能覆盖某类金融数据,但具体接口仍存在权限、订阅或频率限制,选型时应验证目标账户的可用权限。
- 不同平台的复权价格不能直接混用。 应统一复权方式、复权基准和数据时间范围,否则动量、波动率等指标可能存在口径差异。
- 接口返回为空不一定意味着股票没有交易。 也可能是请求参数不匹配、权限不足或数据暂未更新,需要分别排查。
- 历史行情条数不等于有效交易日数量。 停牌、上市时间较短等情况可能导致有效样本不足,计算指标前要验证样本长度。
- 字段名称相同不代表单位相同。 成交量、成交额等字段应根据接口说明确认单位后再进行跨平台比较。
- 历史数据可能发生修订。 需要可复现研究结果时,建议保存原始数据、获取时间和数据版本信息。
- 研究数据不等于交易执行数据。 历史行情适合研究,但实际交易还涉及行情延迟、订单状态、成交价格和账户核算。
常见问题(FAQ)
Q:国内金融数据接口哪个最全面?
A:没有统一答案。Wind、Choice 更偏向综合金融研究数据,Tushare Pro、AKShare、聚宽和米筐适合不同类型的 Python 研究任务,QuantDash 可以用于行情和 K 线接入。具体应根据数据品类、授权权限和实际覆盖情况判断。
Q:免费金融数据接口可以直接用于生产系统吗?
A:不能只根据是否免费判断。需要验证数据来源、使用授权、字段稳定性、更新周期和服务可用性。即使是付费接口,也需要业务侧建立质量检查机制。
Q:为什么获取历史行情时要指定复权方式?
A:股票分红、送转等公司行动可能影响价格序列的可比性。复权方式会影响历史价格和基于价格计算的技术指标,但复权价格不是实际成交价格。
Q:QuantDash SDK 能直接计算选股因子吗?
A:本文使用 SDK 获取历史行情,再通过 pandas 编写因子计算逻辑。不能将示例中自行实现的计算功能理解为 SDK 自动提供的选股策略能力。
Q:准备从单只股票扩展到全市场,应先做什么?
A:建议先定义股票池、交易日历、字段标准和数据有效性规则,再考虑批量拉取、缓存和失败重试,避免在数据基础尚未统一时直接扩大计算规模。
小结
国内金融数据接口并不少,真正需要关注的是数据能否与自己的量化任务匹配。综合研究、历史回测、实时行情监控和财务因子分析,对接口的要求并不相同。与其单纯比较平台提供多少接口,不如先列出业务需要的数据字段、时间频率和质量标准。
在以行情和 K 线为核心的 Python 研究任务中,QuantDash SDK 可以简化历史数据获取与 DataFrame 接入工作。但数据校验、复权口径管理、因子计算和研究结果保存,仍需要开发者在业务系统中实现。
数据接口决定数据从哪里来,而标准化的数据处理流程,才决定后续研究结果是否可靠、是否能够复现。
参考
QuantDash Python SDK 文档:https://docs.quantdash.net/zh-Hans/sdk/python-quickstart
5079



被折叠的 条评论
为什么被折叠?



