[Add] 增加okexFutureApi.trade
[Add] okexFutureApi:增加自动登录
This commit is contained in:
parent
46dda98d07
commit
1f37a5ebeb
@ -1,4 +1,5 @@
|
|||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
|
from enum import Enum
|
||||||
from typing import Any, Callable, List, Union
|
from typing import Any, Callable, List, Union
|
||||||
|
|
||||||
from vnpy.api.okexfuture.vnokexFuture import OkexFutureRestBase, OkexFutureWebSocketBase
|
from vnpy.api.okexfuture.vnokexFuture import OkexFutureRestBase, OkexFutureWebSocketBase
|
||||||
@ -126,6 +127,68 @@ class OkexFuturePositionDetail(object):
|
|||||||
self.contractType = None
|
self.contractType = None
|
||||||
|
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
class OkexFutureTickInfo(object):
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def __init__(self, symbol, remoteContractType, last, limitHigh, limitLow, vol, sell, buy, unitAmount, holdAmount,
|
||||||
|
contractId, high, low):
|
||||||
|
self.symbol = symbol
|
||||||
|
self.remoteContractType = remoteContractType
|
||||||
|
self.last = last
|
||||||
|
self.limitHigh = limitHigh # type: str # 最高买入限制价格
|
||||||
|
self.limitLow = limitLow # type: str # 最低卖出限制价格
|
||||||
|
self.vol = vol # type: float # 24 小时成交量
|
||||||
|
self.sell = sell # type: float # 卖一价格
|
||||||
|
self.buy = buy # type: float # 买一价格
|
||||||
|
self.unitAmount = unitAmount # type: float # 合约价值
|
||||||
|
self.holdAmount = holdAmount # type: float # 当前持仓量
|
||||||
|
self.contractId = contractId # type: long # 合约ID
|
||||||
|
self.high = high # type: float # 24 小时最高价格
|
||||||
|
self.low = low # type: float # 24 小时最低价格
|
||||||
|
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
class OkexFutureTradeInfo(object):
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def __init__(self, symbol, remoteContractType, index, price, volume, time, direction, coinVolume):
|
||||||
|
self.symbol = symbol
|
||||||
|
self.remoteContractType = remoteContractType
|
||||||
|
self.index = index
|
||||||
|
self.price = price
|
||||||
|
self.volume = volume
|
||||||
|
self.time = time
|
||||||
|
self.direction = direction
|
||||||
|
self.coinVolume = coinVolume
|
||||||
|
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
class OkexFutureUserTradeInfo(object):
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def __init__(self, symbol, remoteContractType, amount,
|
||||||
|
contractName, createdDate, createDateStr, dealAmount, fee,
|
||||||
|
orderId, price, priceAvg, status, type, unitAmount, leverRate, systemType
|
||||||
|
):
|
||||||
|
self.symbol = symbol # type: str # btcUsd ltcUsd ethUsd etcUsd bchUsd
|
||||||
|
self.remoteContractType = remoteContractType
|
||||||
|
self.amount = amount # type: float # 委托数量
|
||||||
|
self.contractName = contractName # type: str # 合约名称
|
||||||
|
self.createdDate = createdDate # type: long # 委托时间
|
||||||
|
self.createDateStr = createDateStr # type: str # 委托时间字符串
|
||||||
|
self.dealAmount = dealAmount # type: float # 成交数量
|
||||||
|
self.fee = fee # type: float # 手续费
|
||||||
|
self.remoteId = orderId # type: long # 订单ID
|
||||||
|
self.price = price # type: float # 订单价格
|
||||||
|
self.priceAvg = priceAvg # type: float # 平均价格
|
||||||
|
self.status = status # type: int # 订单状态(0等待成交 1部分成交 2全部成交 -1撤单 4撤单处理中)
|
||||||
|
self.type = type # type: int # 订单类型 1:开多 2:开空 3:平多 4:平空
|
||||||
|
self.unitAmount = unitAmount # type: float # 合约面值
|
||||||
|
self.leverRate = leverRate # type: float # 杠杆倍数 value:10/20 默认10
|
||||||
|
self.systemType = systemType # type: int # 订单类型 0:普通 1:交割 2:强平 4:全平 5:系统反单
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
class OkexFutureRestClient(OkexFutureRestBase):
|
class OkexFutureRestClient(OkexFutureRestBase):
|
||||||
|
|
||||||
@ -443,6 +506,12 @@ class OkexFutureRestClient(OkexFutureRestBase):
|
|||||||
########################################################################
|
########################################################################
|
||||||
class OkexFutureWebSocketClient(OkexFutureWebSocketBase):
|
class OkexFutureWebSocketClient(OkexFutureWebSocketBase):
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def __init__(self):
|
||||||
|
super(OkexFutureWebSocketClient, self).__init__()
|
||||||
|
self.onTick = self.defaultOnTick
|
||||||
|
self.onUserTrade = self.defaultOnUserTrade
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def subscribe(self, easySymbol, contractType): # type: (OkexFutureEasySymbol, OkexFutureContractType)->None
|
def subscribe(self, easySymbol, contractType): # type: (OkexFutureEasySymbol, OkexFutureContractType)->None
|
||||||
self.sendPacket({
|
self.sendPacket({
|
||||||
@ -450,6 +519,72 @@ class OkexFutureWebSocketClient(OkexFutureWebSocketBase):
|
|||||||
'channel': 'ok_sub_futureusd_' + easySymbol + '_ticker_' + contractType
|
'channel': 'ok_sub_futureusd_' + easySymbol + '_ticker_' + contractType
|
||||||
})
|
})
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def defaultOnPacket(self, packets):
|
||||||
|
|
||||||
|
for packet in packets:
|
||||||
|
print('packets:')
|
||||||
|
print(packets)
|
||||||
|
channelName = None
|
||||||
|
if 'channel' in packet:
|
||||||
|
channelName = packet['channel']
|
||||||
|
if not channelName or channelName == 'addChannel':
|
||||||
|
return
|
||||||
|
|
||||||
|
packet = packet['data']
|
||||||
|
channel = parseChannel(channelName) # type: ExtraSymbolChannel
|
||||||
|
|
||||||
|
if channel.type == ChannelType.Tick:
|
||||||
|
self.onTick(OkexFutureTickInfo(
|
||||||
|
symbol=channel.symbol,
|
||||||
|
remoteContractType=channel.remoteContractType,
|
||||||
|
last=packet['last'], # float # 最高买入限制价格
|
||||||
|
limitHigh=packet['limitHigh'], # str # 最高买入限制价格
|
||||||
|
limitLow=packet['limitLow'], # str # 最低卖出限制价格
|
||||||
|
vol=packet['vol'], # float # 24 小时成交量
|
||||||
|
sell=packet['sell'], # float # 卖一价格
|
||||||
|
buy=packet['buy'], # float # 买一价格
|
||||||
|
unitAmount=packet['unitAmount'], # float # 合约价值
|
||||||
|
holdAmount=packet['hold_amount'], # float # 当前持仓量
|
||||||
|
contractId=packet['contractId'], # long # 合约ID
|
||||||
|
high=packet['high'], # float # 24 小时最高价格
|
||||||
|
low=packet['low'], # float # 24 小时最低价格
|
||||||
|
))
|
||||||
|
# elif channel.type == ChannelType.Trade:
|
||||||
|
# trades = []
|
||||||
|
# for tradeInfo in packet:
|
||||||
|
# trades.append(OkexFutureTradeInfo(
|
||||||
|
# channel.symbol, channel.remoteContractType, *tradeInfo
|
||||||
|
# ))
|
||||||
|
# self.onTrades(trades)
|
||||||
|
elif channel.type == ChannelType.UserTrade:
|
||||||
|
self.onUserTrade(OkexFutureUserTradeInfo(
|
||||||
|
symbol=packet['symbol'], # str # btc_usd ltc_usd eth_usd etc_usd bch_usd
|
||||||
|
remoteContractType=packet['contract_type'],
|
||||||
|
amount=packet['amount'], # float # 委托数量
|
||||||
|
contractName=packet['contract_name'], # str # 合约名称
|
||||||
|
createdDate=packet['created_date'], # long # 委托时间
|
||||||
|
createDateStr=packet['create_date_str'], # str # 委托时间字符串
|
||||||
|
dealAmount=packet['deal_amount'], # float # 成交数量
|
||||||
|
fee=packet['fee'], # float # 手续费
|
||||||
|
orderId=packet['order_id'], # long # 订单ID
|
||||||
|
price=packet['price'], # float # 订单价格
|
||||||
|
priceAvg=packet['price_avg'], # float # 平均价格
|
||||||
|
status=packet['status'], # int # 订单状态(0等待成交 1部分成交 2全部成交 -1撤单 4撤单处理中)
|
||||||
|
type=packet['type'], # int # 订单类型 1:开多 2:开空 3:平多 4:平空
|
||||||
|
unitAmount=packet['unit_amount'], # float # 合约面值
|
||||||
|
leverRate=packet['lever_rate'], # float # 杠杆倍数 value:10/20 默认10
|
||||||
|
systemType=packet['system_type'], # int # 订单类型 0:普通 1:交割 2:强平 4:全平 5:系统反单
|
||||||
|
))
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def defaultOnTick(self, tick): # type: (OkexFutureTickInfo)->None
|
||||||
|
pass
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def defaultOnUserTrade(self, tick): # type: (OkexFutureUserTradeInfo)->None
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
restErrorCodeMap = {
|
restErrorCodeMap = {
|
||||||
0: '远程服务器并未给出错误代码',
|
0: '远程服务器并未给出错误代码',
|
||||||
@ -597,3 +732,86 @@ webSocketErrorCodeMap = {
|
|||||||
1208: '没有该转账用户',
|
1208: '没有该转账用户',
|
||||||
1209: '当前api不可用',
|
1209: '当前api不可用',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
class ChannelType(Enum):
|
||||||
|
Login = 1
|
||||||
|
ForecastPrice = 2
|
||||||
|
Tick = 3
|
||||||
|
Depth = 4
|
||||||
|
Trade = 5
|
||||||
|
Index = 6
|
||||||
|
UserTrade = 7
|
||||||
|
UserInfo = 8
|
||||||
|
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
class Channel(object):
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def __init__(self, type):
|
||||||
|
self.type = type
|
||||||
|
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
class SymbolChannel(Channel):
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def __init__(self, type, symbol):
|
||||||
|
super(SymbolChannel, self).__init__(type)
|
||||||
|
self.symbol = symbol
|
||||||
|
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
class FutureSymbolChannel(SymbolChannel):
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def __init__(self, type, symbol, remoteContractType):
|
||||||
|
super(FutureSymbolChannel, self).__init__(type, symbol)
|
||||||
|
self.remoteContractType = remoteContractType
|
||||||
|
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
class ExtraSymbolChannel(FutureSymbolChannel):
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def __init__(self, type, symbol, remoteContractType, extra):
|
||||||
|
super(ExtraSymbolChannel, self).__init__(type, symbol, remoteContractType)
|
||||||
|
self.extra = extra
|
||||||
|
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def parseChannel(channel): # type: (str)->Channel
|
||||||
|
if channel == 'login':
|
||||||
|
return Channel(ChannelType.Login)
|
||||||
|
|
||||||
|
# 还未提供订阅的channel都注释掉
|
||||||
|
# elif channel[4:12] == 'forecast': # eg: 'btc_forecast_price'
|
||||||
|
# return SymbolChannel(ChannelType.ForecastPrice, channel[:3])
|
||||||
|
|
||||||
|
sp = channel.split('_')
|
||||||
|
if sp[-1] == 'trades': # eg: 'ok_sub_futureusd_trades'
|
||||||
|
return Channel(ChannelType.UserTrade)
|
||||||
|
# if sp[-1] == 'userinfo': # eg: 'ok_sub_futureusd_btc_userinfo'
|
||||||
|
# return Channel(ChannelType.UserInfo)
|
||||||
|
# if sp[-1] == 'index': # eg: 'ok_sub_futureusd_btc_index'
|
||||||
|
# return SymbolChannel(ChannelType.Index, channel[17:20])
|
||||||
|
|
||||||
|
# if len(sp) == 9:
|
||||||
|
# _, _, _, easySymbol, crash, typeName, contractTypePrefix, _, depth = sp
|
||||||
|
# return ExtraSymbolChannel(ChannelType.Depth, easySymbol + '_' + crash,
|
||||||
|
# remotePrefixToRemoteContractType(contractTypePrefix),
|
||||||
|
# depth)
|
||||||
|
_, _, _, easySymbol, crash, typeName, contractTypePrefix, _ = sp
|
||||||
|
return FutureSymbolChannel(ChannelType.Tick, easySymbol + '_' + crash,
|
||||||
|
remotePrefixToRemoteContractType(contractTypePrefix))
|
||||||
|
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def remotePrefixToRemoteContractType(prefix):
|
||||||
|
return _prefixForRemoteContractType[prefix]
|
||||||
|
|
||||||
|
|
||||||
|
_prefixForRemoteContractType = {v.split('_')[0]: v for k, v in OkexFutureContractType.__dict__.items() if
|
||||||
|
not k.startswith('_')}
|
||||||
|
@ -6,9 +6,20 @@ from vnpy.api.rest import Request, RestClient
|
|||||||
from vnpy.api.websocket import WebSocketClient
|
from vnpy.api.websocket import WebSocketClient
|
||||||
|
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def paramsToData(params):
|
||||||
|
return urllib.urlencode(sorted(params.items()))
|
||||||
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def sign(dataWithApiKey, apiSecret):
|
def sign(dataWithApiKey, apiSecret):
|
||||||
"""
|
"""
|
||||||
|
usage:
|
||||||
|
params = { ... , 'api_key': ...}
|
||||||
|
data = paramsToData(params)
|
||||||
|
signature = sign(data, apiSecret)
|
||||||
|
data += "&sign" + signature
|
||||||
|
|
||||||
:param dataWithApiKey: sorted urlencoded args with apiKey
|
:param dataWithApiKey: sorted urlencoded args with apiKey
|
||||||
:return: param 'sign' for okex api
|
:return: param 'sign' for okex api
|
||||||
"""
|
"""
|
||||||
@ -42,7 +53,7 @@ class OkexFutureRestBase(RestClient):
|
|||||||
args.pop('sign')
|
args.pop('sign')
|
||||||
if 'apiKey' not in args:
|
if 'apiKey' not in args:
|
||||||
args['api_key'] = self.apiKey
|
args['api_key'] = self.apiKey
|
||||||
data = urllib.urlencode(sorted(args.items()))
|
data = paramsToData(args)
|
||||||
signature = sign(data, self.apiSecret)
|
signature = sign(data, self.apiSecret)
|
||||||
data += "&sign=" + signature
|
data += "&sign=" + signature
|
||||||
|
|
||||||
@ -64,13 +75,17 @@ class OkexFutureWebSocketBase(WebSocketClient):
|
|||||||
super(OkexFutureWebSocketBase, self).init(OkexFutureWebSocketBase.host)
|
super(OkexFutureWebSocketBase, self).init(OkexFutureWebSocketBase.host)
|
||||||
self.apiKey = None
|
self.apiKey = None
|
||||||
self.apiSecret = None
|
self.apiSecret = None
|
||||||
|
self.autoLogin = True
|
||||||
|
|
||||||
|
self.onConnected = self._onConnected
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
# noinspection PyMethodOverriding
|
# noinspection PyMethodOverriding
|
||||||
def init(self, apiKey, secretKey):
|
def init(self, apiKey, secretKey, autoLogin=True):
|
||||||
|
|
||||||
self.apiKey = apiKey
|
self.apiKey = apiKey
|
||||||
self.apiSecret = secretKey
|
self.apiSecret = secretKey
|
||||||
|
self.autoLogin = autoLogin
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def sendPacket(self, dictObj, authenticate=False):
|
def sendPacket(self, dictObj, authenticate=False):
|
||||||
@ -79,3 +94,21 @@ class OkexFutureWebSocketBase(WebSocketClient):
|
|||||||
signature = sign(data, self.apiSecret)
|
signature = sign(data, self.apiSecret)
|
||||||
dictObj['sign'] = signature
|
dictObj['sign'] = signature
|
||||||
return super(OkexFutureWebSocketBase, self).sendPacket(dictObj)
|
return super(OkexFutureWebSocketBase, self).sendPacket(dictObj)
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def _login(self, ):
|
||||||
|
|
||||||
|
params = {"api_key": self.apiKey, }
|
||||||
|
data = paramsToData(params)
|
||||||
|
signature = sign(data, self.apiSecret)
|
||||||
|
params['sign'] = signature
|
||||||
|
|
||||||
|
self.sendPacket({
|
||||||
|
"event": "login",
|
||||||
|
"parameters": params
|
||||||
|
}, authenticate=False)
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def _onConnected(self):
|
||||||
|
if self.autoLogin:
|
||||||
|
self._login()
|
||||||
|
@ -3,9 +3,8 @@
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from abc import abstractmethod, abstractproperty
|
from abc import abstractmethod
|
||||||
|
|
||||||
from enum import Enum
|
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
from vnpy.api.okexfuture.OkexFutureApi import *
|
from vnpy.api.okexfuture.OkexFutureApi import *
|
||||||
@ -75,7 +74,8 @@ class OkexFutureGateway(VnpyGateway):
|
|||||||
self.restApi = OkexFutureRestClient()
|
self.restApi = OkexFutureRestClient()
|
||||||
|
|
||||||
self.webSocket = OkexFutureWebSocketClient()
|
self.webSocket = OkexFutureWebSocketClient()
|
||||||
self.webSocket.onPacket = self._onWebsocketPacket
|
self.webSocket.onTick = self._onTick
|
||||||
|
self.webSocket.onUserTrade = self._onUserTrade
|
||||||
|
|
||||||
self.leverRate = 1
|
self.leverRate = 1
|
||||||
self.symbols = []
|
self.symbols = []
|
||||||
@ -125,11 +125,15 @@ class OkexFutureGateway(VnpyGateway):
|
|||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def _getOrderByLocalId(self, localId):
|
def _getOrderByLocalId(self, localId):
|
||||||
|
if localId in self._orders:
|
||||||
return self._orders[localId]
|
return self._orders[localId]
|
||||||
|
return None
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def _getOrderByRemoteId(self, remoteId):
|
def _getOrderByRemoteId(self, remoteId):
|
||||||
|
if remoteId in self._remoteIds:
|
||||||
return self._remoteIds[remoteId]
|
return self._remoteIds[remoteId]
|
||||||
|
return None
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def _saveRemoteId(self, remoteId, myorder):
|
def _saveRemoteId(self, remoteId, myorder):
|
||||||
@ -184,6 +188,8 @@ class OkexFutureGateway(VnpyGateway):
|
|||||||
def cancelOrder(self, vtCancel): # type: (VtCancelOrderReq)->None
|
def cancelOrder(self, vtCancel): # type: (VtCancelOrderReq)->None
|
||||||
"""撤单"""
|
"""撤单"""
|
||||||
myorder = self._getOrderByLocalId(vtCancel.orderID)
|
myorder = self._getOrderByLocalId(vtCancel.orderID)
|
||||||
|
assert myorder is not None, u"理论上是无法取消一个不存在的本地单的"
|
||||||
|
|
||||||
symbol, contractType = localSymbolToRemote(vtCancel.symbol)
|
symbol, contractType = localSymbolToRemote(vtCancel.symbol)
|
||||||
self.restApi.cancelOrder(symbol=symbol,
|
self.restApi.cancelOrder(symbol=symbol,
|
||||||
contractType=contractType,
|
contractType=contractType,
|
||||||
@ -257,9 +263,9 @@ class OkexFutureGateway(VnpyGateway):
|
|||||||
for order in orders:
|
for order in orders:
|
||||||
remoteId = order.remoteId
|
remoteId = order.remoteId
|
||||||
|
|
||||||
if remoteId in self._remoteIds:
|
|
||||||
# 如果订单已经缓存在本地,则尝试更新订单状态
|
|
||||||
myorder = self._getOrderByRemoteId(remoteId)
|
myorder = self._getOrderByRemoteId(remoteId)
|
||||||
|
if myorder:
|
||||||
|
# 如果订单已经缓存在本地,则尝试更新订单状态
|
||||||
|
|
||||||
# 有新交易才推送更新
|
# 有新交易才推送更新
|
||||||
if order.tradedVolume != myorder.vtOrder.tradedVolume:
|
if order.tradedVolume != myorder.vtOrder.tradedVolume:
|
||||||
@ -316,35 +322,37 @@ class OkexFutureGateway(VnpyGateway):
|
|||||||
self.onPosition(pos)
|
self.onPosition(pos)
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def _onWebsocketPacket(self, packets): # type: (dict)->None
|
def _onTick(self, info): # type: (OkexFutureTickInfo)->None
|
||||||
|
uiSymbol = remoteSymbolToLocal(info.symbol, remoteContractTypeToLocal(info.remoteContractType))
|
||||||
for packet in packets:
|
self.onTick(VtTickData.createFromGateway(
|
||||||
print('packets:')
|
|
||||||
print(packets)
|
|
||||||
channelName = None
|
|
||||||
if 'channel' in packet:
|
|
||||||
channelName = packet['channel']
|
|
||||||
if not channelName or channelName == 'addChannel':
|
|
||||||
return
|
|
||||||
|
|
||||||
packet = packet['data']
|
|
||||||
channel = parseChannel(channelName) # type: ExtraSymbolChannel
|
|
||||||
|
|
||||||
if channel.type == ChannelType.Tick:
|
|
||||||
uiSymbol = remoteSymbolToLocal(channel.symbol, remoteContractTypeToLocal(channel.remoteContractType))
|
|
||||||
tick = VtTickData.createFromGateway(
|
|
||||||
gateway=self,
|
gateway=self,
|
||||||
symbol=uiSymbol,
|
symbol=uiSymbol,
|
||||||
exchange=self.exchange,
|
exchange=self.exchange,
|
||||||
lastPrice=float(packet['last']),
|
lastPrice=info.last,
|
||||||
lastVolume=float(packet['vol']),
|
lastVolume=info.vol,
|
||||||
highPrice=float(packet['high']),
|
highPrice=info.high,
|
||||||
lowPrice=float(packet['low']),
|
lowPrice=info.low,
|
||||||
openInterest=int(packet['hold_amount']),
|
openInterest=info.holdAmount,
|
||||||
lowerLimit=float(packet['limitLow']),
|
lowerLimit=info.limitLow,
|
||||||
upperLimit=float(packet['limitHigh'])
|
upperLimit=info.limitHigh,
|
||||||
)
|
))
|
||||||
self.onTick(tick)
|
|
||||||
|
def _onUserTrade(self, info): # type: (OkexFutureUserTradeInfo)->None
|
||||||
|
tradeID = str(self.tradeID)
|
||||||
|
self.tradeID += 1
|
||||||
|
order = self._getOrderByRemoteId(info.remoteId)
|
||||||
|
if order:
|
||||||
|
self.onTrade(VtTradeData.createFromOrderData(
|
||||||
|
order=order.vtOrder,
|
||||||
|
tradeID=tradeID,
|
||||||
|
tradePrice=info.price,
|
||||||
|
tradeVolume=info.dealAmount # todo: 这里应该填写的到底是order总共成交了的数量,还是该次trade成交的数量
|
||||||
|
))
|
||||||
|
else:
|
||||||
|
# todo: 与order无关联的trade该如何处理?
|
||||||
|
# uiSymbol = remoteSymbolToLocal(info.symbol, remoteContractTypeToLocal(info.remoteContractType))
|
||||||
|
pass
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
@ -384,77 +392,6 @@ def remoteSymbolToLocal(remoteSymbol, localContractType):
|
|||||||
return remoteSymbol.upper() + '_' + localContractType
|
return remoteSymbol.upper() + '_' + localContractType
|
||||||
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
def remotePrefixToRemoteContractType(prefix):
|
|
||||||
return _prefixForRemoteContractType[prefix]
|
|
||||||
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
class ChannelType(Enum):
|
|
||||||
Login = 1
|
|
||||||
ForecastPrice = 2
|
|
||||||
Tick = 3
|
|
||||||
Depth = 4
|
|
||||||
Trade = 5
|
|
||||||
Index = 6
|
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
class Channel(object):
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
def __init__(self, type):
|
|
||||||
self.type = type
|
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
class SymbolChannel(Channel):
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
def __init__(self, type, symbol):
|
|
||||||
super(SymbolChannel, self).__init__(type)
|
|
||||||
self.symbol = symbol
|
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
class FutureSymbolChannel(SymbolChannel):
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
def __init__(self, type, symbol, remoteContractType):
|
|
||||||
super(FutureSymbolChannel, self).__init__(type, symbol)
|
|
||||||
self.remoteContractType = remoteContractType
|
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
class ExtraSymbolChannel(FutureSymbolChannel):
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
def __init__(self, type, symbol, remoteContractType, extra):
|
|
||||||
super(ExtraSymbolChannel, self).__init__(type, symbol, remoteContractType)
|
|
||||||
self.extra = extra
|
|
||||||
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
def parseChannel(channel): # type: (str)->Channel
|
|
||||||
if channel == 'login':
|
|
||||||
return Channel(ChannelType.Login)
|
|
||||||
elif channel[4:12] == 'forecast': # eg: 'btc_forecast_price'
|
|
||||||
return SymbolChannel(ChannelType.ForecastPrice, channel[:3])
|
|
||||||
sp = channel.split('_')
|
|
||||||
if sp[-1] == 'index': # eg: 'ok_sub_futureusd_btc_index'
|
|
||||||
return SymbolChannel(ChannelType.Index, channel[17:20])
|
|
||||||
|
|
||||||
l = len(sp)
|
|
||||||
if len(sp) == 9:
|
|
||||||
_, _, _, easySymbol, crash, typeName, contractTypePrefix, _, depth = sp
|
|
||||||
return ExtraSymbolChannel(ChannelType.Depth, easySymbol + '_' + crash,
|
|
||||||
remotePrefixToRemoteContractType(contractTypePrefix),
|
|
||||||
depth)
|
|
||||||
_, _, _, easySymbol, crash, typeName, contractTypePrefix, _ = sp
|
|
||||||
return FutureSymbolChannel(ChannelType.Tick, easySymbol + '_' + crash,
|
|
||||||
remotePrefixToRemoteContractType(contractTypePrefix))
|
|
||||||
|
|
||||||
|
|
||||||
_orderTypeMap = {
|
_orderTypeMap = {
|
||||||
(constant.DIRECTION_LONG, constant.OFFSET_OPEN): OkexFutureOrderType.OpenLong,
|
(constant.DIRECTION_LONG, constant.OFFSET_OPEN): OkexFutureOrderType.OpenLong,
|
||||||
(constant.DIRECTION_SHORT, constant.OFFSET_OPEN): OkexFutureOrderType.OpenShort,
|
(constant.DIRECTION_SHORT, constant.OFFSET_OPEN): OkexFutureOrderType.OpenShort,
|
||||||
@ -463,9 +400,6 @@ _orderTypeMap = {
|
|||||||
}
|
}
|
||||||
_orderTypeMapReverse = {v: k for k, v in _orderTypeMap.items()}
|
_orderTypeMapReverse = {v: k for k, v in _orderTypeMap.items()}
|
||||||
|
|
||||||
_prefixForRemoteContractType = {v.split('_')[0]: v for k, v in OkexFutureContractType.__dict__.items() if
|
|
||||||
not k.startswith('_')}
|
|
||||||
|
|
||||||
_contractTypeMap = {
|
_contractTypeMap = {
|
||||||
k.upper(): v for k, v in OkexFutureContractType.__dict__.items() if not k.startswith('_')
|
k.upper(): v for k, v in OkexFutureContractType.__dict__.items() if not k.startswith('_')
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user