一、
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.6amount volume \
300740.SZ 4.95822e+08 360816
601318.SH 2.04286e+09 389771askPrice \
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.6amount volume \
300740.SZ 4.95833e+08 360824
601318.SH 2.04435e+09 390055askPrice \
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
三、这里有一个坑。
当前时间: 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