[增强功能] 加固订单委托

This commit is contained in:
msincenselee 2020-07-04 22:40:20 +08:00
parent 3a086af423
commit 22535f7acf
2 changed files with 81 additions and 19 deletions

View File

@ -6,6 +6,8 @@ import urllib
import hashlib import hashlib
import hmac import hmac
import time import time
import json
from copy import copy from copy import copy
from datetime import datetime, timedelta from datetime import datetime, timedelta
from enum import Enum from enum import Enum
@ -37,7 +39,7 @@ from vnpy.trader.object import (
) )
from vnpy.trader.event import EVENT_TIMER from vnpy.trader.event import EVENT_TIMER
from vnpy.event import Event from vnpy.event import Event
from vnpy.trader.utility import print_dict
REST_HOST = "https://www.binance.com" REST_HOST = "https://www.binance.com"
WEBSOCKET_TRADE_HOST = "wss://stream.binance.com:9443/ws/" WEBSOCKET_TRADE_HOST = "wss://stream.binance.com:9443/ws/"
WEBSOCKET_DATA_HOST = "wss://stream.binance.com:9443/stream?streams=" WEBSOCKET_DATA_HOST = "wss://stream.binance.com:9443/stream?streams="
@ -168,6 +170,9 @@ class BinanceGateway(BaseGateway):
func() func()
self.query_functions.append(func) self.query_functions.append(func)
def get_order(self, orderid: str):
return self.rest_api.get_order(orderid)
class BinanceRestApi(RestClient): class BinanceRestApi(RestClient):
""" """
BINANCE REST API BINANCE REST API
@ -197,6 +202,10 @@ class BinanceRestApi(RestClient):
self.assets = {} # 币资产的合约信息, symbol: contract self.assets = {} # 币资产的合约信息, symbol: contract
self.positions = {} # 币持仓信息, symbol: position self.positions = {} # 币持仓信息, symbol: position
self.orders = {}
self.accountid = ""
def sign(self, request): def sign(self, request):
""" """
Generate BINANCE signature. Generate BINANCE signature.
@ -333,6 +342,10 @@ class BinanceRestApi(RestClient):
self.order_count += 1 self.order_count += 1
return self.order_count return self.order_count
def get_order(self, orderid: str):
"""返回缓存的Order"""
return self.orders.get(orderid, None)
def send_order(self, req: OrderRequest): def send_order(self, req: OrderRequest):
"""""" """"""
orderid = str(self.connect_time + self._new_order_id()) orderid = str(self.connect_time + self._new_order_id())
@ -340,6 +353,11 @@ class BinanceRestApi(RestClient):
orderid, orderid,
self.gateway_name self.gateway_name
) )
order.accountid = self.accountid
order.vt_accountid = f"{self.gateway_name}.{self.accountid}"
order.datetime = datetime.now()
self.orders.update({orderid: copy(order)})
self.gateway.write_log(f'委托返回订单更新:{order.__dict__}')
self.gateway.on_order(order) self.gateway.on_order(order)
data = { data = {
@ -439,8 +457,11 @@ class BinanceRestApi(RestClient):
def on_query_account(self, data, request): def on_query_account(self, data, request):
"""""" """"""
# ==》 account event # ==》 account event
if not self.accountid:
self.accountid = self.gateway_name
account = AccountData( account = AccountData(
accountid=self.gateway_name, accountid=self.accountid,
balance=0, balance=0,
frozen=0, frozen=0,
gateway_name=self.gateway_name gateway_name=self.gateway_name
@ -476,6 +497,7 @@ class BinanceRestApi(RestClient):
time = dt.strftime("%Y-%m-%d %H:%M:%S") time = dt.strftime("%Y-%m-%d %H:%M:%S")
order = OrderData( order = OrderData(
accountid=self.accountid,
orderid=d["clientOrderId"], orderid=d["clientOrderId"],
symbol=d["symbol"], symbol=d["symbol"],
exchange=Exchange.BINANCE, exchange=Exchange.BINANCE,
@ -488,6 +510,8 @@ class BinanceRestApi(RestClient):
time=time, time=time,
gateway_name=self.gateway_name, gateway_name=self.gateway_name,
) )
self.orders.update({order.orderid: copy(order)})
self.gateway.write_log(f'返回订单查询结果:{order.__dict__}')
self.gateway.on_order(order) self.gateway.on_order(order)
self.gateway.write_log("委托信息查询成功") self.gateway.write_log("委托信息查询成功")
@ -551,6 +575,13 @@ class BinanceRestApi(RestClient):
""" """
order = request.extra order = request.extra
order.status = Status.REJECTED order.status = Status.REJECTED
self.orders.update({order.orderid: copy(order)})
self.gateway.write_log(f'订单委托失败:{order.__dict__}')
if not order.accountid:
order.accountid = self.accountid
order.vt_accountid = f"{self.gateway_name}.{self.accountid}"
if not order.datetime:
order.datetime = datetime.now()
self.gateway.on_order(order) self.gateway.on_order(order)
msg = f"委托失败,状态码:{status_code},信息:{request.response.text}" msg = f"委托失败,状态码:{status_code},信息:{request.response.text}"
@ -564,6 +595,13 @@ class BinanceRestApi(RestClient):
""" """
order = request.extra order = request.extra
order.status = Status.REJECTED order.status = Status.REJECTED
self.orders.update({order.orderid: copy(order)})
self.gateway.write_log(f'发送订单异常:{order.__dict__}')
if not order.accountid:
order.accountid = self.accountid
order.vt_accountid = f"{self.gateway_name}.{self.accountid}"
if not order.datetime:
order.datetime = datetime.now()
self.gateway.on_order(order) self.gateway.on_order(order)
# Record exception if not ConnectionError # Record exception if not ConnectionError
@ -691,7 +729,10 @@ class BinanceTradeWebsocketApi(WebsocketClient):
self.on_order(packet) self.on_order(packet)
def on_account(self, packet): def on_account(self, packet):
"""""" """web socket的账号更新信息"""
# 这里不处理改为定时resful查询进行更新
"""
for d in packet["B"]: for d in packet["B"]:
account = AccountData( account = AccountData(
accountid=d["a"], accountid=d["a"],
@ -702,31 +743,49 @@ class BinanceTradeWebsocketApi(WebsocketClient):
if account.balance: if account.balance:
self.gateway.on_account(account) self.gateway.on_account(account)
"""
return
def on_order(self, packet: dict): def on_order(self, packet: dict):
"""""" """"""
self.gateway.write_log('ws返回订单更新:\n'.format(json.dumps(packet, indent=2)))
dt = datetime.fromtimestamp(packet["O"] / 1000) dt = datetime.fromtimestamp(packet["O"] / 1000)
time = dt.strftime("%Y-%m-%d %H:%M:%S") time = dt.strftime("%Y-%m-%d %H:%M:%S")
if packet["C"] == "null": if packet["C"] == "null" or len(packet['C']) == 0:
orderid = packet["c"] orderid = packet["c"]
else: else:
orderid = packet["C"] orderid = packet["C"]
# 尝试从缓存中获取订单
order = self.gateway.get_order(orderid)
if order:
order.traded = float(packet["z"])
order.status = STATUS_BINANCE2VT[packet["X"]]
if order.status in [Status.CANCELLED, Status.REJECTED]:
order.cancel_time = time
if len(order.sys_orderid) == 0:
order.sys_orderid = str(packet["i"])
else:
self.gateway.write_log(f'缓存中根据orderid:{orderid} 找不到Order,创建一个新的')
self.gateway.write_log(print_dict(packet))
order = OrderData( order = OrderData(
accountid=self.gateway_name,
symbol=packet["s"], symbol=packet["s"],
exchange=Exchange.BINANCE, exchange=Exchange.BINANCE,
orderid=orderid, orderid=orderid,
sys_orderid=str(packet['i']),
type=ORDERTYPE_BINANCE2VT[packet["o"]], type=ORDERTYPE_BINANCE2VT[packet["o"]],
direction=DIRECTION_BINANCE2VT[packet["S"]], direction=DIRECTION_BINANCE2VT[packet["S"]],
price=float(packet["p"]), price=float(packet["p"]),
volume=float(packet["q"]), volume=float(packet["q"]),
traded=float(packet["z"]), traded=float(packet["z"]),
status=STATUS_BINANCE2VT[packet["X"]], status=STATUS_BINANCE2VT[packet["X"]],
datetime=dt,
time=time, time=time,
gateway_name=self.gateway_name gateway_name=self.gateway_name
) )
self.gateway.write_log(f'WS订单更新:\n{order.__dict__}')
self.gateway.on_order(order) self.gateway.on_order(order)
# Push trade event # Push trade event
@ -738,6 +797,7 @@ class BinanceTradeWebsocketApi(WebsocketClient):
trade_time = trade_dt.strftime("%Y-%m-%d %H:%M:%S") trade_time = trade_dt.strftime("%Y-%m-%d %H:%M:%S")
trade = TradeData( trade = TradeData(
accountid=self.gateway_name,
symbol=order.symbol, symbol=order.symbol,
exchange=order.exchange, exchange=order.exchange,
orderid=order.orderid, orderid=order.orderid,
@ -746,8 +806,10 @@ class BinanceTradeWebsocketApi(WebsocketClient):
price=float(packet["L"]), price=float(packet["L"]),
volume=trade_volume, volume=trade_volume,
time=trade_time, time=trade_time,
datetime=trade_dt,
gateway_name=self.gateway_name, gateway_name=self.gateway_name,
) )
self.gateway.write_log(f'WS成交更新:\n{trade.__dict__}')
self.gateway.on_trade(trade) self.gateway.on_trade(trade)

View File

@ -959,7 +959,7 @@ class BinancefTradeWebsocketApi(WebsocketClient):
price=float(ord_data["L"]), price=float(ord_data["L"]),
volume=trade_volume, volume=trade_volume,
time=trade_time, time=trade_time,
datetime=trade_time, datetime=trade_dt,
gateway_name=self.gateway_name, gateway_name=self.gateway_name,
) )
self.gateway.write_log(f'WS成交更新:\n{trade.__dict__}') self.gateway.write_log(f'WS成交更新:\n{trade.__dict__}')