def get_orderbook(self, currency=None): marketdata = {} orderBook = {"bids": [], "offers": []} if currency is None: tmpData = self.unauthenticated_request( 'public/orderbook/all')['data'] self.timestamp = int(tmpData['timestamp']) for currency in self.get_currencies: marketdata[currency] = tmpData[currency] else: marketdata[currency] = self.unauthenticated_request( 'public/orderbook/%s' % currency)['data'] self.timestamp = int(marketdata[currency]['timestamp']) for currency in marketdata.keys(): # if int(marketdata[currency]['timestamp']) > int(self.timestamp): for bid in marketdata[currency]['bids']: o = Order(currency, int(bid['price']), float(bid['quantity'])) orderBook['bids'].append(o) for ask in marketdata[currency]['asks']: o = Order(currency, int(ask['price']), float(ask['quantity'])) orderBook['offers'].append(o) return orderBook
def createPendingOrdersLIST(pending_orders): orders = [] for i in range(len(pending_orders)): orders.append( Order(pending_orders[i][0], pending_orders[i][1], pending_orders[i][2], pending_orders[i][3], pending_orders[i][4])) return orders
def createActiveOrdersLIST(active_orders): orders = [] for i in range(len(active_orders)): orders.append( Order(active_orders[i][0], active_orders[i][1], active_orders[i][2], active_orders[i][3], active_orders[i][4], active_orders[i][5])) return orders
def get_orderbook(self, currency=None): marketdata = {} orderBook = {"bids": [], "offers": []} if currency is None: for currency in self.get_currencies: marketdata[currency] = self.unauthenticated_request( 'orderbook?currency=%s' % currency) else: marketdata[currency] = self.unauthenticated_request( 'orderbook?currency=%s' % currency) for currency in marketdata.keys(): # if int(marketdata[currency]['timestamp']) > int(self.timestamp): self.timestamp = int(marketdata[currency]['timestamp']) for bid in marketdata[currency]['bid']: o = Order(currency, int(bid['price']), float(bid['qty'])) orderBook['bids'].append(o) for ask in marketdata[currency]['ask']: o = Order(currency, int(ask['price']), float(ask['qty'])) orderBook['offers'].append(o) return orderBook
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]
plot_macd_long.append(macd.ma_long) plot_macd_short.append(macd.ma_short) # We got a new signal that difference from last signal => open an order # if macd.macd and strategy.signal != last_signal and ( # (strategy.signal == 'buy' and macd.macd > 0) or (strategy.signal == 'sell' and macd.macd < 0) # ): if strategy.signal and strategy.signal != last_signal: if pos.status != 'ACTIVE': if not order: if strategy.signal == 'buy': price = candle.close - (candle.close * order_diff / 100) elif strategy.signal == 'sell': price = candle.close + (candle.close * order_diff / 100) else: price = candle.close order = Order(candle.end, order_valid_time, price, strategy.signal) # Check order status if order: if order.status == 'ACTIVE': order.check_status(candle) if order.status == 'FILLED': if order.side == 'buy': logging.info('Open long position @ ' + str(order.price) + " diff: " + str(strategy.up_percent * 100)) pos.open('btcusd', order.price, start_margin / float(order.price)) plot_buy_index.append(datetime.fromtimestamp(float(candle.start / 1000))) plot_buy_value.append(order.price) if order.side == 'sell': logging.info('Open short position @ ' + str(order.price) + " diff: " + str(strategy.down_percent * 100)) pos.open('btcusd', order.price, -start_margin / float(order.price)) plot_sell_index.append(datetime.fromtimestamp(float(candle.start / 1000))) plot_sell_value.append(order.price)
# We got a new signal that difference from last signal => open an order # if macd.macd and strategy.signal != last_signal and ( # (strategy.signal == 'buy' and macd.macd > 0) or (strategy.signal == 'sell' and macd.macd < 0) # ): if strategy.signal and strategy.signal != last_signal: if pos.status != 'ACTIVE': if not order: if strategy.signal == 'buy': price = candle.close - (candle.close * order_diff / 100) elif strategy.signal == 'sell': price = candle.close + (candle.close * order_diff / 100) else: price = candle.close order = Order(candle.end, order_valid_time, price, strategy.signal) candle = OHLCV() if pos.status == 'ACTIVE': positions.append(pos) # print(pos.base, pos.amount, pos.pl, pos.pl_pct) profit = 0 wins = 0 loses = 0 for position in positions: # print(position.pl) profit += position.pl if position.pl > 0: wins += 1 else: loses += 1
def calculate_order_simple(self, bidder, bids, asker, asks): """ in my original algorithm design, we traverse the depth to fill the minimum volume desired. this is too complicated and hairy. instead, i will only proceed if the top order volume naturally exceeds the best price. cases where the second best is ``hidden'' under a small order will be ignored for now. """ """ first check - do the best orders have sufficient volume to satisfy xchg minimums? """ bidder_min_base_vol = bidder.xchg.get_min_vol((base,alt), None) asker_min_base_vol = asker.xchg.get_min_vol((base,alt), None) min_base_vol = min(bidder_min_base_vol, asker_min_base_vol) # remember, we have to trade approx same amount if (bids[0].v < min_base_vol): print('%s insufficient best order volume to satisfy min trade: %f' % (bidder.xchg.name, bids[0].v)) return None if (asks[0].v < min_base_vol): print('%s insufficient best order volume to satisfy min trade: %f' % (asker.xchg.name, asks[0].v)) return None """ next thing to check - see if we have enough funds to make the trade """ bidder_base_balance = self.balances[bidder.xchg.name]['base'] # check how much base we can afford to sell to bidder asker_alt_balance = self.balances[asker.xchg.name]['alt'] asker_base_afford = asker_alt_balance / self.prices[asker.xchg.name]['ask'] # check how much base we can afford to buy from asker poor = False if (bidder_base_balance < min_base_vol): print(bidder.xchg.name) print('Can\'t afford min vol trade - insufficient bidder balance!') print('\t %s +%f %s' % (bidder.xchg.name, bidder_min_base_vol - bidder_base_balance, base)) poor = True if (asker_base_afford < min_base_vol): print('Can\'t afford min vol trade - insufficient asker balance!') print('\t %s +%f %s' % (asker.xchg.name, (asker_min_base_vol-asker_base_afford)*self.prices[asker.xchg.name]['ask'], alt)) poor = True if poor: return None """ size the volume of base traded """ asker_tx = 1.0 - asker.xchg.trading_fee bidder_tx = 1.0 - bidder.xchg.trading_fee # TODO - weird shit going on here, fix this!! # the line below computes how much base we could trade if we had unlimited balance # but are limited by the order volumes of base between the exchanges. # we receive a maximum of asks[0].v * asker_tx units of base from the asker # and we can sell a maximum of bids[0].v to the bidder max_base_xchg = min(bids[0].v, asks[0].v * asker_tx) # computes how much base we could trade if we had unlimited volume, limited balance max_base_balance = min(bidder_base_balance, asker_base_afford) # how much we will end up buying and selling base_vol = min(max_base_xchg, max_base_balance) bidder_order = Order(bids[0].p, base_vol) asker_order = Order(asks[0].p, base_vol / asker_tx) # profit in units alt (BTC) net_base = asker_order.v * asker_tx - bidder_order.v net_alt = bidder_order.p * bidder_order.v * bidder_tx - asker_order.p * asker_order.v # this is the final checkpoint - if the trade's profits are too small compared to the amount of BTC # we have to move, then the trade is probably too risky to make. if net_alt/(asker_order.p * asker_order.v) < config.BTC_RISK: print('Order volume too large to justify risk of performing the trade') return None else: return { "bidder_order":bidder_order, "asker_order":asker_order, "profit":net_alt }