🚀 AI 一键生成 qmt 策略代码

QMT set_universe 高级用法:结合板块与指数构建动态股票池

qmt | 发布时间: 2025/12/29
以下内容由 EasyQuant 生成。

问题描述

可以在 init 函数里动态设置股票池吗?比如只选沪深300成分股。

解决方案

是的,可以在 init 函数中动态设置股票池。这是 QMT 策略编写中非常标准的做法。

您可以使用 ContextInfo.get_stock_list_in_sector(根据板块名称)或 ContextInfo.get_sector(根据指数代码)来获取成分股列表,然后将其传递给 ContextInfo.set_universe

以下是具体的代码实现示例:

动态设置沪深300成分股示例代码

# -*- coding: gbk -*-

def init(ContextInfo):
    """
    策略初始化函数
    """
    print("正在初始化策略...")
    
    # 方法一:使用板块名称获取(推荐用于 '沪深300'、'上证50' 等明确板块名)
    # 注意:第二个参数是时间戳,不填默认取当前最新成分股
    stock_list = ContextInfo.get_stock_list_in_sector('沪深300')
    
    # 方法二:使用指数代码获取(如果您更习惯使用代码,如 000300.SH)
    # stock_list = ContextInfo.get_sector('000300.SH')
    
    # 打印获取到的股票数量,用于验证
    print(f"获取到沪深300成分股数量: {len(stock_list)}")
    
    # 关键步骤:将获取到的列表设置为策略的股票池
    ContextInfo.set_universe(stock_list)
    
    # 设置其他回测参数(可选)
    ContextInfo.set_account('account_id') # 设置账号
    
def handlebar(ContextInfo):
    """
    行情驱动函数
    """
    # 获取当前设置的股票池
    universe = ContextInfo.get_universe()
    
    # 简单示例:打印当前K线位置和股票池第一只股票代码
    if ContextInfo.is_new_bar():
        print(f"当前Bar位置: {ContextInfo.barpos}, 股票池首只股票: {universe[0] if universe else '空'}")

关键函数说明

  1. ContextInfo.get_stock_list_in_sector(sectorname, realtime):

    • 用途: 获取指定板块(如“沪深300”、“主板”、“创业板”等)的成分股列表。
    • 参数: sectorname 为板块名称字符串;realtime 为毫秒级时间戳(可选),不填则默认为最新成分股。
  2. ContextInfo.get_sector(sector, realtime):

    • 用途: 获取指数成分股(如 '000300.SH')。
    • 参数: sector 为指数代码(如 '000300.SH');realtime 同上。
  3. ContextInfo.set_universe(stocklist):

    • 用途: 将一个股票代码列表设置为当前策略的股票池。
    • 作用:
      • 回测模式: handlebar 函数会针对股票池中的数据进行驱动(取决于数据下载情况和运行机制)。
      • 实盘/模拟: 系统会自动订阅这些股票的行情数据。

注意事项

  • 数据补充: 在回测之前,请确保您已经通过“数据管理”下载了沪深300成分股的历史行情数据,否则 handlebar 可能因为没有数据而不运行或报错。
  • 历史成分股: 如果您在回测中需要动态获取历史某时刻的成分股(例如防止幸存者偏差,即只选了现在是沪深300的股票,而忽略了历史上被剔除的),您需要在 handlebar 中配合时间戳调用 get_sector,或者在 init 中不填时间戳(默认最新)。通常简单的策略在 init 中设置最新成分股即可,但严谨的回测可能需要处理成分股变动。

Q&A

Q: ContextInfo.set_universe 设置的股票池有数量限制吗?
A: QMT 平台本身对 Python 策略的股票池大小没有硬性的小额限制,可以放入几千只股票(如全A股)。但在实盘运行时,订阅过多的股票行情(如超过 3000 只)可能会消耗较多的内存和网络带宽,建议根据硬件配置量力而行。

Q: 如果我想把“沪深300”和“中证500”合并在一起怎么做?
A: 您可以分别获取两个列表,然后使用 Python 的列表相加功能,例如:

list1 = ContextInfo.get_stock_list_in_sector('沪深300')
list2 = ContextInfo.get_stock_list_in_sector('中证500')
# 合并并去重
full_list = list(set(list1 + list2))
ContextInfo.set_universe(full_list)

Q: init 函数只会运行一次吗?
A: 是的,init(ContextInfo) 在策略启动(点击运行或回测)时只运行一次。因此,它是进行静态股票池设置、全局变量初始化、账号绑定的最佳位置。