QMT vs PTrade资金更新速度|高频中如何处理

QMT vs PTrade资金更新速度|高频中如何处理

平时在手动交易中,下单委托后,再切换回去持仓页面,可以看到你的可用资金变少了。而在QMT和PTrade里面,却可能会表现得不一样。本文用代码和实盘来作对比。希望本文对量化新手有所帮助,记得收藏哦! 公众号首页链接了视频号,里面也有不少的新手入门教程和进阶教程,欢迎观看。

了解量化交易程序里面的资金更新速度,无论对量化T+0日内交易(可转债,T+0 ETF),还是轮动策略调仓,都是必须的。

Ptrade

以交易逆回购为例,这也便于量化新手也可以实践,可以放心跑,不会亏钱。

代码很简单,每个tick_data行情更新时间(3秒)里打印当前的可用资金。中途买入(借出)逆回购后,看看当面打印的可用资金什么时候发生变化。
 
import datetime

def initialize(context):
# 初始化策略
g.already_run = False

def handle_data(context, data):
pass

def get_available_cash(context):
# 读取变量protfolio里的可用资金的值
return context.portfolio.cash

def current_time():
return datetime.datetime.now().strftime('%H:%M:%S.%f')

def tick_data(context, data):
log.info('可用资金{}'.format(get_available_cash(context)))
if not g.already_run:
g.already_run = True
# 卖出100手 R-001
ret = order_tick('131810.SZ', -10, priceGear='1', limit_price=None)

def on_order_response(context, trade_list):
# 委托回调函数,有委托出现就调用此函数
log.info('已委托下单 {}'.format(current_time()))


放到Ptrade的实盘里执行,得到下面日志


20230706001.jpg



下单前可用资金为17902,程序启动后下单时间在10:41:08,卖出10张R-001,市值1000元;间隔3s后打印可用资金,在10:41:13的时候,可用资金依然是17902,此时时间已经过去了5秒;

在10:41:18打印的时候资产才发生了变化,此时可用资金为16902,此时距离下单时的10:41:08,已经过去了10秒。所以如果在高频下单时,使用读取内置的context.portfolio.cash 来获取可用资金,那就寄了。那是不是意味着Ptrade无法进行高频率的交易了呢?当然不是的,此时可以使用内置的成交主推函数来更新可用资金,后面下面再介绍。

QMT

而qmt的代码如下,把打印的可用资金的操作放到handlebar里面,它和上面的Ptrade作用一样,每隔3s执行一次。
# encoding:gbk
import datetime


ACCOUNT = '你的账户ID'
start = True

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

def current_time():
return datetime.datetime.now().strftime('%H:%M:%S.%f')


def get_available_cash(ContextInfo):
acct_info = get_trade_detail_data(ACCOUNT, 'stock', 'account')
return acct_info[0].m_dAvailable


def deal_callback(ContextInfo, dealInfo):
print('before')
print(dealInfo.m_strProductID)
print(dealInfo.m_nDirection)
print(dealInfo.m_dTradeAmount)
print(dealInfo.m_nVolume)
print(dealInfo.m_dPrice)
print('call back --- ')
print(current_time())

def buy_action(ContextInfo):
opType = 24
orderType = 1101
accountID = ACCOUNT
orderCode = '131810.SZ'
prType = 11
price = 1.8
volume = 10
quickTrade = 2
passorder(opType, orderType, accountID, orderCode, prType, price, volume, quickTrade, ContextInfo)

def handlebar(ContextInfo):
global start
if ContextInfo.is_last_bar():

cash = get_available_cash(ContextInfo)
print('{} 可用资金{}'.format(current_time(),cash))
if start:
print('下单逆回购 131810 ')
buy_action(ContextInfo)
start = False

 
部署到QMT实盘后,执行。

得到下面的运行日志:


20230705001.jpg



从上面的日志看出,程序在14:35:11启动,马上使用passorder下单,卖出1000元的R-001,此时时间14:35:12,马上成交了。而可用资金在下单后的0.47秒后,14:35:12,显示少了1000元。此时的资金状态已经被更新了。

所以QMT的资金持仓更新速度要比Ptrade快出不少的,如果不是追求毫秒级别的话,这个速度足够满足大部分的轮动和T+0操作了。

虽然QMT的资金持仓更新很快,但如果你的策略是高频或偏高频运行,比如你这一个时刻刚刚买入,下一个tick来到时就要卖出,或者采用驱动成交型的网格交易,你无法知道挂单是在哪一个时刻成交的,此时也亦不能一直循环读取你的可以资金或者持仓来判断是否成交,因为这样会阻塞QMT无法进行下一步的操作(除非你本身就是一直在等待成交,成交后才进行下程序一步)。

委托、成交回调函数

Ptrade和QMT都有对应的委托成交回调函数,用于应对需要即时获取成交状态的情景下。

接口文档介绍如下 
Ptrade http://ptradeapi.com/#on_trade_response

QMT:http://qmt.ptradeapi.com/QMT_Python_API_Doc.html#deal-callback


20230706002.jpg



里面就说明了,“该函数会在成交主推回调时响应,比引擎和get_trades()函数更新Order状态的速度更快,适合对速度要求比较高的策略。”

Ptrade的部分代码片段如下:
# 交易回调
def on_trade_response(context, trade_list):
# 成交主推
now = context.blotter.current_dt.strftime("%H:%M:%S")

for trade_info in trade_list:
if trade_info['order_id'] == '':
# 不是本策略跳过
log.info('非本策略订单')
continue

code = trade_info['stock_code']
code = post_fix_convert(code)
business_time = trade_info['business_time']
business_amount = trade_info['business_amount'] # 这个是负数,如果卖出
business_price = trade_info['business_price']
g.total_cash -= business_amount # 马上更新资金状态

 
g.total_cash -= business_amount # 马上更新资金状态g.total_cash是一个全局的可用资金, 可以提前设定好,亦可以是开盘前读取一次你的账户可用资金。

每次成交的那一刻,on_trade_response这个函数就会被动触发,在这里就可以简单的更新你的资金状态了。上面的例子是最基础的更新资金。

实际可以使用其他的诸如dict或类对象来更新仓位。


20230706003.jpg



上面代码是把仓位更新放到一个全局dict里面,key是股票代码,value也是一个dict,里面包含交易时间,持仓数目,价格等等。

好了,时间有限,今天的教程就到这里了,码字不易,欢迎点赞+收藏哦~
 

0 个评论

要回复文章请先登录注册