背景
希望不用在QMT軟體裡面憋屈地寫代碼,想使用pychar、vscode、notepad++等IDE編寫python代碼,因為有代碼提示、補全。這完全沒問題!QMT簡直是為個人量化交易者量身打造的神器,它支援以上想法。
前提
想在Python本地調用(隻支援python 36\37\38),需要兩個前提條件:
- 啟動XtMiniQmt.exe,它存在于QMT安裝目錄下的bin.x64子目錄中。
- 将xtquant庫,從bin.x64\Lib\site-packages拷貝到python本地的Lib\site-packages中。比如這裡我的安裝路徑是G:\Anaconda3\Lib\site-packages\xtquant。
xtquant簡介
xtquant是QMT官方内置的XtMiniQmt極簡用戶端對應的Python接口,目前支援Python的版本為3.6~3.8,可支援曆史行情下載下傳、實時資料訂閱、外部資料通路、普通賬戶和兩融賬戶交易(需開通相關權限),對量化交易支援的比較完善,跟極速政策交易系統相比最主要的優勢是簡潔、靈活,不局限在bar、kline的事件觸發,可以容易地內建多種資料源進行綜合分析、判斷。
QMT内置的Python版本為3.6,第一次使用的話需手動下載下傳相關的庫,或直接拷貝已經下載下傳好的xtquant庫。
XtMiniQmt.exe存在于QMT安裝目錄下的bin.x64子目錄中, xtquant庫預設安裝在bin.x64\Lib\site-packages中。
内置的Python版本較老,對于一些較新的庫支援有限,是以,如果我們想在自定義的Python中調用,如Python3.8,隻需将xtquant拷貝到我們自己python安裝目錄的Lib\site-packages中便可,這裡我的安裝路徑是 C:\ProgramData\Anaconda3\Lib\site-packages\xtquant。
QMT這個東東基本是由兩部分組成的:QMT交易終端(看盤界面 + 政策界面) + 量化庫(xtquant)
XtQuant:基于迅投MiniQMT衍生出來的一套完善的Python政策運作架構,以Python庫的形式提供政策交易所需要的:行情 + 交易 API接口。
它封裝了政策交易所需要的Python API接口,可以和MiniQMT用戶端互動,報單、撤單、查資産、查委托、查成交、查持倉以及收到資金、委托、成交和持倉等變動的主推消息。
xtquant主要包含兩大塊:
- xtdata:xtdata提供和MiniQmt的互動接口,本質是和MiniQmt建立連接配接,由MiniQmt處理行情資料請求,再把結果回傳傳回到python層。需要注意的是這個子產品的使用目前并不需要登入,是以隻要安裝了QMT,就可以無門檻的使用其提供的資料服務。
- xttrader:xttrader是基于迅投MiniQMT衍生出來的一套完善的Python政策運作架構,對外以Python庫的形式提供政策交易所需要的交易相關的API接口。該接口需開通A股實盤版權限方可登入使用。
啟動XtMiniQmt用戶端
啟動MiniQMT用戶端。通常有兩種方式,一種是直接啟動極簡QMT用戶端XtMiniQmt.exe:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5CNmVjMkFjM0QWYjJmMwUWOhNzN1AjZ1kTO1Q2MwImYk9CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
另一種是啟動QMT量化交易終端XtItClient.exe,在登入界面選擇極簡模式:
部分券商不支援政策的雲伺服器運作,但接收行情資料不受影響。設定好用戶端後,便可在ipython、jupyter等環境中調試資料和政策了。
xttrader驗證Demo
需要調整的參數:①:77行的path變量需要改為本地用戶端路徑 ②:84行的資金賬号需要調整為自身資金賬号
注意:本政策隻用于提供政策寫法及參考,若您直接進行實盤下單,造成損失本部落客概不負擔責任。
# 建立政策
#coding=utf-8
from xtquant.xttrader import XtQuantTrader, XtQuantTraderCallback
from xtquant.xttype import StockAccount
from xtquant import xtconstant
class MyXtQuantTraderCallback(XtQuantTraderCallback):
def on_disconnected(self):
"""
連接配接斷開
:return:
"""
print("connection lost")
def on_stock_order(self, order):
"""
委托回報推送
:param order: XtOrder對象
:return:
"""
print("on order callback:")
print(order.stock_code, order.order_status, order.order_sysid)
def on_stock_asset(self, asset):
"""
資金變動推送
:param asset: XtAsset對象
:return:
"""
print("on asset callback")
print(asset.account_id, asset.cash, asset.total_asset)
def on_stock_trade(self, trade):
"""
成交變動推送
:param trade: XtTrade對象
:return:
"""
print("on trade callback")
print(trade.account_id, trade.stock_code, trade.order_id)
def on_stock_position(self, position):
"""
持倉變動推送
:param position: XtPosition對象
:return:
"""
print("on position callback")
print(position.stock_code, position.volume)
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)
def on_cancel_error(self, cancel_error):
"""
撤單失敗推送
:param cancel_error: XtCancelError 對象
:return:
"""
print("on cancel_error callback")
print(cancel_error.order_id, cancel_error.error_id,
cancel_error.error_msg)
def on_order_stock_async_response(self, response):
"""
異步下單回報推送
:param response: XtOrderResponse 對象
:return:
"""
print("on_order_stock_async_response")
print(response.account_id, response.order_id, response.seq)
if __name__ == "__main__":
print("demo test")
# path為mini qmt用戶端安裝目錄下userdata_mini路徑
path =r'輸入你本地的userdata_mini目錄'
# session_id為會話編号,政策使用方對于不同的Python政策需要使用不同的會話編号
session_id = 123456
xt_trader = XtQuantTrader(path, session_id)
# 建立資金賬号為1000000365的證券賬号對象
#acc = StockAccount('1000000365')
acc = StockAccount('輸入你的QMT資金賬号')
# 建立交易回調類對象,并聲明接收回調
callback = MyXtQuantTraderCallback()
xt_trader.register_callback(callback)
# 啟動交易線程
xt_trader.start()
# 建立交易連接配接,傳回0表示連接配接成功
connect_result = xt_trader.connect()
print(connect_result)
# 對交易回調進行訂閱,訂閱後可以收到交易主推,傳回0表示訂閱成功
subscribe_result = xt_trader.subscribe(acc)
print(subscribe_result)
#stock_code = '600000.SH'
stock_code = '000768.SZ'
# 使用指定價下單,接口傳回訂單編号,後續可以用于撤單操作以及查詢委托狀态
print("order using the fix price:")
fix_result_order_id = xt_trader.order_stock(acc, stock_code,
xtconstant.STOCK_BUY, 200, xtconstant.FIX_PRICE, 10.5, 'strategy_name',
'remark')
print(fix_result_order_id)
# 使用訂單編号撤單
print("cancel order:")
cancel_order_result = xt_trader.cancel_order_stock(acc, fix_result_order_id)
print(cancel_order_result)
# 使用異步下單接口,接口傳回下單請求序号seq,seq可以和on_order_stock_async_response 的委托回報response對應起來
print("order using async api:")
async_seq = xt_trader.order_stock(acc, stock_code, xtconstant.STOCK_BUY,
200, xtconstant.FIX_PRICE, 10.5, 'strategy_name', 'remark')
print(async_seq)
# 查詢證券資産
print("query asset:")
asset = xt_trader.query_stock_asset(acc)
if asset:
print("asset:")
print("cash {0}".format(asset.cash))
# 根據訂單編号查詢委托
print("query order:")
order = xt_trader.query_stock_order(acc, fix_result_order_id)
if order:
print("order:")
print("order {0}".format(order.order_id))
# 查詢當日所有的委托
print("query orders:")
orders = xt_trader.query_stock_orders(acc)
print("orders:", len(orders))
if len(orders) != 0:
print("last order:")
print("{0} {1} {2}".format(orders[-1].stock_code,
orders[-1].order_volume, orders[-1].price))
# 查詢當日所有的成交
print("query trade:")
trades = xt_trader.query_stock_trades(acc)
print("trades:", len(trades))
if len(trades) != 0:
print("last trade:")
print("{0} {1} {2}".format(trades[-1].stock_code,
trades[-1].traded_volume, trades[-1].traded_price))
# 查詢當日所有的持倉
print("query positions:")
positions = xt_trader.query_stock_positions(acc)
print("positions:", len(positions))
if len(positions) != 0:
print("last position:")
print("{0} {1} {2}".format(positions[-1].account_id,
positions[-1].stock_code, positions[-1].volume))
# 根據股票代碼查詢對應持倉
print("query position:")
position = xt_trader.query_stock_position(acc, stock_code)
if position:
print("position:")
print("{0} {1} {2}".format(position.account_id, position.stock_code,
position.volume))
# 阻塞線程,接收交易推送
xt_trader.run_forever()