def run(): logger = setup_logger() # Instantiating the WS will make it connect. Be sure to add your api_key/api_secret. ws = BitMEXWebsocket( endpoint="https://testnet.bitmex.com/api/v1", symbol="XBTUSD", api_key='-H4GmpGWNC505KogaaKyxoch', api_secret='GBM8hOsE9PYnKj374IHqv7M096sEpRSfoLZvA3hvY6oIHizJ') logger.info("Instrument data: %s" % ws.get_instrument()) # Run forever while (ws.ws.sock.connected): # print("test") logger.info("Ticker: %s" % ws.get_ticker()) data = ws.get_ticker() data = [str(data[k]) for k in data] with open(r'bitmex.csv', 'a') as f: writer = csv.writer(f) writer.writerow(data) f.close() # if ws.api_key: # logger.info("Funds: %s" % ws.funds()) # logger.info("Market Depth: %s" % ws.market_depth()) # logger.info("Recent Trades: %s\n\n" % ws.recent_trades()) sleep(10)
def run_ws(queue, evt_init_1min, testing=config.testing): setup_logger() endpoint = endpoint_real if not testing else endpoint_test ws = BitMEXWebsocket( endpoint=endpoint, symbol="XBTUSD", # api_key='', # api_secret='') ) df_tick_null = pandas.DataFrame(columns=['timestamp', 'price']) df_tick = df_tick_null time_now = datetime.datetime.strptime(ws.get_ticker()[0], UTC_FORMAT) # get the timestamp return with WS time_init = (time_now + timedelta_1min).replace(microsecond=0, second=0) # get the time which add 1min time_cyc = time_init + timedelta_1min # get the time added 2min '''may got some bug in this sleep, could cause sleep less''' sleep((time_init - datetime.datetime.strptime(ws.get_ticker()[0], UTC_FORMAT)).total_seconds()) evt_init_1min.set() while 1: # while ws.ws.sock.connected: # if ws.api_key: # logger.info("Funds: %s" % ws.funds()) price = ws.get_ticker()[1] time_now = datetime.datetime.strptime(ws.get_ticker()[0], UTC_FORMAT) # '>=' will contain the whole point time situation if time_now >= time_cyc: df_1min = df_tick.set_index(['timestamp']) # get all the tick in 1 min by DataFrame form # convert to 1_min ohlc df_1min = df_1min['price'].resample(rule='1Min').ohlc() # # if got 2 row, delete first row # if df_1min.shape[0] == 2: # df_1min = df_1min.iloc[1:] queue.put(df_1min) logging.debug(df_1min) # logging.info('******WS put 1-min kline******') time_cyc = time_cyc + timedelta_1min # rest the time used for judge time_init = time_init + timedelta_1min df_tick = df_tick_null # reset the df_tick for the next LOOP df_temp = pandas.DataFrame([[time_now, price]], columns=['timestamp', 'price']) # to put the time_now's data to df df_tick = df_tick.append(df_temp) # append the last tick to the temporary df elif time_now >= time_init: df_temp = pandas.DataFrame([[time_now, price]], columns=['timestamp', 'price']) df_tick = df_tick.append(df_temp) # append the last tick to the temporary df sleep(0.5)
def update_ticker(): ws_ticker = BitMEXWebsocket(endpoint="https://testnet.bitmex.com/api/v1", symbol="XBTUSD", api_key=None, api_secret=None) while (ws_ticker.ws.sock.connected): ws_ticker.get_instrument() ticker=ws_ticker.get_ticker() db.mkt.update_one({"_id":"ticker"},{"$set":ticker}) logging.info("ticker done") sleep(5)
def run(): logger = setup_logger() config = configparser.ConfigParser() config.read('config.ini') client = bitmex.bitmex(api_key=config['AUTH']['api_key'], api_secret=config['AUTH']['api_secret']) # Instantiating the WS will make it connect. Be sure to add your api_key/api_secret. ws = BitMEXWebsocket(endpoint="https://testnet.bitmex.com/api/v1", symbol="XBTUSD", api_key=config['AUTH']['api_key'], api_secret=config['AUTH']['api_secret']) # logger.info("Instrument data: %s" % ws.get_instrument()) a1 = config['VALUES']['a1'] a2 = config['VALUES']['a2'] aQty = config['VALUES']['aQty'] b1 = config['VALUES']['b1'] b2 = config['VALUES']['b2'] bQty = config['VALUES']['bQty'] # Run forever triggered = False try: (body, response) = client.Order.Order_new( symbol='XBTUSD', orderQty=aQty, price="8999", contingencyType="OneTriggersTheOther", clOrdLinkID="Triggered").result() while(ws.ws.sock.connected): price = ws.get_ticker() print(price['mid']) if not triggered and price['mid'] > float(a1): (body, response) = client.Order.Order_new( symbol='XBTUSD', orderQty=aQty, price=a1, contingencyType="OneTriggersTheOther", clOrdLinkID="Triggered").result() (body, response) = client.Order.Order_new( symbol='XBTUSD', orderQty=aQty, price=a2, side="Sell", clOrdLinkID="Triggered").result() triggered = True elif not triggered and price['mid'] < float(b1): (body, response) = client.Order.Order_new( symbol='XBTUSD', orderQty=bQty, price=b1, side="Sell", contingencyType="OneTriggersTheOther", clOrdLinkID="Triggered").result() (body, response) = client.Order.Order_new( symbol='XBTUSD', orderQty=bQty, price=b2, clOrdLinkID="Triggered").result() triggered = True pp = pprint.PrettyPrinter(indent=4) sleep(1) except KeyboardInterrupt as e: print(client.Order.Order_cancelAll().result())
def run(mexbot): mexbot.logger.debug("Started Ticker thread") # Instantiating the WS will make it connect. Be sure to add your api_key/api_secret. ws = BitMEXWebsocket(endpoint="https://testnet.bitmex.com/api/v1", symbol=mexbot.symbol, api_key=mexbot.config.get("api_key"), api_secret=mexbot.config.get("api_secret")) mexbot.logger.debug("Instrument data: %s" % ws.get_instrument()) # Run forever while (ws.ws.sock.connected): mexbot.update_ticker(ws.get_ticker()) mexbot.logger.error("Websocket disconnected")
def run(mexbot): print("in thread") logger = setup_logger() # Instantiating the WS will make it connect. Be sure to add your api_key/api_secret. ws = BitMEXWebsocket(endpoint="https://testnet.bitmex.com/api/v1", symbol=mexbot.symbol, api_key=None, api_secret=None) logger.info("Instrument data: %s" % ws.get_instrument()) # Run forever while (ws.ws.sock.connected): # logger.info("Ticker: %s" % ws.get_ticker()) mexbot.updateTicker(ws.get_ticker())
def run(): logger = setup_logger() # Instantiating the WS will make it connect. Be sure to add an auth method. You can use login/password # or api_key/api_secret. ws = BitMEXWebsocket(endpoint="https://testnet.bitmex.com/api/v1", symbol="XBT24H", login="******", password="******", api_key=None, api_secret=None) logger.info("Instrument data: %s" % ws.get_instrument()) # Run forever while(ws.ws.sock.connected): logger.info("Ticker: %s" % ws.get_ticker()) logger.info("Funds: %s" % ws.funds()) logger.info("Market Depth: %s" % ws.market_depth()) logger.info("Recent Trades: %s\n\n" % ws.recent_trades()) sleep(10)
def run(): logger = setup_logger() # Instantiating the WS will make it connect. Be sure to add your api_key/api_secret. ws = BitMEXWebsocket(endpoint="https://testnet.bitmex.com/api/v1", symbol="XBTUSD", api_key=None, api_secret=None) logger.info("Instrument data: %s" % ws.get_instrument()) # Run forever while(ws.ws.sock.connected): logger.info("Ticker: %s" % ws.get_ticker()) if ws.config['api_key']: logger.info("Funds: %s" % ws.funds()) logger.info("Market Depth: %s" % ws.market_depth()) logger.info("Recent Trades: %s\n\n" % ws.recent_trades()) sleep(10)
def run(): logger = setup_logger() # Instantiating the WS will make it connect. Be sure to add your api_key/api_secret. ws = BitMEXWebsocket(endpoint="https://testnet.bitmex.com/api/v1", symbol="XBTUSD", api_key=None, api_secret=None) logger.info("Instrument data: %s" % ws.get_instrument()) # Run forever while(ws.ws.sock.connected): logger.info("Ticker: %s" % ws.get_ticker()) if ws.api_key: logger.info("Funds: %s" % ws.funds()) logger.info("Market Depth: %s" % ws.market_depth()) logger.info("Recent Trades: %s\n\n" % ws.recent_trades()) sleep(10)
def run(): logger = setup_logger() config = configparser.ConfigParser() config.read('config/config.ini') ws = BitMEXWebsocket(endpoint=config['bitmex']['endpoint'], symbol="XBTUSD", api_key=config['bitmex']['api_key'], api_secret=config['bitmex']['api_secret']) logger.info("Instrument data: %s" % ws.get_instrument()) # Run forever while(ws.ws.sock.connected): logger.info("Ticker: %s" % ws.get_ticker()) if ws.api_key: logger.info("Funds: %s" % ws.funds()) logger.info("Market Depth: %s" % ws.market_depth()) logger.info("Recent Trades: %s\n\n" % ws.recent_trades()) sleep(10)
def run(): logger = setup_logger() # Instantiating the WS will make it connect. Be sure to add your api_key/api_secret. ws = BitMEXWebsocket( endpoint="wss://testnet.bitmex.com/realtime", symbol="XBTUSD", api_key="wwvS30igJDo6Ksxa0h2EP1Eq", api_secret="-DOHRIUObpSQilqyr2y18YcTRi5NWFIV95du4i8rG4VveOBI") logger.info("Instrument data: {}".format(ws.get_instrument())) # Run forever while (ws.ws.sock.connected): logger.info("Ticker: %s" % ws.get_ticker()) if ws.config['api_key']: logger.info("Funds: %s" % ws.funds()) logger.info("Market Depth: %s" % ws.market_depth()) logger.info("Recent Trades: %s\n\n" % ws.recent_trades()) sleep(10)
def run(): logger = setup_logger() # Instantiating the WS will make it connect. Be sure to add an auth method. You can use login/password # or api_key/api_secret. ws = BitMEXWebsocket(endpoint="https://testnet.bitmex.com/api/v1", symbol="XBT24H", login="******", password="******", api_key=None, api_secret=None) logger.info("Instrument data: %s" % ws.get_instrument()) # Run forever while (ws.ws.sock.connected): logger.info("Ticker: %s" % ws.get_ticker()) logger.info("Funds: %s" % ws.funds()) logger.info("Market Depth: %s" % ws.market_depth()) logger.info("Recent Trades: %s\n\n" % ws.recent_trades()) sleep(10)
class BitMexWS(object): """ 适合订阅数据 """ def __init__(self, api_key=None, api_secret=None, symbol="XBTUSD"): endpoint = "https://testnet.bitmex.com/api/v1" if api_key: endpoint = "https://www.bitmex.com/api/v1" self.ws = BitMEXWebsocket(endpoint=endpoint, symbol=symbol, api_key=api_key, api_secret=api_secret) def run(self): logger = self.setup_logger() # Instantiating the WS will make it connect. Be sure to add your api_key/api_secret. logger.info("Instrument data: %s" % self.ws.get_instrument()) # Run forever while self.ws.ws.sock.connected: logger.info("Ticker: %s" % self.ws.get_ticker()) if self.ws.api_key: logger.info("Funds: %s" % self.ws.funds()) logger.info("Market Depth: %s" % self.ws.market_depth()) logger.info("Recent Trades: %s\n\n" % self.ws.recent_trades()) sleep(10) def setup_logger(self): # Prints logger info to terminal logger = logging.getLogger() logger.setLevel(logging.INFO) # Change this to DEBUG if you want a lot more info ch = logging.StreamHandler() # create formatter formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") # add formatter to ch ch.setFormatter(formatter) logger.addHandler(ch) return logger
class Algorithm(object): def __init__(self, value_pair): global Flag_of_begining Flag_of_begining = False api_key = '6AnZMBW9F-a2Yf1cH28v_l8j' self.value_pair = value_pair self.Flag_of_begining = False secret_key = 'JsFkkeg2AMQziEsWioNmQzGm9LDNS5310NkXAT1FRxZdpu6k' self.ws = BitMEXWebsocket(endpoint="https://testnet.bitmex.com/api/v1", symbol=f'{self.value_pair}', api_key=api_key, api_secret=secret_key) self.ws.get_instrument() self.counter = 0 self.shoulder = 50 self.start_money = 10 pass def currancy_value(self, count=1): start_time = time.time() time.sleep(1.05) price_response = self.ws.get_ticker() #print(self.counter,' ',price_response['last']) self.counter += 1 return (time.time() - start_time), price_response['last'], def currancy_value1(self, value='XBT', count=1): start_time = time.time() time.sleep(2.05) price_response = requests.get( f'https://testnet.bitmex.com/api/v1/trade?symbol={value}&filter=%7B%22side%22%3A%22Sell%22%7D&count={count}&reverse=true' ).json() return (time.time() - start_time), price_response[0]['price'], def first_proizvod(self, mass, time): return (mass[-1] - mass[-2]) / (time[-1] - time[-2]) def second_proizvod(self, mass, time): buf=((mass[-1]-mass[-2])/(time[-1]-time[-2])-(mass[-2]-mass[-3])/(time[-2]-time[-3]))/\ (time[-1]-time[-3]) return buf def dt(self, mas): return mas[-1] - mas[-2] def analysis(self): iteracia = 0 Flag = False f = open(f'calculation_{self.value_pair}.txt', 'w') f.write( 'итерация цена dt первая производная вторая производная \n' ) f1 = open('analysis.txt', 'w') f1.write( 'первая производная вторая производная доход в $ доход в процентах % плечо \n' ) time, price = self.currancy_value() self.price_mas, self.time_mas = [price], [0] while True: if iteracia > 10: self.Flag_of_begining = True print(iteracia + 1) time, price = self.currancy_value() self.price_mas.append(price) self.time_mas.append(time + self.time_mas[-1]) #print(self.price_mas,self.time_mas) if len(self.price_mas) > 1: try: first_proizvod_mas except: first_proizvod_mas = [ self.first_proizvod(self.price_mas, self.time_mas) ] else: first_proizvod_mas.append( self.first_proizvod(self.price_mas, self.time_mas)) if abs(first_proizvod_mas[-1]) > 0: print('первая производная = ', first_proizvod_mas[-1]) #print('dt',self.time_mas[-1]-self.time_mas[-2]) if len(first_proizvod_mas) > 1: try: second_proizvod_mas except: second_proizvod_mas = [ self.second_proizvod(self.price_mas, self.time_mas) ] else: second_proizvod_mas.append( self.second_proizvod(self.price_mas, self.time_mas)) if abs(first_proizvod_mas[-1]) > 0: print('вторая производная = ', second_proizvod_mas[-1]) # begining of analysis' calculatios with 1st and 2nd derivative if len(self.price_mas) > 5: if first_proizvod_mas[-1] > 0 and first_proizvod_mas[ -2] > 0 and first_proizvod_mas[-3] > 0: if second_proizvod_mas[-1] > 0 and second_proizvod_mas[ -2] > 0: print('!!!!!!!!!!!!') winsound.MessageBeep() winsound.MessageBeep() purchase_price = self.price_mas[-1] flag_purchase = True '''if Flag: if first_proizvod_mas[-1]<0: profit_L=(self.price_mas[-1]-purchase_price)/purchase_price f1.write(f'{first_proizvod_mas[-4]} ---- ------- -------- {self.shoulder} \n') f1.write(f'{first_proizvod_mas[-3]} {second_proizvod_mas[-3]} ------- -------- {self.shoulder} \n') f1.write(f'{first_proizvod_mas[-2]} {second_proizvod_mas[-2]} ------- -------- {self.shoulder} \n') f1.write(f'{first_proizvod_mas[-1]} {second_proizvod_mas[-1]} {(1+profit_L)*self.start_money} {profit_L*100} {self.shoulder} \n') f.close() f1.close() winsound.MessageBeep() winsound.MessageBeep() winsound.MessageBeep() exit()''' if iteracia > 2: f.write( f'{iteracia} {self.price_mas[-1]} {self.dt(self.time_mas)} {first_proizvod_mas[-1]} {second_proizvod_mas[-1]} \n' ) if iteracia == 500: f.close() exit() iteracia += 1 if (iteracia % 500) == 0: print('очистка массивов') buf_1 = first_proizvod_mas[-10:] buf_2 = second_proizvod_mas[-10:] buf_p = self.price_mas[-10:] buf_t = self.time_mas[-10:] first_proizvod_mas = buf_1 second_proizvod_mas = buf_2 self.price_mas = buf_p self.time_mas = buf_t
parsedURL = urllib.parse.urlparse(url) path = parsedURL.path if parsedURL.query: path = path + '?' + parsedURL.query # print("Computing HMAC: %s" % verb + path + str(nonce) + data) message = (verb + path + str(nonce) + data).encode('utf-8') print("Signing: %s" % str(message)) signature = hmac.new(apiSecret.encode('utf-8'), message, digestmod=hashlib.sha256).hexdigest() print("Signature: %s" % signature) return signature def test(): expires = int(time.time()) + 5 # See signature generation reference at https://www.bitmex.com/app/apiKeys signature = bitmex_signature(secret_key, VERB, ENDPOINT, expires) print(signature) # Initial connection - BitMEX sends a welcome message. ws = websocket.create_connection(BITMEX_URL + ENDPOINT) #test() ws = BitMEXWebsocket(endpoint="https://testnet.bitmex.com/api/v1", symbol="XBTUSD", api_key=api_key, api_secret=secret_key) ws.get_ticker()
class Market_maker(): def __init__(self, symbol): self.ctr = 0 self.symbol = symbol #self.logger = self.setup_logger() # hoang: wbFfEOkZqut7OG8rueCPTmEsCsYHyqxakxlg1dNoZbz7EJ6w # hoang: ZJ7ZG0bDrem884wQkNnvv2PB api_key = "ZJ7ZG0bDrem884wQkNnvv2PB" #"9FR7reF9F71NDZG_BDoMsfm9" # 8vXVw923QlDRoRtXSwvwbXlU api_secret = "wbFfEOkZqut7OG8rueCPTmEsCsYHyqxakxlg1dNoZbz7EJ6w" #"TiXEEabXxJ_KX5ev_RoOnB-JVQqDdj4AAMJvRBXpPhtAKGVH" # nFZS4qiArohuyY_4J9oGBk49X2iL5LteAXCrHcHveF6j5Gwi # Instantiating the WS will make it connect. Be sure to add your api_key/api_secret. self.ws = BitMEXWebsocket(endpoint="https://www.bitmex.com/api/v1", symbol=self.symbol, api_key=api_key, api_secret=api_secret) self.ws.get_instrument() #self.logger.info("Instrument data: %s" % self.ws.get_instrument()) self.client = bitmex.bitmex(test=False, api_key=api_key, api_secret=api_secret) self.last_r = None self.last_spread = None #self.clean = False self.tick = [] self.cur_volatility = None self.act_volatility = None self.streak = 0 self.prev_len = 0 self.cur_len = 0 self.idle = 0 self.first = True self.sleep_ctr = 0 self.general_ctr = 0 exchange = ccxt.bitmex() date_N_days_ago = ( datetime.datetime.now() - datetime.timedelta(hours=2)).strftime("%Y-%m-%d %H:%M:%S") since = time.mktime( datetime.datetime.strptime(date_N_days_ago, "%Y-%m-%d %H:%M:%S").timetuple()) * 1000 df = exchange.fetch_ohlcv('ETH/USD', timeframe='1m', since=since, limit=500) df = pd.DataFrame(df) df.columns = ["Timestamp", "Open", "High", "Low", "tick", "Volume"] self.df = pd.DataFrame({'tick': df.tick.values.tolist()}) #print (df.tail()) #print (self.df.tail()) # always fetch df using ccxt # check number of pos: if len(pos) > 0 : self.first = False logging.info("App Initiated!") def restart(self): # api_key = "ZJ7ZG0bDrem884wQkNnvv2PB" #"9FR7reF9F71NDZG_BDoMsfm9" # 8vXVw923QlDRoRtXSwvwbXlU # api_secret = "wbFfEOkZqut7OG8rueCPTmEsCsYHyqxakxlg1dNoZbz7EJ6w" #"TiXEEabXxJ_KX5ev_RoOnB-JVQqDdj4AAMJvRBXpPhtAKGVH" # nFZS4qiArohuyY_4J9oGBk49X2iL5LteAXCrHcHveF6j5Gwi # # Instantiating the WS will make it connect. Be sure to add your api_key/api_secret. # self.ws = BitMEXWebsocket(endpoint="https://www.bitmex.com/api/v1", symbol=self.symbol, # api_key=api_key, api_secret=api_secret) # self.ws.get_instrument() # self.client = bitmex.bitmex(test=False, api_key=api_key, api_secret=api_secret) print('Restart finished.') logging.info("Restarting the market maker...") self.clean() os.execv(sys.executable, [sys.executable] + sys.argv) def round_to(self, n, precision): correction = 0.5 if n >= 0 else -0.5 return int(n / precision + correction) * precision def round_to_05(self, n): return self.round_to(n, 0.05) def test(self): print('Restarting') logging.info('Restarting') return self.restart() def run(self): threading.Timer(15.0, self.run).start() sys.stdout.write("---------------------\n") logging.info("---------------------\n") #sys.stdout.flush() # TODO 1: write check_file_change & add settings. #self.check_file_change() #sleep(settings.LOOP_INTERVAL) # This will restart on very short downtime, but if it's longer, # the MM will crash entirely as it is unable to connect to the WS on boot. if not self.check_connection(): print('No connection detected! Restarting...') logging.error( "Realtime data connection unexpectedly closed, restarting.") self.restart() # TODO 2: sanity_check, print_status self.ctr += 1 self.general_ctr += 1 ticker = self.ws.get_ticker() self.test = False print('Mid: ', ticker['mid']) #logging.info('New Ticker: ', ticker['mid']) start_cond = (self.ctr == 1 and len(self.df) > 60) if self.ctr == 4: print('FULL MINUTE') logging.info('FULL MINUTE') self.ctr = 0 #print ("Df length: ", len(self.df)) #print(self.df) self.df = self.df.append(pd.DataFrame({'tick': [ticker['mid']]}), ignore_index=True) if len(self.df) > 60: # self.write = True self.df = self.df.iloc[-80:] self.df['ret'] = (self.df['tick'] - self.df['tick'].shift())**2 self.df['vola'] = self.df['ret'].rolling(60).apply(np.mean) self.cur_volatility = self.df.iloc[-1].vola print("Volatility: ", self.cur_volatility) logging.info('Full minute -- Volatility: {}'.format( self.cur_volatility)) if self.first: print(self.df.tail(5)) print(self.df.iloc[-1], self.df.iloc[-1].tick, self.df.iloc[-2], self.df.iloc[-2].tick) try: pos = self.client.Position.Position_get().result( )[0][-1]['currentQty'] except: pos = 0 try: ord_list = self.client.Order.Order_getOrders( filter=json.dumps({"open": True})).result()[0] #print(ord_list) #print (len(ord_list)) except Exception as e: ord_list = [] logging.info('Error when getting OrderList: {}'.format(e)) if self.test: print('TEST! RESTART TRIGGERING') logging.info('TEST! RESTART TRIGGERING') self.restart() if self.first == True and pos != 0: self.first = False if self.first == True and len(ord_list) != 0: self.first = False if (self.df.iloc[-1].tick == self.df.iloc[-2].tick) and (self.df.iloc[-3].tick == self.df.iloc[-2].tick): print('Repetition! RESTART TRIGGERING') logging.info('Repetition! RESTART TRIGGERING') self.restart() if self.general_ctr == 2880: print('RAN FOR 12 HRS! RESTART TRIGGERING') logging.info('RAN FOR 12 HRS! RESTART TRIGGERING') self.general_ctr = 0 self.restart() self.cur_len = len(ord_list) if (self.cur_len == self.prev_len) and (self.cur_len > 0): # could incur errors self.idle += 1 elif (self.cur_len < self.prev_len): self.streak += 1 self.idle = 0 #wont use idle for now else: self.idle = 0 logging.info( 'Subminute -- Mid price {}; Position Size: {}; OrderList: {}; OrderLength: {}' .format(ticker['mid'], pos, ord_list, len(ord_list))) if self.act_volatility != None: #abrupt change in volatility cond1 = self.cur_volatility > self.act_volatility * 1.25 cond2 = self.cur_volatility < self.act_volatility * .75 else: cond1 = cond2 = False cond3 = (self.cur_volatility != None) and ( self.first ) # no order placed before + enough data to calc volatility cond4 = (ord_list != None) and (ord_list != []) and (len(ord_list) < 2) and ( self.cur_len < self.prev_len ) # 1 order just filled --> left 1 order on the other side #cond5 = (self.idle == 60) # if orders don't get filled for too long cond5 = False cond6 = (ord_list == [] and self.first == False) # no orders after the first trade cond7 = (ord_list != None) and (ord_list != []) and (len(ord_list) < 2) and ( ord_list[0]['side'] == 'Buy') and (pos != 0) and ( pos > 0) # 1 order left + on the same side of the pos cond8 = (ord_list != None) and (ord_list != []) and (len(ord_list) < 2) and ( ord_list[0]['side'] == 'Sell') and (pos != 0) and ( pos < 0) # 1 order left + on the same side of the pos cond9 = (len(ord_list) >= 10) if self.streak == 3: logging.info('Sleep to prevent successive market orders.') cond4 = False self.sleep_ctr += 1 logging.info( 'assess conditions: {}, {}, {}, {}, {}, {}, {}, {}, {}'.format( cond1, cond2, cond3, cond4, cond5, cond6, cond7, cond8, cond9)) if cond1 or cond2 or cond3 or cond4 or cond5 or cond6 or cond7 or cond8 or cond9: if cond3: logging.info('First Trade!') self.first = False if cond4 or cond1 or cond2 or cond7 or cond8 or cond9: logging.info('Revise') self.client.Order.Order_cancelAll().result() if cond5: logging.info('Idle') self.idle = 0 r, spread = self.calc_res_price(ticker["mid"], pos, self.cur_volatility) print('Real mid: ', r) print('Spread: ', spread) buy_qty, sell_qty = self.get_qty(pos) self.post_orders(spread, r, buy_qty, sell_qty, pos) self.act_volatility = self.cur_volatility self.cur_len += bool(buy_qty) + bool(sell_qty) logging.info('Orders post: {}, {}, {}, {}'.format( r, spread, buy_qty, sell_qty)) else: pass self.prev_len = self.cur_len """ if self.write: self.df.to_csv() """ # if self.ws.api_key: # self.logger.info("Funds: %s" % self.ws.funds()) #logger.info("Market Depth: %s" % self.ws.market_depth()) #logger.info("Recent Trades: %s\n\n" % self.ws.recent_trades()) def collect(self): threading.Timer(10.0, self.collect).start() self.ctr += 1 ticker = self.ws.get_ticker()['mid'] self.tick.append(ticker) print('ticker collected: ', ticker) if self.ctr == 360: df = pd.DataFrame({'tick': ticker}) df.to_csv('collected.csv') print('Done!') def clean(self): print("CANCEL ALL ORDERS") logging.info('CANCEL ALL ORDERS') #self.clean = True return self.client.Order.Order_cancelAll().result() def calc_res_price(self, mid, qty, vola): #print (qty) VAR = vola r = mid - (qty * GAMMA * VAR * D) / MAX_POS spread = max(0.1, GAMMA * VAR * D + np.log(1 + GAMMA / K)) return r, spread def post_orders(self, spread, mid, buy_qty, sell_qty, pos): getcontext().prec = 4 if pos > 0: buy = { 'orderQty': buy_qty, 'price': self.round_to_05( float(Decimal(mid) - Decimal(spread) / Decimal(2))), 'side': 'Buy', 'symbol': self.symbol, 'execInst': 'ParticipateDoNotInitiate' } sell = { 'orderQty': sell_qty, 'price': self.round_to_05( float(Decimal(mid) + Decimal(spread) / Decimal(2))), 'side': 'Sell', 'symbol': self.symbol } elif pos < 0: buy = { 'orderQty': buy_qty, 'price': self.round_to_05( float(Decimal(mid) - Decimal(spread) / Decimal(2))), 'side': 'Buy', 'symbol': self.symbol } sell = { 'orderQty': sell_qty, 'price': self.round_to_05( float(Decimal(mid) + Decimal(spread) / Decimal(2))), 'side': 'Sell', 'symbol': self.symbol, 'execInst': 'ParticipateDoNotInitiate' } else: buy = { 'orderQty': buy_qty, 'price': self.round_to_05( float(Decimal(mid) - Decimal(spread) / Decimal(2))), 'side': 'Buy', 'symbol': self.symbol, 'execInst': 'ParticipateDoNotInitiate' } sell = { 'orderQty': sell_qty, 'price': self.round_to_05( float(Decimal(mid) + Decimal(spread) / Decimal(2))), 'side': 'Sell', 'symbol': self.symbol, 'execInst': 'ParticipateDoNotInitiate' } if buy_qty == 0: to_create = [sell] elif sell_qty == 0: to_create = [buy] else: to_create = [buy, sell] print('Buy: {}; Sell: {}'.format(buy['price'], sell['price'])) logging.info('Buy: {}; Sell: {}'.format(buy['price'], sell['price'])) self.client.Order.Order_newBulk(orders=json.dumps(to_create)).result() def get_qty(self, qty): buy_qty = THETA * np.exp(-ETA2 * qty) if qty < 0 else THETA * np.exp( -ETA * qty) sell_qty = THETA * np.exp(ETA2 * qty) if qty > 0 else THETA * np.exp( ETA * qty) return int(round(buy_qty)), int(round(sell_qty)) def setup_logger(self): # Prints logger info to terminal logger = logging.getLogger() logger.setLevel( logging.INFO) # Change this to DEBUG if you want a lot more info ch = logging.StreamHandler() # create formatter formatter = logging.Formatter( "%(asctime)s - %(name)s - %(levelname)s - %(message)s") # add formatter to ch ch.setFormatter(formatter) logger.addHandler(ch) return logger def check_connection(self): """Ensure the WS connections are still open.""" print('STATUS: ', not self.ws.exited) logging.info('STATUS: ', not self.ws.exited) return not self.ws.exited def run_loop(self): while True: sys.stdout.write("-----\n") sys.stdout.flush() # TODO 1: write check_file_change & add settings. #self.check_file_change() #sleep(settings.LOOP_INTERVAL) # This will restart on very short downtime, but if it's longer, # the MM will crash entirely as it is unable to connect to the WS on boot. if not self.check_connection(): print('No connection detected! Restarting...') logging.error( "Realtime data connection unexpectedly closed, restarting." ) self.restart() # TODO 2: sanity_check, print_status self.run()
print("Instrument: %s" % ws.get_instrument()) connection = pymysql.connect( unix_socket='/opt/local/var/run/mysql57/mysqld.sock', host=db_host, user=db_user, password=db_password, db=db, charset='latin1', cursorclass=pymysql.cursors.DictCursor) current_minute = time.gmtime()[4] while current_minute != 0: ticker = ws.get_ticker() print(strftime("%Y-%m-%d %H:%M:%S", gmtime()), ':::', ticker) l = ticker['last'] b = ticker['buy'] s = ticker['sell'] m = ticker['mid'] cnt = 0 with connection.cursor() as cursor: # Create a new record # sql = "INSERT INTO `ticker` (`symbol`, `dt`, `l`, `b`, `s`, `m`) VALUES (%s, now(), %s, %s, %s, %s)" # cursor.execute(sql, (symbol,l,b,s,m)) # connection is not autocommit by default. So you must commit to save your changes. # connection.commit()
class MyRobot: lever = 5 contract_name = 'XBTZ18' new_position_thd = 350 re_position_thd = 30 price_table = { '8': [4, 10, 21, 43], '12': [6, 15, 31, 64], '16': [8, 20, 42, 85], '24': [12, 30, 63, 127], '32': [16, 40, 84, 170] } open_price_list = 'open_price_list' base_price_list = 'base_price_list' base_price = 'base_price' filled_order_set = 'filled_order_set' unit_amount_list = 'unit_amount_list' def __init__(self): self.logger = setup_logger() test = False api_key = os.getenv('API_KEY') api_secret = os.getenv('API_SECRET') test_url = 'https://testnet.bitmex.com/api/v1' product_url = 'https://www.bitmex.com/api/v1' self.logger.info('APIKEY: %s' % api_key) if test: url = test_url else: url = product_url self.cli = bitmex(test=test, api_key=api_key, api_secret=api_secret) self.ws = BitMEXWebsocket(endpoint=url, symbols=["XBTUSD", self.contract_name], api_key=api_key, api_secret=api_secret) # init redis client self.redis_cli = redis.Redis(host='35.230.143.112', password='******', port=6379, decode_responses=True) self.last_sms_time = 0 """ 2018/6/14 更新 每次选取最邻近的订单 2018/7/23 更新 解决当价格变动很大,订单没有按照顺序成交,导致重复订单 """ def get_filled_order(self, last_trans_qty=0, last_trans_side='', last_trans_type=''): recent_order = None for order in self.ws.open_orders(): if order['ordStatus'] == 'Filled' and ( not self.redis_cli.sismember('filled_order_set', order['orderID'])): # 目前仅考虑买单 if last_trans_side == 'Sell' and order['ordType'] == 'Limit': if order[ 'side'] == 'Buy' and last_trans_type == 'Limit' and order[ 'cumQty'] != last_trans_qty: continue elif last_trans_side == 'Buy' and order['ordType'] == 'Limit': if order[ 'side'] == 'Buy' and last_trans_type == 'Limit' and order[ 'cumQty'] != last_trans_qty * 2: continue if not recent_order: recent_order = order else: if order['timestamp'] > recent_order['timestamp']: recent_order = order return recent_order # 2018/7/26 添加 def get_unfilled_order(self): unfilled_orders = [] for o in self.ws.open_orders(): if o['ordStatus'] == 'New' or o['ordStatus'] == 'PartiallyFilled': unfilled_orders.append(o) return unfilled_orders """ 2018/7/23 更新 增加异常多次请求 2018/7/25 修改过滤条件, 增加PartiallyFilled 2018/7/26 重写函数,并命名为get_unfilled_order """ def get_delegated_orders(self): times = 0 result = [] while times < 200: self.logger.info('第%s次获取未成交委托' % (times + 1)) try: orders = self.cli.Order.Order_getOrders(reverse=True).result() except Exception as e: self.logger.error('get orders error: %s' % e) time.sleep(1) else: for o in orders[0]: if o['ordStatus'] == 'New' or o[ 'ordStatus'] == 'PartiallyFilled': result.append(o) break times += 1 return result def get_ticker(self, symbol): # tickers = self.ws.get_ticker() while True: tickers = self.ws.get_ticker() if len(tickers) > 0: for ticker in tickers[::-1]: if ticker['symbol'] == symbol: return ticker time.sleep(0.5) def send_order(self, symbol, side, qty, price, ordtype='Limit'): times = 0 result = 0 for o in self.get_delegated_orders(): if o['side'] == side and o['price'] == price: self.logger.info('委托已存在, orderid: %s' % o['orderID']) return 1 while times < 500: self.logger.info('第%s次发起订单委托' % (times + 1)) if ordtype == 'Limit': try: order = self.cli.Order.Order_new(symbol=symbol, side=side, orderQty=qty, price=price, ordType=ordtype).result() except Exception as e: self.logger.error('订单error: %s,1秒后重试' % e) time.sleep(1) else: self.logger.info('委托成功') result = order[0]['orderID'] break else: try: order = self.cli.Order.Order_new(symbol=symbol, side=side, orderQty=qty, ordType=ordtype).result() except Exception as e: self.logger.error('订单error: %s,1秒后重试' % e) time.sleep(1) else: result = order[0]['orderID'] break times += 1 return result def cancel_order(self, orderid): times = 0 result = False while times < 500: self.logger.info('第%s次发起撤销委托, orderId: %s' % (times + 1, orderid)) try: self.cli.Order.Order_cancel(orderID=orderid).result() except Exception as e: self.logger.error('撤销错误: %s, 1秒后重试' % e) time.sleep(1) else: result = True break times += 1 return result def amend_order(self, orderid, qty): times = 0 while times < 500: self.logger.info('第%s次修改订单信息, orderID: %s' % (times + 1, orderid)) try: self.cli.Order.Order_amend(orderID=orderid, orderQty=qty).result() except Exception as e: logging.error('修改订单错误: %s' % e) time.sleep(1) else: self.logger.info('修改成功') break times += 1 def sms_notify(self, msg): if int(time.time() - self.last_sms_time > 900): self.logger.info('短信通知: %s' % msg) url = 'http://221.228.17.88:8080/sendmsg/send' params = {'phonenum': '18118999630', 'msg': msg} # requests.get(url, params=params) self.last_sms_time = int(time.time()) """ 2018/6/28 修改使支持len>3的情形 """ def get_current_index(self, price): key = 'open_price_list' index = 0 for i in range(10): if i < self.redis_cli.llen(key) and price < float( self.redis_cli.lindex(key, i)): index = i return index def run(self): self.logger.info('start') last_trans_qty = 0 last_trans_side = '' last_trans_type = '' last_unit_amount = 0 while True: filled_order = self.get_filled_order(last_trans_qty, last_trans_side, last_trans_type) if filled_order: cum_qty = filled_order['cumQty'] order_px = filled_order['price'] avg_px = adjust_price(filled_order['avgPx']) side = filled_order['side'] ord_type = filled_order['ordType'] self.logger.info( '--------------------------------------------------------------------------------' ) self.logger.info( 'side: %s, type: %s, cum_qty: %s, order_px: %s, avg_px: %s, orderID: %s' % (side, ord_type, cum_qty, order_px, avg_px, filled_order['orderID'])) index = self.get_current_index(order_px) price_base = 8 if self.redis_cli.llen('open_price_list') > 0: price_base = int( self.redis_cli.lindex('base_price_list', index)) self.logger.info('index: %s, price_base: %s' % (index, price_base)) price_table = self.price_table[str(price_base)] if ord_type == 'Market': if side == 'Buy': self.logger.info('建仓 仓位: %s, 价格: %a' % (cum_qty, avg_px)) self.logger.info('rpush') self.redis_cli.rpush('open_price_list', avg_px) self.redis_cli.rpush('unit_amount_list', cum_qty) if self.redis_cli.get('base_price'): self.redis_cli.rpush( 'base_price_list', self.redis_cli.get('base_price')) else: self.logger.info('base_price未赋值') time.sleep(300) price_base = float(self.redis_cli.get('base_price')) self.logger.info('买入: %s,价格: %s' % (cum_qty, avg_px - price_base)) orderid = self.send_order(self.contract_name, 'Buy', cum_qty, avg_px - price_base) if orderid == 0: self.logger.info('委托失败,程序终止') break else: self.logger.info('平仓 仓位: %s, 价格: %s' % (cum_qty, avg_px)) self.logger.info('市价开启新的仓位 仓位: %s' % last_unit_amount) orderid = self.send_order(self.contract_name, 'Buy', last_unit_amount, 0, 'Market') if orderid == 0: self.logger.info('委托失败,程序终止') break else: if side == 'Buy': if cum_qty % 16 == 0: self.logger.info( '卖出: %s,价格: %s' % (cum_qty * 2, order_px + price_table[3])) orderid = self.send_order( self.contract_name, 'Sell', cum_qty * 2, order_px + price_table[3]) if orderid == 0: self.logger.info('委托失败,程序终止') break elif cum_qty % 2 == 0: if cum_qty % 8 == 0: price_buy = order_px - price_base * 8 price_sell = order_px + price_table[2] elif cum_qty % 4 == 0: price_buy = order_px - price_base * 4 price_sell = order_px + price_table[1] else: price_buy = order_px - price_base * 2 price_sell = order_px + price_table[0] self.logger.info('卖出: %s,价格: %s' % (cum_qty, price_sell)) orderid = self.send_order(self.contract_name, 'Sell', cum_qty, price_sell) if orderid == 0: self.logger.info('委托失败,程序终止') break self.logger.info('买入: %s,价格: %s' % (cum_qty * 2, price_buy)) orderid = self.send_order(self.contract_name, 'Buy', cum_qty * 2, price_buy) if orderid == 0: self.logger.info('委托失败,程序终止') break else: if cum_qty % 32 == 0: self.logger.info('撤销多余Buy委托') open_price = float( self.redis_cli.lindex('open_price_list', index)) unfilled_orders = self.get_delegated_orders() if open_price < order_px: self.logger.info('open price: %s' % open_price) for o in unfilled_orders: if o['side'] == 'Buy' and o[ 'price'] < open_price: self.logger.info( 'cancel order orderID: %s, price: %s' % (o['orderID'], o['price'])) self.cancel_order(o['orderID']) self.logger.info('rpop') self.redis_cli.rpop('open_price_list') self.redis_cli.rpop('base_price_list') self.redis_cli.rpop('unit_amount_list') open_price = float( self.redis_cli.lindex( 'open_price_list', index)) else: self.logger.info('没有多余的Buy委托') self.logger.info('撤销多余Sell委托') self.logger.info('open price: %s' % open_price) for o in unfilled_orders: if o['side'] == 'Sell' and order_px < o[ 'price'] < open_price: self.logger.info( 'cancel order orderID: %s, price: %s' % (o['orderID'], o['price'])) self.cancel_order(o['orderID']) # self.logger.info('rpop') self.redis_cli.rpop('open_price_list') self.redis_cli.rpop('base_price_list') self.redis_cli.rpop('unit_amount_list') self.logger.info('已全部平仓,待重建仓位') elif cum_qty % 2 == 0: if cum_qty % 16 == 0: buy_price = order_px - price_table[3] elif cum_qty % 8 == 0: buy_price = order_px - price_table[2] elif cum_qty % 4 == 0: buy_price = order_px - price_table[1] else: buy_price = order_px - price_table[0] self.logger.info('买入: %s,价格: %s' % (cum_qty, buy_price)) orderid = self.send_order(self.contract_name, 'Buy', cum_qty, buy_price) if orderid == 0: self.logger.info('委托失败,程序终止') break # self.redis_cli.sadd('filled_order_set', filled_order['orderID']) last_trans_side = side last_trans_qty = cum_qty last_trans_type = ord_type if self.redis_cli.llen('open_price_list') > 0: ticker = self.get_ticker(self.contract_name) bid_price = ticker['bidPrice'] last_open_price = float( self.redis_cli.lindex('open_price_list', -1)) unit_amount = int(self.redis_cli.lindex( 'unit_amount_list', -1)) if bid_price - last_open_price < -1 * self.new_position_thd: self.sms_notify( '开启新的仓位 bid_price: %s, last_open_price: %s' % (bid_price, self.redis_cli.lindex( 'open_price_list', -1))) # if bid_price - last_open_price > self.re_position_thd: min_sell_price = 100000 for o in self.get_delegated_orders(): if o['side'] == 'Sell' and o['price'] < min_sell_price: min_sell_price = o['price'] if min_sell_price - bid_price > 100: self.logger.info('rpop') open_price = float( self.redis_cli.rpop('open_price_list')) self.redis_cli.rpop('base_price_list') self.redis_cli.rpop('unit_amount_list') self.logger.info('撤销多余委托') # PartiallyFilled 需要特别处理 unfilled_amount = 0 for o in self.get_delegated_orders(): if o['price'] < open_price and o['side'] == 'Buy': if o['ordStatus'] == 'PartiallyFilled': self.logger.info('已部分成交: %s' % o['cumQty']) unfilled_amount += o['cumQty'] self.logger.info( 'cancel order, orderID: %s, price: %s' % (o['orderID'], o['price'])) self.cancel_order(o['orderID']) # self.sms_notify('重建仓位, bid_price: %s, last_open_price: %s' % ( # bid_price, self.redis_cli.lindex('open_price_list', -1))) orderid = self.send_order( self.contract_name, 'Sell', unit_amount + unfilled_amount, 0, 'Market') if orderid == 0: self.logger.info('委托失败,程序终止') break last_unit_amount = unit_amount time.sleep(0.2)