[Mod]add trader api of xtp
This commit is contained in:
parent
72dd05dcb5
commit
8a2489ebf9
@ -9,6 +9,9 @@ from vnpy.api.xtp.vnxtp import (
|
|||||||
XTPSpecificTickerStruct,
|
XTPSpecificTickerStruct,
|
||||||
XTPTickByTickStruct,
|
XTPTickByTickStruct,
|
||||||
XTPTickerPriceInfo,
|
XTPTickerPriceInfo,
|
||||||
|
XTPQueryOrderReq,
|
||||||
|
XTPQueryTraderReq,
|
||||||
|
XTPOrderInsertInfo,
|
||||||
XTP_EXCHANGE_TYPE,
|
XTP_EXCHANGE_TYPE,
|
||||||
XTP_LOG_LEVEL,
|
XTP_LOG_LEVEL,
|
||||||
XTP_PROTOCOL_TYPE,
|
XTP_PROTOCOL_TYPE,
|
||||||
@ -18,11 +21,17 @@ from vnpy.api.xtp.vnxtp import (
|
|||||||
XTP_TICKER_TYPE_BOND,
|
XTP_TICKER_TYPE_BOND,
|
||||||
XTP_TICKER_TYPE_OPTION,
|
XTP_TICKER_TYPE_OPTION,
|
||||||
XTP_PROTOCOL_TCP,
|
XTP_PROTOCOL_TCP,
|
||||||
XTP_PROTOCOL_UDP
|
XTP_PROTOCOL_UDP,
|
||||||
|
XTP_TERT_RESTART,
|
||||||
|
XTP_SIDE_BUY,
|
||||||
|
XTP_SIDE_SELL,
|
||||||
|
XTP_PRICE_LIMIT,
|
||||||
|
XTP_PRICE_BEST5_OR_CANCEL,
|
||||||
|
XTP_BUSINESS_TYPE_CASH
|
||||||
)
|
)
|
||||||
|
|
||||||
from vnpy.event import EventEngine
|
from vnpy.event import EventEngine
|
||||||
from vnpy.trader.constant import Exchange, Product
|
from vnpy.trader.constant import Exchange, Product, Direction, OrderType
|
||||||
from vnpy.trader.gateway import BaseGateway
|
from vnpy.trader.gateway import BaseGateway
|
||||||
from vnpy.trader.object import (CancelRequest, OrderRequest, SubscribeRequest,
|
from vnpy.trader.object import (CancelRequest, OrderRequest, SubscribeRequest,
|
||||||
TickData, ContractData, OrderData, TradeData,
|
TickData, ContractData, OrderData, TradeData,
|
||||||
@ -45,6 +54,18 @@ PRODUCT_XTP2VT = {
|
|||||||
XTP_TICKER_TYPE_OPTION: Product.OPTION
|
XTP_TICKER_TYPE_OPTION: Product.OPTION
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DIRECTION_VT2XTP = {
|
||||||
|
Direction.LONG: XTP_SIDE_BUY,
|
||||||
|
Direction.SHORT: XTP_SIDE_SELL
|
||||||
|
}
|
||||||
|
DIRECTION_XTP2VT = {v: k for k, v in DIRECTION_VT2XTP.items()}
|
||||||
|
|
||||||
|
ORDERTYPE_VT2XTP = {
|
||||||
|
OrderType.LIMIT: XTP_PRICE_LIMIT,
|
||||||
|
OrderType.MARKET: XTP_PRICE_BEST5_OR_CANCEL
|
||||||
|
}
|
||||||
|
ORDERTYPE_XTP2VT = {v: k for k, v in ORDERTYPE_VT2XTP.items()}
|
||||||
|
|
||||||
|
|
||||||
symbol_name_map = {}
|
symbol_name_map = {}
|
||||||
|
|
||||||
@ -67,6 +88,7 @@ class XtpGateway(BaseGateway):
|
|||||||
super().__init__(event_engine, "XTP")
|
super().__init__(event_engine, "XTP")
|
||||||
|
|
||||||
self.quote_api = XtpQuoteApi(self)
|
self.quote_api = XtpQuoteApi(self)
|
||||||
|
self.trader_api = XtpTraderApi(self)
|
||||||
|
|
||||||
def connect(self, setting: dict):
|
def connect(self, setting: dict):
|
||||||
""""""
|
""""""
|
||||||
@ -75,38 +97,47 @@ class XtpGateway(BaseGateway):
|
|||||||
client_id = setting['客户号']
|
client_id = setting['客户号']
|
||||||
quote_ip = setting['行情地址']
|
quote_ip = setting['行情地址']
|
||||||
quote_port = setting['行情端口']
|
quote_port = setting['行情端口']
|
||||||
trade_ip = setting['交易地址']
|
trader_ip = setting['交易地址']
|
||||||
trade_port = setting['交易端口']
|
trader_port = setting['交易端口']
|
||||||
quote_protocol = setting["行情协议"]
|
quote_protocol = setting["行情协议"]
|
||||||
|
|
||||||
self.quote_api.connect(userid, password, client_id,
|
self.quote_api.connect(userid, password, client_id,
|
||||||
quote_ip, quote_port, quote_protocol)
|
quote_ip, quote_port, quote_protocol)
|
||||||
|
self.trader_api.connect(userid, password, client_id,
|
||||||
|
trader_ip, trader_port)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
""""""
|
""""""
|
||||||
pass
|
self.quote_api.close()
|
||||||
|
self.trader_api.close()
|
||||||
|
|
||||||
def subscribe(self, req: SubscribeRequest):
|
def subscribe(self, req: SubscribeRequest):
|
||||||
""""""
|
""""""
|
||||||
self.quote_api.subscrbie(req)
|
self.quote_api.subscrbie(req)
|
||||||
|
|
||||||
def send_order(self, req: OrderRequest) -> str:
|
def send_order(self, req: OrderRequest) -> str:
|
||||||
pass
|
""""""
|
||||||
|
return self.trader_api.send_order(req)
|
||||||
|
|
||||||
def cancel_order(self, req: CancelRequest):
|
def cancel_order(self, req: CancelRequest):
|
||||||
pass
|
""""""
|
||||||
|
self.trader_api.cancel_order(req)
|
||||||
|
|
||||||
def query_account(self):
|
def query_account(self):
|
||||||
pass
|
""""""
|
||||||
|
self.trader_api.query_account()
|
||||||
|
|
||||||
def query_position(self):
|
def query_position(self):
|
||||||
pass
|
""""""
|
||||||
|
self.trader_api.query_position()
|
||||||
|
|
||||||
|
|
||||||
class XtpQuoteApi(API.QuoteSpi):
|
class XtpQuoteApi(API.QuoteSpi):
|
||||||
|
|
||||||
def __init__(self, gateway: BaseGateway):
|
def __init__(self, gateway: BaseGateway):
|
||||||
""""""
|
""""""
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
self.gateway = gateway
|
self.gateway = gateway
|
||||||
self.gateway_name = gateway.gateway_name
|
self.gateway_name = gateway.gateway_name
|
||||||
|
|
||||||
@ -166,12 +197,17 @@ class XtpQuoteApi(API.QuoteSpi):
|
|||||||
|
|
||||||
if not ret:
|
if not ret:
|
||||||
msg = "行情服务器登录成功"
|
msg = "行情服务器登录成功"
|
||||||
|
|
||||||
self.query_contract()
|
self.query_contract()
|
||||||
else:
|
else:
|
||||||
msg = f"行情服务器登录失败,原因:{ret}"
|
msg = f"行情服务器登录失败,原因:{ret}"
|
||||||
self.gateway.write_log(msg)
|
self.gateway.write_log(msg)
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
""""""
|
||||||
|
if self.api:
|
||||||
|
self.api.RegisterSpi(None)
|
||||||
|
self.api.Release()
|
||||||
|
|
||||||
def subscrbie(self, req: SubscribeRequest):
|
def subscrbie(self, req: SubscribeRequest):
|
||||||
""""""
|
""""""
|
||||||
xtp_exchange = EXCHANGE_VT2XTP.get(req.exchange, "")
|
xtp_exchange = EXCHANGE_VT2XTP.get(req.exchange, "")
|
||||||
@ -314,23 +350,22 @@ class XtpQuoteApi(API.QuoteSpi):
|
|||||||
def OnQueryAllTickers(self, ticker_info: XTPQuoteStaticInfo, error_info: XTPRspInfoStruct,
|
def OnQueryAllTickers(self, ticker_info: XTPQuoteStaticInfo, error_info: XTPRspInfoStruct,
|
||||||
is_last: bool) -> Any:
|
is_last: bool) -> Any:
|
||||||
""""""
|
""""""
|
||||||
return
|
if self.check_error("查询合约", error_info):
|
||||||
# if self.check_error("查询合约", error_info):
|
return
|
||||||
# return
|
|
||||||
|
|
||||||
# contract = ContractData(
|
contract = ContractData(
|
||||||
# symbol=ticker_info.ticker,
|
symbol=ticker_info.ticker,
|
||||||
# exchange=EXCHANGE_XTP2VT[ticker_info.exchange_id],
|
exchange=EXCHANGE_XTP2VT[ticker_info.exchange_id],
|
||||||
# name=ticker_info.ticker_name,
|
name=ticker_info.ticker_name,
|
||||||
# product=PRODUCT_XTP2VT[ticker_info.ticker_type],
|
product=PRODUCT_XTP2VT[ticker_info.ticker_type],
|
||||||
# size=1,
|
size=1,
|
||||||
# pricetick=ticker_info.pricetick,
|
pricetick=ticker_info.pricetick,
|
||||||
# min_volume=ticker_info.buy_qty_unit,
|
min_volume=ticker_info.buy_qty_unit,
|
||||||
# gateway_name=self.gateway_name
|
gateway_name=self.gateway_name
|
||||||
# )
|
)
|
||||||
# self.gateway.on_contract(contract)
|
self.gateway.on_contract(contract)
|
||||||
|
|
||||||
# symbol_name_map[contract.vt_symbol] = contract.name
|
symbol_name_map[contract.vt_symbol] = contract.name
|
||||||
|
|
||||||
def OnQueryTickersPriceInfo(self, ticker_info: XTPTickerPriceInfo, error_info: XTPRspInfoStruct,
|
def OnQueryTickersPriceInfo(self, ticker_info: XTPTickerPriceInfo, error_info: XTPRspInfoStruct,
|
||||||
is_last: bool) -> Any:
|
is_last: bool) -> Any:
|
||||||
@ -366,3 +401,126 @@ class XtpQuoteApi(API.QuoteSpi):
|
|||||||
error_info: XTPRspInfoStruct) -> Any:
|
error_info: XTPRspInfoStruct) -> Any:
|
||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class XtpTraderApi(API.TraderSpi):
|
||||||
|
|
||||||
|
def __init__(self, gateway: BaseGateway):
|
||||||
|
""""""
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.gateway = gateway
|
||||||
|
self.gateway_name = gateway.gateway_name
|
||||||
|
|
||||||
|
self.userid = ""
|
||||||
|
self.password = ""
|
||||||
|
self.client_id = ""
|
||||||
|
self.server_ip = ""
|
||||||
|
self.server_port = ""
|
||||||
|
|
||||||
|
self.api = None
|
||||||
|
self.session_id = 0
|
||||||
|
|
||||||
|
self.reqid = 0
|
||||||
|
self.orderid = 0
|
||||||
|
|
||||||
|
def connect(
|
||||||
|
self,
|
||||||
|
userid: str,
|
||||||
|
password: str,
|
||||||
|
client_id: str,
|
||||||
|
server_ip: str,
|
||||||
|
server_port: str
|
||||||
|
):
|
||||||
|
""""""
|
||||||
|
if self.api:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.userid = userid
|
||||||
|
self.password = password
|
||||||
|
self.client_id = client_id
|
||||||
|
self.server_ip = server_ip
|
||||||
|
self.server_port = server_port
|
||||||
|
|
||||||
|
# Create API object
|
||||||
|
path = str(get_folder_path(self.gateway_name.lower()))
|
||||||
|
|
||||||
|
self.api = API.TraderApi.CreateTraderApi(
|
||||||
|
self.client_id,
|
||||||
|
path,
|
||||||
|
XTP_LOG_LEVEL.XTP_LOG_LEVEL_TRACE
|
||||||
|
)
|
||||||
|
|
||||||
|
self.api.RegisterSpi(self)
|
||||||
|
self.api.SubscribePublicTopic(XTP_TERT_RESTART)
|
||||||
|
|
||||||
|
self.gateway.write_log("交易接口初始化成功")
|
||||||
|
|
||||||
|
# Login to server
|
||||||
|
self.session_id = self.api.Login(
|
||||||
|
self.server_ip,
|
||||||
|
self.server_port,
|
||||||
|
self.userid,
|
||||||
|
self.password,
|
||||||
|
XTP_PROTOCOL_TCP
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.session_id:
|
||||||
|
msg = "交易服务器登录成功"
|
||||||
|
else:
|
||||||
|
reason = self.api.GetApiLastError()
|
||||||
|
msg = f"交易服务器登录失败,原因:{reason}"
|
||||||
|
|
||||||
|
self.gateway.write_log(msg)
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
""""""
|
||||||
|
if self.api:
|
||||||
|
self.api.RegisterSpi(None)
|
||||||
|
self.api.Release()
|
||||||
|
|
||||||
|
def send_order(self, req: OrderRequest) -> str:
|
||||||
|
""""""
|
||||||
|
self.orderid += 1
|
||||||
|
|
||||||
|
xtp_req = XTPOrderInsertInfo()
|
||||||
|
xtp_req.ticker = req.symbol
|
||||||
|
xtp_req.market = EXCHANGE_XTP2VT[req.exchange]
|
||||||
|
xtp_req.price = req.price
|
||||||
|
xtp_req.quantity = req.volume
|
||||||
|
xtp_req.order_client_id = self.client_id
|
||||||
|
xtp_req.order_xtp_id = self.orderid
|
||||||
|
xtp_req.side = DIRECTION_XTP2VT.get(req.direction, "")
|
||||||
|
xtp_req.price_type = ORDERTYPE_XTP2VT.get(req.type, "")
|
||||||
|
xtp_req.business_type = XTP_BUSINESS_TYPE_CASH
|
||||||
|
|
||||||
|
self.api.InsertOrder(xtp_req, self.session_id)
|
||||||
|
|
||||||
|
order = req.create_order_data(str(self.orderid))
|
||||||
|
self.gateway.on_order(order)
|
||||||
|
|
||||||
|
return order.vt_orderid
|
||||||
|
|
||||||
|
def cancel_order(self, req: CancelRequest):
|
||||||
|
""""""
|
||||||
|
self.api.CancelOrder(req.orderid, self.session_id)
|
||||||
|
|
||||||
|
def query_account(self):
|
||||||
|
""""""
|
||||||
|
self.reqid += 1
|
||||||
|
self.api.QueryAsset(self.session_id, self.reqid)
|
||||||
|
|
||||||
|
def query_position(self):
|
||||||
|
""""""
|
||||||
|
self.reqid += 1
|
||||||
|
self.api.QueryPosition("", self.session_id, self.reqid)
|
||||||
|
|
||||||
|
def query_order(self):
|
||||||
|
""""""
|
||||||
|
self.reqid += 1
|
||||||
|
self.api.QueryOrders(XTPQueryOrderReq(), self.session_id, self.reqid)
|
||||||
|
|
||||||
|
def query_trade(self):
|
||||||
|
""""""
|
||||||
|
self.reqid += 1
|
||||||
|
self.api.QueryTrades(XTPQueryTraderReq(), self.session_id, self.reqid)
|
||||||
|
Loading…
Reference in New Issue
Block a user