def get_best_type2_roundtrip(self): """ [Buy(C_B)Buy(A_C)] Sell(A_B) """ A, B = self.pair # use A_B notation instead of base, alt b = self.broker alt = B tx = 1 - b.xchg.trading_fee bids_ab = b.get_orders((A, B), "bids") # people who are selling A_B for C, spread in self.type2_spreads.items(): if spread > config.PROFIT_THRESH[B]: self.type2_roundtrips[C] = {} asks_cb = b.get_orders((C, B), "asks") # people who are buying C_B asks_ac = b.get_orders((A, C), "asks") # people who are buying A_C # minimum volume constraints min_cb = b.xchg.get_min_vol((A, C), asks_cb) # how much DOGE we have to sell in the first trade min_ac = b.xchg.get_min_vol((C, B), asks_ac) # how much LTC we have to sell in the second trade min_ab = b.xchg.get_min_vol((A, B), bids_ab) # how much DOGE we have to buy in the third trade asks_cb_clipped = b.xchg.get_clipped_base_volume(asks_cb, min_cb) # buy exactly minimum quantity asks_ac_clipped = b.xchg.get_clipped_alt_volume( asks_ac, min_cb * tx ) # can probably spend less than 0.01 LTC buying 0.01 DOGE v3 = utils.total_base_volume(asks_ac_clipped) * tx # total DOGE we receive bids_ab_clipped = b.xchg.get_clipped_base_volume(bids_ab, v3) # sell all the DOGE for BTC # construct the orders that we submit o1 = Order( utils.highest_price(asks_cb_clipped), utils.total_base_volume(asks_cb_clipped), type="buy", pair=(C, B), ) o2 = Order( utils.highest_price(asks_ac_clipped), utils.total_base_volume(asks_ac_clipped), type="buy", pair=(A, C), ) o3 = Order( utils.lowest_price(bids_ab_clipped), utils.total_base_volume(bids_ab_clipped), type="sell", pair=(A, B), ) self.type2_roundtrips[C]["orders"] = [o1, o2, o3] # these calculations should adequately take volume into account netA = o2.v * tx - o3.v netB = -utils.total_alt_volume(asks_cb_clipped) + utils.total_alt_volume(bids_ab_clipped) * tx netC = o1.v * tx - utils.total_alt_volume(asks_ac_clipped) self.type2_roundtrips[C]["profit"] = netB print("check ... ") # loop through C and choose the one with the largest profit return self._get_highest_profit(self.type2_roundtrips)
def get_best_type1_roundtrip(self): """ sell(AC), sell(CB) buy(AB) """ A, B = self.pair # use A_B notation instead of base, alt b = self.broker alt = B tx = 1 - b.xchg.trading_fee asks_ab = b.get_orders((A, B), "asks") # people who are selling A_B for C, spread in self.type1_spreads.items(): if spread > config.PROFIT_THRESH[alt]: self.type1_roundtrips[C] = {} bids_ac = b.get_orders((A, C), "bids") # people who are buying A_C bids_cb = b.get_orders((C, B), "bids") # people who are buying C_B # minimum volume constraints min_ac = b.xchg.get_min_vol((A, C), bids_ac) # how much DOGE we have to sell in the first trade min_cb = b.xchg.get_min_vol((C, B), bids_cb) # how much LTC we have to sell in the second trade min_ab = b.xchg.get_min_vol((A, B), asks_ab) # how much DOGE we have to buy in the third trade # assuming value A << value C, first trade has to acquire enough LTC to perform the second trade bids_ac_clipped = b.xchg.get_clipped_alt_volume(bids_ac, min_ac / tx) # how much DOGE we sold to acquire 0.01 LTC v1 = utils.total_base_volume(bids_ac) # performing the second trade will net enough BTC to buy back at least 0.01 DOGE bids_cb_clipped = b.xchg.get_clipped_base_volume(bids_cb, min_ac) # buy back exactly how much DOGE we spent in the first place asks_ab_clipped = b.xchg.get_clipped_base_volume(asks_ab, v1 / tx) # construct the orders o1 = Order( utils.lowest_price(bids_ac_clipped), utils.total_base_volume(bids_ac_clipped), type="sell", pair=(A, C), ) o2 = Order( utils.lowest_price(bids_cb_clipped), utils.total_base_volume(bids_cb_clipped), type="sell", pair=(C, B), ) o3 = Order( utils.highest_price(asks_ab_clipped), utils.total_base_volume(asks_ab_clipped), type="buy", pair=(A, B), ) # test orders for profitability self.type1_roundtrips[C]["orders"] = [o1, o2, o3] netA = -o1.v + o3.v * tx netB = utils.total_alt_volume(bids_cb_clipped) * tx - utils.total_alt_volume(asks_ab_clipped) netC = utils.total_alt_volume(bids_ac_clipped) * tx - o2.v self.type1_roundtrips[C]["profit"] = netB print("check...") return self._get_highest_profit(self.type1_roundtrips)
def get_clipped_base_volume(self, orders, desired_base_vol): # it is already assumed that the orders are base_alt # reduces given array of orders to match specific base vol # borrowed from the original profit calculator i = 1 while utils.total_base_volume(orders[:i]) < desired_base_vol: i += 1 if i > len(orders): # not enough orders in the orderbook! print('Not enough orders in orderbook to satisfy required base volume!') break # cor base_remainder = utils.total_base_volume(orders[:i]) - desired_base_vol # convert back to units base and subtract from last order orders[i-1].v -= base_remainder return orders[:i]
def clip_orders(self, orders, desired_volume): # given an array of bid or ask orders, # and a desired volume, resize the orders so that # the total volume == desired_volume #total_volume = lambda arr : sum([a.v for a in arr]) # volume = total_volume(orders) # original volume, in units base i = 1 while total_base_volume(orders[:i]) < desired_volume: i += 1 if i > len(orders): # not enough orders in the orderbook! break # more than likely, adding on the last order tacked on a bit of overshoot. # the remainder MUST be spanned by last order (i.e. cannot be in the second # to last otherwise we would have caught it) if desired_volume is None: wtf = 1 remainder = total_base_volume(orders[:i]) - desired_volume last_order = orders[i-1] orders[i-1] = Order(last_order.p, last_order.v - remainder) return orders[:i]
def clip_orders(self, orders, desired_volume): # given an array of bid or ask orders, # and a desired volume, resize the orders so that # the total volume == desired_volume #total_volume = lambda arr : sum([a.v for a in arr]) # volume = total_volume(orders) # original volume, in units base i = 1 while total_base_volume(orders[:i]) < desired_volume: i += 1 if i > len(orders): # not enough orders in the orderbook! break # more than likely, adding on the last order tacked on a bit of overshoot. # the remainder MUST be spanned by last order (i.e. cannot be in the second # to last otherwise we would have caught it) if desired_volume is None: wtf = 1 remainder = total_base_volume(orders[:i]) - desired_volume last_order = orders[i - 1] orders[i - 1] = Order(last_order.p, last_order.v - remainder) return orders[:i]
def get_best_type2_roundtrip(self): """ [Buy(C_B)Buy(A_C)] Sell(A_B) """ A, B = self.pair # use A_B notation instead of base, alt b = self.broker alt = B tx = 1 - b.xchg.trading_fee bids_ab = b.get_orders((A, B), 'bids') # people who are selling A_B for C, spread in self.type2_spreads.items(): if spread > config.PROFIT_THRESH[B]: self.type2_roundtrips[C] = {} asks_cb = b.get_orders((C, B), 'asks') # people who are buying C_B # people who are buying A_C #asks_ac = b.get_orders((A,C), 'asks') asks_ac = b.get_orders((C, A), 'asks') # minimum volume constraints # how much DOGE we have to sell in the first trade #min_cb = b.xchg.get_min_vol((A,C), asks_cb) min_cb = b.xchg.get_min_vol((C, A), asks_cb) # how much LTC we have to sell in the second trade min_ac = b.xchg.get_min_vol((C, B), asks_ac) min_ab = b.xchg.get_min_vol( (A, B), bids_ab) # how much DOGE we have to buy in the third trade asks_cb_clipped = b.xchg.get_clipped_base_volume( asks_cb, min_cb) # buy exactly minimum quantity asks_ac_clipped = b.xchg.get_clipped_alt_volume( asks_ac, min_cb * tx ) # can probably spend less than 0.01 LTC buying 0.01 DOGE #print ('type of asks_cb_clipped: %s ' % str(type(asks_cb_clipped))) #print ('type of asks_ac_clipped: %s ' % str(type(asks_ac_clipped))) # total DOGE we receive v3 = utils.total_base_volume(asks_ac_clipped) * tx bids_ab_clipped = b.xchg.get_clipped_base_volume( bids_ab, v3) # sell all the DOGE for BTC #print ('type of bids_ab_clipped: %s ' % str(type(bids_ab_clipped))) # construct the orders that we submit o1 = Order(utils.highest_price(asks_cb_clipped), utils.total_base_volume(asks_cb_clipped), order_type="buy", pair=(C, B)) o2 = Order(utils.highest_price(asks_ac_clipped), utils.total_base_volume(asks_ac_clipped), order_type="buy", pair=(A, C)) o3 = Order(utils.lowest_price(bids_ab_clipped), utils.total_base_volume(bids_ab_clipped), order_type="sell", pair=(A, B)) self.type2_roundtrips[C]["orders"] = [o1, o2, o3] # these calculations should adequately take volume into account netA = o2.v * tx - o3.v netB = -utils.total_alt_volume( asks_cb_clipped) + utils.total_alt_volume( bids_ab_clipped) * tx netC = o1.v * tx - utils.total_alt_volume(asks_ac_clipped) self.type2_roundtrips[C]["profit"] = netB #print('check ... ') # loop through C and choose the one with the largest profit return self._get_highest_profit(self.type2_roundtrips)
def get_best_type1_roundtrip(self): """ sell(AC), sell(CB) buy(AB) """ A, B = self.pair # use A_B notation instead of base, alt b = self.broker alt = B tx = 1 - b.xchg.trading_fee asks_ab = b.get_orders((A, B), 'asks') # people who are selling A_B for C, spread in self.type1_spreads.items(): if spread > config.PROFIT_THRESH[alt]: self.type1_roundtrips[C] = {} bids_ac = b.get_orders((A, C), 'bids') # people who are buying A_C bids_cb = b.get_orders((C, B), 'bids') # people who are buying C_B # minimum volume constraints min_ac = b.xchg.get_min_vol( (A, C), bids_ac ) # how much DOGE we have to sell in the first trade min_cb = b.xchg.get_min_vol( (C, B), bids_cb ) # how much LTC we have to sell in the second trade min_ab = b.xchg.get_min_vol( (A, B), asks_ab) # how much DOGE we have to buy in the third trade # assuming value A << value C, first trade has to acquire enough LTC to perform the second trade bids_ac_clipped = b.xchg.get_clipped_alt_volume( bids_ac, min_ac / tx) # how much DOGE we sold to acquire 0.01 LTC v1 = utils.total_base_volume(bids_ac) # performing the second trade will net enough BTC to buy back at least 0.01 DOGE bids_cb_clipped = b.xchg.get_clipped_base_volume( bids_cb, min_ac) # buy back exactly how much DOGE we spent in the first place asks_ab_clipped = b.xchg.get_clipped_base_volume( asks_ab, v1 / tx) # construct the orders o1 = Order(utils.lowest_price(bids_ac_clipped), utils.total_base_volume(bids_ac_clipped), order_type="sell", pair=(A, C)) o2 = Order(utils.lowest_price(bids_cb_clipped), utils.total_base_volume(bids_cb_clipped), order_type="sell", pair=(C, B)) o3 = Order(utils.highest_price(asks_ab_clipped), utils.total_base_volume(asks_ab_clipped), order_type="buy", pair=(A, B)) # test orders for profitability self.type1_roundtrips[C]["orders"] = [o1, o2, o3] netA = -o1.v + o3.v * tx netB = utils.total_alt_volume( bids_cb_clipped) * tx - utils.total_alt_volume( asks_ab_clipped) netC = utils.total_alt_volume(bids_ac_clipped) * tx - o2.v self.type1_roundtrips[C]["profit"] = netB #print('check...') return self._get_highest_profit(self.type1_roundtrips)