[Add] 增加okexFutureApi.trade
[Add] okexFutureApi:增加自动登录
This commit is contained in:
parent
46dda98d07
commit
1f37a5ebeb
@ -1,4 +1,5 @@
|
||||
# encoding: UTF-8
|
||||
from enum import Enum
|
||||
from typing import Any, Callable, List, Union
|
||||
|
||||
from vnpy.api.okexfuture.vnokexFuture import OkexFutureRestBase, OkexFutureWebSocketBase
|
||||
@ -126,6 +127,68 @@ class OkexFuturePositionDetail(object):
|
||||
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):
|
||||
|
||||
@ -443,6 +506,12 @@ class OkexFutureRestClient(OkexFutureRestBase):
|
||||
########################################################################
|
||||
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
|
||||
self.sendPacket({
|
||||
@ -450,6 +519,72 @@ class OkexFutureWebSocketClient(OkexFutureWebSocketBase):
|
||||
'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 = {
|
||||
0: '远程服务器并未给出错误代码',
|
||||
@ -597,3 +732,86 @@ webSocketErrorCodeMap = {
|
||||
1208: '没有该转账用户',
|
||||
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
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def paramsToData(params):
|
||||
return urllib.urlencode(sorted(params.items()))
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
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
|
||||
:return: param 'sign' for okex api
|
||||
"""
|
||||
@ -42,7 +53,7 @@ class OkexFutureRestBase(RestClient):
|
||||
args.pop('sign')
|
||||
if 'apiKey' not in args:
|
||||
args['api_key'] = self.apiKey
|
||||
data = urllib.urlencode(sorted(args.items()))
|
||||
data = paramsToData(args)
|
||||
signature = sign(data, self.apiSecret)
|
||||
data += "&sign=" + signature
|
||||
|
||||
@ -64,13 +75,17 @@ class OkexFutureWebSocketBase(WebSocketClient):
|
||||
super(OkexFutureWebSocketBase, self).init(OkexFutureWebSocketBase.host)
|
||||
self.apiKey = None
|
||||
self.apiSecret = None
|
||||
self.autoLogin = True
|
||||
|
||||
self.onConnected = self._onConnected
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# noinspection PyMethodOverriding
|
||||
def init(self, apiKey, secretKey):
|
||||
def init(self, apiKey, secretKey, autoLogin=True):
|
||||
|
||||
self.apiKey = apiKey
|
||||
self.apiSecret = secretKey
|
||||
self.autoLogin = autoLogin
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def sendPacket(self, dictObj, authenticate=False):
|
||||
@ -79,3 +94,21 @@ class OkexFutureWebSocketBase(WebSocketClient):
|
||||
signature = sign(data, self.apiSecret)
|
||||
dictObj['sign'] = signature
|
||||
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
|
||||
|
||||
import json
|
||||
from abc import abstractmethod, abstractproperty
|
||||
from abc import abstractmethod
|
||||
|
||||
from enum import Enum
|
||||
from typing import Dict
|
||||
|
||||
from vnpy.api.okexfuture.OkexFutureApi import *
|
||||
@ -75,7 +74,8 @@ class OkexFutureGateway(VnpyGateway):
|
||||
self.restApi = OkexFutureRestClient()
|
||||
|
||||
self.webSocket = OkexFutureWebSocketClient()
|
||||
self.webSocket.onPacket = self._onWebsocketPacket
|
||||
self.webSocket.onTick = self._onTick
|
||||
self.webSocket.onUserTrade = self._onUserTrade
|
||||
|
||||
self.leverRate = 1
|
||||
self.symbols = []
|
||||
@ -125,11 +125,15 @@ class OkexFutureGateway(VnpyGateway):
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def _getOrderByLocalId(self, localId):
|
||||
if localId in self._orders:
|
||||
return self._orders[localId]
|
||||
return None
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def _getOrderByRemoteId(self, remoteId):
|
||||
if remoteId in self._remoteIds:
|
||||
return self._remoteIds[remoteId]
|
||||
return None
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def _saveRemoteId(self, remoteId, myorder):
|
||||
@ -184,6 +188,8 @@ class OkexFutureGateway(VnpyGateway):
|
||||
def cancelOrder(self, vtCancel): # type: (VtCancelOrderReq)->None
|
||||
"""撤单"""
|
||||
myorder = self._getOrderByLocalId(vtCancel.orderID)
|
||||
assert myorder is not None, u"理论上是无法取消一个不存在的本地单的"
|
||||
|
||||
symbol, contractType = localSymbolToRemote(vtCancel.symbol)
|
||||
self.restApi.cancelOrder(symbol=symbol,
|
||||
contractType=contractType,
|
||||
@ -257,9 +263,9 @@ class OkexFutureGateway(VnpyGateway):
|
||||
for order in orders:
|
||||
remoteId = order.remoteId
|
||||
|
||||
if remoteId in self._remoteIds:
|
||||
# 如果订单已经缓存在本地,则尝试更新订单状态
|
||||
myorder = self._getOrderByRemoteId(remoteId)
|
||||
if myorder:
|
||||
# 如果订单已经缓存在本地,则尝试更新订单状态
|
||||
|
||||
# 有新交易才推送更新
|
||||
if order.tradedVolume != myorder.vtOrder.tradedVolume:
|
||||
@ -316,35 +322,37 @@ class OkexFutureGateway(VnpyGateway):
|
||||
self.onPosition(pos)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def _onWebsocketPacket(self, packets): # type: (dict)->None
|
||||
|
||||
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:
|
||||
uiSymbol = remoteSymbolToLocal(channel.symbol, remoteContractTypeToLocal(channel.remoteContractType))
|
||||
tick = VtTickData.createFromGateway(
|
||||
def _onTick(self, info): # type: (OkexFutureTickInfo)->None
|
||||
uiSymbol = remoteSymbolToLocal(info.symbol, remoteContractTypeToLocal(info.remoteContractType))
|
||||
self.onTick(VtTickData.createFromGateway(
|
||||
gateway=self,
|
||||
symbol=uiSymbol,
|
||||
exchange=self.exchange,
|
||||
lastPrice=float(packet['last']),
|
||||
lastVolume=float(packet['vol']),
|
||||
highPrice=float(packet['high']),
|
||||
lowPrice=float(packet['low']),
|
||||
openInterest=int(packet['hold_amount']),
|
||||
lowerLimit=float(packet['limitLow']),
|
||||
upperLimit=float(packet['limitHigh'])
|
||||
)
|
||||
self.onTick(tick)
|
||||
lastPrice=info.last,
|
||||
lastVolume=info.vol,
|
||||
highPrice=info.high,
|
||||
lowPrice=info.low,
|
||||
openInterest=info.holdAmount,
|
||||
lowerLimit=info.limitLow,
|
||||
upperLimit=info.limitHigh,
|
||||
))
|
||||
|
||||
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
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
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 = {
|
||||
(constant.DIRECTION_LONG, constant.OFFSET_OPEN): OkexFutureOrderType.OpenLong,
|
||||
(constant.DIRECTION_SHORT, constant.OFFSET_OPEN): OkexFutureOrderType.OpenShort,
|
||||
@ -463,9 +400,6 @@ _orderTypeMap = {
|
||||
}
|
||||
_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 = {
|
||||
k.upper(): v for k, v in OkexFutureContractType.__dict__.items() if not k.startswith('_')
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user