def testIsTimeBetweenParamsEmpty(self): c = self.setup() c.from_time = "" c.to_time = "" c.on_days_of_week = "" rv = Utils.is_time_between(c, datetime.time(5, 0)) self.assertTrue(rv)
async def deliver(ws, coin: str): repo_market = coin + '-USD-REPO-LIN' swap_market = coin + '-USD-SWAP-LIN' min_size = 10**-TD.size_inc[repo_market] total_balance = TD.total[coin] delivery_imbalance = TD.net_imbal[swap_market] ask = TD.asks[repo_market]['6'] # [placed, size, price, orderId] placed, o_id = ask[0], ask[3] if (utils.is_time_between(TD.noon_deliv_start, TD.noon_deliv_end) or utils.is_time_between(TD.am_deliv_start, TD.am_deliv_end) or utils.is_time_between(TD.pm_deliv_start, TD.pm_deliv_end)): # Deliver outstanding positions prior to the 30 minute auction cut-off. if total_balance != 0: if placed: await cfws.cancel_order(TD, ws, o_id, repo_market) TD.net_imbal[ swap_market] -= total_balance # Subtract because shorts are being delivered. delivery = { 'instrumentId': swap_market, 'qtyDeliver': str(abs(total_balance)) } TD.logger.info(f'{delivery}') resp = rest.deliver(delivery) await asyncio.sleep(5) if 'data' in resp: if resp['data']: TD.total[coin] = 0 TD.delivery_timer[repo_market] = time.time() # Deliver early if there is an opposite delivery outstanding. elif (delivery_imbalance >= min_size and total_balance >= min_size and time.time() > TD.delivery_timer[repo_market] + 8 * 60 + 1): size = delivery_imbalance if abs( delivery_imbalance) < total_balance else total_balance if placed: await cfws.cancel_order(TD, ws, o_id, repo_market) delivery = {'instrumentId': swap_market, 'qtyDeliver': str(abs(size))} TD.logger.info(f'{delivery}') resp = rest.deliver(delivery) await asyncio.sleep(5) if 'data' in resp: if resp['data']: TD.delivery_timer[repo_market] = time.time() return
def should_we_sleep(): best_schedule=[] first_run = [x for x in db_dates.all() if x == Dates.first_run][0]['first_run'] # log.info("first run: {}".format(first_run)) log.info('choosing schedule') sorted_schedules = sorted(BOT_SCHEDULES, key=lambda k: k['days']) for day in sorted_schedules: day_epoch = first_run + (int(day['days']) * DAY) current_epoch = int(time.time()) if current_epoch > day_epoch: log.info("using schedule: {}".format(day)) best_schedule=day['schedule'] break CHECKS = [] for schedule in best_schedule: if is_time_between(schedule[0], schedule[1]): if SHOW_SLEEP_LOGGING: log.info("sleep?: {} awake: {}, sleep: {}, current: {}".format(False, schedule[0], schedule[1], datetime.datetime.utcnow().time())) CHECKS.append(True) else: if SHOW_SLEEP_LOGGING: log.info("sleep?: {} awake: {}, sleep: {}, current: {}".format(True, schedule[0], schedule[1], datetime.datetime.utcnow().time())) CHECKS.append(False) # check if any of the time between checks returned true. # if there's a True in the list, it means we're between one of the scheduled times # and so this function returns False so the bot doesn't sleep log.info("check list: {}".format(CHECKS)) if True in CHECKS: log.info("no need to sleep") return False else: log.info("it's sleepy time") return True
def can_send_alert(self): dt = Utils.get_date_time() if self.use_alerts: return Utils.is_day_of_week( self, dt.weekday()) and Utils.is_time_between(self, dt.time()) return False
def testIsTimeBetween0000_2359Valid(self): c = self.setup() c.from_time = '00:01' c.to_time = '23:59' rv = Utils.is_time_between(c, datetime.time(3, 1)) self.assertTrue(rv)
def testIsTimeBetweenInvalid(self): c = self.setup() c.from_time = '00:01' c.to_time = '02:00' rv = Utils.is_time_between(c, datetime.time(2, 2)) self.assertFalse(rv)
async def distribute_bids(ws): for repo_market in TD.repo_market: if TD.available['USD'] > 0: coin = utils.market_to_coin(repo_market) if coin not in TD.coin_allocation: continue spot_market = coin + '-USD' filled = TD.total[coin] size_inc = TD.size_inc[repo_market] min_size = 10**-size_inc coin_alloc = TD.coin_allocation[coin] # Determine which distribution the coin is in. if coin in TD.coin_definition['large']: distribution = TD.large_cap_distribution elif coin in TD.coin_definition['medium']: distribution = TD.medium_cap_distribution else: distribution = TD.small_cap_distribution # Place or edit orders according to the distribution. for order in distribution: bid = TD.bids[repo_market][ order] # [placed, size, price, orderId] placed, o_size, o_price, o_id = bid[0], bid[1], bid[2], bid[3] price = distribution[order][0] bid_fraction = distribution[order][1] # Cancel bids if a buy auction is coming up if (utils.is_time_between(TD.noon_deliv_end, TD.noon_bid_end) or utils.is_time_between(TD.am_deliv_end, TD.am_bid_end) or utils.is_time_between(TD.pm_deliv_end, TD.pm_bid_end) ) and TD.net_imbal[coin + '-USD-SWAP-LIN'] >= min_size: if placed: await cfws.cancel_order(TD, ws, o_id, repo_market) continue # expected_size = Original bid size expected_size = (TD.total['USD'] * bid_fraction * coin_alloc * TD.safety_buffer) expected_size /= TD.mark_prices[spot_market] if filled > 0: size = math.floor( (expected_size - filled) * 10**size_inc) / 10**size_inc filled -= expected_size else: size = math.floor( expected_size * 10**size_inc) / 10**size_inc if not placed and size >= min_size: await cfws.place_order(TD, ws, order, repo_market, 'BUY', 'LIMIT', size, 'GTC', price) await asyncio.sleep(0.075) elif (size * 1.001 < o_size or size * 0.999 > o_size or price != o_price) and size >= min_size: await cfws.cancel_order(TD, ws, o_id, repo_market) await cfws.place_order(TD, ws, order, repo_market, 'BUY', 'LIMIT', size, 'GTC', price) # await cfws.ModifyOrder(TD, ws, count, o_id, market, 'BUY', size, price) await asyncio.sleep(0.075) elif size < min_size and placed: await cfws.cancel_order(TD, ws, o_id, repo_market) elif TD.available['USD'] < 0: for count in range(1, 3): count = str(count) o_id = TD.bids[repo_market][count][3] if int(count) >= 3: break await cfws.cancel_order(TD, ws, o_id, repo_market) return
async def trade(): while True: while not TD.repo_market: await asyncio.sleep(3) # Initialise parameters using rest. await trade_prep() # Connect to CoinFLEX's WebSocket. async with websockets.connect(Conn.WS_URL) as ws: # Authenticate the WebSocket connection. await ws.send( json.dumps(await cfws.auth(Conn.API_KEY, Conn.API_SECRET))) # Subscribe to the order book, order, position, and balance channels. await ws.send(json.dumps(TD.subscription)) # Confirm all of the markets are subscribed to. await subscribe(ws) # This is where the trading logic starts. while TD.WS_FLAG and ws.open: try: # Await a message from CoinFLEX's WebSocket. response = await ws.recv() msg = json.loads(response) # Output the message from CoinFLEX's WebSocket. # TD.logger.info(str(msg)) if 'table' in msg: if msg['table'] == 'order': skip = await cfws.parse_message(TD, msg) if skip: continue if msg['table'] == 'balance': # TD.logger.info(str(msg)) data = msg['data'] TD.logger.info(str(msg)) for asset in data: TD.total[asset['instrumentId']] = float( asset['total']) TD.available[ asset['instrumentId']] = math.floor( float(asset['available']) * 1000) / 1000 # Start trading # Get the total amount of USD originally input into the system. for asset in TD.total: spot_market = asset + '-USD' if asset != 'USD' and spot_market in TD.mark_prices: TD.total['USD'] += TD.total[ asset] * TD.mark_prices[spot_market] # Check for opportunities to match deliveries and deliver before each auction await deliver(ws, asset) # Distribute bids and asks at the pre-defined levels from TradeData. for asset in TD.total: if asset == 'USD': await distribute_bids(ws) else: await distribute_asks(ws, asset) if (utils.is_time_between( TD.noon_bid_start, TD.noon_bid_end) or utils.is_time_between( TD.am_bid_start, TD.am_bid_end) or utils.is_time_between( TD.pm_bid_start, TD.pm_bid_end)): # Wait for the auction, yield calculations, and interest payments to be processed. await asyncio.sleep(120) # Reset allocations after the auction. TD.coin_allocation = TD.reset_coin_alloc() TD.bids = { str(i): TD.reset_bids() for i in TD.bids } TD.asks = { str(i): TD.reset_asks() for i in TD.asks } await trade_prep() continue except Exception: TD.logger.exception('trade caught this error') TD.WS_FLAG = False await ws.close()