今天继续更新qmt的使用教程,前面更新了2qmt教程--qmt常见量化问题解答2
1如何使用Python在QMT中进行一篮子股票买卖?
主要使用set_basket和passorder(或algo_passorder)配合实现。
- **配置篮子结构**:使用set_basket函数设置一个篮子,包含多只股票及其权重、数量、买卖方向。
- **执行篮子交易**:调用passorder函数,将orderType参数设置为篮子交易对应的代码(如1102代表按篮子权重下单),并将orderCode参数指定为篮子名称。
文档7qmt中如何使用python进行一篮子买卖.txt提供了具体的代码示例,包括按数量下单和按权重下单两种方式。

简单参考
#coding:gbk
"""
大QMT 一篮子股票买卖完整示例
演示了使用 set_basket 配置篮子,以及用 passorder 执行按数量和按权重大下单的两种方式。
仅作学习使用,不构成投资建议。
"""
def init(C):
# 请将 'your_account' 替换为您的实际资金账号
account = 'your_account'
# =========================================================================
# 方式一:按篮子中设定的【股票数量】下单
# =========================================================================
# 1. 定义一个篮子表格,包含股票代码、权重、数量、买卖方向
table1 = [
{'stock': '6000.SH', 'weight': 0.11, 'quantity': 100, 'optType': 23}, # optType=23 表示买入
{'stock': '6028.SH', 'weight': 0.11, 'quantity': 200, 'optType': 24}, # optType=24 表示卖出
]
basket1 = {'name': 'basket1', 'stocks': table1}
# 2. 设置篮子
set_basket(basket1)
# 3. 执行篮子交易,下单2份篮子
# orderType=2101 表示按组合股票数量下单,volume的单位是“篮子的份数”
pice = 2 # 下2份,即:买入200股600.SH,卖出400股6028.SH
passorder(
35, # opType=35 表示“一键买卖” (同时买入和卖出)
2101, # orderType=2101 按组合股票数量(份)下单
account, # 资金账号
'basket1', # orderCode 篮子名称
5, # prType=5 最新价下单
1, # price 最新价时该参数无效,填任意数占位
pice, # volume 篮子份数
'', # strategyName 策略名(可选)
2, # quickTrade=2 立即触发下单
'按数量下单', # userOrderId 投资备注
C # ContextInfo
)
print("已发出篮子交易(按数量):basket1,份数:", pice)
# =========================================================================
# 方式二:按篮子中设定的【股票权重】下单(按金额分配)
# =========================================================================
# 1. 定义一个篮子表格,重点是设置 weight(权重),quantity 设为0
table2 = [
{'stock': '60.SH', 'weight': 0.4, 'quantity': 0, 'optType': 23}, # 40% 资金买入
{'stock': '608.SH', 'weight': 0.6, 'quantity': 0, 'optType': 24}, # 60% 资金卖出
]
basket2 = {'name': 'basket2', 'stocks': table2}
# 2. 设置篮子
set_basket(basket2)
# 3. 执行篮子交易,指定总金额
# orderType=2102 表示按组合股票权重下单,volume的单位是“元”
money = 10000 # 总额10000元
passorder(
35, # opType=35 一键买卖
2102, # orderType=2102 按组合股票权重(金额)下单
account, # 资金账号
'basket2', # orderCode 篮子名称
5, # prType=5 最新价下单
1, # price 占位
money, # volume 总金额(元)
'', # strategyName
2, # quickTrade=2 立即下单
'按权重下单', # userOrderId
C # ContextInfo
)
print("已发出篮子交易(按权重):basket2,总金额:", money)
# =========================================================================
# 额外提示:如果您希望使用算法交易(拆单),可以用 algo_passorder 替代 passorder
# 如下面这段注释掉的代码所示:
# =========================================================================
"""
import time
userparam = {
'OrderType': 1, # 表示要下算法
'PriceType': 4, # 卖5价下单
'MaxOrderCount': 12, # 最大委托次数
'SuperPriceType': 0, # 超价类型,0表示按比例
'SuperPriceRate': 0, # 超价比例
'VolumeRate': 1, # 单笔下单比率
'VolumeType': 10, # 单笔基准量类型
'SingleNumMax': 1000000, # 单笔拆单最大值
'ValidTimeStart': int(time.time()),
'ValidTimeEnd': int(time.time() + 60 * 60),
}
# 按篮子数量下单的算法版本
algo_passorder(35, 2101, account, 'basket1', -1, -1, pice, '', 2, '普通算法', userparam, C)
# 按篮子权重下单的算法版本
algo_passorder(35, 2102, account, 'basket2', -1, -1, money, '', 2, '组合算法', userparam, C)
"""
def handlebar(C):
"""
本示例没有在handlebar中处理逻辑,
因为init中已通过quickTrade=2实现了立即下单。
"""
pass

2如何设置定时器,在盘中定时执行某些判断或交易?
使用ContextInfo.run_time(period, callback, startTime='')函数。
- period:时间间隔(秒)。
- callback:用户自定义的回调函数名(该函数需要自己定义)。
- startTime:首次运行的时间点(格式'HH:MM:SS'),为空则立即开始(但首次运行前可能等待一个period)。
**注意**:定时器在回测中无效,仅在实盘或模拟盘中有效。定时器没有独立的结束方法,依赖于策略的运行。在定时器回调函数中调用下单函数时,passorder的quickTrade参数必须传2。

#coding:gbk
"""
大QMT 定时器使用示例:使用 run_time 在盘中定时执行任务
本示例演示了如何设置一个定时器,每5秒检查一次行情并打印信息。
仅供学习使用,不构成投资建议。
"""
def init(C):
"""
策略初始化函数
在这里设置定时器,指定要调用的函数、时间间隔和首次启动时间。
"""
# 设置定时器:每5秒运行一次名为 'my_timer_handler' 的函数
# 首次运行时间设置为一个历史时间,这样定时器会立刻开始等待5秒后触发
C.run_time("my_timer_handler", "5nSecond", "2024-01-01 09:30:00")
print("定时器已注册:每5秒执行一次 my_timer_handler 函数")
def my_timer_handler(C):
"""
用户自定义的回调函数
这是定时器每次触发时调用的函数,入参为 ContextInfo 对象。
你可以在这个函数中编写自己的判断逻辑或交易指令。
"""
# 示例:打印当前时间
import time
current_time = time.strftime('%H:%M:%S')
print(f"定时器触发!当前时间: {current_time}")
# 示例:获取并打印一只股票的最新价格
# 使用 get_full_tick 获取全推最新数据(实盘有效)
tick_data = C.get_full_tick(['01.SZ'])
if '000001.SZ' in tick_data:
price = tick_data['01.SZ']['lastPrice']
print(f" 银(01.SZ) 最新价: {price:.2f}")
# 示例:如果满足条件,可以在这里下单
# 注意:在定时器回调中下单,passorder 的 quickTrade 参数必须传 2
# 下面是一个注释掉的下单示例,方便您理解
# if some_condition:
# passorder(
# 23, # opType: 股票买入
# 1101, # orderType: 按股下单
# account, # 资金账号 (实际使用时请替换)
# '001.SZ', # orderCode
# 5, # prType: 最新价
# 0, # price
# 100, # volume: 100股
# '', # strategyName
# 2, # quickTrade: 必须传2,表示立即触发下单
# '定时器买入', # userOrderId
# C # ContextInfo
# )
# print(" 已发出买入委托")
def handlebar(C):
"""
handlebar 函数不是必须的,但通常作为占位。
本示例中,所有定时任务都在 my_timer_handler 中完成。
"""
pass
3如何订阅全推数据,并获取增量推送?
使用ContextInfo.subscribe_whole_quote(stock_list, callback)函数。
- stock_list:代码列表,如['001.SZ', '600.SH']。为空则订阅全市场。
- callback:用户自定义的回调函数名,当订阅的品种行情有变化时,会调用此函数并传入变化的数据。
函数返回一个订阅号subId,可用于后续的unsubscribe_whole_quote反订阅。全推数据仅支持分笔周期,增量推送变化品种的行情信息。
#coding:gbk
"""
大QMT 订阅全推数据使用示例:使用 subscribe_whole_quote 获取增量行情
本示例演示了如何订阅全推数据,并在回调函数中处理增量推送的行情信息。
仅供学习使用,不构成投资建议。
"""
# 用于存储订阅号,方便后续反订阅
sub_nums = []
def init(C):
"""
策略初始化函数
在这里订阅全推数据,指定要订阅的品种和回调函数。
"""
global sub_nums
# 定义回调函数
def on_whole_quote(data):
"""
用户自定义的回调函数
当订阅的品种行情有变化时,系统会自动调用此函数,并传入变化的数据。
参数 data 是一个字典,key为股票代码,value为该股票的行情数据字典。
"""
for stock_code in data:
stock_data = data[stock_code]
print(f"收到增量推送 - {stock_code}:")
print(f" 最新价: {stock_data['lastPrice']}")
print(f" 成交量: {stock_data['volume']} 手")
print(f" 成交额: {stock_data['amount']:.2f} 元")
print(f" 买一价: {stock_data['bidPrice'][0]}, 买一量: {stock_data['bidVol'][0]}")
print(f" 卖一价: {stock_data['askPrice'][0]}, 卖一量: {stock_data['askVol'][0]}")
print("-" * 40)
# 定义要订阅的品种列表
stock_list = ["01.SZ", "19.SH", "0.SH"]
# 订阅全推数据
# subscribe_whole_quote 会返回一个订阅号,用于后续反订阅
sub_id = C.subscribe_whole_quote(
code_list=stock_list, # 品种代码列表
callback=on_whole_quote # 指定回调函数
)
# 记录订阅号
sub_nums.append(sub_id)
print(f"订阅成功,订阅号: {sub_id}")
print(f"订阅品种: {stock_list}")
print("等待增量推送...\n")
def handlebar(C):
"""
handlebar 函数
本示例中不需要在 handlebar 中做额外操作,所有行情处理都在回调函数中完成。
"""
pass
def stop(C):
"""
策略停止函数
当策略停止时,反订阅行情数据,释放资源。
"""
global sub_nums
for sub_id in sub_nums:
C.unsubscribe_quote(sub_id)
print(f"已反订阅,订阅号: {sub_id}")
4如何订阅指定品种的行情数据?
使用ContextInfo.subscribe_quote(stock_list, period, callback, start_time='', end_time='', count=-1, dividend_type='follow')函数。
- stock_list:代码列表。
- period:周期,如'1m'(1分钟)、'5m'(5分钟)、'1d'(日线)、'tick'(分笔)。
- callback:行情变化时的回调函数。
函数返回订阅号subId。订阅有最大数量限制(如300个),超过限制会导致数据不更新。订阅后,可以在回调函数中处理实时数据,或使用get_market_data_ex(subscribe=True)获取数据。
#coding:gbk
"""
大QMT 订阅行情使用示例:使用 subscribe_quote 订阅指定品种的行情数据
本示例演示了如何订阅指定股票的行情,并在回调函数中处理实时数据。
仅供学习使用,不构成投资建议。
"""
# 用于存储订阅号,方便后续反订阅
sub_nums = []
def init(C):
"""
策略初始化函数
在这里订阅指定品种的行情数据。
"""
global sub_nums
# 定义回调函数
def on_quote(data):
"""
用户自定义的回调函数
当订阅的品种有新的行情数据推送时,系统会自动调用此函数。
参数 data 是一个字典,key为股票代码,value为行情数据。
"""
for stock_code in data:
stock_data = data[stock_code]
print(f"收到行情推送 - {stock_code}:")
# 根据周期不同,数据结构有所不同
# 对于日线('1d'),数据包含开高低收等信息
print(f" 开盘价: {stock_data.get('open', 'N/A')}")
print(f" 最高价: {stock_data.get('high', 'N/A')}")
print(f" 最低价: {stock_data.get('low', 'N/A')}")
print(f" 收盘价: {stock_data.get('close', 'N/A')}")
print(f" 成交量: {stock_data.get('volume', 'N/A')} 手")
print(f" 成交额: {stock_data.get('amount', 'N/A'):.2f} 元")
print("-" * 40)
# 定义要订阅的品种列表
stock_list = ["01.SZ", "619.SH"]
# 订阅行情数据
# subscribe_quote 会返回一个订阅号,用于后续反订阅
# 订阅成功后,当行情数据更新时,回调函数 on_quote 会自动被调用
for stock in stock_list:
sub_id = C.subscribe_quote(
stock_code=stock, # 股票代码,格式为 'code.market'
period='1d', # 订阅周期:'1d' 日线,'5m' 5分钟,'1m' 1分钟,'tick' 分笔
dividend_type='none', # 除权方式:'none' 不复权,'front' 前复权,'back' 后复权
callback=on_quote # 指定回调函数
)
sub_nums.append(sub_id)
print(f"订阅成功 - {stock},订阅号: {sub_id}")
print("\n等待行情推送...\n")
def handlebar(C):
"""
handlebar 函数
本示例中不需要在 handlebar 中做额外操作,所有行情处理都在回调函数中完成。
"""
pass
def stop(C):
"""
策略停止函数
当策略停止时,反订阅行情数据,释放资源。
"""
global sub_nums
for sub_id in sub_nums:
C.unsubscribe_quote(sub_id)
print(f"已反订阅,订阅号: {sub_id}")
5QMT中有哪几种主要的策略运行机制?各自适用什么场景?
主要有三类:
- **逐K线驱动(handlebar)**:策略随主图K线更新(每个tick)被调用,但信号只在K线结束时生效(quickTrade=0)。适用于基于K线技术指标、希望信号不闪烁的经典趋势或反转策略。
- **订阅推送(subscribe)**:通过subscribe_quote订阅品种,在回调函数中接收实时行情并判断交易。适用于需要随分笔行情高频判断、对实时性要求高的策略(如盘口策略)。
- **定时任务(run_time)**:通过run_time设置定时器,周期性执行判断。适用于不需要紧密跟随行情,而是固定时间间隔执行任务的策略(如定时轮动、收盘前交易)。
#coding:gbk
"""
大QMT 策略运行机制对比示例
本文件通过三个独立的示例,展示了QMT的三种主要策略运行机制:
1. 逐K线驱动 (handlebar)
2. 订阅推送 (subscribe)
3. 定时任务 (run_time)
仅供学习使用,不构成投资建议。
"""
# =============================================================================
# 示例一:逐K线驱动 (handlebar)
# -- 适用于基于K线技术指标、希望信号不闪烁的经典趋势或反转策略。
# =============================================================================
def init_handlebar(C):
"""
逐K线驱动示例的初始化函数。
"""
C.account = 'test_account' # 请替换为您的实际账号
print("逐K线驱动示例已启动...")
def handlebar(C):
"""
逐K线驱动示例的核心函数。
策略随主图K线更新被调用,但信号仅在K线结束时生效 (passorder的quickTrade默认传0)。
"""
# 只在最新的K线上执行逻辑
if not C.is_last_bar():
return
# 示例:简单的双均线策略逻辑
# 计算5日、20日移动平均线
close = C.get_market_data_ex(fields=['close'], stock_code=['000001.SZ'], period='1d', count=20)
if close is None or '01.SZ' not in close:
return
df_close = close['001.SZ']
if len(df_close) < 20:
return
ma5 = df_close['close'].rolling(window=5).mean().iloc[-1]
ma20 = df_close['close'].rolling(window=5).mean().iloc[-1] # 简化计算,仅做演示
# 信号判断
if ma5 > ma20:
# 金叉买入 (quickTrade默认0,信号在K线结束时生效)
passorder(
23, # opType: 股票买入
1101, # orderType: 按股/手数量下单
C.account, # 资金账号
'01.SZ', # 股票代码
5, # prType: 最新价
0, # price: 价格占位
100, # volume: 100股
'', # strategyName
0, # quickTrade=0 (K线结束生效)
'handlebar买入', # userOrderId
C # ContextInfo
)
print(f"[handlebar] K线结束,发出买入信号:1.SZ 100股")
# =============================================================================
# 示例二:订阅推送 (subscribe)
# -- 适用于需要随分笔行情高频判断、对实时性要求高的策略。
# =============================================================================
# 用于存储订阅号
sub_ids = []
def init_subscribe(C):
"""
订阅推送示例的初始化函数。
"""
global sub_ids
C.account = 'test_account' # 请替换为您的实际账号
# 定义回调函数
def on_tick(data):
"""
当订阅的行情数据更新时,此函数会被自动调用。
"""
for stock_code in data:
stock_data = data[stock_code]
current_price = stock_data.get('lastPrice', 0)
print(f"[subscribe] 收到 {stock_code} 实时行情:最新价 {current_price}")
# 示例:在盘中实时判断并下单
# 假设:如果价格突然低于某个阈值,立即买入
if current_price < 10.50 and current_price > 0:
print(f"[subscribe] 触发买入条件,立即下单!")
passorder(
23, 1101, C.account, stock_code,
5, 0, 100, # 以最新价买入100股
'', 2, # quickTrade=2 (立即触发)
'subscribe买入', C
)
# 订阅平行的实时分笔行情
stock_list = ['01.SZ']
for stock in stock_list:
sub_id = C.subscribe_quote(
stock_code=stock,
period='tick', # 订阅分笔线,实时性最高
dividend_type='none',
callback=on_tick
)
sub_ids.append(sub_id)
print(f"[subscribe] 已订阅 {stock} 的实时行情,订阅号: {sub_id}")
def handlebar(C):
"""
订阅推送示例:handlebar作为占位,所有逻辑在回调函数中处理。
"""
pass
# =============================================================================
# 示例三:定时任务 (run_time)
# -- 适用于固定时间间隔执行任务的策略,如定时轮动、收盘前交易。
# =============================================================================
def init_timer(C):
"""
定时任务示例的初始化函数。
"""
C.account = 'test_account' # 请替换为您的实际账号
# 设置定时器:每10秒执行一次 my_timer_callback 函数
# 首次启动时间设置一个历史时间,让定时器立刻开始
C.run_time("my_timer_callback", "10nSecond", "2024-01-01 09:30:00")
print("[timer] 定时器已设置,每10秒执行一次 my_timer_callback")
def my_timer_callback(C):
"""
定时任务的回调函数。
注意:在定时器回调中下单,quickTrade 必须传 2。
"""
import time
current_time = time.strftime('%H:%M:%S')
print(f"[timer] 定时任务触发!当前时间: {current_time}")
# 示例:每10秒获取一次最新行情并打印
tick_data = C.get_full_tick(['01.SZ'])
if '01.SZ' in tick_data:
price = tick_data['01.SZ']['lastPrice']
print(f"[timer] 平行(01.SZ) 最新价: {price}")
# 示例:如果满足条件,在定时器中下单 (quickTrade必传2)
# 例如:收盘前5分钟清仓
# if current_time > '14:55:00':
# passorder(24, 1101, C.account, '000001.SZ', 5, 0, 100, '', 2, '收盘前清仓', C)
def handlebar(C):
"""
定时任务示例:handlebar作为占位。
"""
pass
"""
使用说明:
在实际使用时,您需要根据策略类型(回测/实盘)选择对应的函数。
- 示例一 (init_handlebar / handlebar):主要用于回测和实盘模拟逐K线运行。
- 示例二 (init_subscribe):主要用于实盘,对特定品种进行高频跟踪。
- 示例三 (init_timer / my_timer_callback):主要用于实盘,固定时间间隔执行任务。
注意:请将 'test_account' 替换为您的账号。
"""
后面继续更新不懂的问我就可以
