问题描述
解决方案
在 QMT 中对一组股票进行批量买入和卖出,通常是通过 Python 的循环结构(for 循环)遍历股票列表,并针对每一个标的调用交易函数(如 order_shares、order_value 或 passorder)来实现的。
以下是一个完整的策略示例代码,展示了如何定义一个股票池,并实现“批量买入指定数量”和“批量清仓卖出”的功能。
策略代码示例
# -*- coding: gbk -*-
def init(ContextInfo):
"""
初始化函数
"""
# 1. 设置资金账号 (请替换为您的真实账号)
ContextInfo.accid = '6000000000'
ContextInfo.set_account(ContextInfo.accid)
# 2. 定义需要批量操作的股票列表
ContextInfo.stock_list = ['600000.SH', '000001.SZ', '600519.SH']
# 3. 设置一个标志位,防止在handlebar中重复下单(仅作演示用)
ContextInfo.has_traded = False
print("策略初始化完成,监控股票列表:", ContextInfo.stock_list)
def handlebar(ContextInfo):
"""
K线周期运行函数
"""
# 仅在最后一根K线(实时行情或回测结束点)执行,避免历史K线重复触发
if not ContextInfo.is_last_bar():
return
# 示例:只执行一次
if not ContextInfo.has_traded:
# --- 执行批量买入操作 ---
print("开始执行批量买入...")
batch_buy(ContextInfo, ContextInfo.stock_list, 100) # 每只买入100股
# --- 执行批量卖出操作 (通常根据逻辑触发,这里仅作代码展示,默认注释掉) ---
# print("开始执行批量卖出...")
# batch_sell_all(ContextInfo)
ContextInfo.has_traded = True
def batch_buy(ContextInfo, stock_list, volume):
"""
自定义函数:批量买入
:param stock_list: 股票代码列表
:param volume: 每只股票买入的股数
"""
account_id = ContextInfo.accid
for stock_code in stock_list:
# 使用 order_shares 按股数下单
# 参数说明: 代码, 数量, 报价类型('fix'指定价, 'LATEST'最新价), 价格(最新价模式下填-1), ContextInfo, 账号
# 这里使用 'LATEST' 最新价下单
order_shares(stock_code, volume, 'LATEST', -1, ContextInfo, account_id)
print(f"已发送买入指令: {stock_code}, 数量: {volume}")
def batch_sell_all(ContextInfo):
"""
自定义函数:批量卖出(清仓所有持仓)
"""
account_id = ContextInfo.accid
# 1. 获取当前持仓信息
# get_trade_detail_data 获取交易明细,'STOCK'代表股票,'POSITION'代表持仓
positions = get_trade_detail_data(account_id, 'STOCK', 'POSITION')
for pos in positions:
stock_code = pos.m_strInstrumentID + "." + pos.m_strExchangeID # 拼接代码,如 600000.SH
can_use_volume = pos.m_nCanUseVolume # 获取可用持仓(排除冻结)
if can_use_volume > 0:
# 卖出操作,数量为负数
order_shares(stock_code, -can_use_volume, 'LATEST', -1, ContextInfo, account_id)
print(f"已发送卖出指令: {stock_code}, 数量: {can_use_volume}")
else:
print(f"股票 {stock_code} 无可用持仓,跳过卖出")
代码逻辑解析
-
初始化 (
init):- 使用
ContextInfo.set_account绑定交易账号。 - 定义
ContextInfo.stock_list列表,存储需要批量操作的股票代码。
- 使用
-
批量买入 (
batch_buy):- 接收一个股票列表。
- 使用
for循环遍历列表。 - 调用
order_shares函数进行下单。示例中使用的是'LATEST'(最新价)模式,也可以改为'fix'(指定价)并传入具体价格。
-
批量卖出 (
batch_sell_all):- 获取持仓: 卖出前通常需要知道当前持有多少股。使用
get_trade_detail_data(..., 'POSITION')获取当前账户的所有持仓对象。 - 遍历持仓: 遍历返回的持仓对象列表。
- 拼接代码: 返回的对象中,代码(InstrumentID)和市场(ExchangeID)是分开的,需要拼接成 QMT 标准格式(如
600000.SH)。 - 检查可用: 使用
m_nCanUseVolume属性获取可用股份(防止卖出已冻结的股份)。 - 下单: 调用
order_shares,数量传入负数表示卖出。
- 获取持仓: 卖出前通常需要知道当前持有多少股。使用
-
执行控制 (
handlebar):- 使用
ContextInfo.is_last_bar()确保只在最新的行情切片上执行交易,防止在回测的历史数据加载阶段重复下单。
- 使用
常用交易函数说明
在批量操作中,您可以根据需求替换 order_shares 为其他函数:
order_shares(code, num, ...): 按股数下单(最常用)。order_value(code, value, ...): 按金额下单。例如每只股票买入 10000 元,系统会自动计算股数(向下取整到100股)。order_target_percent(code, percent, ...): 按目标仓位比例下单。例如将某股票调整至总资产的 5%。
Q&A
Q: 如何控制批量下单的速度,避免瞬间发送过多请求?
A: 可以在循环中引入 Python 的 time 模块,使用 time.sleep(0.1) 来在每次下单间增加微小的延迟。但在高频交易场景下不建议阻塞主线程。
Q: 如果我想用指定价格(例如限价)批量买入怎么办?
A: 在 order_shares 函数中,将 'LATEST' 改为 'fix',并将第四个参数 -1 改为您计算出的具体价格(例如 ContextInfo.get_market_data 获取的最新价 * 0.99)。
Q: 批量卖出时,如何只卖出列表中的股票,而不是卖出账户里所有的票?
A: 在 batch_sell_all 函数的循环中增加一个判断:if stock_code in ContextInfo.stock_list:。只有当持仓的股票在您的目标列表中时,才执行卖出操作。
Q: 这种方式支持组合交易(Basket Trading)吗?
A: 上述代码是应用层的批量循环,属于最灵活的方式。QMT 底层 API (passorder) 也支持组合交易指令(如 opType=25),但配置较为复杂,通常建议使用上述 Python 循环方式,便于调试和控制单只股票的逻辑。