返回列表 发布新帖

qmt教程-qmt常见问题使用解答3

16 1

今天继续更新qmt的使用教程,前面更新了2qmt教程--qmt常见量化问题解答2

1如何使用Python在QMT中进行一篮子股票买卖?

主要使用set_basket和passorder(或algo_passorder)配合实现。

  1. **配置篮子结构**:使用set_basket函数设置一个篮子,包含多只股票及其权重、数量、买卖方向。
  2. **执行篮子交易**:调用passorder函数,将orderType参数设置为篮子交易对应的代码(如1102代表按篮子权重下单),并将orderCode参数指定为篮子名称。

文档7qmt中如何使用python进行一篮子买卖.txt提供了具体的代码示例,包括按数量下单和按权重下单两种方式。

383b13836833488d23f9825c6bf3e139.png

简单参考

#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

822c9c5a55af26fb9160bda144e71cff.png

2如何设置定时器,在盘中定时执行某些判断或交易?

使用ContextInfo.run_time(period, callback, startTime='')函数。

  • period:时间间隔(秒)。
  • callback:用户自定义的回调函数名(该函数需要自己定义)。
  • startTime:首次运行的时间点(格式'HH:MM:SS'),为空则立即开始(但首次运行前可能等待一个period)。

**注意**:定时器在回测中无效,仅在实盘或模拟盘中有效。定时器没有独立的结束方法,依赖于策略的运行。在定时器回调函数中调用下单函数时,passorder的quickTrade参数必须传2。

f505afb1284cfe35bfd867b341ce5425.png

#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中有哪几种主要的策略运行机制?各自适用什么场景?

主要有三类:

  1. **逐K线驱动(handlebar)**:策略随主图K线更新(每个tick)被调用,但信号只在K线结束时生效(quickTrade=0)。适用于基于K线技术指标、希望信号不闪烁的经典趋势或反转策略。
  2. **订阅推送(subscribe)**:通过subscribe_quote订阅品种,在回调函数中接收实时行情并判断交易。适用于需要随分笔行情高频判断、对实时性要求高的策略(如盘口策略)。
  3. **定时任务(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' 替换为您的账号。
"""

后面继续更新不懂的问我就可以

1d1ac2526ffba11a95c511cc896febad.jpg

评论1

落花忆流年楼主
发表于 2 小时前 | 显示全部楼层
不懂的问我就可以作者微信xg_quant

回复

您需要登录后才可以回帖 登录 | 立即注册

客服专线

400-080-8112

用思考的速度交易,用真诚的态度合作,我们是认真的!
  • 关注公众号
  • 添加微信客服
Copyright © 2001-2026 迅投QMT社区 版权所有 All Rights Reserved. 京ICP备2025122616号-3
关灯 快速发帖
扫一扫添加微信客服
QQ客服返回顶部
快速回复 返回顶部 返回列表