- Square
- OkEX合约 仓位管理系统
OkEX合约 仓位管理系统
Author:
FawkesPan, Date: 2018-10-16 17:56:45
Tags:
import time
import math
import threading
import decimal
from uuid import uuid4 as _uuid
def genUUID():
return str(_uuid())
class PositionManager:
def __init__(self, exchange, symbol, contract, getDepth, tickSize=0.01):
self.okex = exchange
self.symbol = symbol
self.contract = contract
self.tickSize = tickSize
self.isFMZ = False
if 'Asks' in getDepth().keys():
self.isFMZ = True
self.okexGetDepth = getDepth
self.orderLock = threading.Lock()
self.orderLocks = {}
self.orders = {}
self.cancels = []
self.completeds = []
self.init()
def init(self):
self.okex.IO("currency", self.symbol.upper())
self.okex.SetContractType(self.contract)
self.order_logs = {
'buySent': 0,
'buyCanceled': 0,
'sellSent': 0,
'sellCanceled': 0
}
def toNearest(self, num):
tickDec = decimal.Decimal(str(self.tickSize))
return float((decimal.Decimal(round(num / self.tickSize, 0)) * tickDec))
def getDepth(self):
depth = self.okexGetDepth()
if self.isFMZ:
depth['asks'] = [[x['Price'], x['Amount']] for x in depth['Asks']]
depth['bids'] = [[x['Price'], x['Amount']] for x in depth['Bids']]
return depth
def getOrderLogs(self):
return self.order_logs
def getBestPrices(self):
bestPrices = {}
depth = self.getDepth()
ask, bid = depth['asks'][0][0], depth['bids'][0][0]
spread = ask - bid
if spread <= self.tickSize*2:
bestPrices['ask'] = ask
bestPrices['bid'] = bid
elif spread <= self.tickSize*6:
bestPrices['ask'] = ask-self.tickSize
bestPrices['bid'] = bid+self.tickSize
elif spread >= self.tickSize*20:
bestPrices['ask'] = ask-self.tickSize*5
bestPrices['bid'] = bid+self.tickSize*5
else:
midPrice = self.toNearest((ask+bid)/2)
bestPrices['ask'] = midPrice+self.tickSize*2
bestPrices['bid'] = midPrice-self.tickSize*2
return {
'ask': self.toNearest(bestPrices['ask']),
'bid': self.toNearest(bestPrices['bid'])
}
def getPositions(self, noRetry=False, maxRetries=10):
if noRetry:
return self.okex.GetPosition()
attempts = 0
while True:
time.sleep(0.4)
positions = self.okex.GetPosition()
attempts+=1
if len(positions) != 0:
return positions
if attempts == maxRetries:
return False
def havePosition(self, type=None, noRetry=True, maxRetries=10):
positions = self.getPositions(noRetry=True)
if not positions:
positions = []
if type == None:
pass
elif type == 'buy':
key = 'buy_amount'
elif type == 'sell':
key = 'sell_amount'
for position in positions:
if type is not None:
if position['Info'][key] != 0:
return positions
else:
return positions
if noRetry:
return False
attempts = 0
while True:
time.sleep(0.4)
positions = self.getPositions(noRetry=True)
if not positions:
positions = []
attempts+=1
for position in positions:
if type is not None:
if position['Info'][key] != 0:
return positions
else:
return positions
if attempts == maxRetries:
return False
def orderDone(self, orderID):
orders = self.okex.GetOrders()
for order in orders:
if order['Info']['order_id'] == orderID:
return order['Info']['price'], order['Info']['amount']-order['Info']['deal_amount']
return True
def getOrder(self, uuid):
try:
self.orders[uuid]
except KeyError:
Log('不存在订单 %s' % uuid)
return 0
return self.orders[uuid]
def getOrderInfo(self, uuid):
return self.okex.GetOrder(self.getOrder(uuid))
def awaitOrder(self, uuid, timeout=None):
start = time.time()
try:
self.orderLocks[uuid]
except KeyError:
return False
while True:
if self.orderLocks[uuid].acquire(False):
del self.orderLocks[uuid]
return self.getOrder(uuid)
else:
if timeout is not None:
if time.time()-timeout>start:
Log('等待订单成交已超时.')
return
time.sleep(0.001)
def isDone(self, uuid):
if uuid in self.completeds:
return True
return False
def cancel(self, uuid):
self.cancels.append(uuid)
_cancel = self.okex.CancelOrder(self.getOrder(uuid))
self.orderLocks[uuid].acquire()
self.orderLocks[uuid].release()
if _cancel:
Log(uuid, str(self.getOrder(uuid)), '已取消.')
return True
Log(uuid, str(self.getOrder(uuid)), '取消失败.', str(self.okex.GetRawJSON()))
return False
def trade(self, type, price, amount, matchPrice=False, noRetry=False, uuid=None):
if type == 'buy' or type == 'closesell':
_trader = self.okex.Buy
_side = 'buy'
__side = 'bid'
else:
_trader = self.okex.Sell
_side = 'sell'
__side = 'ask'
def trader(price, amount):
self.orderLock.acquire()
self.okex.SetDirection(type)
order = _trader(price, amount)
self.orders[uuid] = order
self.orderLock.release()
self.order_logs['%sSent' % _side]+=1
return order
def isBestPrice(currentPrice, depth):
ret = False
if _side == 'buy':
if currentPrice > depth['bids'][1][0]:
ret = True
else:
if currentPrice < depth['asks'][1][0]:
ret = True
return ret
if price is None:
price = self.getBestPrices()[__side]
if matchPrice:
price = -1
order = trader(price, amount)
if noRetry:
self.completeds.append(uuid)
self.orderLocks[uuid].release()
return
if order == False:
if 20016 in str(self.okex.GetRawJSON()):
order = trader(price, amount)
if order == False:
Log('%s 返回值: %s', (uuid, str(self.okex.GetRawJSON())))
self.completeds.append(uuid)
self.orderLocks[uuid].release()
return
time.sleep(1)
while True:
if uuid in self.cancels:
Log('%s 已停止下单尝试.' % uuid)
self.completeds.append(uuid)
self.orderLocks[uuid].release()
return
time.sleep(1)
depth = self.getDepth()
isDone = self.orderDone(order)
if isDone == True:
self.completeds.append(uuid)
self.orderLocks[uuid].release()
return
if isBestPrice(isDone[0], depth):
continue
if not self.okex.CancelOrder(order):
time.sleep(1)
if self.orderDone(order):
self.completeds.append(uuid)
self.orderLocks[uuid].release()
return
self.order_logs['%sCanceled' % _side]+=1
time.sleep(1)
if price != -1:
price = self.getBestPrices()[__side]
if uuid in self.cancels:
Log('%s 已停止下单尝试.' % uuid)
self.completeds.append(uuid)
self.orderLocks[uuid].release()
return
order = trader(price, isDone[1])
def openLong(self, amount, price=None, matchPrice=False, noRetry=False):
uuid = genUUID()
Log('%s 买入做多 是否使用对手价 %s 阻塞直至成功 %s' % (uuid, str(matchPrice), str(not noRetry)))
threading.Thread(target=self.trade, kwargs=dict({'type': 'buy',
'price': price,
'amount': amount,
'matchPrice': matchPrice,
'noRetry': noRetry,
'uuid': uuid}), daemon=True).start()
self.orderLocks[uuid] = threading.Lock()
self.orderLocks[uuid].acquire()
return uuid
def openShort(self, amount, price=None, matchPrice=False, noRetry=False):
uuid = genUUID()
Log('%s 卖出做空 是否使用对手价 %s 阻塞直至成功 %s' % (uuid, str(matchPrice), str(not noRetry)))
threading.Thread(target=self.trade, kwargs=dict({'type': 'sell',
'price': price,
'amount': amount,
'matchPrice': matchPrice,
'noRetry': noRetry,
'uuid': uuid}), daemon=True).start()
self.orderLocks[uuid] = threading.Lock()
self.orderLocks[uuid].acquire()
return uuid
def coverLong(self, amount, price=None, matchPrice=False, noRetry=False):
uuid = genUUID()
Log('%s 卖出平多 是否使用对手价 %s 阻塞直至成功 %s' % (uuid, str(matchPrice), str(not noRetry)))
threading.Thread(target=self.trade, kwargs=dict({'type': 'closebuy',
'price': price,
'amount': amount,
'matchPrice': matchPrice,
'noRetry': noRetry,
'uuid': uuid}), daemon=True).start()
self.orderLocks[uuid] = threading.Lock()
self.orderLocks[uuid].acquire()
return uuid
def coverShort(self, amount, price=None, matchPrice=False, noRetry=False):
uuid = genUUID()
Log('%s 买入平空 是否使用对手价 %s 阻塞直至成功 %s' % (uuid, str(matchPrice), str(not noRetry)))
threading.Thread(target=self.trade, kwargs=dict({'type': 'closesell',
'price': price,
'amount': amount,
'matchPrice': matchPrice,
'noRetry': noRetry,
'uuid': uuid}), daemon=True).start()
self.orderLocks[uuid] = threading.Lock()
self.orderLocks[uuid].acquire()
return uuid
ext.okexPositionManager = PositionManager
More