3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
这是一个基于 QMT 平台的动态选股策略脚本。
该脚本实现了以下筛选逻辑:
ContextInfo.set_universe)。# -*- coding: gbk -*-
import pandas as pd
import numpy as np
def init(ContextInfo):
"""
初始化函数
"""
print("策略初始化...")
# 设置基准,这里设为沪深300
ContextInfo.benchmark = '000300.SH'
# 设定初始股票池为空,后续动态更新
ContextInfo.set_universe([])
# 定义筛选参数
ContextInfo.target_sector = '沪深300' # 基础板块
ContextInfo.pe_min = 0 # 最小市盈率
ContextInfo.pe_max = 30 # 最大市盈率
ContextInfo.ma_period = 20 # 均线周期
def handlebar(ContextInfo):
"""
K线周期运行函数
"""
# 为了避免盘中每个Tick都计算,我们只在K线生成的新Bar时计算
# 如果是回测模式,每根K线都会触发;如果是实盘,建议配合定时器或is_new_bar使用
if not ContextInfo.is_new_bar():
return
# 获取当前K线的时间
current_date = timetag_to_datetime(ContextInfo.get_bar_timetag(ContextInfo.barpos), '%Y%m%d')
print(f"当前日期: {current_date},开始执行选股...")
# 1. 获取基础股票池 (沪深300)
stock_list = ContextInfo.get_stock_list_in_sector(ContextInfo.target_sector)
if not stock_list:
print("未获取到板块成分股")
return
# 2. 剔除 ST 和 停牌股
valid_stocks = []
for code in stock_list:
# 剔除停牌
if ContextInfo.is_suspended_stock(code):
continue
# 剔除 ST / *ST
name = ContextInfo.get_stock_name(code)
if 'ST' in name:
continue
valid_stocks.append(code)
if not valid_stocks:
print("剔除ST和停牌后无剩余股票")
return
# 3. 获取基本面数据 (PE - 市盈率)
# 使用 get_factor_data 获取因子数据
# 字段: Valuation_and_Market_Cap.PE (市盈率)
factor_fields = ['Valuation_and_Market_Cap.PE']
# 注意:get_factor_data 获取的是时间序列数据,我们需要取最后一天
# 这里简单处理,start和end都设为当前日期
factor_data = ContextInfo.get_factor_data(
factor_fields,
valid_stocks,
current_date,
current_date
)
# 筛选 PE 符合条件的股票
fundamental_select = []
# 处理返回的数据格式,通常是 Dict 或 DataFrame
# 如果返回的是 Dict {code: df}
if isinstance(factor_data, dict):
for code in valid_stocks:
if code in factor_data:
df = factor_data[code]
if not df.empty:
pe_val = df['Valuation_and_Market_Cap.PE'].iloc[-1]
if ContextInfo.pe_min < pe_val < ContextInfo.pe_max:
fundamental_select.append(code)
# 如果返回的是 DataFrame (视版本和参数而定)
elif isinstance(factor_data, pd.DataFrame):
# 这里假设是 Panel 转成的 DF 或者直接是 DF,具体需根据实盘调试
# 为保证稳健性,建议使用上面的 dict 遍历方式,或者打印 type(factor_data) 确认
pass
if not fundamental_select:
print("基本面筛选后无股票")
return
# 4. 获取技术面数据 (收盘价 和 均线)
# 获取过去 ma_period + 5 天的数据,确保能计算出 MA
market_data = ContextInfo.get_market_data_ex(
['close'],
fundamental_select,
period='1d',
count=ContextInfo.ma_period + 1,
dividend_type='front' # 前复权
)
final_pool = []
for code in fundamental_select:
if code in market_data:
df_price = market_data[code]
if len(df_price) >= ContextInfo.ma_period:
# 计算 MA20
ma_value = df_price['close'].rolling(window=ContextInfo.ma_period).mean().iloc[-1]
current_price = df_price['close'].iloc[-1]
# 筛选:收盘价 > 20日均线
if current_price > ma_value:
final_pool.append(code)
# 5. 更新股票池
print(f"选股完成,共选中 {len(final_pool)} 只股票")
if len(final_pool) > 0:
print(f"部分选中股票示例: {final_pool[:5]}")
# 将选出的股票设定为当前的 ContextInfo 股票池
# 后续的交易函数可以直接对这个池子进行操作
ContextInfo.set_universe(final_pool)
# 可选:在这里直接根据 final_pool 进行买卖操作
# rebalance_portfolio(ContextInfo, final_pool)
# -*- coding: gbk -*-:
ContextInfo.get_stock_list_in_sector:
ContextInfo.get_factor_data:
Valuation_and_Market_Cap.PE 是市盈率因子。如果需要市净率可以使用 Valuation_and_Market_Cap.PB。ContextInfo.get_market_data_ex:
count=ContextInfo.ma_period + 1:为了计算 20 日均线,我们需要至少 20 根 K 线的数据。dividend_type='front':技术分析通常使用前复权数据,以消除分红配股对价格走势的干扰。ContextInfo.set_universe(final_pool):
get_universe())获取到的列表。Q: 如何修改筛选条件,例如改成筛选市净率(PB)小于 2 的股票?
A: 修改 init 函数中的参数,并更改 get_factor_data 的字段。
init 中添加 ContextInfo.pb_max = 2。factor_fields 改为 ['Valuation_and_Market_Cap.PB']。df['Valuation_and_Market_Cap.PB'].iloc[-1] < ContextInfo.pb_max。Q: 为什么 get_factor_data 返回的数据是空的?
A: 这通常是因为本地没有下载多因子数据。请在 QMT 客户端顶部菜单栏找到【数据】->【数据管理】,选择【多因子数据】,勾选对应的市场和时间段进行下载补充。
Q: 这个脚本会自动买入选中的股票吗?
A: 目前的代码只负责筛选(生成股票池)。如果需要自动交易,需要在 handlebar 函数的最后添加交易逻辑,例如遍历 final_pool 调用 passorder 或 order_target_value 函数进行下单。