问题描述
get_fundamentals 如果参数只用了过滤条件,没有排序条件(没有order_by),是按照什么顺序返回的呢?
解决方案
在 JoinQuant(聚宽)量化平台中,使用 get_fundamentals 查询财务数据时,如果没有显式指定 order_by 排序条件,返回的数据顺序是不确定的(随机的)。
原理解析
get_fundamentals 底层使用的是 SQLAlchemy 来构建 SQL 查询语句,并从关系型数据库(如 MySQL)中获取数据。在关系型数据库的 SQL 标准中,如果查询语句没有包含 ORDER BY 子句,数据库引擎不保证返回结果的顺序。它通常会按照数据在磁盘上的物理存储顺序、索引顺序或者数据库缓存的读取顺序来返回,这意味着:
- 每次查询的顺序可能不同:即使是相同的查询条件,在不同的时间执行,返回的顺序也可能发生变化。
- 结合
limit使用时极度危险:由于get_fundamentals默认最多只返回 5000 条数据,如果你没有指定排序规则,截取出的前 5000 条数据将是随机的,这会导致你的策略在回测或模拟交易中产生不可预期的、不稳定的结果(即引入了随机性)。
最佳实践建议
为了保证策略的稳定性和结果的可复现性,强烈建议在调用 get_fundamentals 时,始终显式地加上 order_by 条件,特别是当你需要结合 limit 限制返回数量时。
正确的代码示例
如果你想选出市值大于 100 亿的股票,并取前 100 只,应该按照市值(或其他指标)进行明确排序:
# 导入聚宽函数库
from jqdata import *
def handle_data(context, data):
# 正确做法:显式指定按照总市值降序排列
q = query(
valuation.code,
valuation.market_cap
).filter(
valuation.market_cap > 100
).order_by(
valuation.market_cap.desc() # 明确指定降序排列
).limit(
100
)
df = get_fundamentals(q)
print(df)
总结:永远不要依赖数据库的默认返回顺序,写量化策略时,数据的确定性至关重要,请务必加上 order_by。