def test_updatePosition(self): BookKeeper.instance().addExchange(Exchange.BINANCE) BookKeeper.instance().addCurrencyToExchange( exch=Exchange.BINANCE, curr=Currency.BTC, value_pair=(1,1) ) BookKeeper.instance().addCurrencyToExchange( exch=Exchange.BINANCE, curr=Currency.ETH, value_pair=(0,0) ) mockPosition = { Currency.BTC: (50, 20), Currency.ETH: (100, 100), } BookKeeper.instance().updatePosition( exch=Exchange.BINANCE, position=mockPosition ) self.assertEqual(BookKeeper.instance().getPositions(), { Exchange.BINANCE: { Currency.BTC: (50, 20), Currency.ETH: (100, 100), } })
def _fetchBinanceBalance(self): """ Makes an API POST request to the Binance API instance asking for our account balances Example response: { "makerCommission": 15, "takerCommission": 15, "buyerCommission": 0, "sellerCommission": 0, "canTrade": true, "canWithdraw": true, "canDeposit": true, "updateTime": 123456789, "balances": [ { "asset": "BTC", "free": "4723846.89208129", <= USD? "locked": "0.00000000" }, { "asset": "LTC", "free": "4763368.68006011", <= USD? "locked": "0.00000000" } ] } """ if not self._binance: raise AttributeError('Binance API instance has not been instanciated') resp = self._binance.privateGetAccount() if not 'balances' in resp: raise ApiError('binance api did not return a correct response') else: balances = resp['balances'] position = {} supported_currencies_string = self.supportedCurrenciesString() for entry in balances: if entry['asset'] in supported_currencies_string: currency = Currency[entry['asset']] amount = float(entry['free']) usd_amount = VirtualMarket.instance().convertCurrency( exch=Exchange.BINANCE, amt=amount, start=currency, end=Currency.USDT ) position[currency] = ValuePair(amount, usd_amount) BookKeeper.instance().updateBalance( exch=Exchange.BINANCE, balance=position ) return position
def makeUnsafeTrade(self, order: Order, updateBookKeeper: bool = True): """ Given an Order object, will post a trade to the market. WARNING: Ignores all safety standards and does not check BookKeeper for our current assets """ resp = None if order.exchange is Exchange.KRAKEN: resp = self._makeTradeKraken(order) BookKeeper.instance().reportOrder(order=order) return resp if order.exchange is Exchange.BINANCE: resp = self._makeTradeBinance(order) BookKeeper.instance().reportOrder(order=order) return resp else: raise NotImplementedError('make trade is not implemented for {}'.format(order.exchange))
def createSafeTrades(self, orders: List[Order], updateBookKeeper: bool = True): """ Given a list of trades, will convert them to safe trades -> AKA trades that: - Below our maximum - Make sure we have enough assets to complete the trade """ safe_orders = [] max_vol = min([VirtualMarket.instance().convertCurrency( exch=order.exchange, amt=order.volume, start=order.pair[0], end=Currency.USDT ) for order in orders]) max_vol = min(max_vol, float(SafetyValues.MaximumOrderValueUSD.value)) for order in orders: required_currency = None if order.buyOrSell == BS.BUY: required_currency = order.pair[1] elif order.buyOrSell == BS.SELL: required_currency = order.pair[0] available_assets = BookKeeper.instance().getValuePairOfCurrencyInExchange( exch=order.exchange, curr=required_currency, ) max_vol = min(max_vol, available_assets.amt_usd * 0.8) if max_vol < SafetyValues.MinimumOrderValueUSD.value: print("Max Vol: {}".format(max_vol)) return None max_vol = VirtualMarket.instance().convertCurrency( exch=order.exchange, amt=max_vol, start=Currency.USDT, end=order.pair[0] ) max_vol = float(self._binance.amount_to_precision("{0}/{1}".format(order.pair[0].value, order.pair[1].value), max_vol)) for order in orders: safe_orders.append( Order( exchange=order.exchange, buyOrSell=order.buyOrSell, orderType=order.orderType, pair=order.pair, price=(order.price*0.999), volume=max_vol, ) ) return safe_orders
def test_addExchange(self): BookKeeper.instance().addExchange(Exchange.KRAKEN) try: BookKeeper.instance().addExchange(Exchange.KRAKEN) except: self.assertTrue(True) self.assertEqual(BookKeeper.instance().getPositions(), { Exchange.KRAKEN: {} } ) BookKeeper.instance().clear()
def _fetchKrakenBalance(self): """ Makes an API POST request to the Kraken API instance asking for our account balances Example Response: { 'error': [], 'result': { 'XETH': '0.0998591200', } } """ if not self._kraken: raise AttributeError('Kraken API instance has not been instanciated') resp = self._kraken.privatePostBalance() if resp['error']: raise ApiError('kraken api did not return a correct response') else: balances = resp['result'] position = {} supported_currencies_string = list(map(lambda x: nTOk[x.value], self._supportedCurrencies)) for (curr, amt) in balances.items(): if curr in supported_currencies_string: currency = Currency[kTOn[curr]] amount = float(amt) usd_amount = VirtualMarket.instance().convertCurrency( exch=Exchange.KRAKEN, amt=amount, start=currency, end=Currency.USDT ) position[currency] = ValuePair(amount, usd_amount) BookKeeper.instance().updateBalance( exch=Exchange.KRAKEN, balance=position ) return position
def test_addCurrencyToExchange(self): BookKeeper.instance().addExchange(Exchange.KRAKEN) BookKeeper.instance().addCurrencyToExchange( exch=Exchange.KRAKEN, curr=Currency.BCH, value_pair=(1,1) ) try: BookKeeper.instance().addCurrencyToExchange( exch=Exchange.BINANCE, curr=Currency.BTC, value_pair=(0,0) ) except: self.assertTrue(True) self.assertEqual(BookKeeper.instance().getPositions(), { Exchange.KRAKEN: { Currency.BCH: (1, 1) } }) BookKeeper.instance().clear()
def run(): exchanges, pairs = initializeEverything() searchForOpportunities = True while searchForOpportunities: try: marketData = {} for exchange in exchanges: marketData[exchange] = MarketEngine.instance().fetchTickers( exch=exchange, pairs=pairs) VirtualMarket.instance().updateMarket(marketData=marketData) ArbitrageEngine.instance().updateGraph() ArbitrageEngine.instance()._graph.print() arbitrage_path = ArbitrageEngine.instance().findArbitrage( graph=ArbitrageEngine.instance()._graph, src=Currency.USDT, ) if arbitrage_path: percentGrowth = ArbitrageEngine.instance().verifyArbitrage(path=arbitrage_path) if percentGrowth >= SafetyValues.MinimumOpportunity.value: orders = ArbitrageEngine.instance().pathToOrders( path=arbitrage_path, graph=ArbitrageEngine.instance()._graph) pprint(orders) safe_orders = MarketEngine.instance().createSafeTrades(orders) if safe_orders: print('\n{0}Safe Orders:{1}'.format('\033[92m', '\033[0m')) pprint(safe_orders) print('\n\n') for order in safe_orders: pprint(MarketEngine.instance().makeUnsafeTrade(order=order)) print("Executed Order: {}".format(order.toStringShort())) pprint(BookKeeper.instance()._balances) else: print("{0}No arbitrage opportunity found!{1}\n".format('\033[91m','\033[0m')) sleep(5) except Exception as e: pprint(e) break
def initializeEverything(): currencies = [ Currency.BTC, Currency.ETH, Currency.LTC, Currency.XRP, ] exchanges = [ Exchange.BINANCE, Exchange.KRAKEN ] MarketEngine.initialize(currencies, exchanges, None) pairs = MarketEngine.instance().supportedCurrencyPairs() ArbitrageEngine.initialize(currencies, exchanges, pairs) BookKeeper.initialize(currencies, exchanges) VirtualMarket.initialize(currencies, exchanges, pairs) try: marketData = {} for exchange in exchanges: marketData[exchange] = MarketEngine.instance().fetchTickers( exch=exchange, pairs=pairs) VirtualMarket.instance().updateMarket(marketData=marketData) print("Market Initialized!") for key,value in VirtualMarket.instance()._market.items(): pprint(value.print()) for exchange in exchanges: MarketEngine.instance().fetchBalance(exch=exchange) print("Book Keeper Initialized!") pprint(BookKeeper.instance()._balances) except Exception as e: print("Initialization failed!") pprint(e) return return (exchanges, pairs)