3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 JoinQuant (聚宽) 平台中,底层使用的是 SQLAlchemy 来构建数据库查询。当您使用 func 进行聚合计算并使用 .label() 命名后,想要对这个新生成的字段进行排序,通常有两种最直接有效的方法。
order_by 中重复聚合表达式(推荐)这是最稳妥且兼容性最好的方法。直接将计算 avg_pe 的表达式放入 .order_by() 中,并调用 .desc()(降序)或 .asc()(升序)。
from jqdata import *
from sqlalchemy.sql import func
# 构建查询
q = query(
valuation.day,
(func.count() / func.sum(1 / valuation.pe_ratio)).label('avg_pe')
).filter(
valuation.pe_ratio > 0
).group_by(
valuation.day
).order_by(
# 直接使用相同的表达式进行排序,这里以倒序(desc)为例
(func.count() / func.sum(1 / valuation.pe_ratio)).desc()
).limit(10)
# 获取数据
df = get_fundamentals(q, date='2023-01-01')
print(df)
sqlalchemy.text 或 sqlalchemy.desc 引用 label 名称如果您觉得重复写表达式太长,可以导入 SQLAlchemy 的相关模块,直接通过字符串引用您定义的 label 名称。
from jqdata import *
from sqlalchemy.sql import func
from sqlalchemy import desc, text
# 构建查询
q = query(
valuation.day,
(func.count() / func.sum(1 / valuation.pe_ratio)).label('avg_pe')
).filter(
valuation.pe_ratio > 0
).group_by(
valuation.day
).order_by(
# 使用 text 引用 label 名称进行排序
text('avg_pe DESC')
# 或者使用 desc(text('avg_pe'))
).limit(10)
# 获取数据
df = get_fundamentals(q, date='2023-01-01')
print(df)
group_by 是必须的:当您使用了聚合函数(如 func.count(), func.sum())并且查询中还包含非聚合字段(如 valuation.day)时,必须加上 .group_by(valuation.day),否则 SQL 语法会报错或返回非预期结果。valuation.pe_ratio > 0 过滤了负数和零,但在实际应用中,如果某一天没有任何符合条件的股票,func.sum 可能返回 NULL,导致除法报错。在 JoinQuant 的 get_fundamentals 中通常会自动处理,但需留意数据清洗。get_fundamentals 中进行复杂的聚合计算可能会比较慢,如果查询超时,建议先取出基础数据(如 pe_ratio),然后使用 Pandas 在内存中进行 groupby 和聚合计算。