国金证券QMT测试客户端 - 获取可融券股票数据

回复

李魔佛 回复了问题 • 1 人关注 • 1 个回复 • 202 次浏览 • 2024-06-19 10:53 • 来自相关话题

QMT获取持仓信息报错:AttributeError: 'NoneType' object has no attribute 'request_id'

李魔佛 发表了文章 • 0 个评论 • 151 次浏览 • 2024-06-17 14:03 • 来自相关话题

这个是新手经常遇到的问题。读取持仓信息的时候报错:
代码如下:
 
 
原因就是不能init之前去读取
# encoding:gbk
'''
实盘可以执行
固定数量
'''
import datetime


ACCOUNT = ''


def init(ContextInfo):
ContextInfo.set_account(ACCOUNT)


def get_position_infos():
# 信用账户可用资金
position_infos = get_trade_detail_data(ACCOUNT, 'stock', 'position')


pos_dict={}
for pos in position_infos:
code = pos.m_strInstrumentID
if pos.m_nVolume > 0:
pos_dict[code] = pos.m_nVolume
return pos_dict

datax = get_position_infos() # 这里error

def handlebar(ContextInfo):
if ContextInfo.is_last_bar():
current = datetime.datetime.now().strftime('%H:%M:%S.%f')
print(datax)


datax = get_position_infos()  #这里error
这个函数再最开始的时候就被定义了。没有经过initial初始话函数,很多数据没有获取,从而导致的报错。
 欢迎关注交流

  查看全部
这个是新手经常遇到的问题。读取持仓信息的时候报错:
代码如下:
 
 
原因就是不能init之前去读取
# encoding:gbk
'''
实盘可以执行
固定数量
'''
import datetime


ACCOUNT = ''


def init(ContextInfo):
ContextInfo.set_account(ACCOUNT)


def get_position_infos():
# 信用账户可用资金
position_infos = get_trade_detail_data(ACCOUNT, 'stock', 'position')


pos_dict={}
for pos in position_infos:
code = pos.m_strInstrumentID
if pos.m_nVolume > 0:
pos_dict[code] = pos.m_nVolume
return pos_dict

datax = get_position_infos() # 这里error

def handlebar(ContextInfo):
if ContextInfo.is_last_bar():
current = datetime.datetime.now().strftime('%H:%M:%S.%f')
print(datax)


datax = get_position_infos()  #这里error
这个函数再最开始的时候就被定义了。没有经过initial初始话函数,很多数据没有获取,从而导致的报错。
 欢迎关注交流

 

QMT股票两融对冲建仓实盘

李魔佛 发表了文章 • 0 个评论 • 595 次浏览 • 2024-05-29 12:02 • 来自相关话题

为了避免速度过快造成价格波动,提供速度,数量,延时控制。





 
成交了多少量,就融券多少量。达到指标即可停止。
 
代写量化程序,可以关注公众号,后台联系。 价格比QMT官网低的多了。实战性选手,选过N多QMT,ptrade实盘代码。
  查看全部
为了避免速度过快造成价格波动,提供速度,数量,延时控制。

20240529111758.png

 
成交了多少量,就融券多少量。达到指标即可停止。
 
代写量化程序,可以关注公众号,后台联系。 价格比QMT官网低的多了。实战性选手,选过N多QMT,ptrade实盘代码。
 

迅投官网的实例代码好多问题,惨不忍睹

李魔佛 发表了文章 • 0 个评论 • 314 次浏览 • 2024-05-12 16:55 • 来自相关话题

以前喜欢用C替代ContextInfo,现在改过去了,又有部分改的不完整。
 
还有更多的缩进的问题。
 





 
pep8的规范早已经不用tab来做缩进,而是用4个空格。
 
之前的文章里面也提到了,可以在qmt的配置文件里面改的。不过在UI上是不提供修改的地方。
http://www.30daydo.com/article/44602
  查看全部

20240512165205.png

以前喜欢用C替代ContextInfo,现在改过去了,又有部分改的不完整。
 
还有更多的缩进的问题。
 

20240512165415.png

 
pep8的规范早已经不用tab来做缩进,而是用4个空格。
 
之前的文章里面也提到了,可以在qmt的配置文件里面改的。不过在UI上是不提供修改的地方。
http://www.30daydo.com/article/44602
 

QMT里定时任务运行时间操作定时任务的间隔,会怎么样?

李魔佛 发表了文章 • 0 个评论 • 325 次浏览 • 2024-05-06 10:32 • 来自相关话题

代码很简单,就是在run_time这个定期运行的任务里面,定期1秒执行一次任务
 







当时任务运行时间超过1秒钟,比如上面的代码里面用time.sleep(3) 模拟这个超时,等待3秒。

在tick 实盘模式下运行,输出什么的?

答案如下:








每次的start和end之间间隔了3秒钟,然后下一次的start和上一次start的间隔也是在3秒钟,也就是当然时刻的定时任务没有执行完成,下一个时刻的定时任务不会被执行。

那么有人会要求,不想要被运行时间长的任务阻碍了当前的任务,要怎么操作呢? 最简单的方式,加一个多线程就好了。

稍微改动一下上面的代码:







把要执行的任务,写成一个函数,然后使用threading.Thread去执行这个函数, t.star() 就是启动任务。








执行结果如上图,每次的start 间隔只有1秒,当时end是要等待3秒之后才打印出来。但end的输出不会阻塞当前的start输出,start稳定地1秒间隔输出一次,end也在当前start的3秒之后打印出来。
 
  查看全部
代码很简单,就是在run_time这个定期运行的任务里面,定期1秒执行一次任务
 

20240506101947.png



当时任务运行时间超过1秒钟,比如上面的代码里面用time.sleep(3) 模拟这个超时,等待3秒。

在tick 实盘模式下运行,输出什么的?

答案如下:


20240506101516.png



每次的start和end之间间隔了3秒钟,然后下一次的start和上一次start的间隔也是在3秒钟,也就是当然时刻的定时任务没有执行完成,下一个时刻的定时任务不会被执行。

那么有人会要求,不想要被运行时间长的任务阻碍了当前的任务,要怎么操作呢? 最简单的方式,加一个多线程就好了。

稍微改动一下上面的代码:

20240506101043.png



把要执行的任务,写成一个函数,然后使用threading.Thread去执行这个函数, t.star() 就是启动任务。


20240506101030.png



执行结果如上图,每次的start 间隔只有1秒,当时end是要等待3秒之后才打印出来。但end的输出不会阻塞当前的start输出,start稳定地1秒间隔输出一次,end也在当前start的3秒之后打印出来。
 
 

使用量化程序获取ETF的成分股与实时净值

李魔佛 发表了文章 • 0 个评论 • 432 次浏览 • 2024-04-11 12:22 • 来自相关话题

代码只有几行:
# coding:gbk
def init(C):
pass

def handlebar(C):
iopv = get_etf_iopv("159928.SZ")
print(f'基金净值为{iopv}')
info = get_etf_info('513520.SH')
print(f'基金申购信息: {info}')
得到的数据如下:





 
需要开通低门槛量化QMT的朋友,可以扫码关注公众号开通: 查看全部
代码只有几行:
# coding:gbk
def init(C):
pass

def handlebar(C):
iopv = get_etf_iopv("159928.SZ")
print(f'基金净值为{iopv}')
info = get_etf_info('513520.SH')
print(f'基金申购信息: {info}')

得到的数据如下:

20240411122042.png

 
需要开通低门槛量化QMT的朋友,可以扫码关注公众号开通:

QMT回测会跳过当前的周六日和节假日吗

李魔佛 发表了文章 • 0 个评论 • 389 次浏览 • 2024-04-09 13:13 • 来自相关话题

使用的handle_bar进行回测,它是会自动跳过周六日和节假日的。
比如回测日期选择 2024年3月28日到2024年4月2日。
其中3月30日和31日是周六日。
下面回测的数据是不执行这两天的数据。从3月30日 15:00的数据,下一个bar就是4月1日09:30了




需要低门槛开通量化QMT,Ptrade,可以扫码联系。
开通后可加入技术交流群。 查看全部
使用的handle_bar进行回测,它是会自动跳过周六日和节假日的。
比如回测日期选择 2024年3月28日到2024年4月2日。
其中3月30日和31日是周六日。
下面回测的数据是不执行这两天的数据。从3月30日 15:00的数据,下一个bar就是4月1日09:30了
20240409130951.png

需要低门槛开通量化QMT,Ptrade,可以扫码联系。
开通后可加入技术交流群。

qmt下载完数据之后,记得重启一次qmt,不然get_market_data_ex依然还是获取不到数据的

李魔佛 发表了文章 • 0 个评论 • 466 次浏览 • 2024-04-01 13:38 • 来自相关话题

最近群里问这个问题的人比较多。
 
qmt下载完数据之后,get_market_data_ex依然还是获取不到数据。
 
其实主要数据没有刷新。
 
只需要你手动关闭QMT,再打开一次就好了。
 





 
反正呢,这些问题,QMT也不会告诉你,要靠自己摸索了。
 
欢迎收藏网站哦! 查看全部
最近群里问这个问题的人比较多。
 
qmt下载完数据之后,get_market_data_ex依然还是获取不到数据。
 
其实主要数据没有刷新。
 
只需要你手动关闭QMT,再打开一次就好了。
 

20240401133759.png

 
反正呢,这些问题,QMT也不会告诉你,要靠自己摸索了。
 
欢迎收藏网站哦!

QMT每次自动升级,都会把改过的配置文件给覆盖掉

李魔佛 发表了文章 • 0 个评论 • 479 次浏览 • 2024-03-31 14:23 • 来自相关话题

太业余。
感觉设计模式有问题。
 
本来我配置了缩进用的4个空格,(这是pep8的标准好吧)
而qmt默认是用tab做缩进。
 
导致从vs code或者pycharm上的代码迁移迁移过来qmt的编辑器,你按tab键,是制表符,而不是4个空格。
 
运行或者回测就会报错。





 
每次升级都把我的配置给改了。
 
难道不覆盖config文件不行吗? 每次类似全量升级,一点点bug fix都在全量升级
  查看全部
太业余。
感觉设计模式有问题。
 
本来我配置了缩进用的4个空格,(这是pep8的标准好吧)
而qmt默认是用tab做缩进。
 
导致从vs code或者pycharm上的代码迁移迁移过来qmt的编辑器,你按tab键,是制表符,而不是4个空格。
 
运行或者回测就会报错。

20240331004.png

 
每次升级都把我的配置给改了。
 
难道不覆盖config文件不行吗? 每次类似全量升级,一点点bug fix都在全量升级
 

不同券商的数据质量简单对比:国金QMT vs 国信QMT(iquant)

李魔佛 发表了文章 • 0 个评论 • 935 次浏览 • 2024-03-31 11:57 • 来自相关话题

同一段代码,先在国信上跑回测,先获取可转债的1分钟的分笔数据,发现一些时间段里的成交额居然是0. (数据已经先下载好了)

点击打开大图





上面的amount字段(成交额),返回的是0。

看了一下对应的转债,没有停牌,是有正常数据交易的。

然后用国金的QMT记性交叉验证。同样的代码
点击打开大图




 
国金的是正常的。只是成交量的小数浮点位是不是有点多了? 可能用的numy的默认9位,没有做处理而已。

【在写这个文章的时候发现国信的qmt的volume成交量是有数据的,那么其实可以用价格x成交量=成交额,间接获取成交额,大坑】

点击打开大图




 
附测试源码:
 # coding:gbk
# 公众号:可转债量化分析
DEBUG = True
import time
def get_datetime(ContextInfo):
# 获取当前时间
index = ContextInfo.barpos
realtime = ContextInfo.get_bar_timetag(index)
date = timetag_to_datetime(realtime, "%Y-%m-%d %H:%M:%S")
if DEBUG:
print('当前日期 ', date)
return date

def init(ContextInfo):
print("==============start==========")
ContextInfo.start = '2024-03-27 10:00:00'
ContextInfo.end = '2024-03-29 10:00:00'
#
#ContextInfo.end = '2023-01-05'
#ContextInfo.start = '2023-01-16'
print('init')

def handlebar(ContextInfo):
# 回测的时候不需要
#if not ContextInfo.is_last_bar():
# print('return')
# return
get_datetime(ContextInfo)
print('handlebar')
data = ContextInfo.get_market_data(['quoter'], stock_code = ['123167.SZ'], skip_paused = True, period = 'tick', dividend_type = 'front')

#data = ContextInfo.get_market_data(['close'], stock_code = ['113567.SH'], skip_paused = True, period = '1d', dividend_type = 'front')
#print(type(data))
print(data)

def stop(ContextInfo):
print( 'strategy is stop !') 查看全部
同一段代码,先在国信上跑回测,先获取可转债的1分钟的分笔数据,发现一些时间段里的成交额居然是0. (数据已经先下载好了)

点击打开大图
20240331002.png


上面的amount字段(成交额),返回的是0。

看了一下对应的转债,没有停牌,是有正常数据交易的。

然后用国金的QMT记性交叉验证。同样的代码
点击打开大图
20240331001.png

 
国金的是正常的。只是成交量的小数浮点位是不是有点多了? 可能用的numy的默认9位,没有做处理而已。

【在写这个文章的时候发现国信的qmt的volume成交量是有数据的,那么其实可以用价格x成交量=成交额,间接获取成交额,大坑】

点击打开大图
20240331003.png

 
附测试源码:
 
# coding:gbk
# 公众号:可转债量化分析
DEBUG = True
import time
def get_datetime(ContextInfo):
# 获取当前时间
index = ContextInfo.barpos
realtime = ContextInfo.get_bar_timetag(index)
date = timetag_to_datetime(realtime, "%Y-%m-%d %H:%M:%S")
if DEBUG:
print('当前日期 ', date)
return date

def init(ContextInfo):
print("==============start==========")
ContextInfo.start = '2024-03-27 10:00:00'
ContextInfo.end = '2024-03-29 10:00:00'
#
#ContextInfo.end = '2023-01-05'
#ContextInfo.start = '2023-01-16'
print('init')

def handlebar(ContextInfo):
# 回测的时候不需要
#if not ContextInfo.is_last_bar():
# print('return')
# return
get_datetime(ContextInfo)
print('handlebar')
data = ContextInfo.get_market_data(['quoter'], stock_code = ['123167.SZ'], skip_paused = True, period = 'tick', dividend_type = 'front')

#data = ContextInfo.get_market_data(['close'], stock_code = ['113567.SH'], skip_paused = True, period = '1d', dividend_type = 'front')
#print(type(data))
print(data)

def stop(ContextInfo):
print( 'strategy is stop !')

miniQMT安装包路径 | 下载地址

李魔佛 发表了文章 • 0 个评论 • 800 次浏览 • 2024-02-29 20:09 • 来自相关话题

安装好QMT之后,在QMT的设置里面选择安装python。
 
等待几分钟,python文件下载好了之后。
 
找到qmt的安装目录,
 
进去这里面
 
\bin.x64\Lib\site-packages\xtquant
 
把这个目录复制到你的python路径的site-package 下面, 就可以在你的python环境下运行miniQMT了。
 
当然首先还是要启动你的QMT客户端,勾选极速模式。 (不开的话连不到券商服务器,这以为这无法再linux上单独跑,wine额外另说)
 
比如下面的获取行情的示例代码,还有直接下单代码
 # 用前须知

## xtdata提供和MiniQmt的交互接口,本质是和MiniQmt建立连接,由MiniQmt处理行情数据请求,再把结果回传返回到python层。使用的行情服务器以及能获取到的行情数据和MiniQmt是一致的,要检查数据或者切换连接时直接操作MiniQmt即可。

## 对于数据获取接口,使用时需要先确保MiniQmt已有所需要的数据,如果不足可以通过补充数据接口补充,再调用数据获取接口获取。

## 对于订阅接口,直接设置数据回调,数据到来时会由回调返回。订阅接收到的数据一般会保存下来,同种数据不需要再单独补充。

# 代码讲解

# 从本地python导入xtquant库,如果出现报错则说明安装失败
from xtquant import xtdata
import time

# 设定一个标的列表
code_list = ["000001.SZ"]
# 设定获取数据的周期
period = "1d"

# 下载标的行情数据
if 1:
## 为了方便用户进行数据管理,xtquant的大部分历史数据都是以压缩形式存储在本地的
## 比如行情数据,需要通过download_history_data下载,财务数据需要通过
## 所以在取历史数据之前,我们需要调用数据下载接口,将数据下载到本地
for i in code_list:
xtdata.download_history_data(i,period=period,incrementally=True) # 增量下载行情数据(开高低收,等等)到本地

xtdata.download_financial_data(code_list) # 下载财务数据到本地
xtdata.download_sector_data() # 下载板块数据到本地
# 更多数据的下载方式可以通过数据字典查询

# 读取本地历史行情数据
history_data = xtdata.get_market_data_ex(,code_list,period=period,count=-1)
print(history_data)
print("=" * 20)

# 如果需要盘中的实时行情,需要向服务器进行订阅后才能获取
# 订阅后,get_market_data函数于get_market_data_ex函数将会自动拼接本地历史行情与服务器实时行情

# 向服务器订阅数据
for i in code_list:
xtdata.subscribe_quote(i,period=period,count=-1) # 设置count = -1来取到当天所有实时行情

# 等待订阅完成
time.sleep(1)

# 获取订阅后的行情
kline_data = xtdata.get_market_data_ex(,code_list,period=period)
print(kline_data)

# 获取订阅后的行情,并以固定间隔进行刷新,预期会循环打印10次
for i in range(10):
# 这边做演示,就用for来循环了,实际使用中可以用while True
kline_data = xtdata.get_market_data_ex(,code_list,period=period)
print(kline_data)
time.sleep(3) # 三秒后再次获取行情

# 如果不想用固定间隔触发,可以以用订阅后的回调来执行
# 这种模式下当订阅的callback回调函数将会异步的执行,每当订阅的标的tick发生变化更新,callback回调函数就会被调用一次
# 本地已有的数据不会触发callback

# 定义的回测函数
## 回调函数中,data是本次触发回调的数据,只有一条
def f(data):
# print(data)

code_list = list(data.keys()) # 获取到本次触发的标的代码

kline_in_callabck = xtdata.get_market_data_ex(,code_list,period = period) # 在回调中获取klines数据
print(kline_in_callabck)

for i in code_list:
xtdata.subscribe_quote(i,period=period,count=-1,callback=f) # 订阅时设定回调函数

# 使用回调时,必须要同时使用xtdata.run()来阻塞程序,否则程序运行到最后一行就直接结束退出了。
xtdata.run()





 
异步下单#coding:utf-8
import time, datetime, traceback, sys
from xtquant import xtdata
from xtquant.xttrader import XtQuantTrader, XtQuantTraderCallback
from xtquant.xttype import StockAccount
from xtquant import xtconstant

#定义一个类 创建类的实例 作为状态的容器
class _a():
pass
A = _a()
A.bought_list =
A.hsa = xtdata.get_stock_list_in_sector('沪深A股')

def interact():
"""执行后进入repl模式"""
import code
code.InteractiveConsole(locals=globals()).interact()
xtdata.download_sector_data()

def f(data):
now = datetime.datetime.now()
for stock in data:
if stock not in A.hsa:
continue
cuurent_price = data[stock]['lastPrice']
pre_price = data[stock]['lastClose']
ratio = cuurent_price / pre_price - 1 if pre_price > 0 else 0
if ratio > 0.09 and stock not in A.bought_list:
print(f"{now} 最新价 买入 {stock} 200股")
async_seq = xt_trader.order_stock_async(acc, stock, xtconstant.STOCK_BUY, 200, xtconstant.LATEST_PRICE, -1, 'strategy_name', stock)
A.bought_list.append(stock)

class MyXtQuantTraderCallback(XtQuantTraderCallback):
def on_disconnected(self):
"""
连接断开
:return:
"""
print(datetime.datetime.now(),'连接断开回调')

def on_stock_order(self, order):
"""
委托回报推送
:param order: XtOrder对象
:return:
"""
print(datetime.datetime.now(), '委托回调', order.order_remark)


def on_stock_trade(self, trade):
"""
成交变动推送
:param trade: XtTrade对象
:return:
"""
print(datetime.datetime.now(), '成交回调', trade.order_remark)


def on_order_error(self, order_error):
"""
委托失败推送
:param order_error:XtOrderError 对象
:return:
"""
# print("on order_error callback")
# print(order_error.order_id, order_error.error_id, order_error.error_msg)
print(f"委托报错回调 {order_error.order_remark} {order_error.error_msg}")

def on_cancel_error(self, cancel_error):
"""
撤单失败推送
:param cancel_error: XtCancelError 对象
:return:
"""
print(datetime.datetime.now(), sys._getframe().f_code.co_name)

def on_order_stock_async_response(self, response):
"""
异步下单回报推送
:param response: XtOrderResponse 对象
:return:
"""
print(f"异步委托回调 {response.order_remark}")

def on_cancel_order_stock_async_response(self, response):
"""
:param response: XtCancelOrderResponse 对象
:return:
"""
print(datetime.datetime.now(), sys._getframe().f_code.co_name)

def on_account_status(self, status):
"""
:param response: XtAccountStatus 对象
:return:
"""
print(datetime.datetime.now(), sys._getframe().f_code.co_name)


if __name__ == '__main__':
print("start")
#指定客户端所在路径
path = r'D:\qmt\sp3\迅投极速交易终端 睿智融科版\userdata_mini'
# 生成session id 整数类型 同时运行的策略不能重复
session_id = int(time.time())
xt_trader = XtQuantTrader(path, session_id)
# 开启主动请求接口的专用线程 开启后在on_stock_xxx回调函数里调用XtQuantTrader.query_xxx函数不会卡住回调线程,但是查询和推送的数据在时序上会变得不确定
# 详见: http://docs.thinktrader.net/vip/pages/ee0e9b/#开启主动请求接口的专用线程
# xt_trader.set_relaxed_response_order_enabled(True)

# 创建资金账号为 800068 的证券账号对象
acc = StockAccount('800068', 'STOCK')
# 创建交易回调类对象,并声明接收回调
callback = MyXtQuantTraderCallback()
xt_trader.register_callback(callback)
# 启动交易线程
xt_trader.start()
# 建立交易连接,返回0表示连接成功
connect_result = xt_trader.connect()
print('建立交易连接,返回0表示连接成功', connect_result)
# 对交易回调进行订阅,订阅后可以收到交易主推,返回0表示订阅成功
subscribe_result = xt_trader.subscribe(acc)
print('对交易回调进行订阅,订阅后可以收到交易主推,返回0表示订阅成功', subscribe_result)

#这一行是注册全推回调函数 包括下单判断 安全起见处于注释状态 确认理解效果后再放开
# xtdata.subscribe_whole_quote(["SH", "SZ"], callback=f)
# 阻塞主线程退出
xt_trader.run_forever()
# 如果使用vscode pycharm等本地编辑器 可以进入交互模式 方便调试 (把上一行的run_forever注释掉 否则不会执行到这里)
interact()


需要开通miniQMT(低门槛,低费率)的朋友,
可以扫码联系:或者添加 技术公众号:

 
公众号:
 

 
  查看全部
安装好QMT之后,在QMT的设置里面选择安装python。
 
等待几分钟,python文件下载好了之后。
 
找到qmt的安装目录,
 
进去这里面
 
\bin.x64\Lib\site-packages\xtquant
 
把这个目录复制到你的python路径的site-package 下面, 就可以在你的python环境下运行miniQMT了。
 
当然首先还是要启动你的QMT客户端,勾选极速模式。 (不开的话连不到券商服务器,这以为这无法再linux上单独跑,wine额外另说)
 
比如下面的获取行情的示例代码,还有直接下单代码
 
# 用前须知

## xtdata提供和MiniQmt的交互接口,本质是和MiniQmt建立连接,由MiniQmt处理行情数据请求,再把结果回传返回到python层。使用的行情服务器以及能获取到的行情数据和MiniQmt是一致的,要检查数据或者切换连接时直接操作MiniQmt即可。

## 对于数据获取接口,使用时需要先确保MiniQmt已有所需要的数据,如果不足可以通过补充数据接口补充,再调用数据获取接口获取。

## 对于订阅接口,直接设置数据回调,数据到来时会由回调返回。订阅接收到的数据一般会保存下来,同种数据不需要再单独补充。

# 代码讲解

# 从本地python导入xtquant库,如果出现报错则说明安装失败
from xtquant import xtdata
import time

# 设定一个标的列表
code_list = ["000001.SZ"]
# 设定获取数据的周期
period = "1d"

# 下载标的行情数据
if 1:
## 为了方便用户进行数据管理,xtquant的大部分历史数据都是以压缩形式存储在本地的
## 比如行情数据,需要通过download_history_data下载,财务数据需要通过
## 所以在取历史数据之前,我们需要调用数据下载接口,将数据下载到本地
for i in code_list:
xtdata.download_history_data(i,period=period,incrementally=True) # 增量下载行情数据(开高低收,等等)到本地

xtdata.download_financial_data(code_list) # 下载财务数据到本地
xtdata.download_sector_data() # 下载板块数据到本地
# 更多数据的下载方式可以通过数据字典查询

# 读取本地历史行情数据
history_data = xtdata.get_market_data_ex(,code_list,period=period,count=-1)
print(history_data)
print("=" * 20)

# 如果需要盘中的实时行情,需要向服务器进行订阅后才能获取
# 订阅后,get_market_data函数于get_market_data_ex函数将会自动拼接本地历史行情与服务器实时行情

# 向服务器订阅数据
for i in code_list:
xtdata.subscribe_quote(i,period=period,count=-1) # 设置count = -1来取到当天所有实时行情

# 等待订阅完成
time.sleep(1)

# 获取订阅后的行情
kline_data = xtdata.get_market_data_ex(,code_list,period=period)
print(kline_data)

# 获取订阅后的行情,并以固定间隔进行刷新,预期会循环打印10次
for i in range(10):
# 这边做演示,就用for来循环了,实际使用中可以用while True
kline_data = xtdata.get_market_data_ex(,code_list,period=period)
print(kline_data)
time.sleep(3) # 三秒后再次获取行情

# 如果不想用固定间隔触发,可以以用订阅后的回调来执行
# 这种模式下当订阅的callback回调函数将会异步的执行,每当订阅的标的tick发生变化更新,callback回调函数就会被调用一次
# 本地已有的数据不会触发callback

# 定义的回测函数
## 回调函数中,data是本次触发回调的数据,只有一条
def f(data):
# print(data)

code_list = list(data.keys()) # 获取到本次触发的标的代码

kline_in_callabck = xtdata.get_market_data_ex(,code_list,period = period) # 在回调中获取klines数据
print(kline_in_callabck)

for i in code_list:
xtdata.subscribe_quote(i,period=period,count=-1,callback=f) # 订阅时设定回调函数

# 使用回调时,必须要同时使用xtdata.run()来阻塞程序,否则程序运行到最后一行就直接结束退出了。
xtdata.run()





 
异步下单
#coding:utf-8
import time, datetime, traceback, sys
from xtquant import xtdata
from xtquant.xttrader import XtQuantTrader, XtQuantTraderCallback
from xtquant.xttype import StockAccount
from xtquant import xtconstant

#定义一个类 创建类的实例 作为状态的容器
class _a():
pass
A = _a()
A.bought_list =
A.hsa = xtdata.get_stock_list_in_sector('沪深A股')

def interact():
"""执行后进入repl模式"""
import code
code.InteractiveConsole(locals=globals()).interact()
xtdata.download_sector_data()

def f(data):
now = datetime.datetime.now()
for stock in data:
if stock not in A.hsa:
continue
cuurent_price = data[stock]['lastPrice']
pre_price = data[stock]['lastClose']
ratio = cuurent_price / pre_price - 1 if pre_price > 0 else 0
if ratio > 0.09 and stock not in A.bought_list:
print(f"{now} 最新价 买入 {stock} 200股")
async_seq = xt_trader.order_stock_async(acc, stock, xtconstant.STOCK_BUY, 200, xtconstant.LATEST_PRICE, -1, 'strategy_name', stock)
A.bought_list.append(stock)

class MyXtQuantTraderCallback(XtQuantTraderCallback):
def on_disconnected(self):
"""
连接断开
:return:
"""
print(datetime.datetime.now(),'连接断开回调')

def on_stock_order(self, order):
"""
委托回报推送
:param order: XtOrder对象
:return:
"""
print(datetime.datetime.now(), '委托回调', order.order_remark)


def on_stock_trade(self, trade):
"""
成交变动推送
:param trade: XtTrade对象
:return:
"""
print(datetime.datetime.now(), '成交回调', trade.order_remark)


def on_order_error(self, order_error):
"""
委托失败推送
:param order_error:XtOrderError 对象
:return:
"""
# print("on order_error callback")
# print(order_error.order_id, order_error.error_id, order_error.error_msg)
print(f"委托报错回调 {order_error.order_remark} {order_error.error_msg}")

def on_cancel_error(self, cancel_error):
"""
撤单失败推送
:param cancel_error: XtCancelError 对象
:return:
"""
print(datetime.datetime.now(), sys._getframe().f_code.co_name)

def on_order_stock_async_response(self, response):
"""
异步下单回报推送
:param response: XtOrderResponse 对象
:return:
"""
print(f"异步委托回调 {response.order_remark}")

def on_cancel_order_stock_async_response(self, response):
"""
:param response: XtCancelOrderResponse 对象
:return:
"""
print(datetime.datetime.now(), sys._getframe().f_code.co_name)

def on_account_status(self, status):
"""
:param response: XtAccountStatus 对象
:return:
"""
print(datetime.datetime.now(), sys._getframe().f_code.co_name)


if __name__ == '__main__':
print("start")
#指定客户端所在路径
path = r'D:\qmt\sp3\迅投极速交易终端 睿智融科版\userdata_mini'
# 生成session id 整数类型 同时运行的策略不能重复
session_id = int(time.time())
xt_trader = XtQuantTrader(path, session_id)
# 开启主动请求接口的专用线程 开启后在on_stock_xxx回调函数里调用XtQuantTrader.query_xxx函数不会卡住回调线程,但是查询和推送的数据在时序上会变得不确定
# 详见: http://docs.thinktrader.net/vip/pages/ee0e9b/#开启主动请求接口的专用线程
# xt_trader.set_relaxed_response_order_enabled(True)

# 创建资金账号为 800068 的证券账号对象
acc = StockAccount('800068', 'STOCK')
# 创建交易回调类对象,并声明接收回调
callback = MyXtQuantTraderCallback()
xt_trader.register_callback(callback)
# 启动交易线程
xt_trader.start()
# 建立交易连接,返回0表示连接成功
connect_result = xt_trader.connect()
print('建立交易连接,返回0表示连接成功', connect_result)
# 对交易回调进行订阅,订阅后可以收到交易主推,返回0表示订阅成功
subscribe_result = xt_trader.subscribe(acc)
print('对交易回调进行订阅,订阅后可以收到交易主推,返回0表示订阅成功', subscribe_result)

#这一行是注册全推回调函数 包括下单判断 安全起见处于注释状态 确认理解效果后再放开
# xtdata.subscribe_whole_quote(["SH", "SZ"], callback=f)
# 阻塞主线程退出
xt_trader.run_forever()
# 如果使用vscode pycharm等本地编辑器 可以进入交互模式 方便调试 (把上一行的run_forever注释掉 否则不会执行到这里)
interact()


需要开通miniQMT(低门槛,低费率)的朋友,
可以扫码联系:或者添加 技术公众号:

 
公众号:
 

 
 

QMT获取全市场股票,排除ST退市风险股票

李魔佛 发表了文章 • 0 个评论 • 833 次浏览 • 2024-02-07 22:25 • 来自相关话题

因为QMT不能获取北交所的股票历史数据,所以也把北交所的股票也排除了。
 
def get_all_market_code(ContextInfo):

all_market_codes = [item for item in ContextInfo.get_stock_list_in_sector('沪深A股') if not item.endswith('BJ')]
return filter_ST_stock(ContextInfo, all_market_codes)


def filter_ST_stock(ContextInfo, code_list):
result = []
for code in code_list:
if re.search('(st)|(ST)|(\*st)|(\*ST)|(退)',ContextInfo.get_stock_name(code)):
print('排除 : ',ContextInfo.get_stock_name(code),code)
continue
result.append(code)
return result

global_dict = {}

def init(ContextInfo):
now = time.ctime()
print('策略初始化{}'.format(now))
need_download = 1
global_dict['start_date'] = '20231201'
global_dict['end_date'] = ''
global_dict['code_list'] = get_all_market_code(ContextInfo)

 有问题可以咨询公众号或者知识星球
提供策略代写服务
  查看全部
因为QMT不能获取北交所的股票历史数据,所以也把北交所的股票也排除了。
 
def get_all_market_code(ContextInfo):

all_market_codes = [item for item in ContextInfo.get_stock_list_in_sector('沪深A股') if not item.endswith('BJ')]
return filter_ST_stock(ContextInfo, all_market_codes)


def filter_ST_stock(ContextInfo, code_list):
result = []
for code in code_list:
if re.search('(st)|(ST)|(\*st)|(\*ST)|(退)',ContextInfo.get_stock_name(code)):
print('排除 : ',ContextInfo.get_stock_name(code),code)
continue
result.append(code)
return result

global_dict = {}

def init(ContextInfo):
now = time.ctime()
print('策略初始化{}'.format(now))
need_download = 1
global_dict['start_date'] = '20231201'
global_dict['end_date'] = ''
global_dict['code_list'] = get_all_market_code(ContextInfo)

 有问题可以咨询公众号或者知识星球
提供策略代写服务
 

QMT实时获取涨停股,筛选流通盘大于X的股票

李魔佛 发表了文章 • 0 个评论 • 912 次浏览 • 2024-02-07 18:28 • 来自相关话题

基于官方例子修复了一下bug,比如移除了北交所的股票,因为目前qmt获取不了北交所的股票历史数据。
 
直接上代码:# coding:gbk
import time


class G():
pass


g = G()


def init(ContextInfo):
g.hsa = [item for item in ContextInfo.get_stock_list_in_sector('沪深A股') if not item.endswith('BJ')]
g.vol_dict = {}
for stock in g.hsa:
g.vol_dict[stock] = ContextInfo.get_last_volume(stock)
ContextInfo.run_time("execution", "1nSecond", "2019-10-14 13:20:00")


def execution(ContextInfo):
t0 = time.time()
full_tick = ContextInfo.get_full_tick(g.hsa)
total_market_value = 0
total_ratio = 0
count = 0
for stock in g.hsa:
if full_tick[stock]['lastClose'] == 0:
continue
ratio = full_tick[stock]['lastPrice'] / full_tick[stock]['lastClose'] - 1
rise_price = round(full_tick[stock]['lastClose'] * 1.2, 2) if stock[0] == '3' or stock[:3] == '688' else round(
full_tick[stock]['lastClose'] * 1.1, 2)
# 如果要打印涨停品种
if abs(full_tick[stock]['lastPrice'] - rise_price) <0.01:
print(f"涨停股票 {stock} {ContextInfo.get_stock_name(stock)}")

market_value = full_tick[stock]['lastPrice'] * g.vol_dict[stock]
total_ratio += ratio * market_value
total_market_value += market_value
count += 1
# print(count)
total_ratio /= total_market_value
total_ratio *= 100
print(f'A股加权涨幅 {round(total_ratio, 2)}% 函数运行耗时{round(time.time() - t0, 5)}秒')






 
欢迎关注公众号:
可转债量化分析 查看全部
基于官方例子修复了一下bug,比如移除了北交所的股票,因为目前qmt获取不了北交所的股票历史数据。
 
直接上代码:
# coding:gbk
import time


class G():
pass


g = G()


def init(ContextInfo):
g.hsa = [item for item in ContextInfo.get_stock_list_in_sector('沪深A股') if not item.endswith('BJ')]
g.vol_dict = {}
for stock in g.hsa:
g.vol_dict[stock] = ContextInfo.get_last_volume(stock)
ContextInfo.run_time("execution", "1nSecond", "2019-10-14 13:20:00")


def execution(ContextInfo):
t0 = time.time()
full_tick = ContextInfo.get_full_tick(g.hsa)
total_market_value = 0
total_ratio = 0
count = 0
for stock in g.hsa:
if full_tick[stock]['lastClose'] == 0:
continue
ratio = full_tick[stock]['lastPrice'] / full_tick[stock]['lastClose'] - 1
rise_price = round(full_tick[stock]['lastClose'] * 1.2, 2) if stock[0] == '3' or stock[:3] == '688' else round(
full_tick[stock]['lastClose'] * 1.1, 2)
# 如果要打印涨停品种
if abs(full_tick[stock]['lastPrice'] - rise_price) <0.01:
print(f"涨停股票 {stock} {ContextInfo.get_stock_name(stock)}")

market_value = full_tick[stock]['lastPrice'] * g.vol_dict[stock]
total_ratio += ratio * market_value
total_market_value += market_value
count += 1
# print(count)
total_ratio /= total_market_value
total_ratio *= 100
print(f'A股加权涨幅 {round(total_ratio, 2)}% 函数运行耗时{round(time.time() - t0, 5)}秒')


20240207182920.png

 
欢迎关注公众号:
可转债量化分析

迅投QMT投研版 有必要开吗?

李魔佛 发表了文章 • 0 个评论 • 888 次浏览 • 2024-02-06 15:03 • 来自相关话题

没必要。
处处透出一股割韭菜的味道。
 
到处拉人进群,然后群里问问题,他们会让你私聊,加你,说服你开通投研版。
 
投研版无非多一些数据,你用tushare或者自己爬虫就可以获取,他们非要放到投研版里面,付费使用。
 
价格是一年8,9千,感觉没有一点性价比。
 
qmt,minniqmt有交易功能,有数据获取功能,也可以自己接入外部数据。没必要花那些冤枉钱去按年付费买一个不实用的数据。
真的没有数据,或者没有能力获取,付费找人写个api接口,爬虫数据,也不贵。 可以终身使用。 不好过按年付费???
 
关键那群qmt的人水平也不咋地,看他们的文档就知道,变量用A,B,C,D,人品也不咋地,星球上还抄袭我的星球文章,足以说明水平和人品。





 
群里问点问题,就让你开个投研版咨询哈。 还不如来我的qmt ptrade技术群的,free且有求必应哈。
  查看全部
没必要。
处处透出一股割韭菜的味道。
 
到处拉人进群,然后群里问问题,他们会让你私聊,加你,说服你开通投研版。
 
投研版无非多一些数据,你用tushare或者自己爬虫就可以获取,他们非要放到投研版里面,付费使用。
 
价格是一年8,9千,感觉没有一点性价比。
 
qmt,minniqmt有交易功能,有数据获取功能,也可以自己接入外部数据。没必要花那些冤枉钱去按年付费买一个不实用的数据。
真的没有数据,或者没有能力获取,付费找人写个api接口,爬虫数据,也不贵。 可以终身使用。 不好过按年付费???
 
关键那群qmt的人水平也不咋地,看他们的文档就知道,变量用A,B,C,D,人品也不咋地,星球上还抄袭我的星球文章,足以说明水平和人品。

Screenshot_2024_0206_150138.jpg

 
群里问点问题,就让你开个投研版咨询哈。 还不如来我的qmt ptrade技术群的,free且有求必应哈。
 

qmt获取北交所实时行情数据

李魔佛 发表了文章 • 0 个评论 • 785 次浏览 • 2024-01-24 13:39 • 来自相关话题

之前没有试过用qmt交易北交所的股票,后面闻了一下券商,他们说是qmt支持北交所股票交易。
 
首先试试获取实时的行情:
我获取的是这个北交所股票的数据:






获取北交所行情数据如下:
 
#-*-coding:gbk-*-
import datetime
code = '838402.BJ'
def init(ContextInfo):
now = datetime.datetime.now()
print(now)

def handlebar(ContextInfo):
index = ContextInfo.barpos
realtime = ContextInfo.get_bar_timetag(index)
date = timetag_to_datetime(realtime, "%Y-%m-%d %H:%M:%S")
info = ContextInfo.get_full_tick(stock_code=["838402.BJ"])
print(info)
返回下面的数据:





 
对了下时间戳,是正确的。
 
然后试了下获取北交所的历史数据行情:
#-*-coding:gbk-*-
import datetime

code = '838402.BJ'
def init(ContextInfo):
now = datetime.datetime.now()
print(now)
download_history_data(code,"1d","20240105","")

def handlebar(ContextInfo):
index = ContextInfo.barpos
realtime = ContextInfo.get_bar_timetag(index)
date = timetag_to_datetime(realtime, "%Y-%m-%d %H:%M:%S")
print(date)
hist = ContextInfo.get_market_data_ex(['close'],[code], period = "1d",count = 1)
print(hist)

代码里面我想用 download_history_data(code,"1d","20240105","") 下载历史数据。
在数据目录里面也能够获取到这个股票的历史数据文件。
 
可是在qmt里面却输出的是个空的dataframe。






数据目录下面是有数据的。。




感觉是qmt里面的功能还没有完善对北交所股票的支持。
  查看全部
之前没有试过用qmt交易北交所的股票,后面闻了一下券商,他们说是qmt支持北交所股票交易。
 
首先试试获取实时的行情:
我获取的是这个北交所股票的数据:

20240124132926.png


获取北交所行情数据如下:
 
#-*-coding:gbk-*-
import datetime
code = '838402.BJ'
def init(ContextInfo):
now = datetime.datetime.now()
print(now)

def handlebar(ContextInfo):
index = ContextInfo.barpos
realtime = ContextInfo.get_bar_timetag(index)
date = timetag_to_datetime(realtime, "%Y-%m-%d %H:%M:%S")
info = ContextInfo.get_full_tick(stock_code=["838402.BJ"])
print(info)

返回下面的数据:

20240124132856.png

 
对了下时间戳,是正确的。
 
然后试了下获取北交所的历史数据行情:
#-*-coding:gbk-*-
import datetime

code = '838402.BJ'
def init(ContextInfo):
now = datetime.datetime.now()
print(now)
download_history_data(code,"1d","20240105","")

def handlebar(ContextInfo):
index = ContextInfo.barpos
realtime = ContextInfo.get_bar_timetag(index)
date = timetag_to_datetime(realtime, "%Y-%m-%d %H:%M:%S")
print(date)
hist = ContextInfo.get_market_data_ex(['close'],[code], period = "1d",count = 1)
print(hist)

代码里面我想用 download_history_data(code,"1d","20240105","") 下载历史数据。
在数据目录里面也能够获取到这个股票的历史数据文件。
 
可是在qmt里面却输出的是个空的dataframe。

20240124133450.png


数据目录下面是有数据的。。
20240124133533.png

感觉是qmt里面的功能还没有完善对北交所股票的支持。
 

迅投官网的示例代码真的无眼看。。。

李魔佛 发表了文章 • 0 个评论 • 1085 次浏览 • 2023-11-10 01:17 • 来自相关话题

如果拿去做code review,估计会被喷的体无完肤。
 
变量名,类名用A ,B,C 噗, 没有一点含义,做什么鬼
 class a():
pass
A = a()而且也不符合python风格。。。python类名推荐的大写字母开头,实例化对象用小写字母。
所以退一万步讲,上面的代码正常点的程序员写也应该是这样的。
 class A():
pass
a = A()
  
其实正确的应该class GlobalCls():
pass

g = GlobalCls()
其他地方也是有这个毛病。
把代码喂给GPT,让它来分析一下:
得到如下结果:文件编码声明: #coding:gbk 是指定源文件的编码格式为GBK。在Python 3中,通常使用UTF-8作为文件编码格式,因此可以将该行删除或更改为#coding:utf-8。

类名和函数名: 根据PEP 8命名约定,类名应该使用大写字母开头的驼峰命名法(例如A改为A)。同样,函数名应该使用小写字母开头的小写命名法(例如init改为init,f改为f)。

类和实例: 在代码中定义了一个空类a,但没有给它任何属性或方法。如果不需要这个类,可以将其删除。

缩进和代码格式: Python非常依赖于正确的缩进,以指示代码块的层次结构。请确保代码的缩进是一致的,并使用适当的缩进级别(通常是4个空格)。

代码注释: 代码中有一些注释,但是大部分是被注释掉的。良好的注释可以增加代码的可读性和可维护性,建议在关键部分添加更多有用的注释。

异常处理: 代码中没有包含任何异常处理机制。在实际应用中,建议对可能引发异常的操作进行适当的异常处理,以提高代码的健壮性。
 
然后里面计算涨停是这样的: rise_price = round(full_tick[stock]['lastClose'] *1.2,2) if stock[0] == '3' or stock[:3] == '688' else round(full_tick[stock]['lastClose'] *1.1,2)


用昨收价* 1.2和1.1判断当前是否涨跌停。 首先,没有考虑到ST股,部分ST是5%涨停的。 
其次,是直接用的昨收价,如果当天是分红除权日,昨收价没有做除权处理,得到的涨跌幅也是不准的。
 
当然这个文档最大的问题是,很多示例代码运行是直接报错的!!
 

  查看全部
20231110001.jpg

如果拿去做code review,估计会被喷的体无完肤。
 
变量名,类名用A ,B,C 噗, 没有一点含义,做什么鬼
 
class a():
pass
A = a()
而且也不符合python风格。。。python类名推荐的大写字母开头,实例化对象用小写字母。
所以退一万步讲,上面的代码正常点的程序员写也应该是这样的。
 
class A():
pass
a = A()

  
其实正确的应该
class GlobalCls():
pass

g = GlobalCls()

其他地方也是有这个毛病。
把代码喂给GPT,让它来分析一下:
得到如下结果:
文件编码声明: #coding:gbk 是指定源文件的编码格式为GBK。在Python 3中,通常使用UTF-8作为文件编码格式,因此可以将该行删除或更改为#coding:utf-8。

类名和函数名: 根据PEP 8命名约定,类名应该使用大写字母开头的驼峰命名法(例如A改为A)。同样,函数名应该使用小写字母开头的小写命名法(例如init改为init,f改为f)。

类和实例: 在代码中定义了一个空类a,但没有给它任何属性或方法。如果不需要这个类,可以将其删除。

缩进和代码格式: Python非常依赖于正确的缩进,以指示代码块的层次结构。请确保代码的缩进是一致的,并使用适当的缩进级别(通常是4个空格)。

代码注释: 代码中有一些注释,但是大部分是被注释掉的。良好的注释可以增加代码的可读性和可维护性,建议在关键部分添加更多有用的注释。

异常处理: 代码中没有包含任何异常处理机制。在实际应用中,建议对可能引发异常的操作进行适当的异常处理,以提高代码的健壮性。

 
然后里面计算涨停是这样的:
		rise_price = round(full_tick[stock]['lastClose'] *1.2,2) if stock[0] == '3' or stock[:3] == '688' else round(full_tick[stock]['lastClose'] *1.1,2)


用昨收价* 1.2和1.1判断当前是否涨跌停。 首先,没有考虑到ST股,部分ST是5%涨停的。 
其次,是直接用的昨收价,如果当天是分红除权日,昨收价没有做除权处理,得到的涨跌幅也是不准的。
 
当然这个文档最大的问题是,很多示例代码运行是直接报错的!!
 

 

QMT获取A股全市场股票代码

李魔佛 发表了文章 • 0 个评论 • 1201 次浏览 • 2023-10-25 15:23 • 来自相关话题

QMT可以通过板块获取A股的全市场股票代码.
 
"沪深A股"
 
完整代码:#-*-coding:gbk-*-
import time
start = False
ACCOUNT = ''

def init(ContextInfo):
now = time.ctime()
print(now)
ContextInfo.run_time("execution","30nSecond","2023-04-14 13:20:00")


def execution(ContextInfo):
data = ContextInfo.get_stock_list_in_sector('沪深A股')
print(len(data))

def handlebar(ContextInfo):
pass
当前共有5047只股票【2023-10-25 15:18:45.533】 start trading mode
【2023-10-25 15:18:45.533】 Wed Oct 25 15:18:45 2023

【2023-10-25 15:18:45.533】 5074
['000001.SZ', '000002.SZ', '000004.SZ', '000005.SZ', '000006.SZ', '000007.SZ', '000008.SZ', '000009.SZ', '000010.SZ', '000011.SZ', '000012.SZ', '000014.SZ', '000016.SZ', '000017.SZ', '000019.SZ', '000020.SZ', '000021.SZ', '000023.SZ', '000025.SZ', '000026.SZ', '000027.SZ', '000028.SZ', '000029.SZ', '000030.SZ', '000031.SZ', '000032.SZ', '000034.SZ', '000035.SZ', '000036.SZ', '000037.SZ', '000039.SZ', '000040.SZ', '000042.SZ', '000045.SZ', '000046.SZ', '000048.SZ', '000049.SZ', '000050.SZ', '000055.SZ', '000056.SZ', '000058.SZ', '000059.SZ', '000060.SZ', '000061.SZ', '000062.SZ', '000063.SZ', '000065.SZ', '000066.SZ', '000068.SZ', '000069.SZ', '000070.SZ', '000078.SZ', '000088.SZ', '000089.SZ', '000090.SZ', '000096.SZ', '000099.SZ', '000100.SZ', '000151.SZ', '000153.SZ', '000155.SZ', '000156.SZ', '000157.SZ', '000158.SZ', '000159.SZ', '000166.SZ', '000301.SZ', '000333.SZ', '000338.SZ', '000400.SZ', '000401.SZ', '000402.SZ', '000403.SZ', '000404.SZ', '000407.SZ', '000408.SZ', '000409.SZ', '000410.SZ', '000411.SZ', '000413.SZ', '000415.SZ', '000416.SZ', '000417.SZ', '000419.SZ', '000420.SZ', '000421.SZ', '000422.SZ', '000423.SZ', '000425.SZ', '000426.SZ',省略若干...
 
点击查看大图




 
是否遇到QMT或Ptrade的问题, 无从入手? 或者咨询无门 ?
来加入 知识星球 , 获取专业的技术解答, 量化实盘代码, 技术交流群

  查看全部
QMT可以通过板块获取A股的全市场股票代码.
 
"沪深A股"
 
完整代码:
#-*-coding:gbk-*-
import time
start = False
ACCOUNT = ''

def init(ContextInfo):
now = time.ctime()
print(now)
ContextInfo.run_time("execution","30nSecond","2023-04-14 13:20:00")


def execution(ContextInfo):
data = ContextInfo.get_stock_list_in_sector('沪深A股')
print(len(data))

def handlebar(ContextInfo):
pass

当前共有5047只股票
【2023-10-25 15:18:45.533】  start trading mode
【2023-10-25 15:18:45.533】 Wed Oct 25 15:18:45 2023

【2023-10-25 15:18:45.533】 5074
['000001.SZ', '000002.SZ', '000004.SZ', '000005.SZ', '000006.SZ', '000007.SZ', '000008.SZ', '000009.SZ', '000010.SZ', '000011.SZ', '000012.SZ', '000014.SZ', '000016.SZ', '000017.SZ', '000019.SZ', '000020.SZ', '000021.SZ', '000023.SZ', '000025.SZ', '000026.SZ', '000027.SZ', '000028.SZ', '000029.SZ', '000030.SZ', '000031.SZ', '000032.SZ', '000034.SZ', '000035.SZ', '000036.SZ', '000037.SZ', '000039.SZ', '000040.SZ', '000042.SZ', '000045.SZ', '000046.SZ', '000048.SZ', '000049.SZ', '000050.SZ', '000055.SZ', '000056.SZ', '000058.SZ', '000059.SZ', '000060.SZ', '000061.SZ', '000062.SZ', '000063.SZ', '000065.SZ', '000066.SZ', '000068.SZ', '000069.SZ', '000070.SZ', '000078.SZ', '000088.SZ', '000089.SZ', '000090.SZ', '000096.SZ', '000099.SZ', '000100.SZ', '000151.SZ', '000153.SZ', '000155.SZ', '000156.SZ', '000157.SZ', '000158.SZ', '000159.SZ', '000166.SZ', '000301.SZ', '000333.SZ', '000338.SZ', '000400.SZ', '000401.SZ', '000402.SZ', '000403.SZ', '000404.SZ', '000407.SZ', '000408.SZ', '000409.SZ', '000410.SZ', '000411.SZ', '000413.SZ', '000415.SZ', '000416.SZ', '000417.SZ', '000419.SZ', '000420.SZ', '000421.SZ', '000422.SZ', '000423.SZ', '000425.SZ', '000426.SZ',
省略若干...
 
点击查看大图
20231025152005.png

 
是否遇到QMT或Ptrade的问题, 无从入手? 或者咨询无门 ?
来加入 知识星球 , 获取专业的技术解答, 量化实盘代码, 技术交流群

 

国金QMT测试版|模拟盘 安装程序 下载

李魔佛 发表了文章 • 0 个评论 • 2706 次浏览 • 2023-09-02 12:16 • 来自相关话题

国金证券QMT测试账号信息: 
登录账号:******* 登录密码:*********

QMT交易测试客户端下载链接 链接:https://download.gjzq.com.cn/temp/organ/gjzqqmt_ceshi.rar
 

 
 
在线接口文档:
https://qmt.ptradeapi.com
 
需要开通QMT的视频的朋友可以扫码咨询开通,目前国金开通门槛是入金2W就可以了。费率万一,可半年后免五。
开户后可提供技术相关解答。
  查看全部

20230902004.jpg


国金证券QMT测试账号信息: 
登录账号:******* 登录密码:*********

QMT交易测试客户端下载链接 链接:https://download.gjzq.com.cn/temp/organ/gjzqqmt_ceshi.rar
 

 
 
在线接口文档:
https://qmt.ptradeapi.com
 
需要开通QMT的视频的朋友可以扫码咨询开通,目前国金开通门槛是入金2W就可以了。费率万一,可半年后免五。
开户后可提供技术相关解答。
 

国金QMT实盘版本下载地址

李魔佛 发表了文章 • 0 个评论 • 2436 次浏览 • 2023-08-22 22:00 • 来自相关话题

官网没有提供下载地址,QMT一般是找经理开户后,然后申请QMT开通权限后,会发送账号和下载链接,还有接口文档,使用手册。
 

 
QMT实盘版下载地址:
https://download.gjzq.com.cn/gjty/organ/gjzqqmt.rar​
 
 
安装路径最好不要有中文,和空格。
 
实盘版里面可以切换模拟和实盘。
 





 
在线接口文档:
https://qmt.ptradeapi.com
 
需要开通QMT的朋友可以扫码咨询开通,目前国金开通门槛是入金2W就可以了。
开户后可提供技术相关解答。
 

 
 附一个国金Ptrade的下载地址:
Ptrade实盘版下载地址:
https://download.gjzq.com.cn/gjty/organ/gjzqptd.rar
  查看全部
官网没有提供下载地址,QMT一般是找经理开户后,然后申请QMT开通权限后,会发送账号和下载链接,还有接口文档,使用手册。
 

 
QMT实盘版下载地址:
https://download.gjzq.com.cn/gjty/organ/gjzqqmt.rar​
 
 
安装路径最好不要有中文,和空格。
 
实盘版里面可以切换模拟和实盘。
 

Screenshot_2023_0822_215654.png

 
在线接口文档:
https://qmt.ptradeapi.com
 
需要开通QMT的朋友可以扫码咨询开通,目前国金开通门槛是入金2W就可以了。
开户后可提供技术相关解答。
 

 
 附一个国金Ptrade的下载地址:
Ptrade实盘版下载地址:
https://download.gjzq.com.cn/gjty/organ/gjzqptd.rar
 

哪些券商有miniqmt? 门槛如何

李魔佛 发表了文章 • 0 个评论 • 1869 次浏览 • 2023-08-11 12:04 • 来自相关话题

miniqmt可以不在QMT的框架下编写代码,灵活性要高于QMT。
它属于一个精简版的QMT,把回测功能,UI界面操作功能去除。
 
你可以把miniqmt导入到你的项目里面,直接操作下单。
 from xtquant import xtdata
data = xtdata.get_market_data(field_list=['time', 'open', 'close', 'high', 'low', 'volume', 'amount'], stock_list=['603000.SH'], period='1d', start_time='20230101')
print(data)上面代码 可以直接在你的pycharm里面运行, 提前把 xtquant 这个包复制到系统路径,site-packages,或者自己加到环境变量。
 
 
MiniQMT支持新版本的Python
最新已经支持python3.6-3.11
更新方式:主QMT-设置-交易设置-模型设置里更新Python库
 
目前支持miniQTM的券商有哪些?
 
其实miniqmt是附属在QMT上的,正常有QMT的,默认就可以使用miniqmt,除非券商作妖,阉割了。
 
国金,国盛支持miniqmt,开通QMT后 miniqmt就是直接可以使用的。
 





 
而国信的miniqmt默认被阉割了,需要额外去申请。(可能还有些经理不敬业的,会和你说不支持miniqmt,曾经遇到过),不过国信的miniqmt开通后,个人只能拉取行情数据,是没有下单权限,下单券商是需要机构才可以申请。
 
国金的QMT,miniqmt的开通门槛会低一些,有入金2W就可以开通的营业部; 也有入金50W开通的营业部。 需要的盆友可以扫码咨询开通。
 
国盛的QMT,目前门槛比较高,需要资产100W才能开通。本身之前门槛还只是入金30W就可以的了,后面他们不断地提高门槛,提到50W,后面提高到100W,不过最近几天,营业部的经理和我说目前我这边开通只需要50W即可。
 
 所以平时有优惠费率的时候就不要犹犹豫豫,把账户和权限开了再说,因为好事不常有,过了这个桥就没有这个店。
 
 
需要开户的盆友可以扫码咨询

  查看全部
miniqmt可以不在QMT的框架下编写代码,灵活性要高于QMT。
它属于一个精简版的QMT,把回测功能,UI界面操作功能去除。
 
你可以把miniqmt导入到你的项目里面,直接操作下单。
 
from xtquant import xtdata
data = xtdata.get_market_data(field_list=['time', 'open', 'close', 'high', 'low', 'volume', 'amount'], stock_list=['603000.SH'], period='1d', start_time='20230101')
print(data)
上面代码 可以直接在你的pycharm里面运行, 提前把 xtquant 这个包复制到系统路径,site-packages,或者自己加到环境变量。
 
 
MiniQMT支持新版本的Python
最新已经支持python3.6-3.11
更新方式:主QMT-设置-交易设置-模型设置里更新Python库
 
目前支持miniQTM的券商有哪些?
 
其实miniqmt是附属在QMT上的,正常有QMT的,默认就可以使用miniqmt,除非券商作妖,阉割了。
 
国金,国盛支持miniqmt,开通QMT后 miniqmt就是直接可以使用的。
 

国金国盛.jpg

 
而国信的miniqmt默认被阉割了,需要额外去申请。(可能还有些经理不敬业的,会和你说不支持miniqmt,曾经遇到过),不过国信的miniqmt开通后,个人只能拉取行情数据,是没有下单权限,下单券商是需要机构才可以申请。
 
国金的QMT,miniqmt的开通门槛会低一些,有入金2W就可以开通的营业部; 也有入金50W开通的营业部。 需要的盆友可以扫码咨询开通。
 
国盛的QMT,目前门槛比较高,需要资产100W才能开通。本身之前门槛还只是入金30W就可以的了,后面他们不断地提高门槛,提到50W,后面提高到100W,不过最近几天,营业部的经理和我说目前我这边开通只需要50W即可。
 
 所以平时有优惠费率的时候就不要犹犹豫豫,把账户和权限开了再说,因为好事不常有,过了这个桥就没有这个店。
 
 
需要开户的盆友可以扫码咨询

 

国金证券QMT量化新人培训教程

李魔佛 发表了文章 • 0 个评论 • 3654 次浏览 • 2023-05-29 00:37 • 来自相关话题

最近国金证券邀请了QMT技术人员对内部用户进行了新人培训,并提供视频回放。
视频已经整理放到B站:
https://space.bilibili.com/73827743/channel/seriesdetail?sid=3326385&ctype=0
 
视频目录:
 





 
量化新人用QMT+chat GPT快速上手量化策略(一)QMT基础介绍

量化新人用QMT+chat GPT快速上手量化策略(二)QMT均线盘后选股

量化新人用QMT+chat GPT快速上手量化策略(三)一个基本的回测策略代码

量化新人用QMT+chat GPT快速上手量化策略(四) QMT运行一个策略的整体流程

量化新人用QMT+chat GPT快速上手量化策略(五) 获取股票数据

量化新人用QMT+chat GPT快速上手量化策略(六) tablib计算指标

量化新人用QMT+chat GPT快速上手量化策略(七) 下单代码编写
 
欢迎观看并提出疑问。
 
公众号:可转债量化分析 查看全部
最近国金证券邀请了QMT技术人员对内部用户进行了新人培训,并提供视频回放。
视频已经整理放到B站:
https://space.bilibili.com/73827743/channel/seriesdetail?sid=3326385&ctype=0
 
视频目录:
 

20230529001.jpg

 
量化新人用QMT+chat GPT快速上手量化策略(一)QMT基础介绍

量化新人用QMT+chat GPT快速上手量化策略(二)QMT均线盘后选股

量化新人用QMT+chat GPT快速上手量化策略(三)一个基本的回测策略代码

量化新人用QMT+chat GPT快速上手量化策略(四) QMT运行一个策略的整体流程

量化新人用QMT+chat GPT快速上手量化策略(五) 获取股票数据

量化新人用QMT+chat GPT快速上手量化策略(六) tablib计算指标

量化新人用QMT+chat GPT快速上手量化策略(七) 下单代码编写
 
欢迎观看并提出疑问。
 
公众号:可转债量化分析

QMT获取实时分笔委托数据用哪个函数?

李魔佛 发表了文章 • 0 个评论 • 1460 次浏览 • 2023-05-24 15:31 • 来自相关话题

.get_market_data 和 get_market_data_ex (第二版)都可以。
 
现在官方更加推荐使用第二版,速度要比第一版的要快,也就是推荐使用  .get_market_data_ex。
 
具体怎么使用呢?
 
def init(ContextInfo):
ContextInfo.run_time('execution', '3nSecond', '2019-10-14 13:20:00',)

def execution(ContextInfo):
if not ContextInfo.is_last_bar():
return
data = ContextInfo.get_market_data_ex(
[], ['123136.SZ'], period='tick'
, start_time='', end_time='', count=1
, dividend_type='follow', fill_data=True
, subscribe=True)
print(data)


def handlebar(ContextInfo):
#计算当前主图的cci
pass上面代码是每个3秒获取一次 城市转债 的分笔/逐笔数据。
 
然后在实盘重运行得到下面的结果:





 
(点击放大)
 
可以拿到分笔委托的价格,委卖1到5,委托量也可以看到,买和卖的5挡数据。
 
更多QMT的知识分享: 查看全部
.get_market_data 和 get_market_data_ex (第二版)都可以。
 
现在官方更加推荐使用第二版,速度要比第一版的要快,也就是推荐使用  .get_market_data_ex。
 
具体怎么使用呢?
 
def init(ContextInfo):
ContextInfo.run_time('execution', '3nSecond', '2019-10-14 13:20:00',)

def execution(ContextInfo):
if not ContextInfo.is_last_bar():
return
data = ContextInfo.get_market_data_ex(
[], ['123136.SZ'], period='tick'
, start_time='', end_time='', count=1
, dividend_type='follow', fill_data=True
, subscribe=True)
print(data)


def handlebar(ContextInfo):
#计算当前主图的cci
pass
上面代码是每个3秒获取一次 城市转债 的分笔/逐笔数据。
 
然后在实盘重运行得到下面的结果:

20230524152638683.png

 
(点击放大)
 
可以拿到分笔委托的价格,委卖1到5,委托量也可以看到,买和卖的5挡数据。
 
更多QMT的知识分享:

QMT委托对象orderInfo的属性以及对应的值

李魔佛 发表了文章 • 0 个评论 • 1435 次浏览 • 2023-05-18 15:43 • 来自相关话题

又得吐槽一次QMT的文档设计与撰写者。纯粹是业余水平+为了完成任务滥竽充数的API接口文档。
 
官网给出了来的oderInfo里面的字段以及简单的介绍(已经简单得不能再简单了,连对应的是什么类型都不写,懒的一笔)
 
m_strAccountID: 资金账号,账号,账号,资金账号

m_strExchangeID: 证券市场

m_strExchangeName: 交易市场

m_strProductID: 品种代码

m_strProductName: 品种名称

m_strInstrumentID: 证券代码

m_strInstrumentName: 证券名称,合约名称

m_strOrderRef: 内部委托号,下单引用等于股票的内部委托号

m_nOrderPriceType: EBrokerPriceType 类型,例如市价单、限价单

m_nDirection: EEntrustBS 类型,操作,多空,期货多空,股票买卖永远是 48,其他的 dir 同理

m_nOffsetFlag: EOffset_Flag_Type类型,买卖/开平,用此字段区分股票买卖,期货开、平仓,期权买卖等

m_nHedgeFlag: EHedge_Flag_Type 类型,投保

m_dLimitPrice: 委托价格,限价单的限价,就是报价

m_nVolumeTotalOriginal: 委托量,最初委托量

m_nOrderSubmitStatus: EEntrustSubmitStatus 类型,报单状态,提交状态,股票中不需要报单状态

m_strOrderSysID: 合同编号,委托号

m_nOrderStatus: EEntrustStatus,委托状态

m_nVolumeTraded: 成交数量,已成交量

m_nVolumeTotal: 委托剩余量,当前总委托量,股票的含义是总委托量减去成交量

m_nErrorID: 状态信息

m_strErrorMsg: 状态信息

m_nTaskId:任务号

m_dFrozenMargin: 冻结金额,冻结保证金

m_dFrozenCommission: 冻结手续费

m_strInsertDate: 委托日期,报单日期

m_strInsertTime: 委托时间

m_dTradedPrice: 成交均价(股票)

m_dCancelAmount: 已撤数量

m_strOptName: 买卖标记,展示委托属性的中文

m_dTradeAmount: 成交金额,成交额,期货 = 均价 * 量 * 合约乘数

m_eEntrustType: EEntrustTypes,委托类别

m_strCancelInfo: 废单原因

m_strUnderCode: 标的证券代码

m_eCoveredFlag: ECoveredFlag,备兑标记 '0' - 非备兑,'1' - 备兑

m_dOrderPriceRMB: 委托价格(人民币),目前用于港股通

m_dTradeAmountRMB: 成交金额(人民币),目前用于港股通

m_dReferenceRate: 汇率,目前用于港股通

m_strCompactNo: 合约编号

m_eCashgroupProp: EXTCompactBrushSource类型,头寸来源

m_dShortOccupedMargin: 预估在途占用保证金,用于期权

m_strXTTrade: 是否是迅投交易

m_strAccountKey: 账号key,唯一区别不同账号的key

m_strRemark:投资备注但我们可以直接使用枚举的方法,把上面的属性和对应的值列出来。
 
attr EBrokerPriceType value <class 'EBrokerPriceType'>
attr ECoveredFlag value <class 'ECoveredFlag'>
attr EEntrustBS value <class 'EEntrustBS'>
attr EEntrustStatus value <class 'EEntrustStatus'>
attr EEntrustSubmitStatus value <class 'EEntrustSubmitStatus'>
attr EEntrustTypes value <class 'EEntrustTypes'>
attr EFutureTradeType value <class 'EFutureTradeType'>
attr EHedge_Flag_Type value <class 'EHedge_Flag_Type'>
attr EOffset_Flag_Type value <class 'EOffset_Flag_Type'>
attr ESideFlag value <class 'ESideFlag'>
attr EXTCompactBrushSource value <class 'EXTCompactBrushSource'>
attr EXTCompactStatus value <class 'EXTCompactStatus'>
attr EXTCompactType value <class 'EXTCompactType'>
attr EXTSloTypeQueryMode value <class 'EXTSloTypeQueryMode'>
attr EXTSubjectsStatus value <class 'EXTSubjectsStatus'>
attr __class__ value <class 'COrderDetail'>
attr __delattr__ value <method-wrapper '__delattr__' of COrderDetail object at 0x000000004AD59A60>
attr __dict__ value {}
attr __dir__ value <built-in method __dir__ of COrderDetail object at 0x000000004AD59A60>
attr __doc__ value None
attr __eq__ value <method-wrapper '__eq__' of COrderDetail object at 0x000000004AD59A60>
attr __format__ value <built-in method __format__ of COrderDetail object at 0x000000004AD59A60>
attr __ge__ value <method-wrapper '__ge__' of COrderDetail object at 0x000000004AD59A60>
attr __getattribute__ value <method-wrapper '__getattribute__' of COrderDetail object at 0x000000004AD59A60>
attr __gt__ value <method-wrapper '__gt__' of COrderDetail object at 0x000000004AD59A60>
attr __hash__ value <method-wrapper '__hash__' of COrderDetail object at 0x000000004AD59A60>
attr __init__ value <bound method __init__ of <COrderDetail object at 0x000000004AD59A60>>
attr __init_subclass__ value <built-in method __init_subclass__ of Boost.Python.class object at 0x0000000044C55368>
attr __instance_size__ value 1088
attr __le__ value <method-wrapper '__le__' of COrderDetail object at 0x000000004AD59A60>
attr __lt__ value <method-wrapper '__lt__' of COrderDetail object at 0x000000004AD59A60>
attr __ne__ value <method-wrapper '__ne__' of COrderDetail object at 0x000000004AD59A60>
attr __new__ value <built-in method __new__ of Boost.Python.class object at 0x000007FEDCF525C0>
attr __reduce__ value <bound method <unnamed Boost.Python function> of <COrderDetail object at 0x000000004AD59A60>>
attr __reduce_ex__ value <built-in method __reduce_ex__ of COrderDetail object at 0x000000004AD59A60>
attr __repr__ value <method-wrapper '__repr__' of COrderDetail object at 0x000000004AD59A60>
attr __setattr__ value <method-wrapper '__setattr__' of COrderDetail object at 0x000000004AD59A60>
attr __sizeof__ value <built-in method __sizeof__ of COrderDetail object at 0x000000004AD59A60>
attr __str__ value <method-wrapper '__str__' of COrderDetail object at 0x000000004AD59A60>
attr __subclasshook__ value <built-in method __subclasshook__ of Boost.Python.class object at 0x0000000044C55368>
attr __weakref__ value None
attr j value j
attr m_bEnable value True
attr m_dCancelAmount value 0.0
attr m_dFrozenCommission value 0.15
attr m_dFrozenMargin value 1000.0
attr m_dLimitPrice value 2.3
具体的获取方式,可以到个人的知识星球获取。
星球也会不定时更新一些QMT常见的坑和问题,也可以提问:





 
 
这里简单介绍一下几个常用的字段:
attr m_nOrderStatus value  50
委托状态: 50代表已报, 注意,这里有个坑, 委托状态会返回2次,一次是先显示49,下一次是显示50,状态从待报-变成已报。 
 
  查看全部
又得吐槽一次QMT的文档设计与撰写者。纯粹是业余水平+为了完成任务滥竽充数的API接口文档。
 
官网给出了来的oderInfo里面的字段以及简单的介绍(已经简单得不能再简单了,连对应的是什么类型都不写,懒的一笔)
 
m_strAccountID: 资金账号,账号,账号,资金账号

m_strExchangeID: 证券市场

m_strExchangeName: 交易市场

m_strProductID: 品种代码

m_strProductName: 品种名称

m_strInstrumentID: 证券代码

m_strInstrumentName: 证券名称,合约名称

m_strOrderRef: 内部委托号,下单引用等于股票的内部委托号

m_nOrderPriceType: EBrokerPriceType 类型,例如市价单、限价单

m_nDirection: EEntrustBS 类型,操作,多空,期货多空,股票买卖永远是 48,其他的 dir 同理

m_nOffsetFlag: EOffset_Flag_Type类型,买卖/开平,用此字段区分股票买卖,期货开、平仓,期权买卖等

m_nHedgeFlag: EHedge_Flag_Type 类型,投保

m_dLimitPrice: 委托价格,限价单的限价,就是报价

m_nVolumeTotalOriginal: 委托量,最初委托量

m_nOrderSubmitStatus: EEntrustSubmitStatus 类型,报单状态,提交状态,股票中不需要报单状态

m_strOrderSysID: 合同编号,委托号

m_nOrderStatus: EEntrustStatus,委托状态

m_nVolumeTraded: 成交数量,已成交量

m_nVolumeTotal: 委托剩余量,当前总委托量,股票的含义是总委托量减去成交量

m_nErrorID: 状态信息

m_strErrorMsg: 状态信息

m_nTaskId:任务号

m_dFrozenMargin: 冻结金额,冻结保证金

m_dFrozenCommission: 冻结手续费

m_strInsertDate: 委托日期,报单日期

m_strInsertTime: 委托时间

m_dTradedPrice: 成交均价(股票)

m_dCancelAmount: 已撤数量

m_strOptName: 买卖标记,展示委托属性的中文

m_dTradeAmount: 成交金额,成交额,期货 = 均价 * 量 * 合约乘数

m_eEntrustType: EEntrustTypes,委托类别

m_strCancelInfo: 废单原因

m_strUnderCode: 标的证券代码

m_eCoveredFlag: ECoveredFlag,备兑标记 '0' - 非备兑,'1' - 备兑

m_dOrderPriceRMB: 委托价格(人民币),目前用于港股通

m_dTradeAmountRMB: 成交金额(人民币),目前用于港股通

m_dReferenceRate: 汇率,目前用于港股通

m_strCompactNo: 合约编号

m_eCashgroupProp: EXTCompactBrushSource类型,头寸来源

m_dShortOccupedMargin: 预估在途占用保证金,用于期权

m_strXTTrade: 是否是迅投交易

m_strAccountKey: 账号key,唯一区别不同账号的key

m_strRemark:投资备注
但我们可以直接使用枚举的方法,把上面的属性和对应的值列出来。
 
attr EBrokerPriceType value  <class 'EBrokerPriceType'>
attr ECoveredFlag value <class 'ECoveredFlag'>
attr EEntrustBS value <class 'EEntrustBS'>
attr EEntrustStatus value <class 'EEntrustStatus'>
attr EEntrustSubmitStatus value <class 'EEntrustSubmitStatus'>
attr EEntrustTypes value <class 'EEntrustTypes'>
attr EFutureTradeType value <class 'EFutureTradeType'>
attr EHedge_Flag_Type value <class 'EHedge_Flag_Type'>
attr EOffset_Flag_Type value <class 'EOffset_Flag_Type'>
attr ESideFlag value <class 'ESideFlag'>
attr EXTCompactBrushSource value <class 'EXTCompactBrushSource'>
attr EXTCompactStatus value <class 'EXTCompactStatus'>
attr EXTCompactType value <class 'EXTCompactType'>
attr EXTSloTypeQueryMode value <class 'EXTSloTypeQueryMode'>
attr EXTSubjectsStatus value <class 'EXTSubjectsStatus'>
attr __class__ value <class 'COrderDetail'>
attr __delattr__ value <method-wrapper '__delattr__' of COrderDetail object at 0x000000004AD59A60>
attr __dict__ value {}
attr __dir__ value <built-in method __dir__ of COrderDetail object at 0x000000004AD59A60>
attr __doc__ value None
attr __eq__ value <method-wrapper '__eq__' of COrderDetail object at 0x000000004AD59A60>
attr __format__ value <built-in method __format__ of COrderDetail object at 0x000000004AD59A60>
attr __ge__ value <method-wrapper '__ge__' of COrderDetail object at 0x000000004AD59A60>
attr __getattribute__ value <method-wrapper '__getattribute__' of COrderDetail object at 0x000000004AD59A60>
attr __gt__ value <method-wrapper '__gt__' of COrderDetail object at 0x000000004AD59A60>
attr __hash__ value <method-wrapper '__hash__' of COrderDetail object at 0x000000004AD59A60>
attr __init__ value <bound method __init__ of <COrderDetail object at 0x000000004AD59A60>>
attr __init_subclass__ value <built-in method __init_subclass__ of Boost.Python.class object at 0x0000000044C55368>
attr __instance_size__ value 1088
attr __le__ value <method-wrapper '__le__' of COrderDetail object at 0x000000004AD59A60>
attr __lt__ value <method-wrapper '__lt__' of COrderDetail object at 0x000000004AD59A60>
attr __ne__ value <method-wrapper '__ne__' of COrderDetail object at 0x000000004AD59A60>
attr __new__ value <built-in method __new__ of Boost.Python.class object at 0x000007FEDCF525C0>
attr __reduce__ value <bound method <unnamed Boost.Python function> of <COrderDetail object at 0x000000004AD59A60>>
attr __reduce_ex__ value <built-in method __reduce_ex__ of COrderDetail object at 0x000000004AD59A60>
attr __repr__ value <method-wrapper '__repr__' of COrderDetail object at 0x000000004AD59A60>
attr __setattr__ value <method-wrapper '__setattr__' of COrderDetail object at 0x000000004AD59A60>
attr __sizeof__ value <built-in method __sizeof__ of COrderDetail object at 0x000000004AD59A60>
attr __str__ value <method-wrapper '__str__' of COrderDetail object at 0x000000004AD59A60>
attr __subclasshook__ value <built-in method __subclasshook__ of Boost.Python.class object at 0x0000000044C55368>
attr __weakref__ value None
attr j value j
attr m_bEnable value True
attr m_dCancelAmount value 0.0
attr m_dFrozenCommission value 0.15
attr m_dFrozenMargin value 1000.0
attr m_dLimitPrice value 2.3

具体的获取方式,可以到个人的知识星球获取。
星球也会不定时更新一些QMT常见的坑和问题,也可以提问:

20230518001.jpg

 
 
这里简单介绍一下几个常用的字段:
attr m_nOrderStatus value  50
委托状态: 50代表已报, 注意,这里有个坑, 委托状态会返回2次,一次是先显示49,下一次是显示50,状态从待报-变成已报。 
 
 

QMT运行后的历史日志保存在哪个位置?

李魔佛 发表了文章 • 0 个评论 • 1434 次浏览 • 2023-05-11 14:10 • 来自相关话题

如果退出了QMT,那么在当前窗口运行的日志就会跟着消失。
 
PS: 知乎上这位是抄袭我的:
https://zhuanlan.zhihu.com/p/650119640
 
我这里有很多QMT的文章,都是没有原创没有加水印的





 
如果想要找回以前的历史日志,可以到下面的路径寻找;
以国信证券的iquant为例:
 
C:\iquant_gx\userdata\log
 
具体以你的券商路径安装名字为准
 





 
个人的日志输出在文件名:
XtClient_FormulaOutput_20230426 (后面的是日期,具体根据你要查找的时间来找)
 





 
看到没?
上面的日志就是记录当时的策略输出。
 
国信证券iQuant, 万一免五 开户,无门槛开通,
需要的可以联系:
可开通miniqmt 查看全部
如果退出了QMT,那么在当前窗口运行的日志就会跟着消失。
 
PS: 知乎上这位是抄袭我的:
https://zhuanlan.zhihu.com/p/650119640
 
我这里有很多QMT的文章,都是没有原创没有加水印的

20230511001.jpg

 
如果想要找回以前的历史日志,可以到下面的路径寻找;
以国信证券的iquant为例:
 
C:\iquant_gx\userdata\log
 
具体以你的券商路径安装名字为准
 

mmexport1683784887096.png

 
个人的日志输出在文件名:
XtClient_FormulaOutput_20230426 (后面的是日期,具体根据你要查找的时间来找)
 

20230511002.jpg

 
看到没?
上面的日志就是记录当时的策略输出。
 
国信证券iQuant, 万一免五 开户,无门槛开通,
需要的可以联系:
可开通miniqmt

迅投QMT修改编辑器字体大小,4个空格缩进(默认是TAB),背景颜色

李魔佛 发表了文章 • 0 个评论 • 1696 次浏览 • 2023-04-25 12:22 • 来自相关话题

QMT的默认编辑器是非常难用的。字体,大小,颜色,编码,缩进,一言难尽。
 
而且在菜单里面也找不到设置的地方。
 
其实用户是可以修改这个编辑器的配置的。
 
找到QMT的安装目录,找到config文件夹,里面有个editor.xml 的文件,用记事本或者notepad++等文本编辑器打开。
 





 
如果要修改字体大小,可以修改: 
 
  <font FamilyName="Courier New" IsBold="false" size="16"/>
 
把size设置大一点,字体即可变大。
 
如果要把tab缩进改为空格缩进(主流IDE,pycharm vscode都是4个空格缩进的),可以改成下面的
        <font FamilyName="Courier New" IsBold="false" size="20"/>

        <align TabStop="4" AutoIndent="true" IndentationsUseTabs="false" WrapWord="false"/>
 






 
如果需要修改背景色:
同理:
        <color bgcolor="255,255,255"/>
修改这一行,
比如变成黑色背景
        <color bgcolor="0,0,0"/>
 
PS: 上述配置部分券商可以在QMT的IDE上设置,比如字体大小等,而在这个xml里面修改却生效不了
 
改为后记得重启QMT生效
 
公众号后台回复:
qmt配置文件 
可以获取修改为tab缩进的配置文件
  查看全部
QMT的默认编辑器是非常难用的。字体,大小,颜色,编码,缩进,一言难尽。
 
而且在菜单里面也找不到设置的地方。
 
其实用户是可以修改这个编辑器的配置的。
 
找到QMT的安装目录,找到config文件夹,里面有个editor.xml 的文件,用记事本或者notepad++等文本编辑器打开。
 

20230425001.jpg

 
如果要修改字体大小,可以修改: 
 
  <font FamilyName="Courier New" IsBold="false" size="16"/>
 
把size设置大一点,字体即可变大。
 
如果要把tab缩进改为空格缩进(主流IDE,pycharm vscode都是4个空格缩进的),可以改成下面的
        <font FamilyName="Courier New" IsBold="false" size="20"/>

        <align TabStop="4" AutoIndent="true" IndentationsUseTabs="false" WrapWord="false"/>
 

20231012200620.png


 
如果需要修改背景色:
同理:
        <color bgcolor="255,255,255"/>
修改这一行,
比如变成黑色背景
        <color bgcolor="0,0,0"/>
 
PS: 上述配置部分券商可以在QMT的IDE上设置,比如字体大小等,而在这个xml里面修改却生效不了
 
改为后记得重启QMT生效
 
公众号后台回复:
qmt配置文件 
可以获取修改为tab缩进的配置文件
 

QMT vs Ptrade 速度对比 (二)实时行情速度对比

李魔佛 发表了文章 • 0 个评论 • 1675 次浏览 • 2023-04-23 00:33 • 来自相关话题

上一篇文章(QMT vs Ptrade 速度对比 (一) 历史行情获取速度)对了了QMT和Ptrade的获取历史行情速度,本篇文章继续对它俩的实时行情速度。

本文以获取市场所有可转债的实时行情为例子,比较二者的速度。



Ptrade获取所有可转债实时行情

目前市场上有480多只可转债,由于Ptrade内置的数据源不足以支撑可转债的大部分策略,所以需要调用外部数据源,因此使用国盛证券的Ptrade进行交易,因为目前只有它可以链接外网,你可以把可转债的数据写入到数据库或者写成自己的接口,传递给Ptrade就可以了。

比如下面的基础数据接口。



【目前星球用户可以提供数据接口免费调用功能,提供实时数据功能,强赎倒数多个API接口】

然后调用端使用python的requests库请求下就有了。下面代码可以在Ptrade里面部署运行,用于获取可转债溢价率,剩余规模等数据。







然后在Ptrade的定时执行函数里面获取实时tick数据,使用get_snapshot,把所有的转债代码传入get_snapshot就可以拿到可转债的行情数据了,行情数据3秒更新一次。





在Ptrade里面的运行情况



红框的地方是几个时间点要关注的。

481:获取的转债个数有481

红色数字1的位置: time used

获取行情数据所用的时间,大概在17毫秒(ms)左右,数据一直比较稳定。返回的数据里面字段除了价格,还有昨收价,委买卖1队列,涨停价,成交量等多个数据,参考上图里面的那个字典格式的数据。 具体可以参考接口文档(http://ptradeapi.com)

红色数字2的位置:日志输出时候的时间,也就是程序当前所在时刻,在目前程序在14:42:51,红色数字3的时间,是当前价格的里面的时间,也就tick对应的时间,当前的tick时间是hsTimeStamp: 20230419144251000, 也就是 2023-04-19 14:42:51:000, 所以当前时间程序获取的tick时间是一致的。为什么这里要强调这个呢? 假如当前程序时刻是14:42:51, 而获取的tick timestamp数据是14:42:48,那么说明当前程序拿到的最新tick数据却是在48秒时的数据,也就是数据延时了3秒。所以Ptrade里面的tick数据并没有出现延时滞后。



QMT 实时行情

同样QMT提供的可转债基础也是少的可怜,几乎为零。所以同样调用个人部署的可转债接口数据,如法炮制。PS:通过数据解耦的方式,不同数据可以在不同的量化软件里面使用,省去很多重复编写的代码,即使后面接入掘金,聚宽等平台,你只需要编写下单接口逻辑即可。



QMT取实时行情代码如下:








Bond是一个类,和ptrade里面的一样的,用来获取转债基础数据。

同样在QMT的实盘模式下执行:



网络环境:500M宽带网络,PC:CPU I7 - 内存24GB


stock num : 481 同样获取的是481个转债实时行情数据

红色数字1时间:日志输出的当前时间,获取行情数据前的时间14:43:25

红色数字2时间:日志输出的当前时间,此时为已经获取行情数据后的时间:14:43:34

红色数字3:第一次获取行情数据时间差,达到了9.5秒! 这个数字简直惊呆了。 反复测试几次后,依然如此,使用get_market_data获取实时行情数据,第一次数据到达的时候都要挺久的。

新人刚使用这个函数获取实时行情的时候,往往会以为自己代码出bug,等待很久没数据出来,尤其是获取超过1000个股票代码的行情的时候,等待时候更久,等待时间随着输入的个数增加而增加; 同时QMT占用内存也会稳步增加,如果机子的内存太小,可能还会卡死了。(qmt里面的坑还挺多的)









红色数字6,第二次获取实时行情所用的时间,这一次就快很多了,只用了800毫秒。



随着后续运行,获取实时行情的时间就趋于稳定,从800毫秒慢慢降到150毫秒,最后到13-20毫秒,基本和ptrade差不多级别了。











实时行情延时方面,对比通达信








取110048.SH 这个转债的行情数据作为参考,因为QMT返回字段里面没有带tick的时间戳,所以拿通达信作的分时数据作为的对比,没有用L2,所以框住的位置时间约在14:47:03 ~ 14:47:06

图片上半部分通达信的分时数据,左下角的数据时间是14:47:06,所以数据并没有出现很大的延时。



总结

QMT稳定运行的时候,实时行情基本和Ptrade同一级别水平。但QMT的行情波动性大一些。而在初始启动获取数据时,QMT会非常耗费资源,且等待时间较长,而Ptrade则不存在这种问题。

QMT可以随意获取外部数据,所以对券商没有很高要求;而Ptrade目前只有一家券商(国盛证券)可以自由访问外部数据,如果缺少需要的数据或者指标,将无法实现相应的策略。


参考API接口文档:

Ptrade: http://ptradeapi.com/
QMT: http://qmt.ptradeapi.com/

公众号: 查看全部

上一篇文章(QMT vs Ptrade 速度对比 (一) 历史行情获取速度)对了了QMT和Ptrade的获取历史行情速度,本篇文章继续对它俩的实时行情速度。

本文以获取市场所有可转债的实时行情为例子,比较二者的速度。



Ptrade获取所有可转债实时行情

目前市场上有480多只可转债,由于Ptrade内置的数据源不足以支撑可转债的大部分策略,所以需要调用外部数据源,因此使用国盛证券的Ptrade进行交易,因为目前只有它可以链接外网,你可以把可转债的数据写入到数据库或者写成自己的接口,传递给Ptrade就可以了。

比如下面的基础数据接口。



【目前星球用户可以提供数据接口免费调用功能,提供实时数据功能,强赎倒数多个API接口】

然后调用端使用python的requests库请求下就有了。下面代码可以在Ptrade里面部署运行,用于获取可转债溢价率,剩余规模等数据。







然后在Ptrade的定时执行函数里面获取实时tick数据,使用get_snapshot,把所有的转债代码传入get_snapshot就可以拿到可转债的行情数据了,行情数据3秒更新一次。





在Ptrade里面的运行情况



红框的地方是几个时间点要关注的。

481:获取的转债个数有481

红色数字1的位置: time used

获取行情数据所用的时间,大概在17毫秒(ms)左右,数据一直比较稳定。返回的数据里面字段除了价格,还有昨收价,委买卖1队列,涨停价,成交量等多个数据,参考上图里面的那个字典格式的数据。 具体可以参考接口文档(http://ptradeapi.com

红色数字2的位置:日志输出时候的时间,也就是程序当前所在时刻,在目前程序在14:42:51,红色数字3的时间,是当前价格的里面的时间,也就tick对应的时间,当前的tick时间是hsTimeStamp: 20230419144251000, 也就是 2023-04-19 14:42:51:000, 所以当前时间程序获取的tick时间是一致的。为什么这里要强调这个呢? 假如当前程序时刻是14:42:51, 而获取的tick timestamp数据是14:42:48,那么说明当前程序拿到的最新tick数据却是在48秒时的数据,也就是数据延时了3秒。所以Ptrade里面的tick数据并没有出现延时滞后。



QMT 实时行情

同样QMT提供的可转债基础也是少的可怜,几乎为零。所以同样调用个人部署的可转债接口数据,如法炮制。PS:通过数据解耦的方式,不同数据可以在不同的量化软件里面使用,省去很多重复编写的代码,即使后面接入掘金,聚宽等平台,你只需要编写下单接口逻辑即可。



QMT取实时行情代码如下:


20230420013.jpg



Bond是一个类,和ptrade里面的一样的,用来获取转债基础数据。

同样在QMT的实盘模式下执行:



网络环境:500M宽带网络,PC:CPU I7 - 内存24GB


stock num : 481 同样获取的是481个转债实时行情数据

红色数字1时间:日志输出的当前时间,获取行情数据前的时间14:43:25

红色数字2时间:日志输出的当前时间,此时为已经获取行情数据后的时间:14:43:34

红色数字3:第一次获取行情数据时间差,达到了9.5秒! 这个数字简直惊呆了。 反复测试几次后,依然如此,使用get_market_data获取实时行情数据,第一次数据到达的时候都要挺久的。

新人刚使用这个函数获取实时行情的时候,往往会以为自己代码出bug,等待很久没数据出来,尤其是获取超过1000个股票代码的行情的时候,等待时候更久,等待时间随着输入的个数增加而增加; 同时QMT占用内存也会稳步增加,如果机子的内存太小,可能还会卡死了。(qmt里面的坑还挺多的)









红色数字6,第二次获取实时行情所用的时间,这一次就快很多了,只用了800毫秒。



随着后续运行,获取实时行情的时间就趋于稳定,从800毫秒慢慢降到150毫秒,最后到13-20毫秒,基本和ptrade差不多级别了。











实时行情延时方面,对比通达信

20230420004-v1.jpg




取110048.SH 这个转债的行情数据作为参考,因为QMT返回字段里面没有带tick的时间戳,所以拿通达信作的分时数据作为的对比,没有用L2,所以框住的位置时间约在14:47:03 ~ 14:47:06

图片上半部分通达信的分时数据,左下角的数据时间是14:47:06,所以数据并没有出现很大的延时。



总结

QMT稳定运行的时候,实时行情基本和Ptrade同一级别水平。但QMT的行情波动性大一些。而在初始启动获取数据时,QMT会非常耗费资源,且等待时间较长,而Ptrade则不存在这种问题。

QMT可以随意获取外部数据,所以对券商没有很高要求;而Ptrade目前只有一家券商(国盛证券)可以自由访问外部数据,如果缺少需要的数据或者指标,将无法实现相应的策略。


参考API接口文档:

Ptrade: http://ptradeapi.com/
QMT: http://qmt.ptradeapi.com/

公众号:

QMT vs Ptrade 速度对比 (一) 历史行情获取速度

李魔佛 发表了文章 • 0 个评论 • 2154 次浏览 • 2023-04-11 16:45 • 来自相关话题

众所周知(狗头),QMT是在你本地电脑运行的,包括行情获取,计算指标,选股选债,下单都在你的本地电脑执行。行情数据通过网络去券商服务器或者迅投(QMT)服务器获取,拿到数据在你的本地电脑处理,比如计算涨速,量比,然后再使用下单接口把下单指令通过网络提交到券商柜台,券商柜台接到QMT的委托指令后,再提交给交易所。

Ptrade(恒生电子)则是在券商部署的服务器上执行,你下载的Ptrade在你的本地电脑,只是负责写代码,把代码部署到券商服务器,然后在券商服务其执行你的策略,当然你的代码在券商服务器运行时是被加密的。行情获取,计算指标,下单委托都在券商机房内部执行,属于云策略的类型,策略部署好了,就不需要开着本地电脑观察它的状态。

对比环境均为同一个券商下的QMT和Ptrade,均为生产环境的实盘版本。(PS:温馨提示,平时少用模拟版本,bug多,交易不准,还浪费时间。我平时调试都直接在实盘上调试的,要对自己的策略有信心哈,至少回测过了的嘛O(∩_∩)O~~)

历史行情数据获取

目标:获取2022年到昨天的沪深300所有股票的日线收盘价数据。

QMT

获取行情数据 使用这个函数:ContextInfo.get_market_data()用法: ContextInfo.get_market_data(fields, stock_code = , start_time = '',
end_time = '', skip_paused = True, period = 'follow',
dividend_type = 'follow', count = -1)
 open -- 开盘价(str:numpy.float64);
high -- 最高价(str:numpy.float64);
low --最低价(str:numpy.float64);
close -- 收盘价(str:numpy.float64);
volume -- 交易量(str:numpy.float64);
money -- 交易金额(str:numpy.float64);
price -- 最新价(str:numpy.float64);
preclose -- 昨收盘价(str:numpy.float64)(仅日线返回);
high_limit -- 涨停价(str:numpy.float64)(仅日线返回);
low_limit -- 跌停价(str:numpy.float64)(仅日线返回);
unlimited -- 判断查询日是否无涨跌停限制(1:该日无涨跌停限制;0:该日有涨跌停限制)(str:numpy.float64)(仅日线返回);
 
在fields里面指定只获取close价格即可。

QMT测试代码如下:(需要的也可以后台留言回复获取)

[vscode里面的代码,需要复制到qmt里面执行]

把代码复制到QMT里面,然后切换到模型交易,在中间切换到实盘模式,就会运行上面代码。

注意,这里需要第一次运行上面的代码来计算时间,因为QMT会有个cache缓存机制,它会把曾经跑过的历史数据自动下载下来,保存到你的电脑硬盘里,从而加快QMT后续的读取速度,同样的数据没有必要每次再去网络上拉。

大部分情况下网络IO都会是任何一个量化交易系通最大的性能瓶颈。

运行得到下面的结果:







上面运行时间是22秒。不要惊讶哦,首次获取历史行情数据都是挺慢的。如果你的电脑网速够快,或者但在阿里云,腾讯云之类的云服务上跑,获取历史行情速度会有所提高。

在你运行了上面的代码之后,QMT会在某个时刻,在后台把数据下载到本地QMT安装目录下。








文件按照股票代码作为文件名存储。当然里面不是txt格式,而是QMT做了相应的封装的。上面按照修改日期排序,4月11日多了很多新的DAT数据文件,显然是刚刚生成的。

QMT在获取历史行情数据后,会有个触发器,在后台一次性保存大量的文件,所以QMT会在某一个瞬间,界面会出现卡顿,甚至无响应,而看任务管理器会看到内存飙升甚至爆满100%,有些新人菜鸟就认为QMT太占内存,太垃圾的结论,这也是片面的。实际上在数据完备的情况下,QMT需要的内存4GB就够的了。如果你经常会有扫描全市场股票代码历史数据的话,内存还是尽量选大一点的。如果无法避免内存突然飙升,可以每次把获取行情的股票代码列表减少,细分多几批获取,用时间换空间。

当然 QMT也提供了一个下载历史数据的一个菜单入口,用于在图形界面下手动下载历史行情,从而加速历史行情读取速度。








等数据下载完成后,

第二次跑上面的同一个代码,运行时间明显快了。








但用时还是要7.9秒,反复测试几次,获取时间依然是在6-8秒之间波动。 因为程序读取历史行情数据的一个个独立的文件,所以这里硬盘的性能因素对获取行情影响还是很大的。

笔者感觉7.9秒这个速度还是很慢的,换了台性能好一点的的windows机子,下载了历史数据后再跑了一次:







但用时依然在6秒左右。

所以个人是不推荐大家在tick策略里面,在盘中去获取历史数据的,这个动作应该在盘前就应该完成,把数据保存到内存列表或者dataframe变量中,盘中用的时候去取就可以了。 当然低频策略就无所谓啦。

Ptrade

操作上ptrade相对而言更加简洁,容易上手。

它的API设计和它对应的API文档更加规范,可读性更好。

直接把代码复制到量化->策略,新建策略,然后在交易里面添加策略,直接启动策略。代码设置定时运行,在启动策略后的一分钟后运行。








同样获取沪深300的日线数据,2022年1月到2023年4月10日。
get_price - 获取历史数据 get_price(security, start_date=None, end_date=None, frequency='1d', fields=None, fq=None, count=None)
运行 







上面的结果显示,Ptrade获取同样的历史数据耗时只有700毫秒,0.7秒左右。测试多几次,获取时间基本每次都比较平稳,在0.6-0.8秒之间。(下面打印的306不是沪深300的个数,而是获取到的日期的天数,它返回的结构虽然都是panel,但和QMT的轴有点不同)。

结论

总的来说,获取历史行情数据的速度,Ptrade是秒杀了QMT的,不在一个量级上的。

本来想继续对比实时行情,下单延时对比等等,但开盘时间有限,写了一下时间就不够用了。所以把教程拆分为多个系列,下一篇再对比QMT和PTrade的实时行情数据,下单回调等等啦。


如果想要自己测试文中的数据,可以获取代码,公众号 后台回复: 历史行情数据代码

参考API接口文档:

Ptrade: http://ptradeapi.com/

QMT: http://qmt.ptradeapi.com/
 
公众号: 查看全部
众所周知(狗头),QMT是在你本地电脑运行的,包括行情获取,计算指标,选股选债,下单都在你的本地电脑执行。行情数据通过网络去券商服务器或者迅投(QMT)服务器获取,拿到数据在你的本地电脑处理,比如计算涨速,量比,然后再使用下单接口把下单指令通过网络提交到券商柜台,券商柜台接到QMT的委托指令后,再提交给交易所。

Ptrade(恒生电子)则是在券商部署的服务器上执行,你下载的Ptrade在你的本地电脑,只是负责写代码,把代码部署到券商服务器,然后在券商服务其执行你的策略,当然你的代码在券商服务器运行时是被加密的。行情获取,计算指标,下单委托都在券商机房内部执行,属于云策略的类型,策略部署好了,就不需要开着本地电脑观察它的状态。

对比环境均为同一个券商下的QMT和Ptrade,均为生产环境的实盘版本。(PS:温馨提示,平时少用模拟版本,bug多,交易不准,还浪费时间。我平时调试都直接在实盘上调试的,要对自己的策略有信心哈,至少回测过了的嘛O(∩_∩)O~~)

历史行情数据获取

目标:获取2022年到昨天的沪深300所有股票的日线收盘价数据。

QMT

获取行情数据 使用这个函数:ContextInfo.get_market_data()
用法: ContextInfo.get_market_data(fields, stock_code = , start_time = '', 
end_time = '', skip_paused = True, period = 'follow',
dividend_type = 'follow', count = -1)

 
open -- 开盘价(str:numpy.float64);
high -- 最高价(str:numpy.float64);
low --最低价(str:numpy.float64);
close -- 收盘价(str:numpy.float64);
volume -- 交易量(str:numpy.float64);
money -- 交易金额(str:numpy.float64);
price -- 最新价(str:numpy.float64);
preclose -- 昨收盘价(str:numpy.float64)(仅日线返回);
high_limit -- 涨停价(str:numpy.float64)(仅日线返回);
low_limit -- 跌停价(str:numpy.float64)(仅日线返回);
unlimited -- 判断查询日是否无涨跌停限制(1:该日无涨跌停限制;0:该日有涨跌停限制)(str:numpy.float64)(仅日线返回);

 
在fields里面指定只获取close价格即可。

QMT测试代码如下:(需要的也可以后台留言回复获取)

[vscode里面的代码,需要复制到qmt里面执行]

把代码复制到QMT里面,然后切换到模型交易,在中间切换到实盘模式,就会运行上面代码。

注意,这里需要第一次运行上面的代码来计算时间,因为QMT会有个cache缓存机制,它会把曾经跑过的历史数据自动下载下来,保存到你的电脑硬盘里,从而加快QMT后续的读取速度,同样的数据没有必要每次再去网络上拉。

大部分情况下网络IO都会是任何一个量化交易系通最大的性能瓶颈。

运行得到下面的结果:


20230411015.jpg


上面运行时间是22秒。不要惊讶哦,首次获取历史行情数据都是挺慢的。如果你的电脑网速够快,或者但在阿里云,腾讯云之类的云服务上跑,获取历史行情速度会有所提高。

在你运行了上面的代码之后,QMT会在某个时刻,在后台把数据下载到本地QMT安装目录下。


20230411014.jpg



文件按照股票代码作为文件名存储。当然里面不是txt格式,而是QMT做了相应的封装的。上面按照修改日期排序,4月11日多了很多新的DAT数据文件,显然是刚刚生成的。

QMT在获取历史行情数据后,会有个触发器,在后台一次性保存大量的文件,所以QMT会在某一个瞬间,界面会出现卡顿,甚至无响应,而看任务管理器会看到内存飙升甚至爆满100%,有些新人菜鸟就认为QMT太占内存,太垃圾的结论,这也是片面的。实际上在数据完备的情况下,QMT需要的内存4GB就够的了。如果你经常会有扫描全市场股票代码历史数据的话,内存还是尽量选大一点的。如果无法避免内存突然飙升,可以每次把获取行情的股票代码列表减少,细分多几批获取,用时间换空间。

当然 QMT也提供了一个下载历史数据的一个菜单入口,用于在图形界面下手动下载历史行情,从而加速历史行情读取速度。


20230411017.jpg



等数据下载完成后,

第二次跑上面的同一个代码,运行时间明显快了。


20230411018.jpg



但用时还是要7.9秒,反复测试几次,获取时间依然是在6-8秒之间波动。 因为程序读取历史行情数据的一个个独立的文件,所以这里硬盘的性能因素对获取行情影响还是很大的。

笔者感觉7.9秒这个速度还是很慢的,换了台性能好一点的的windows机子,下载了历史数据后再跑了一次:


20230411019.jpg


但用时依然在6秒左右。

所以个人是不推荐大家在tick策略里面,在盘中去获取历史数据的,这个动作应该在盘前就应该完成,把数据保存到内存列表或者dataframe变量中,盘中用的时候去取就可以了。 当然低频策略就无所谓啦。

Ptrade

操作上ptrade相对而言更加简洁,容易上手。

它的API设计和它对应的API文档更加规范,可读性更好。

直接把代码复制到量化->策略,新建策略,然后在交易里面添加策略,直接启动策略。代码设置定时运行,在启动策略后的一分钟后运行。


20230411016.jpg



同样获取沪深300的日线数据,2022年1月到2023年4月10日。
get_price - 获取历史数据 get_price(security, start_date=None, end_date=None, frequency='1d', fields=None, fq=None, count=None)
运行 

20230411013.jpg



上面的结果显示,Ptrade获取同样的历史数据耗时只有700毫秒,0.7秒左右。测试多几次,获取时间基本每次都比较平稳,在0.6-0.8秒之间。(下面打印的306不是沪深300的个数,而是获取到的日期的天数,它返回的结构虽然都是panel,但和QMT的轴有点不同)。

结论

总的来说,获取历史行情数据的速度,Ptrade是秒杀了QMT的,不在一个量级上的。

本来想继续对比实时行情,下单延时对比等等,但开盘时间有限,写了一下时间就不够用了。所以把教程拆分为多个系列,下一篇再对比QMT和PTrade的实时行情数据,下单回调等等啦。


如果想要自己测试文中的数据,可以获取代码,公众号 后台回复: 历史行情数据代码

参考API接口文档:

Ptrade: http://ptradeapi.com/

QMT: http://qmt.ptradeapi.com/
 
公众号:

国信如何运行miniQMT

李魔佛 发表了文章 • 0 个评论 • 2366 次浏览 • 2023-03-30 02:31 • 来自相关话题

国信的QMT名字叫iQuant, 它也有属于自己的miniQMT。
不过它需要额外申请。就看你的经理愿不愿意帮你去申请了。
毕竟申请这个没有资金要求,纯粹看经理的心情了。申请需要打印纸质电子版文件并签字,拍照发给营业部审核。
 
而且开通了miniQMT后,只能拉取数据,无法进行交易,因为个人是没有交易权限的,只有机构才可以申请miniQMT的交易权限。
 这也是经理不愿意帮你开通的原因,他们有可能会说国信目前不支持miniQMT这样的胡话来推搪打发你。如果需要申请开通,可以联系文末二维码开通国信iquant和miniQMT,这位经理比较热心肠,只要申请,就可以帮你开通miniQMT权限。
 
如何打开国信的miniQMT?
 
国信的miniQMT并不是和iQuant绑定的,笔者怀疑是因为iQuant定制化过多,甚至把miniQMT给阉割了。以至于为了补回miniQMT,他们还得特意要下载一个QMT的客户端(其实这个就是其他券商的QMT客户端),然后使用这个客户端和xtquant通讯。
 
 
输入个人的账户和密码后,登录极速版,对,国信的极速版即使miniQMT了。勾选极简模式。 国信的miniQMT支持自动登录,这个比国金的要好。国金的由于没有自动登录,每天还得自己手动的登录一次。(笔者之前也提供了几个版本的自动登录脚本,需要的可以到星球获取)





 





 
 
行情源这里要注意,如果你选择的获取最新价,那么在获取行情数据的返回值里面,只有最新价格,没有5档委托价格。( 国信iquant并没有这个选择菜单,估计是深度定制了,删除了)。
 
由于没有交易权限,账户里面没有显示个人的持仓信息,直接是空白一片





然后把xtquant的文件夹复制到本地的python site-package目录下。用以下下载数据的代码测试一下:
 import pandas as pd
import datetime


def get_tick(code, start_time, end_time, period='tick'):
from xtquant import xtdata

xtdata.download_history_data(code, period=period, start_time=start_time, end_time=end_time)
data = xtdata.get_local_data(field_list=, stock_code=, period=period, count=10)
result_list = data df = pd.DataFrame(result_list)

df['time_str'] = df['time'].apply(lambda x: datetime.datetime.fromtimestamp(x / 1000.0))
return df


def process_timestamp(df, filename):
df = df.set_index('time_str')
result = df.resample('3S').first().ffill()
# result = result[(result.index >= '2022-07-20 09:30') & (result.index <= '2022-07-20 15:00')]
result = result.reset_index()
result.to_csv(filename + '.csv')


def dump_single_code_tick():
# 导出单个转债的tick数据
code='128022'
start_date = '20210113'
end_date = '20210130'

post_fix = 'SZ' if code.startswith('12') else 'SH'
code = '{}.{}'.format(code,post_fix)
filename = '{}'.format(code)
df = get_tick(code, start_date, end_date)
process_timestamp(df, filename)

dump_single_code_tick()保存上述代码为app.py
运行python app.py
 
稍等片刻,数据导出到当前路径,名字为:

128022.sz 
 
打开看一下,数据在csv里面的了。
 
可关注下面关注号; 如需要开通国信,可以后台回复:开通国信证券
 

  查看全部
国信的QMT名字叫iQuant, 它也有属于自己的miniQMT。
不过它需要额外申请。就看你的经理愿不愿意帮你去申请了。
毕竟申请这个没有资金要求,纯粹看经理的心情了。申请需要打印纸质电子版文件并签字,拍照发给营业部审核。
 
而且开通了miniQMT后,只能拉取数据,无法进行交易,因为个人是没有交易权限的,只有机构才可以申请miniQMT的交易权限。
 这也是经理不愿意帮你开通的原因,他们有可能会说国信目前不支持miniQMT这样的胡话来推搪打发你。如果需要申请开通,可以联系文末二维码开通国信iquant和miniQMT,这位经理比较热心肠,只要申请,就可以帮你开通miniQMT权限。
 
如何打开国信的miniQMT?
 
国信的miniQMT并不是和iQuant绑定的,笔者怀疑是因为iQuant定制化过多,甚至把miniQMT给阉割了。以至于为了补回miniQMT,他们还得特意要下载一个QMT的客户端(其实这个就是其他券商的QMT客户端),然后使用这个客户端和xtquant通讯。
 
 
输入个人的账户和密码后,登录极速版,对,国信的极速版即使miniQMT了。勾选极简模式。 国信的miniQMT支持自动登录,这个比国金的要好。国金的由于没有自动登录,每天还得自己手动的登录一次。(笔者之前也提供了几个版本的自动登录脚本,需要的可以到星球获取)

20230330002.jpg

 

20230330001.jpg

 
 
行情源这里要注意,如果你选择的获取最新价,那么在获取行情数据的返回值里面,只有最新价格,没有5档委托价格。( 国信iquant并没有这个选择菜单,估计是深度定制了,删除了)。
 
由于没有交易权限,账户里面没有显示个人的持仓信息,直接是空白一片

20230330003.jpg

然后把xtquant的文件夹复制到本地的python site-package目录下。用以下下载数据的代码测试一下:
 
import pandas as pd
import datetime


def get_tick(code, start_time, end_time, period='tick'):
from xtquant import xtdata

xtdata.download_history_data(code, period=period, start_time=start_time, end_time=end_time)
data = xtdata.get_local_data(field_list=, stock_code=
, period=period, count=10)
result_list = data
    df = pd.DataFrame(result_list)

df['time_str'] = df['time'].apply(lambda x: datetime.datetime.fromtimestamp(x / 1000.0))
return df


def process_timestamp(df, filename):
df = df.set_index('time_str')
result = df.resample('3S').first().ffill()
# result = result[(result.index >= '2022-07-20 09:30') & (result.index <= '2022-07-20 15:00')]
result = result.reset_index()
result.to_csv(filename + '.csv')


def dump_single_code_tick():
# 导出单个转债的tick数据
code='128022'
start_date = '20210113'
end_date = '20210130'

post_fix = 'SZ' if code.startswith('12') else 'SH'
code = '{}.{}'.format(code,post_fix)
filename = '{}'.format(code)
df = get_tick(code, start_date, end_date)
process_timestamp(df, filename)

dump_single_code_tick()
保存上述代码为app.py
运行python app.py
 
稍等片刻,数据导出到当前路径,名字为:

128022.sz 
 
打开看一下,数据在csv里面的了。
 
可关注下面关注号; 如需要开通国信,可以后台回复:开通国信证券
 

 

qmt position对象里面有哪些属性?

李魔佛 发表了文章 • 0 个评论 • 1300 次浏览 • 2023-02-27 22:12 • 来自相关话题

查看属性的代码:
  obj_list = get_trade_detail_data(ACCOUNT,'stock','position')
for obj in obj_list:
print(obj.m_strInstrumentID,obj.m_strInstrumentName,'----')
# 查看有哪些属性字段
print('='*10)
for item in dir(obj):
if not item.startswith('__'):
print(item)

print('='*10)
得到的position的内置属性有下面的:m_bIsToday
m_dAvgOpenPrice
m_dCloseAmount
m_dCloseProfit
m_dFloatProfit
m_dInstrumentValue
m_dLastPrice
m_dLastSettlementPrice
m_dMargin
m_dMarketValue
m_dOpenCost
m_dOpenPrice
m_dPositionCost
m_dPositionProfit
m_dProfitRate
m_dRealUsedMargin
m_dRedemptionVolume
m_dReferenceRate
m_dRoyalty
m_dSettlementPrice
m_dSingleCost
m_dStaticHoldMargin
m_dStockLastPrice
m_dStructFundVol
m_dTotalCost
m_eFutureTradeType
m_eSideFlag
m_nCanUseVolume
m_nCidIncrease
m_nCidIsDelist
m_nCidRateOfCurrentLine
m_nCidRateOfTotalValue
m_nCloseVolume
m_nCoveredVolume
m_nDirection
m_nEnableExerciseVolume
m_nFrozenVolume
m_nHedgeFlag
m_nLegId
m_nOnRoadVolume
m_nOptCombUsedVolume
m_nPREnableVolume
m_nVolume
m_nYesterdayVolume
m_strAccountID
m_strAccountKey
m_strComTradeID
m_strExchangeID
m_strExchangeName
m_strExpireDate
m_strInstrumentID
m_strInstrumentName
m_strOpenDate
m_strProductID
m_strProductName
m_strStockHolder
m_strTradeID
m_strTradingDay
m_xtTag
虽然有上面的属性,但是实际上很可能是空的,并没有值。






  查看全部
查看属性的代码:
 
    obj_list = get_trade_detail_data(ACCOUNT,'stock','position')
for obj in obj_list:
print(obj.m_strInstrumentID,obj.m_strInstrumentName,'----')
# 查看有哪些属性字段
print('='*10)
for item in dir(obj):
if not item.startswith('__'):
print(item)

print('='*10)

得到的position的内置属性有下面的:
m_bIsToday
m_dAvgOpenPrice
m_dCloseAmount
m_dCloseProfit
m_dFloatProfit
m_dInstrumentValue
m_dLastPrice
m_dLastSettlementPrice
m_dMargin
m_dMarketValue
m_dOpenCost
m_dOpenPrice
m_dPositionCost
m_dPositionProfit
m_dProfitRate
m_dRealUsedMargin
m_dRedemptionVolume
m_dReferenceRate
m_dRoyalty
m_dSettlementPrice
m_dSingleCost
m_dStaticHoldMargin
m_dStockLastPrice
m_dStructFundVol
m_dTotalCost
m_eFutureTradeType
m_eSideFlag
m_nCanUseVolume
m_nCidIncrease
m_nCidIsDelist
m_nCidRateOfCurrentLine
m_nCidRateOfTotalValue
m_nCloseVolume
m_nCoveredVolume
m_nDirection
m_nEnableExerciseVolume
m_nFrozenVolume
m_nHedgeFlag
m_nLegId
m_nOnRoadVolume
m_nOptCombUsedVolume
m_nPREnableVolume
m_nVolume
m_nYesterdayVolume
m_strAccountID
m_strAccountKey
m_strComTradeID
m_strExchangeID
m_strExchangeName
m_strExpireDate
m_strInstrumentID
m_strInstrumentName
m_strOpenDate
m_strProductID
m_strProductName
m_strStockHolder
m_strTradeID
m_strTradingDay
m_xtTag

虽然有上面的属性,但是实际上很可能是空的,并没有值。

20230227004.jpg


 

qmt 可转债 双低(阈值)轮动 实盘代码

李魔佛 发表了文章 • 0 个评论 • 2011 次浏览 • 2023-02-26 15:18 • 来自相关话题

之前在星球埋的坑,答应群友写个qmt的双低可转债的轮动实盘代码。
用已有的ptrade的代码,然后部分获取行情和交易接口按照qmt的接口文档(http://qmt.ptradeapi.com )重写,就给了一版。(对,很早以前就有一版ptrade的转债双低的了)
 
无论是qmt还是ptrade,都只是一个工具,用熟悉了,都无所哪个好哪个不好。





 





 





 
 
完整代码在个人星球。
 
觉得之前星球太便宜了,不仅给了代码,还部署了接口免费使用,通过接口获取可转债的实时数据,强赎天数,规模,溢价率,评级等等一系列数据。 而且随着时间的推移,里面积累的数据,代码也越来越多,感觉这样对前面进去并不断续费的星友有点公平,尽管以后他们续费都直接打折扣。所以还是按照一些大v运营的意见,逐年涨价策略。
越往后的朋友,因为前面积累的内容越多,因此价格也随之增长。
 
当然有能力可以自己写接口,部署,实盘,获取三方数据的大v,就没必要加了。
  查看全部
之前在星球埋的坑,答应群友写个qmt的双低可转债的轮动实盘代码。
用已有的ptrade的代码,然后部分获取行情和交易接口按照qmt的接口文档(http://qmt.ptradeapi.com )重写,就给了一版。(对,很早以前就有一版ptrade的转债双低的了)
 
无论是qmt还是ptrade,都只是一个工具,用熟悉了,都无所哪个好哪个不好。

20230217003.jpg

 

20230226011.jpg

 

20230226012.jpg

 
 
完整代码在个人星球。
 
觉得之前星球太便宜了,不仅给了代码,还部署了接口免费使用,通过接口获取可转债的实时数据,强赎天数,规模,溢价率,评级等等一系列数据。 而且随着时间的推移,里面积累的数据,代码也越来越多,感觉这样对前面进去并不断续费的星友有点公平,尽管以后他们续费都直接打折扣。所以还是按照一些大v运营的意见,逐年涨价策略。
越往后的朋友,因为前面积累的内容越多,因此价格也随之增长。
 
当然有能力可以自己写接口,部署,实盘,获取三方数据的大v,就没必要加了。