[bug fix] 修复Offset

This commit is contained in:
msincenselee 2020-03-12 23:25:39 +08:00
parent 59c1b6710f
commit eaffb3caf6

View File

@ -6,6 +6,7 @@ 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
@ -16,6 +17,7 @@ from vnpy.api.rest import RestClient, Request
from vnpy.api.websocket import WebsocketClient from vnpy.api.websocket import WebsocketClient
from vnpy.trader.constant import ( from vnpy.trader.constant import (
Direction, Direction,
Offset,
Exchange, Exchange,
Product, Product,
Status, Status,
@ -162,6 +164,8 @@ class BinancefGateway(BaseGateway):
"""""" """"""
self.rest_api.keep_user_stream() self.rest_api.keep_user_stream()
def get_order(self, orderid: str):
return self.rest_api.get_order(orderid)
class BinancefRestApi(RestClient): class BinancefRestApi(RestClient):
""" """
@ -189,6 +193,8 @@ class BinancefRestApi(RestClient):
self.order_count_lock: Lock = Lock() self.order_count_lock: Lock = Lock()
self.connect_time: int = 0 self.connect_time: int = 0
self.orders = {}
def sign(self, request: Request) -> Request: def sign(self, request: Request) -> Request:
""" """
Generate BINANCE signature. Generate BINANCE signature.
@ -273,6 +279,8 @@ class BinancefRestApi(RestClient):
self.query_position() self.query_position()
self.query_order() self.query_order()
self.query_contract() self.query_contract()
self.query_trade()
self.start_user_stream() self.start_user_stream()
def query_time(self) -> Request: def query_time(self) -> Request:
@ -334,12 +342,32 @@ class BinancefRestApi(RestClient):
data=data data=data
) )
def query_trade(self, vt_symbol: str = '') -> Request:
""""""
data = {"security": Security.SIGNED}
if vt_symbol:
if '.' in vt_symbol:
vt_symbol = vt_symbol.split('.')[0]
data.update({'symbol': vt_symbol})
self.add_request(
method="GET",
path="/fapi/v1/userTrades",
callback=self.on_query_trade,
data=data
)
def _new_order_id(self) -> int: def _new_order_id(self) -> int:
"""""" """"""
with self.order_count_lock: with self.order_count_lock:
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) -> str: def send_order(self, req: OrderRequest) -> str:
"""""" """"""
orderid = str(self.connect_time + self._new_order_id()) orderid = str(self.connect_time + self._new_order_id())
@ -347,6 +375,7 @@ class BinancefRestApi(RestClient):
orderid, orderid,
self.gateway_name self.gateway_name
) )
self.orders.update({orderid: copy(order)})
self.gateway.on_order(order) self.gateway.on_order(order)
data = { data = {
@ -457,18 +486,68 @@ class BinancefRestApi(RestClient):
def on_query_position(self, data: dict, request: Request) -> None: def on_query_position(self, data: dict, request: Request) -> None:
"""""" """"""
for d in data: for d in data:
position = PositionData( volume = float(d["positionAmt"])
symbol=d["symbol"],
exchange=Exchange.BINANCE,
direction=Direction.NET,
volume=int(float(d["positionAmt"])),
price=float(d["entryPrice"]),
pnl=float(d["unRealizedProfit"]),
gateway_name=self.gateway_name,
)
if position.volume: if volume > 0:
self.gateway.on_position(position) long_position = PositionData(
symbol=d["symbol"],
exchange=Exchange.BINANCE,
direction=Direction.LONG,
volume=abs(volume),
price=float(d["entryPrice"]),
pnl=float(d["unRealizedProfit"]),
gateway_name=self.gateway_name,
)
short_position = PositionData(
symbol=d["symbol"],
exchange=Exchange.BINANCE,
direction=Direction.LONG,
volume=0,
price=0,
pnl=0,
gateway_name=self.gateway_name,
)
elif volume < 0:
long_position = PositionData(
symbol=d["symbol"],
exchange=Exchange.BINANCE,
direction=Direction.LONG,
volume=0,
price=0,
pnl=0,
gateway_name=self.gateway_name,
)
short_position = PositionData(
symbol=d["symbol"],
exchange=Exchange.BINANCE,
direction=Direction.SHORT,
volume=abs(volume),
price=float(d["entryPrice"]),
pnl=float(d["unRealizedProfit"]),
gateway_name=self.gateway_name,
)
else:
long_position = PositionData(
symbol=d["symbol"],
exchange=Exchange.BINANCE,
direction=Direction.LONG,
volume=0,
price=0,
pnl=0,
gateway_name=self.gateway_name,
)
short_position = PositionData(
symbol=d["symbol"],
exchange=Exchange.BINANCE,
direction=Direction.SHORT,
volume=0,
price=0,
pnl=0,
gateway_name=self.gateway_name,
)
self.gateway.on_position(long_position)
self.gateway.on_position(short_position)
self.gateway.write_log("持仓信息查询成功") self.gateway.write_log("持仓信息查询成功")
@ -491,10 +570,34 @@ class BinancefRestApi(RestClient):
time=time, time=time,
gateway_name=self.gateway_name, gateway_name=self.gateway_name,
) )
self.orders.update({order.orderid: copy(order)})
self.gateway.on_order(order) self.gateway.on_order(order)
self.gateway.write_log("委托信息查询成功") self.gateway.write_log("委托信息查询成功")
def on_query_trade(self, data: dict, request: Request) -> None:
""""""
for d in data:
dt = datetime.fromtimestamp(d["time"] / 1000)
time = dt.strftime("%Y-%m-%d %H:%M:%S")
trade = TradeData(
symbol=d['symbol'],
exchange=Exchange.BINANCE,
orderid=d['orderId'],
tradeid=d["id"],
direction=Direction.SHORT if d['side'] == 'SELL' else Direction.LONG,
offset=Offset.CLOSE if d['buyer'] else Offset.OPEN,
price=float(d["price"]),
volume=float(d['qty']),
time=time,
gateway_name=self.gateway_name,
)
self.gateway.on_trade(trade)
self.gateway.write_log("委托信息查询成功")
def on_query_contract(self, data: dict, request: Request) -> None: def on_query_contract(self, data: dict, request: Request) -> None:
"""处理合约配置""" """处理合约配置"""
import json import json
@ -528,7 +631,6 @@ class BinancefRestApi(RestClient):
gateway_name=self.gateway_name, gateway_name=self.gateway_name,
) )
self.gateway.on_contract(contract) self.gateway.on_contract(contract)
symbol_name_map[contract.symbol] = contract.name symbol_name_map[contract.symbol] = contract.name
self.gateway.write_log("合约信息查询成功") self.gateway.write_log("合约信息查询成功")
@ -543,6 +645,7 @@ class BinancefRestApi(RestClient):
""" """
order = request.extra order = request.extra
order.status = Status.REJECTED order.status = Status.REJECTED
self.orders.update({order.orderid: copy(order)})
self.gateway.on_order(order) self.gateway.on_order(order)
msg = f"委托失败,状态码:{status_code},信息:{request.response.text}" msg = f"委托失败,状态码:{status_code},信息:{request.response.text}"
@ -556,6 +659,7 @@ class BinancefRestApi(RestClient):
""" """
order = request.extra order = request.extra
order.status = Status.REJECTED order.status = Status.REJECTED
self.orders.update({order.orderid: copy(order)})
self.gateway.on_order(order) self.gateway.on_order(order)
# Record exception if not ConnectionError # Record exception if not ConnectionError
@ -582,7 +686,7 @@ class BinancefRestApi(RestClient):
"""""" """"""
pass pass
def query_history(self, req: HistoryRequest) -> List[OrderData]: def query_history(self, req: HistoryRequest) -> List[BarData]:
"""""" """"""
history = [] history = []
limit = 1000 limit = 1000
@ -605,7 +709,7 @@ class BinancefRestApi(RestClient):
# Get response from server # Get response from server
resp = self.request( resp = self.request(
"GET", "GET",
"/api/v1/klines", "/fapi/v1/klines",
data={"security": Security.NONE}, data={"security": Security.NONE},
params=params params=params
) )
@ -712,24 +816,36 @@ class BinancefTradeWebsocketApi(WebsocketClient):
def on_order(self, packet: dict) -> None: def on_order(self, packet: dict) -> None:
"""""" """"""
self.gateway.write_log(json.dumps(packet, indent=2))
dt = datetime.fromtimestamp(packet["E"] / 1000) dt = datetime.fromtimestamp(packet["E"] / 1000)
time = dt.strftime("%Y-%m-%d %H:%M:%S") time = dt.strftime("%Y-%m-%d %H:%M:%S")
ord_data = packet["o"] ord_data = packet["o"]
orderid = str(ord_data["c"])
order = OrderData( order = self.gateway.get_order(orderid)
symbol=ord_data["s"], if order:
exchange=Exchange.BINANCE, order.traded = float(ord_data["z"])
orderid=str(ord_data["c"]), order.status = STATUS_BINANCEF2VT[ord_data["X"]]
type=ORDERTYPE_BINANCEF2VT[ord_data["o"]], if order.status in [Status.CANCELLED, Status.REJECTED]:
direction=DIRECTION_BINANCEF2VT[ord_data["S"]], order.cancel_time = time
price=float(ord_data["p"]), if len(order.sys_orderid) == 0:
volume=float(ord_data["q"]), order.sys_orderid = str(ord_data["i"])
traded=float(ord_data["z"]), else:
status=STATUS_BINANCEF2VT[ord_data["X"]], self.gateway.write_log(u'缓存中找不到Order,创建一个新的')
time=time, order = OrderData(
gateway_name=self.gateway_name symbol=ord_data["s"],
) exchange=Exchange.BINANCE,
orderid=str(ord_data["c"]),
type=ORDERTYPE_BINANCEF2VT[ord_data["o"]],
direction=DIRECTION_BINANCEF2VT[ord_data["S"]],
price=float(ord_data["p"]),
volume=float(ord_data["q"]),
traded=float(ord_data["z"]),
status=STATUS_BINANCEF2VT[ord_data["X"]],
time=time,
gateway_name=self.gateway_name
)
self.gateway.on_order(order) self.gateway.on_order(order)
@ -747,6 +863,7 @@ class BinancefTradeWebsocketApi(WebsocketClient):
orderid=order.orderid, orderid=order.orderid,
tradeid=ord_data["t"], tradeid=ord_data["t"],
direction=order.direction, direction=order.direction,
offset=order.offset,
price=float(ord_data["L"]), price=float(ord_data["L"]),
volume=trade_volume, volume=trade_volume,
time=trade_time, time=trade_time,