问题描述
解决方案
在 JoinQuant (聚宽) 平台上,要统计当前全市场有多少只股票上涨、多少只股票下跌,核心思路是:获取全市场所有股票的最新价,并与它们的昨日收盘价进行对比。
我们可以通过组合使用 get_all_securities、get_current_data 和 history 这几个 API 来实现。以下是具体的实现步骤和完整的策略代码。
实现思路
- 获取股票池:使用
get_all_securities(['stock'])获取全市场所有 A 股的代码列表。 - 过滤停牌股票并获取最新价:使用
get_current_data()获取当前时刻的快照数据,剔除掉处于停牌状态 (paused == True) 的股票,并记录正常交易股票的最新价 (last_price)。 - 获取昨日收盘价:使用
history(1, '1d', 'close', security_list)获取这些正常交易股票的昨日收盘价。 - 对比统计:遍历股票列表,将最新价与昨日收盘价进行对比,分别累加涨、跌、平盘的数量。
完整 Python 源码示例
您可以将以下代码直接复制到聚宽的回测环境中运行:
# 导入聚宽函数库
import jqdata
def initialize(context):
# 设定沪深300作为基准
set_benchmark('000300.XSHG')
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 每天 14:50 定时运行统计函数
run_daily(count_up_down_stocks, time='14:50')
def count_up_down_stocks(context):
# 1. 获取全市场所有股票代码
all_stocks = list(get_all_securities(['stock']).index)
# 2. 获取当前数据快照
current_data = get_current_data()
# 过滤出今天未停牌的股票
active_stocks = [stock for stock in all_stocks if not current_data[stock].paused]
# 3. 批量获取这些股票的昨日收盘价
# history 返回的 dict 中,key 为股票代码,value 为 numpy 数组
pre_closes = history(1, '1d', 'close', active_stocks, df=False)
# 初始化计数器
up_count = 0
down_count = 0
flat_count = 0
# 4. 遍历对比最新价和昨日收盘价
for stock in active_stocks:
# 获取最新价
last_price = current_data[stock].last_price
# 获取昨日收盘价
pre_close = pre_closes[stock][0]
# 比较并统计
if last_price > pre_close:
up_count += 1
elif last_price < pre_close:
down_count += 1
else:
flat_count += 1
# 打印统计结果
log.info(f"【{context.current_dt.strftime('%Y-%m-%d %H:%M')} 市场涨跌统计】")
log.info(f"正常交易股票总数: {len(active_stocks)} 只")
log.info(f"上涨家数: {up_count} 只")
log.info(f"下跌家数: {down_count} 只")
log.info(f"平盘家数: {flat_count} 只")
代码解析与注意事项
- 性能优化:在获取昨日收盘价时,我们使用了
history(..., df=False)。设置df=False会返回一个字典 (dict) 而不是 pandas.DataFrame,这在处理全市场数千只股票时,能显著提升数据读取和遍历的速度。 - 停牌处理:统计涨跌家数时,通常需要排除停牌的股票,因为它们的价格没有实际的日内波动意义。我们通过
current_data[stock].paused进行了有效过滤。 - 调用时机:
get_current_data()必须在交易时段内(如handle_data或盘中定时任务)调用才能获取到有意义的last_price。如果在盘前 (before_trading_start) 调用,last_price通常等于昨日收盘价。 - 复权影响:由于我们对比的是当天的最新价和昨日的收盘价,建议在
initialize中开启真实价格模式set_option('use_real_price', True),以避免除权除息日因复权因子跳变导致的计算误差。