Home >  > QMT教程三(函数等)

QMT教程三(函数等)

一、
QMT获取行情数据的接口有3种:
1、获取最新分笔数据:get_full_tick(stock_code=[])
2、获取历史数据:get_market_data_ex(subscribe=False)
3、订阅数据:向行情服务器订阅指定品种行情,使用接口函数subscribe_quote

和get_market_data_ex(subscribe=True,),订阅有最大数量限制当前为500个。

今天重点介绍下获取分笔数据接口,及接口使用中的注意事项:

获取分笔数据接口函数:get_full_tick(stock_code=[])

参数stock_code:合约代码列表。注意接口不传参时,默认为当前主图代码。

该接口函数获取当前数据的最新值,支持取全市场品种,数据50ms增量更新一次。

一、测试代码一

fencoding:gbk
import pandas as pd
import numpy
as np
def init (C):
    c.stock=C.stockcode+'.'+C.market
def handlebar (C):
    #获取K线索引号和日期时间
    c_barpos =C.barpos
    c_bar_timetag =c.get_bar_timetag(C_barpos)
    c_bar_datetime = timetag_to_datetime(C_bar_timetag,'gY8m8d 8H:M:8S')
    print('K线索引号:',c_barpos,'K线日期时问:',c_bar_datetime)
    #获取最新分笔数据,默认参数为当前主图
c_tick= c.get_full_tick()
print (C_tick)
return

返回值: 根据合约列表返回一个dict。该字典的key值是股票代码,其值仍然是一个dict。在其值的字典中存放着对应股票代码的最新分笔数据。分笔数据key值有:
timetag:日期时间
lastPrice:最新价
open:开盘价
high:最高价
low:最低价
lastClose:昨收价
amount:成交额
volume:成交量(精确到手)
pvolume:成交量(精确到股)
stockStatus:股票状态(作废)
openInt:若是股票则含义为股票状态,非股票则是持仓量
settlementPrice:结算价
lastSettlementPrice:最新结算价
askPrice:列表,卖价五档
bidPrice:列表,买价五档
askVol:列表,卖量五档
bidVol:列表,买量五档

接口函数使用注意事项:

1、get_full_tick函数只能取最新的分笔,不能取历史分笔。

2、输出的key(timetag)值,无论在哪根K线上运行时都只能获取到当前最新的日期时间。

3、Key值'openInt': 13,表示目前处于连续交易时段。

4、Key值'askPrice'和'bidPrice'分别是卖价和买价五档数据列表。

5、Key值'askVol'和'bidVol'分别是卖量和买量五档数据列表。

6、开收高低价,买卖五档价获取的数值可能在小数点后出现一串0的误差。在程序中要对需要的位数精度做处理。

参考:https://zhuanlan.zhihu.com/p/680368683

二、测试代码二

# encoding:gbk
import datetime as dt
import pandas as pd

'''
    集合竞价获取实时行情数据。

    01_采用run_time函数与get_full_tick函数,来进行获取实时行情;

    02_早盘集合竞价,观察lastPrice字段具体变化情况。
'''


class a():
    pass


A = a()
A.program_start = True  # 程序启动


def init(ContextInfo):
    # 资金账号
    try:
        ContextInfo.accID = str(account)
    except NameError:
        ContextInfo.accID = "资金账号"
    ContextInfo.set_account(ContextInfo.accID)
    # 账户类型
    try:
        ContextInfo.accountType = str(accountType).upper()
    except NameError:
        ContextInfo.accountType = "STOCK"  # 账号类型
    print(f"\n 账户号: {ContextInfo.accountType}  账户类型: {ContextInfo.accountType}")

    # ============ 定时循环 ================
    print(f'\n init执行: {dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}')
    current_time = dt.datetime.now().strftime('%Y%m%d%H%M') + '00'
    ContextInfo.run_time('Timing_Cycle', '1000nMilliSecond', current_time, "SH")

    ContextInfo.stock_list = ["300740.SZ", "601318.SH"]


def handlebar(ContextInfo):
    pass


# 定时循环
def Timing_Cycle(ContextInfo):
    current_time = dt.datetime.now().strftime('%H:%M:%S')
    print(f"\n 当前时间: {current_time}")
    if A.program_start is not True:
        print("\n 资金账号暂未登陆成功, 请检查")
        return

        # =================== 策略逻辑 ====================================
    # 行情模块
    res_dict = ContextInfo.get_full_tick(ContextInfo.stock_list)
    data_df = dict_into_dataframe(res_dict)
    print(f"tick数据展示: \n{data_df}")
    print("=======" * 20)


def account_callback(ContextInfo, accountInfo):
    # 等account_callback有主推了,再启动定时周期函数
    A.program_start = True


def dict_into_dataframe(data_dict):
    """
        字典转换成Dataframe或Series
    """
    print(data_dict)
    if len(data_dict) == 0:
        return {}
    if len(data_dict) >= 1:
        data_df = pd.DataFrame(data_dict)
        data_df = data_df.T[
            ['timetag', 'lastPrice', 'open', 'high', 'low', 'lastClose', 'amount', 'volume', 'askPrice', 'askVol',
             'bidPrice', 'bidVol']]
        data_df.rename(columns={'lastPrice': '最新价', 'lastClose': '昨收价'}, inplace=True)
    return data_df

[2025-05-13 14:53:00][DEMO文件1][SH000300][1分钟]
当前时间: 14:53:00
{'601318.SH':
{'timetag': '20250513 14:52:59.116',
'lastPrice': 52.47,
'open': 52.79,
'high': 52.79,
'low': 52.25,
'lastClose': 52.6,
'amount': 2042859648.0,
'volume': 389771,
'pvolume': 38977100,
'stockStatus': 1,
'openInt': 13,
'settlementPrice': 0.0,
'lastSettlementPrice': 0.0,
'askPrice': [52.480000000000004, 52.49, 52.5, 52.51, 52.52],
'bidPrice': [52.47, 52.46, 52.45, 52.44, 52.43],
'askVol': [712, 457, 852, 268, 694],
'bidVol': [226, 2349, 287, 148, 355]},

'300740.SZ':
{'timetag': '20250513 14:52:57',
'lastPrice': 14.01,
'open': 13.41,
'high': 14.200000000000001,
'low': 13.27,
'lastClose': 13.42,
'amount': 495822112.0,
'volume': 360816,
'pvolume': 36081600,
'stockStatus': 1,
'openInt': 13,
'settlementPrice': 0.0,
'lastSettlementPrice': 0.0,
'askPrice': [14.01, 14.02, 14.030000000000001, 14.040000000000001, 14.05],
'bidPrice': [14.0, 13.99, 13.98, 13.97, 13.96],
'askVol': [362, 1386, 613, 202, 359],
'bidVol': [56, 476, 115, 32, 24]}}
tick数据展示:
timetag 最新价 open high low 昨收价 \
300740.SZ 20250513 14:52:57 14.01 13.41 14.2 13.27 13.42
601318.SH 20250513 14:52:59.116 52.47 52.79 52.79 52.25 52.6

amount volume \
300740.SZ 4.95822e+08 360816
601318.SH 2.04286e+09 389771

askPrice \
300740.SZ [14.01, 14.02, 14.030000000000001, 14.04000000...
601318.SH [52.480000000000004, 52.49, 52.5, 52.51, 52.52]

askVol bidPrice \
300740.SZ [362, 1386, 613, 202, 359] [14.0, 13.99, 13.98, 13.97, 13.96]
601318.SH [712, 457, 852, 268, 694] [52.47, 52.46, 52.45, 52.44, 52.43]

bidVol
300740.SZ [56, 476, 115, 32, 24]
601318.SH [226, 2349, 287, 148, 355]
============================================================================================================================================

[2025-05-13 14:53:01][DEMO文件1][SH000300][1分钟]
当前时间: 14:53:01
{'601318.SH': {'timetag': '20250513 14:53:02.48', 'lastPrice': 52.480000000000004, 'open': 52.79, 'high': 52.79, 'low': 52.25, 'lastClose': 52.6, 'amount': 2044350208.0, 'volume': 390055, 'pvolume': 39005500, 'stockStatus': 1, 'openInt': 13, 'settlementPrice': 0.0, 'lastSettlementPrice': 0.0, 'askPrice': [52.480000000000004, 52.49, 52.5, 52.51, 52.52], 'bidPrice': [52.47, 52.46, 52.45, 52.44, 52.43], 'askVol': [607, 431, 852, 268, 694], 'bidVol': [260, 2356, 317, 148, 355]}, '300740.SZ': {'timetag': '20250513 14:53:00', 'lastPrice': 14.0, 'open': 13.41, 'high': 14.200000000000001, 'low': 13.27, 'lastClose': 13.42, 'amount': 495833312.0, 'volume': 360824, 'pvolume': 36082400, 'stockStatus': 1, 'openInt': 13, 'settlementPrice': 0.0, 'lastSettlementPrice': 0.0, 'askPrice': [14.01, 14.02, 14.030000000000001, 14.040000000000001, 14.05], 'bidPrice': [14.0, 13.99, 13.98, 13.97, 13.96], 'askVol': [362, 1386, 613, 202, 359], 'bidVol': [79, 488, 115, 32, 24]}}

[2025-05-13 14:53:01][DEMO文件1][SH000300][1分钟] tick数据展示:
timetag 最新价 open high low 昨收价 \
300740.SZ 20250513 14:53:00 14 13.41 14.2 13.27 13.42
601318.SH 20250513 14:53:02.48 52.48 52.79 52.79 52.25 52.6

amount volume \
300740.SZ 4.95833e+08 360824
601318.SH 2.04435e+09 390055

askPrice \
300740.SZ [14.01, 14.02, 14.030000000000001, 14.04000000...
601318.SH [52.480000000000004, 52.49, 52.5, 52.51, 52.52]

askVol bidPrice \
300740.SZ [362, 1386, 613, 202, 359] [14.0, 13.99, 13.98, 13.97, 13.96]
601318.SH [607, 431, 852, 268, 694] [52.47, 52.46, 52.45, 52.44, 52.43]

bidVol
300740.SZ [79, 488, 115, 32, 24]
601318.SH [260, 2356, 317, 148, 355]

从上面的代码看,设定的是1000ms(1秒)print一次。

正如上文所述,handlebar()由QMT进行调用,每3秒、或者每5秒,调用一次。
如果我们想更高频呢,比如500毫秒调用一次,可以利用run_time定时器。

需要注意的是,在QMT中没有取消定时器的方法,除非策略结束。

使用方法:

ContextInfo.run_time(funcName,period,startTime)

funcName:回调函数名。
period:重复调用的时间间隔
'5nSecond'表示每5秒运行1次回调函数
'5nDay'表示每5天运行一次回调函数
'500nMilliSecond'表示每500毫秒运行1次回调函数
startTime:表示定时器第一次启动的时间,如果要定时器立刻启动,可以设置历史的时间。

参考:https://kakawanyifan.com/20501

tick

三、这里有一个坑。

当前时间: 14:52:55
{'601318.SH': {'timetag': '20250513 14:52:56.44',

看上面的数据,14:52:55获得了14:52:56的tick数据,这是越跨时空了。
明显代码有问题,一个取的系统时间,一个取的是qmt时间。

四、知识点
交易所只会发布3秒一次的tick行情。
所以上面的代码中,我们每秒打印一次tick,其实数据是一样的,只有3秒后数据才会变化。

1 timetag': '20250513 14:52:29.53
2 timetag': '20250513 14:52:32.40
3 timetag': '20250513 14:52:32.40
4 timetag': '20250513 14:52:32.40'
5 timetag': '20250513 14:52:32.40
6 timetag': '20250513 14:52:35.54
7 timetag': '20250513 14:52:35.54
8 timetag': '20250513 14:52:35.54
9 timetag': '20250513 14:52:38.47
10 timetag': '20250513 14:52:38.47
11 timetag': '20250513 14:52:41.46

但也不是3秒整。

股票行情(level1行情)是每3秒刷新一次快照,显示的是期间成交的汇总。而level2行情是成交同步推送的,每一笔成交即有一次推送,毫秒级的推送频率,因此可以跟踪每一笔成交,比level1行情要详细得多!

五、三种策略结构

init + handlebar,主图行情tick驱动。
init + run_time,定时器(周期函数)驱动。
init + subscribe_quote,订阅行情驱动。

不论是主图驱动,还是定时器驱动。都存在一个缺点,我们需要手动去拉取我们关注的资产的价格数据。
用这种方法,我们可以不用再手动去拉取数据。

参考:https://kakawanyifan.com/20501

六、获取卖价五档中三挡报价

def.init(ContextInfo):
...ContextInfo.set_universe(['600000.SH','300901.s2'l)

def·handlebar(ContextInfo):
    gp=ContextInfo.get universe ()
    wdbj=ContextInfo.get_full_tick(gp)
    for gpdm.in·wdbj.keys():
      print ("====")
      print("股票代码:",gpdm)
      print("卖价五档中三挡报价:",wdbj[gpdm]['askVol'][2])

www.bilibili.com/video/BV1ZM4m127Kc/?vd_source=c91e637d026fd1678270ed758d2fdd47

暧昧帖

本文暂无标签