🚀 AI 一键生成 joinquant 策略代码
立即体验
👉 AI 生成代码 👈

JoinQuant 中 get_fundamentals 没有 order_by 时按什么顺序返回?

joinquant | 发布时间: 2026/6/24
以下内容由 EasyQuant 生成。

问题描述

get_fundamentals返回数据的顺序问题

get_fundamentals 如果参数只用了过滤条件,没有排序条件(没有order_by),是按照什么顺序返回的呢?

解决方案

在 JoinQuant(聚宽)量化平台中,使用 get_fundamentals 查询财务数据时,如果没有显式指定 order_by 排序条件,返回的数据顺序是不确定的(随机的)

原理解析

get_fundamentals 底层使用的是 SQLAlchemy 来构建 SQL 查询语句,并从关系型数据库(如 MySQL)中获取数据。在关系型数据库的 SQL 标准中,如果查询语句没有包含 ORDER BY 子句,数据库引擎不保证返回结果的顺序。它通常会按照数据在磁盘上的物理存储顺序、索引顺序或者数据库缓存的读取顺序来返回,这意味着:

  1. 每次查询的顺序可能不同:即使是相同的查询条件,在不同的时间执行,返回的顺序也可能发生变化。
  2. 结合 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