def orderbook(ctx, market): market = Market(market, bitshares_instance=ctx.bitshares) orderbook = market.orderbook() ta = {} ta["bids"] = PrettyTable(["quote", "base", "price"]) ta["bids"].align = "r" for order in orderbook["bids"]: ta["bids"].add_row([ str(order["quote"]), str(order["base"]), "{:f} {}/{}".format(order["price"], order["base"]["asset"]["symbol"], order["quote"]["asset"]["symbol"]), ]) ta["asks"] = PrettyTable([ "price", "base", "quote", ]) ta["asks"].align = "r" ta["asks"].align["price"] = "l" for order in orderbook["asks"]: ta["asks"].add_row([ "{:f} {}/{}".format(order["price"], order["base"]["asset"]["symbol"], order["quote"]["asset"]["symbol"]), str(order["base"]), str(order["quote"]) ]) t = PrettyTable(["bids", "asks"]) t.add_row([str(ta["bids"]), str(ta["asks"])]) click.echo(t)
def market_orderbook(market_pair: hug.types.text, api_key: hug.types.text, request, hug_timer=5): """Given a valid market pair (e.g. USD:BTS) and your desired orderbook size limit, output the market pair's orderbook (buy/sell order) information in JSON.""" if (check_api_token(api_key) == True): # Check the api key # API KEY VALID google_analytics(request, 'market_orderbook') try: target_market = Market(market_pair) except: # Market is not valid return {'valid_market': False, 'valid_key': True, 'took': float(hug_timer)} target_market_orderbook_data = target_market.orderbook(limit=50) return {'market_orderbook': target_market_orderbook_data, 'market': market_pair, 'valid_market': True, 'valid_key': True, 'took': float(hug_timer)} else: # API KEY INVALID! return {'valid_key': False, 'took': float(hug_timer)}
def get_usdt_orderbook(self): """ Функция для проверки ордеров в стаканах пар указанные в параметре self.sett['usdt_assets'] Функция получает из сети BitShares данные из всех стаканов указанных в параметре self.sett['usdt_assets'] и формирует выборку на основе этих данных. Результаты ее работы сохраняются в переменных класса self.bids и self.asks """ for asset in self.sett['usdt_assets']: market = Market(self.sett['quote'] + ':' + asset) book = market.orderbook( limit=self.sett['orderbook_limit'] ) for bid in book['bids']: amount = bid['base']['amount'] bid = Order( bid['quote'], Amount(amount / self.price['BTS'], 'BTS') ) if not self.create_bids([bid]): break for ask in book['asks']: amount = ask['base']['amount'] ask = Order( ask['quote'], Amount(amount / self.price['BTS'], 'BTS') ) if not self.create_asks([ask]): break
def orderbook(ctx, market): """ Show the orderbook of a particular market """ market = Market(market, bitshares_instance=ctx.bitshares) orderbook = market.orderbook() ta = {} ta["bids"] = PrettyTable( ["quote", "sum quote", "base", "sum base", "price"]) ta["bids"].align = "r" cumsumquote = Amount(0, market["quote"]) cumsumbase = Amount(0, market["base"]) for order in orderbook["bids"]: cumsumbase += order["base"] cumsumquote += order["quote"] ta["bids"].add_row([ str(order["quote"]), str(cumsumquote), str(order["base"]), str(cumsumbase), "{:f} {}/{}".format(order["price"], order["base"]["asset"]["symbol"], order["quote"]["asset"]["symbol"]), ]) ta["asks"] = PrettyTable([ "price", "base", "sum base", "quote", "sum quote", ]) ta["asks"].align = "r" ta["asks"].align["price"] = "l" cumsumquote = Amount(0, market["quote"]) cumsumbase = Amount(0, market["base"]) for order in orderbook["asks"]: cumsumbase += order["base"] cumsumquote += order["quote"] ta["asks"].add_row([ "{:f} {}/{}".format(order["price"], order["base"]["asset"]["symbol"], order["quote"]["asset"]["symbol"]), str(order["base"]), str(cumsumbase), str(order["quote"]), str(cumsumquote), ]) t = PrettyTable(["bids", "asks"]) t.add_row([str(ta["bids"]), str(ta["asks"])]) click.echo(t)
def orderbook(ctx, market): """ Show the orderbook of a particular market """ market = Market(market, bitshares_instance=ctx.bitshares) orderbook = market.orderbook() ta = {} ta["bids"] = [["quote", "sum quote", "base", "sum base", "price"]] cumsumquote = Amount(0, market["quote"]) cumsumbase = Amount(0, market["base"]) for order in orderbook["bids"]: cumsumbase += order["base"] cumsumquote += order["quote"] ta["bids"].append([ str(order["quote"]), str(cumsumquote), str(order["base"]), str(cumsumbase), "{:f} {}/{}".format(order["price"], order["base"]["asset"]["symbol"], order["quote"]["asset"]["symbol"]), ]) ta["asks"] = [[ "price", "base", "sum base", "quote", "sum quote", ]] cumsumquote = Amount(0, market["quote"]) cumsumbase = Amount(0, market["base"]) for order in orderbook["asks"]: cumsumbase += order["base"] cumsumquote += order["quote"] ta["asks"].append([ "{:f} {}/{}".format(order["price"], order["base"]["asset"]["symbol"], order["quote"]["asset"]["symbol"]), str(order["base"]), str(cumsumbase), str(order["quote"]), str(cumsumquote), ]) t = [["bids", "asks"]] t.append([format_table(ta["bids"]), format_table(ta["asks"])]) print_table(t)
def spread_get(ctx, source, allowed, amount): click.echo("%s-%s:%s" % (source, allowed, amount)) allowed_items = allowed.split(",") for item in allowed_items: pair = "%s-%s" % (source, item) market = Market(pair, bitshares_instance=ctx.bitshares) orderbook = market.orderbook() orders_ask = parse_orders(orderbook["asks"], "ask") for order in orders_ask: click.echo("base symbol %s" % (order["base"]["asset"]["symbol"])) click.echo("base %s" % (order["base"])) click.echo("price %s" % (order["price"])) click.echo("quote symbol %s" % (order["quote"]["asset"]["symbol"])) click.echo("buy %s %s @ %s %s/%s for %s %s" % \ (order["quote"]["amount"], order["quote"]["asset"]["symbol"], order["price"], order["base"]["asset"]["symbol"], order["quote"]["asset"]["symbol"], order["base"]["amount"], order["base"]["asset"]["symbol"])) click.echo("order: %s" % (order.json()))
def book(node=''): while 1: time.sleep(1) market = Market(BitPAIR, bitshares_instance=BitShares(node), mode='head') call = Decimal(time.time()) last = market.ticker()['latest'] slast = '%.16f' % last elapsed = Decimal(time.time()) - call raw = market.orderbook(limit=40) bids = raw['bids'] asks = raw['asks'] sbidp = [('%.16f' % bids[i]['price']) for i in range(len(bids))] saskp = [('%.16f' % asks[i]['price']) for i in range(len(asks))] sbidv = [('%.2f' % float(bids[i]['quote'])).rjust(12, ' ') for i in range(len(bids))] saskv = [('%.2f' % float(asks[i]['quote'])).rjust(12, ' ') for i in range(len(asks))] bidv = [float(bids[i]['quote']) for i in range(len(bids))] askv = [float(asks[i]['quote']) for i in range(len(asks))] cbidv = list(np.cumsum(bidv)) caskv = list(np.cumsum(askv)) cbidv = [('%.2f' % i).rjust(12, ' ') for i in cbidv] caskv = [('%.2f' % i).rjust(12, ' ') for i in caskv] print("\033c") print('') print('litepresence - microDEX - proof of concept') print('') print(time.ctime(), ) print(' ', ('%.17f' % elapsed), ' ', node) print('') print(' LAST', slast[:10], slast[10:], ' ', BitPAIR) print('') print(' ', sbidv[0], ' ', (sbidp[0])[:10], (sbidp[0])[10:], ' ', (saskp[0])[:10], (saskp[0])[10:], (saskv[0])) print(' ', 'BIDS', ' ', 'ASKS') for i in range(1, len(sbidp)): print(cbidv[i], sbidv[i], ' ', (sbidp[i])[:10], (sbidp[i])[10:], ' ', (saskp[i])[:10], (saskp[i])[10:], saskv[i], caskv[i])
def dex_book(node, depth=3): # returns latest price on given market(node) try: market = Market(BitPAIR, bitshares_instance=BitShares(node, num_retries=0)) # dictionary of 4 lists containing bid/ask volume/price raw = market.orderbook(limit=depth) bids = raw['bids'] asks = raw['asks'] bidp = [satoshi(bids[i]['price']) for i in range(len(bids))] bidv = [blur(bids[i]['quote']) for i in range(len(bids))] askp = [satoshi(asks[i]['price']) for i in range(len(asks))] askv = [blur(asks[i]['quote']) for i in range(len(asks))] book = {'bidp': bidp, 'bidv': bidv, 'askp': askp, 'askv': askv} if (sum(bidp) > sum(askp)) or (bidp[0] > askp[0]): print ('BIDS > ASKS ???????????????????????????') print (node) global events events +=1 print (time.ctime(), book, events) except: pass
def auto_trans(): bitshares = BitShares() pwd = get_bitshare_pwd() private_key = get_bitshare_private_key() # create usd:cny market obj usd_cny_market = Market("USD:CNY") # create fox wallet obj fox_wallet = Wallet() if not fox_wallet.created(): fox_wallet.newWallet(pwd) # add private key, TODO:keep private key and pwd in safe place usd_cny_market.bitshares.wallet.unlock(pwd) try: usd_cny_market.bitshares.wallet.addPrivateKey(private_key) except ValueError as ve: logger.info('wif is already set') logger.info('start auto trans usd:cny') lb = 6.40 ub = 6.50 fox = Account("zfpx-fdjl") while True: start_time = time.time() logger.info("my open orders:%s", fox.openorders) my_usd = fox.balance("USD") my_cny = fox.balance("CNY") if start_time % 60 < 10: logger.info("my balance:%s", fox.balances) logger.info("my USD:%s my CNY:%s", my_usd, my_cny) # get avg price avg_price = update_market(usd_cny_market)[0] if avg_price < 6 or avg_price > 7: logger.error("!!!!!!!!!!!!!!!!!!!!!!!!:avg price out of range:", avg_price) continue # set upper bound and lower bound lb = avg_price * (1 - 0.005) ub = avg_price * (1 + 0.005) # get top orders top_orders = usd_cny_market.orderbook() # unlock fox wallet for usd:cny maket usd_cny_market.bitshares.wallet.unlock(pwd) # cancel all of the orders orders = usd_cny_market.accountopenorders(fox) for order in orders: logger.info("try cancel %s : %s", order["id"], order) usd_cny_market.cancel(order["id"], fox) time.sleep(1) # sell all for bid in top_orders["bids"]: price = bid["price"] quote = bid["quote"] print("price:%s ub:%s quote:%s", price, ub, quote) if price >= ub: print("price:%s >= ub:%s quote:%s", price, ub, quote) if my_usd > 0: # sell_usd = min(my_usd, quote) if my_usd["amount"] < quote["amount"]: sell_usd = my_usd else: sell_usd = quote left_usd = my_usd["amount"] - sell_usd["amount"] print("sell_usd:%s left_usd:%s price:%s bid:%s", sell_usd, left_usd, price, bid) logger.info("sell_usd:%s left_usd:%s price:%s bid:%s", sell_usd, left_usd, price, bid) try: usd_cny_market.sell(price, sell_usd, 86400, False, fox) except Exception as e: logger.error("on except:%s", e) log_bt() my_usd["amount"] = left_usd else: break # print("price:", price, " < ub:", ub) # buy all for ask in top_orders["asks"]: price = ask["price"] base = ask["base"] print("price:%s lb:%s base:%s", price, lb, base) if price <= lb: print("price:%s <= lb:%s base:%s", price, lb, base) if my_cny > 0: if base["amount"] < my_cny["amount"]: buy_cny = base["amount"] else: buy_cny = my_cny["amount"] buy_usd = buy_cny / price left_cny = my_cny["amount"] - buy_cny print("buy_usd:%s left_cny:%s price:%s ask:%s", buy_usd, left_cny, price, ask) logger.info("buy_usd:%s left_cny:%s price:%s ask:%s", buy_usd, left_cny, price, ask) try: # usd_cny_market.buy(price, buy_usd, 5, False, fox) usd_cny_market.buy(price, 1, 86400, False, fox) except Exception as e: logger.error("on except:%s", e) log_bt() my_cny["amount"] = left_cny else: break # print("price:", price, " > lb:", lb) usd_cny_market.bitshares.wallet.lock() delta_t = time.time() - start_time time.sleep(max(1, 30 - delta_t))
class MarketTab(QtGui.QWidget): def __init__(self, *args, **kwargs): self.iso = kwargs.pop("isolator", None) self.asset_a = kwargs.pop("asset_a", None) self.asset_b = kwargs.pop("asset_b", None) self._pairtag = self.asset_a["symbol"] + ":" + self.asset_b["symbol"] self.ping_callback = kwargs.pop("ping_callback", None) super(MarketTab, self).__init__(*args, **kwargs) self.ui = Ui_MarketTab() self.ui.setupUi(self) replaceAxis(self.ui.marketPlot, "bottom", TimeAxisItem(orientation='bottom')) replaceAxis( self.ui.marketPlot, "left", CoinAxisItem(precision=self.asset_b["precision"], orientation='left')) self.ui.marketPlot.setMenuEnabled(False) self.__vLine = pg.InfiniteLine(angle=90, movable=False, pen=PG_CROSSHAIR) self.__hLine = pg.InfiniteLine(angle=0, movable=False, pen=PG_CROSSHAIR) self.__textPrice = pg.TextItem('price') view = self.ui.marketPlot.getViewBox() view.addItem(self.__textPrice, ignoreBounds=True) view.addItem(self.__vLine, ignoreBounds=True) view.addItem(self.__hLine, ignoreBounds=True) view.setLimits( # yMin = 0, # price never goes below zero xMin=datetime.datetime(2015, 1, 1).timestamp(), # ~BTS started xMax=(datetime.datetime.now() + datetime.timedelta(weeks=52)).timestamp() # 1 year ) self.start_time = None self.stop_time = None self.initfetch = 1 self.ui.marketPlot.sigXRangeChanged.connect(self.updateRange) self.ui.marketPlot.scene().sigMouseMoved.connect(self.updateTooltip) #, # axisItems={'bottom': TimeAxisItem(orientation='bottom')} self._index = 999 self.ui.buyStack.setColumnCount(3) stretch_table(self.ui.buyStack, False, hidehoriz=True) self.ui.sellStack.setColumnCount(3) stretch_table(self.ui.sellStack, False, hidehoriz=True) self.subscribed = False self.updater = RemoteFetch(manager=self.iso.mainwin.Requests) self._frame_buy = { "group": self.ui.buyGroup, "mainLabel": self.ui.buyMainLabel, "mainAmt": self.ui.buyMainAmount, "altLabel": self.ui.buyAltLabel, "altAmt": self.ui.buyAltAmount, "price": self.ui.buyPrice, "account": self.ui.buyAccount, "expireEdit": self.ui.buyExpireEdit, "expireFOK": self.ui.buyFOK, "fee": self.ui.buyFeeAsset, "button": self.ui.buyButton, "_commit_inv": True, "table": self.ui.sellStack, } self._frame_sell = { "group": self.ui.sellGroup, "mainLabel": self.ui.sellMainLabel, "mainAmt": self.ui.sellMainAmount, "altLabel": self.ui.sellAltLabel, "altAmt": self.ui.sellAltAmount, "price": self.ui.sellPrice, "account": self.ui.sellAccount, "expireEdit": self.ui.sellExpireEdit, "expireFOK": self.ui.sellFOK, "fee": self.ui.sellFeeAsset, "button": self.ui.sellButton, "_commit_inv": False, "table": self.ui.buyStack, } self.setupFrame(self._frame_buy, self.asset_a, self.asset_b, title="Buy ") self.setupFrame(self._frame_sell, self.asset_a, self.asset_b, title="Sell ") #self.ui.table.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) #self.ui.table.customContextMenuRequested.connect(self.show_orders_submenu) self.ui.closeButton.clicked.connect(self.close_me) self.ui.swapButton.clicked.connect(self.swap_me) def close_me(self): app().mainwin.closeMarket(self._pairtag) def swap_me(self): try: app().mainwin.swapMarket(self._pairtag) except Exception as error: showexc(error) def close(self): # TODO: unsubscribe from market!!! pass def setupFrame(self, form, asset_a, asset_b, title="Trade "): form["group"].setTitle(title + asset_a["symbol"]) form["mainLabel"].setText(asset_a["symbol"]) form["altLabel"].setText(asset_b["symbol"]) form["price"].valueChanged.connect(self.price_value_changed) form["price"].setSuffix(" " + asset_b["symbol"]) form["price"].setDecimals(asset_b["precision"]) form["price"].setMaximum(asset_b["options"]["max_supply"] * pow(10, asset_b["precision"])) form["mainAmt"].valueChanged.connect(self.main_amount_changed) form["mainAmt"].setDecimals(asset_a["precision"]) form["mainAmt"].setMaximum(asset_a["options"]["max_supply"] * pow(10, asset_a["precision"])) form["altAmt"].valueChanged.connect(self.alt_amount_changed) form["altAmt"].setDecimals(asset_b["precision"]) form["altAmt"].setMaximum(asset_b["options"]["max_supply"] * pow(10, asset_b["precision"])) form["table"].cellClicked.connect(self.cell_click) form["button"].clicked.connect(self.make_limit_order) def make_limit_order(self): form = self._frame_buy if self._frame_buy["button"] == self.sender( ) else self._frame_sell account_from = form["account"].currentText() sell_asset_name = self.asset_a["symbol"] sell_asset_amount = form["mainAmt"].value() buy_asset_name = self.asset_b["symbol"] buy_asset_amount = form["altAmt"].value() if form["_commit_inv"]: sell_asset_name = self.asset_b["symbol"] buy_asset_name = self.asset_a["symbol"] expire_seconds = deltasec(form["expireEdit"].text()) expire_fok = form["expireFOK"].isChecked() fee_asset = anyvalvis(form["fee"], None) #.currentText() buffer = app().mainwin.buffering() try: v = QTransactionBuilder.VSellAsset(account_from, sell_asset_name, sell_asset_amount, buy_asset_name, buy_asset_amount, expiration=expire_seconds, fill_or_kill=expire_fok, fee_asset=fee_asset, isolator=self.iso) if buffer: app().mainwin._txAppend(*v) else: QTransactionBuilder._QExec(self.iso, v) except Exception as error: showexc(error) return False return True def _set_spin_value(self, elem, value): elem.blockSignals(True) elem.setValue(value) elem.blockSignals(False) def price_value_changed(self): form = self._frame_buy if self._frame_buy["price"] == self.sender( ) else self._frame_sell price = form["price"].value() amt_a = form["mainAmt"].value() amt_b = form["altAmt"].value() if amt_a == 0 and price != 0: amt_a = amt_b / price self._set_spin_value(form["mainAmt"], amt_a) return amt_b = amt_a * price self._set_spin_value(form["altAmt"], amt_b) def main_amount_changed(self): form = self._frame_buy if self._frame_buy["mainAmt"] == self.sender( ) else self._frame_sell price = form["price"].value() amt_a = form["mainAmt"].value() amt_b = form["altAmt"].value() if price == 0: if amt_a == 0: return price = amt_b / amt_a self._set_spin_value(form["price"], price) return amt_b = amt_a * price self._set_spin_value(form["altAmt"], amt_b) def alt_amount_changed(self): form = self._frame_buy if self._frame_buy["altAmt"] == self.sender( ) else self._frame_sell price = form["price"].value() amt_a = form["mainAmt"].value() amt_b = form["altAmt"].value() if price == 0: if amt_a == 0: return price = amt_b / amt_a #form["price"].setValue(price) self._set_spin_value(form["price"], price) return amt_a = amt_b / price self._set_spin_value(form["mainAmt"], amt_a) def cell_click(self, row, column): form = self._frame_buy if self._frame_buy["table"] == self.sender( ) else self._frame_sell valstr = form["table"].item(row, column).text().replace(",", "") val = float(str.split(valstr, " ")[0]) if column == 0: # price form["price"].setValue(val) if column == 1: # asset_a form["mainAmt"].setValue(val) if column == 2: # asset_b form["altAmt"].setValue(val) def _refreshTitle(self): #self._title = _translate("MainWindow", "Market", None) + " " + self._pairtag self._title = self._pairtag return self._title def show_orders_submenu(self, position): menu = QtGui.QMenu() qaction(self, menu, "Cancel Order...", self.cancel_order) menu.exec_(self.ui.table.viewport().mapToGlobal(position)) def cancel_order(self): table = self.ui.table indexes = table.selectionModel().selectedRows() if len(indexes) < 1: return index = indexes[0].row() order_id = table.item(index, 0).text() #b = table.item(index, 1).text() try: trx = QTransactionBuilder.QCancelOrder( self._account_name, order_id, #fee_asset=fee_asset, isolator=self.iso) except Exception as error: showexc(error) def desync(self): self.subscribed = False def resync(self): self.updater.fetch(self.mergeMarket_before, self.iso, (self.asset_a, self.asset_b), self._pairtag, self.start_time, self.stop_time, ready_callback=self.mergeMarket_after, ping_callback=self.ping_callback, description="Refreshing market " + self._pairtag) def mergeMarket_before(self, iso, pair, tag, start, stop): asset_a = pair[0] asset_b = pair[1] rpc = iso.bts.rpc if not self.subscribed: s_id = rpc.get_subscription_id() subs = rpc.subscribe_to_market(s_id, asset_a["id"], asset_b["id"]) self._s_id = s_id self._tags.append("!" + str(s_id)) self.subscribed = True from bitshares.market import Market self.market = Market(base=asset_b, quote=asset_a, blockchain_instance=iso.bts) orders = self.market.orderbook() if self.initfetch: trades = self.market.trades(limit=100, start=start, stop=stop) else: trades = iso.getMarketBuckets(self.market["base"], self.market["quote"], start=start, stop=stop) return ( orders, trades, ) def mergeMarket_after(self, request_id, args): ( orders, trades, ) = args self.fillTable(self.ui.buyStack, orders['bids']) self.fillTable(self.ui.sellStack, orders['asks'], True) self.plotChart(trades) def fillTable(self, table, orders, inv=False): color_a = COLOR_GREEN if inv else COLOR_RED color_b = COLOR_RED if inv else COLOR_GREEN table.setRowCount(0) j = -1 for order in orders: j += 1 table.insertRow(j) set_col(table, j, 0, price__repr(order, "base")) set_col(table, j, 1, str(order["quote"]), color=color_a, align="right") set_col(table, j, 2, str(order["base"]), color=color_b, align="right") def plotChart(self, trades): xs = [] ys = [] for trade in trades: dt = datetime.datetime.strptime(trade["date"], "%Y-%m-%dT%H:%M:%S") x = int(dt.timestamp()) #trade["sequence"] y = trade["price"] xs.append(x) ys.append(y) #print(xs, ys) #import numpy as np #x = np.random.normal(size=1000) #y = np.random.normal(size=1000) self.ui.marketPlot.blockSignals(True) self.ui.marketPlot.clear() self.ui.marketPlot.plot(xs, ys, pen=PG_LINEPEN) #, pen=None, symbol=None) obj = self.ui.marketPlot.getPlotItem() axis = obj.axes["bottom"]['item'] axis._dayscale = False if len(xs) > 1: # Hack: adjust X-axis display if (xs[-1] - xs[0]) >= 3600 * 24: # >= 1 day axis._dayscale = True self.ui.marketPlot.blockSignals(False) def updateRange(self, view, rng): if self.initfetch > 0: self.initfetch -= 1 return #price_low, price_high = rng[1] # (as integer) sec_start, sec_end = rng #[0] self.start_time = datetime.datetime.fromtimestamp(sec_start) self.stop_time = datetime.datetime.fromtimestamp(sec_end) self.resync() def updateTooltip(self, pos): data = self.ui.marketPlot.getPlotItem().listDataItems() if len(data) < 1: return points = data[0].curve act_pos = points.mapFromScene(pos) xs, ys = points.getData() x, j = snapTo(act_pos.x(), xs) if j < 0: self.__vLine.hide() self.__hLine.hide() self.__textPrice.hide() return y = ys[j] #print("SNAP:", j, x, y) self.__vLine.setPos(x) self.__hLine.setPos(y) self.__textPrice.setPos(x, y) price = "{price:.{precision}f}".format( price=y, precision=self.asset_b["precision"]) self.__textPrice.setText(price) self.__vLine.show() self.__hLine.show() self.__textPrice.show()
def book(nodes, a=None, b=None): #updates orderbook details # create fresh websocket connections for this child instance account = Account(USERNAME, bitshares_instance=BitShares(nodes, num_retries=0)) market = Market(BitPAIR, bitshares_instance=BitShares(nodes, num_retries=0), mode='head') node = nodes[0] begin = time.time() while time.time() < (begin + TIMEOUT): time.sleep(random()) try: # add unix time to trades dictionary trades = market.trades(limit=100) for t in range(len(trades)): ts = time.strptime(str(trades[t]['time']), '%Y-%m-%d %H:%M:%S') trades[t]['unix'] = int(time.mktime(ts)) fprice = '%.16f' % float(trades[t]['price']) trades[t]['fprice'] = fprice[:10] + ',' + fprice[10:] # last price # last = market.ticker()['latest'] last = float(trades[0]['price']) slast = '%.16f' % last # complete account balances call = decimal(time.time()) raw = list(account.balances) elapsed = float(decimal(time.time()) - call) if elapsed > 1: continue elapsed = '%.17f' % elapsed cbalances = {} for i in range(len(raw)): cbalances[raw[i]['symbol']] = float(raw[i]['amount']) # orderbook raw = market.orderbook(limit=20) bids = raw['bids'] asks = raw['asks'] sbidp = [('%.16f' % bids[i]['price']) for i in range(len(bids))] saskp = [('%.16f' % asks[i]['price']) for i in range(len(asks))] sbidv = [('%.2f' % float(bids[i]['quote'])).rjust(12, ' ') for i in range(len(bids))] saskv = [('%.2f' % float(asks[i]['quote'])).rjust(12, ' ') for i in range(len(asks))] bidv = [float(bids[i]['quote']) for i in range(len(bids))] askv = [float(asks[i]['quote']) for i in range(len(asks))] cbidv = list(np.cumsum(bidv)) caskv = list(np.cumsum(askv)) cbidv = [('%.2f' % i).rjust(12, ' ') for i in cbidv] caskv = [('%.2f' % i).rjust(12, ' ') for i in caskv] # dictionary of currency and assets in this market currency = float(account.balance(BitCURRENCY)) assets = float(account.balance(BitASSET)) balances = {BitCURRENCY: currency, BitASSET: assets} # dictionary of open orders in traditional format: # orderNumber, orderType, market, amount, price orders = [] for order in market.accountopenorders(): orderNumber = order['id'] asset = order['base']['symbol'] currency = order['quote']['symbol'] amount = float(order['base']) price = float(order['price']) orderType = 'buy' if asset == BitASSET: orderType = 'sell' price = 1 / price else: amount = amount / price orders.append({ 'orderNumber': orderNumber, 'orderType': orderType, 'market': BitPAIR, 'amount': amount, 'price': ('%.16f' % price) }) trades = trades[:10] stale = int(time.time() - float(trades[0]['unix'])) # display orderbooks print("\033c") print(time.ctime(), ' ', int(time.time()), ' ', a, b) print(' PING', (elapsed), ' ', node) print('') print(' LAST', slast[:10] + ',' + slast[10:], ' ', BitPAIR) print('') print(' ', sbidv[0], ' ', (sbidp[0])[:10] + ',' + (sbidp[0])[10:], ' ', (saskp[0])[:10] + ',' + (saskp[0])[10:], (saskv[0])) print(' ', 'BIDS', ' ', 'ASKS') for i in range(1, len(sbidp)): print(cbidv[i], sbidv[i], ' ', (sbidp[i])[:10] + ',' + (sbidp[i])[10:], ' ', (saskp[i])[:10] + ',' + (saskp[i])[10:], saskv[i], caskv[i]) print('') for o in orders: print(o) if len(orders) == 0: print(' NO OPEN ORDERS') print('') print('%s BALANCE:' % BitPAIR) print(balances) print('') print('MARKET HISTORY:', stale, 'since last trade') for t in trades: # print(t.items()) print(t['unix'], str(t['time'])[11:19], t['fprice'], ('%.4f' % float(t['quote']['amount'])).rjust(12, ' ')) print('') print('ctrl+shift+\ will EXIT to terminal') print('') print('COMPLETE HOLDINGS:') print(cbalances) except: pass
class MarketTab(QtGui.QWidget): def __init__(self, *args, **kwargs): self.iso = kwargs.pop("isolator", None) self.asset_a = kwargs.pop("asset_a", None) self.asset_b = kwargs.pop("asset_b", None) self._pairtag = self.asset_a["symbol"] + ":" + self.asset_b["symbol"] self.ping_callback = kwargs.pop("ping_callback", None) super(MarketTab, self).__init__(*args, **kwargs) self.ui = Ui_MarketTab() self.ui.setupUi(self) replaceAxis(self.ui.marketPlot, "bottom", TimeAxisItem(orientation='bottom')) #, # axisItems={'bottom': TimeAxisItem(orientation='bottom')} self._index = 999 self.ui.buyStack.setColumnCount(3) stretch_table(self.ui.buyStack, False, hidehoriz=True) self.ui.sellStack.setColumnCount(3) stretch_table(self.ui.sellStack, False, hidehoriz=True) self.subscribed = False self.updater = RemoteFetch() self._frame_buy = { "group": self.ui.buyGroup, "mainLabel": self.ui.buyMainLabel, "mainAmt": self.ui.buyMainAmount, "altLabel": self.ui.buyAltLabel, "altAmt": self.ui.buyAltAmount, "price": self.ui.buyPrice, "account": self.ui.buyAccount, "expireEdit": self.ui.buyExpireEdit, "expireFOK": self.ui.buyFOK, "fee": self.ui.buyFeeAsset, "button": self.ui.buyButton, "_commit_inv": True, "table": self.ui.sellStack, } self._frame_sell = { "group": self.ui.sellGroup, "mainLabel": self.ui.sellMainLabel, "mainAmt": self.ui.sellMainAmount, "altLabel": self.ui.sellAltLabel, "altAmt": self.ui.sellAltAmount, "price": self.ui.sellPrice, "account": self.ui.sellAccount, "expireEdit": self.ui.sellExpireEdit, "expireFOK": self.ui.sellFOK, "fee": self.ui.sellFeeAsset, "button": self.ui.sellButton, "_commit_inv": False, "table": self.ui.buyStack, } self.setupFrame(self._frame_buy, self.asset_a, self.asset_b, title="Buy ") self.setupFrame(self._frame_sell, self.asset_a, self.asset_b, title="Sell ") #self.ui.table.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) #self.ui.table.customContextMenuRequested.connect(self.show_orders_submenu) self.ui.closeButton.clicked.connect(self.close_me) self.ui.swapButton.clicked.connect(self.swap_me) def close_me(self): app().mainwin.closeMarket(self._pairtag) def swap_me(self): app().mainwin.swapMarket(self._pairtag) def close(self): # TODO: unsubscribe from market!!! pass def setupFrame(self, form, asset_a, asset_b, title="Trade "): form["group"].setTitle(title + asset_a["symbol"]) form["mainLabel"].setText(asset_a["symbol"]) form["altLabel"].setText(asset_b["symbol"]) form["price"].valueChanged.connect(self.price_value_changed) form["price"].setDecimals(asset_a["precision"]) form["price"].setMaximum(asset_a["options"]["max_supply"] * pow(10, asset_a["precision"])) form["mainAmt"].valueChanged.connect(self.main_amount_changed) form["mainAmt"].setDecimals(asset_a["precision"]) form["mainAmt"].setMaximum(asset_a["options"]["max_supply"] * pow(10, asset_a["precision"])) form["altAmt"].valueChanged.connect(self.alt_amount_changed) form["altAmt"].setDecimals(asset_b["precision"]) form["altAmt"].setMaximum(asset_b["options"]["max_supply"] * pow(10, asset_b["precision"])) form["table"].cellClicked.connect(self.cell_click) form["button"].clicked.connect(self.make_limit_order) def make_limit_order(self): form = self._frame_buy if self._frame_buy["button"] == self.sender( ) else self._frame_sell account_from = form["account"].currentText() sell_asset_name = self.asset_a["symbol"] sell_asset_amount = form["mainAmt"].value() buy_asset_name = self.asset_b["symbol"] buy_asset_amount = form["altAmt"].value() if form["_commit_inv"]: sell_asset_name = self.asset_b["symbol"] buy_asset_name = self.asset_a["symbol"] expire_seconds = deltasec(form["expireEdit"].text()) expire_fok = form["expireFOK"].isChecked() fee_asset = anyvalvis(form["fee"], None) #.currentText() try: trx = QTransactionBuilder.QSellAsset(account_from, sell_asset_name, sell_asset_amount, buy_asset_name, buy_asset_amount, expiration=expire_seconds, fill_or_kill=expire_fok, fee_asset=fee_asset, isolator=self.iso) except BaseException as error: showexc(error) def _set_spin_value(self, elem, value): elem.blockSignals(True) elem.setValue(value) elem.blockSignals(False) def price_value_changed(self): form = self._frame_buy if self._frame_buy["price"] == self.sender( ) else self._frame_sell price = form["price"].value() amt_a = form["mainAmt"].value() amt_b = form["altAmt"].value() if amt_a == 0 and price != 0: amt_a = amt_b / price self._set_spin_value(form["mainAmt"], amt_a) return amt_b = amt_a * price self._set_spin_value(form["altAmt"], amt_b) def main_amount_changed(self): form = self._frame_buy if self._frame_buy["mainAmt"] == self.sender( ) else self._frame_sell price = form["price"].value() amt_a = form["mainAmt"].value() amt_b = form["altAmt"].value() if price == 0 and amt_a != 0: price = amt_b / amt_a self._set_spin_value(form["price"], price) return amt_b = amt_a * price self._set_spin_value(form["altAmt"], amt_b) def alt_amount_changed(self): form = self._frame_buy if self._frame_buy["altAmt"] == self.sender( ) else self._frame_sell price = form["price"].value() amt_a = form["mainAmt"].value() amt_b = form["altAmt"].value() if price == 0 and amt_a != 0: price = amt_b / amt_a form["price"].setValue(price) self._set_spin_value(form["price"], price) return amt_a = amt_b / price self._set_spin_value(form["mainAmt"], amt_a) def cell_click(self, row, column): form = self._frame_buy if self._frame_buy["table"] == self.sender( ) else self._frame_sell valstr = form["table"].item(row, column).text().replace(",", "") val = float(str.split(valstr, " ")[0]) if column == 0: # price form["price"].setValue(val) if column == 1: # asset_a form["mainAmt"].setValue(val) if column == 2: # asset_b form["altAmt"].setValue(val) def _refreshTitle(self): #self._title = _translate("MainWindow", "Market", None) + " " + self._pairtag self._title = self._pairtag return self._title def show_orders_submenu(self, position): menu = QtGui.QMenu() qaction(self, menu, "Cancel Order...", self.cancel_order) menu.exec_(self.ui.table.viewport().mapToGlobal(position)) def cancel_order(self): table = self.ui.table indexes = table.selectionModel().selectedRows() if len(indexes) < 1: return index = indexes[0].row() order_id = table.item(index, 0).text() #b = table.item(index, 1).text() try: trx = QTransactionBuilder.QCancelOrder( self._account_name, order_id, #fee_asset=fee_asset, isolator=self.iso) except BaseException as error: showexc(error) def desync(self): self.subscribed = False def resync(self): self.updater.fetch(self.mergeMarket_before, self.iso, (self.asset_a, self.asset_b), self._pairtag, ready_callback=self.mergeMarket_after, ping_callback=self.ping_callback, description="Refreshing market") def mergeMarket_before(self, iso, pair, tag): #iso._wait_online(timeout=3) # will raise exception #if not(iso.is_connected()): # raise Exception asset_a = pair[0] asset_b = pair[1] rpc = iso.bts.rpc if not self.subscribed: s_id = rpc.get_subscription_id() subs = rpc.subscribe_to_market(s_id, asset_a["id"], asset_b["id"]) self._s_id = s_id self._tags.append("!" + str(s_id)) self.subscribed = True from bitshares.market import Market self.market = Market(tag, bitshares_instance=iso.bts) orders = self.market.orderbook() trades = self.market.trades(limit=100, raw=True) return ( orders, trades, ) def mergeMarket_after(self, request_id, args): ( orders, trades, ) = args self.fillTable(self.ui.buyStack, orders['bids']) self.fillTable(self.ui.sellStack, orders['asks'], True) self.plotChart(trades) def fillTable(self, table, orders, inv=False): color_a = COLOR_GREEN if inv else COLOR_RED color_b = COLOR_RED if inv else COLOR_GREEN table.setRowCount(0) j = -1 for order in orders: j += 1 table.insertRow(j) set_col(table, j, 0, str(order["price"])) set_col(table, j, 1, str(order["quote"]), color=color_a, align="right") set_col(table, j, 2, str(order["base"]), color=color_b, align="right") def plotChart(self, trades): xs = [] ys = [] import datetime for trade in trades: dt = datetime.datetime.strptime(trade["date"], "%Y-%m-%dT%H:%M:%S") x = int(dt.timestamp()) #trade["sequence"] y = float(trade["price"]) xs.append(x) ys.append(y) #print(xs, ys) #import numpy as np #x = np.random.normal(size=1000) #y = np.random.normal(size=1000) self.ui.marketPlot.clear() self.ui.marketPlot.plot(xs, ys) #, pen=None, symbol=None)
def get_additional_orderbook(self): """ Функция для проверки ордеров в стаканах пар указанные в параметре self.sett['additional_assets'] Функция получает из сети BitShares данные из всех стаканов указанных в параметре self.sett['additional_assets'] и формирует выборку на основе этих данных. Результаты ее работы сохраняются в переменных класса self.bids и self.asks """ for asset in self.sett['additional_assets']: market_base = Market(self.sett['quote'] + ':' + asset) market_core = Market(asset + ':BTS') book_base = market_base.orderbook( limit=self.sett['orderbook_limit'] ) book_core = market_core.orderbook( limit=self.sett['orderbook_limit'] ) for bid_base in book_base['bids']: check = False base_amount = bid_base['base']['amount'] bid_core = book_core['bids'][0] while base_amount > 0: core_amount = bid_core['quote']['amount'] check = self.check_bid(bid_base, bid_core) if base_amount >= core_amount: bid_base['quote'] -= Amount( core_amount / bid_base['price'], bid_base['quote']['asset'] ) bid_base['base'] -= bid_core['quote'] book_core['bids'].pop(0) bid_core = book_core['bids'][0] else: bid_core['base'] -= Amount( base_amount * bid_core['price'], bid_core['base']['asset'] ) bid_core['quote'] -= bid_base['base'] break if not check: base_amount = 0 else: base_amount = bid_base['base']['amount'] if not check: break for ask_base in book_base['asks']: check = False base_amount = ask_base['base']['amount'] ask_core = book_core['asks'][0] while base_amount > 0: core_amount = ask_core['quote']['amount'] check = self.check_ask(ask_base, ask_core) if base_amount >= core_amount: ask_base['quote'] -= Amount( core_amount / ask_base['price'], ask_base['quote']['asset'] ) ask_base['base'] -= ask_core['quote'] book_core['asks'].pop(0) ask_core = book_core['asks'][0] else: ask_core['base'] -= Amount( base_amount * ask_core['price'], ask_core['base']['asset'] ) ask_core['quote'] -= ask_base['base'] break if not check: base_amount = 0 else: base_amount = ask_base['base']['amount'] if not check: break
bundle=True, ) bitshares = BitShares() #print(bitshares.config.items()) chain = Blockchain() mid_rate = 6.31 lower_bound_rate = mid_rate * 1.008 upper_bound_rate = lower_bound_rate * 1.035 print(lower_bound_rate, "|", upper_bound_rate) lb = 6.40 ub = 6.50 usd_cny_market = Market("USD:CNY") top_orders = usd_cny_market.orderbook(10) # sell to bid for bid in top_orders["bids"]: print("bid:", "base:", bid["base"], "quote:", bid["quote"], "price:", bid["price"]) # buy from ask for ask in top_orders["asks"]: print("ask:", "base:", ask["base"], "quote:", ask["quote"], "price:", ask["price"]) #print(market.orderbook(2)) #print(usd_cny_market.ticker())
def get_history_depth(self): """ Функция для рассчета средней цены совершенных сделок Функция собирает все данные из истории, сортирует их по дате, приводит цены к self.sett['base'] и отсекает все сделки выходящие за пределы self.sett['history_depth']. Результаты сохраняет в переменных класса self.history_amount и self.average_history_price """ history = [] sum = 0 start_time = datetime.now() - timedelta( days=self.sett['history_period'] ) for trade in self.quote_market.trades( limit=self.sett['history_limit'], start=start_time ): amount = trade['base']['amount'] * self.price['BTS'] history.append(trade) sum += amount if sum > self.sett['history_depth']: break history.sort(key=self.sortByTime, reverse=True) assets = self.sett['additional_assets'].copy() assets.extend(self.sett['usdt_assets']) for asset in assets: market = Market(asset + ':BTS') book = market.orderbook(limit=1) self.price[asset] = (book['asks'][0]['price'] + book['bids'][0]['price']) / 2*self.price['BTS'] market = Market(self.sett['quote'] + ':' + asset) for trade in market.trades( limit=self.sett['history_limit'], start=start_time ): history.append(trade) history.sort(key=self.sortByTime, reverse=True) amount = trade['base']['amount'] * self.price[asset] sum += amount break_bool = False while sum >= self.sett['history_depth']: last = history.pop() last_amount = (last['base']['amount'] * self.price[last['base']['symbol']]) if last_amount > sum - self.sett['history_depth']: history.append(last) break else: sum -= last_amount if (last['quote']['symbol'] == trade['quote']['symbol'] and last['base']['symbol'] == trade['base']['symbol']): if (collections.Counter(last) == collections.Counter(trade)): break_bool = True break if break_bool: break sum = sum_quote = 0 for h in history: sum += h['base']['amount'] * self.price[h['base']['symbol']] sum_quote += h['quote']['amount'] if sum > self.sett['history_depth']: last = history.pop() ratio = sum / self.sett['history_depth'] sum_quote = sum_quote / ratio sum = self.sett['history_depth'] self.history_amount = sum_quote self.average_history_price = sum / sum_quote
generic_client = GenericClient() market_client = MarketClient() account_client = AccountClient(api_key=APIKEY, secret_key=SECERTKEY) trade_client = TradeClient(api_key=APIKEY, secret_key=SECERTKEY) ##create bts clients bts = BitShares("wss://ws.gdex.top") pw = input("please input the pw: ") bts.wallet.unlock(pw) dexmarket = Market('BTS/GDEX.USDT', blockchain_instance=bts) while True: ##get huobi and bts tickers huobidepth = market_client.get_pricedepth("btsusdt", DepthStep.STEP0, 1) dexticker = dexmarket.orderbook(limit=1) dexbid = dexticker['bids'][0] dexask = dexticker['asks'][0] huobibid = huobidepth.bids[0] huobiask = huobidepth.asks[0] ##compare the ticker and place orders if there are trading chances: if dexbid.price > huobiask.price * 1.006 and min(dexbid['quote'].amount, huobiask.amount) > 100: huobibuyorder_id = trade_client.create_order(symbol='btsusdt', account_id=88888888, order_type='buy-limit', source="api", amount=100, price=huobiask.price) dexmarket.sell(price=dexbid.price, amount=100, account='test') else: print('no chance for trading, dex bid price is %.5f and huobi ask price is %.5f' % (dexbid.price, huobiask.price))
def update_prices(self, data): data['assets'] = re.sub('\(|\,|\'|\)', '', data['assets']) data['assets'] = data['assets'].split(' ') if data['selected_asset'] == 0: selected_asset = data['assets'][0] unselected_asset = data['assets'][1] else: selected_asset = data['assets'][1] unselected_asset = data['assets'][0] market = Market('{}:{}'.format(selected_asset, unselected_asset)) market_cost_track = { 'total': 0, 'cost': 0 } for order in (market.orderbook()['asks'] if data['buy_or_sell'] == 'buy' else market.orderbook()['bids']): if (order['quote'].amount + market_cost_track['total']) <= data['amount']: market_cost_track['total'] += order['quote'].amount market_cost_track['cost'] += order['base'].amount else: order_difference = data['amount'] - market_cost_track['total'] market_cost_track['total'] += order_difference self._order_price = order['price'] final_amount_cost = self.correct_market_precision( order_difference, order['price'], order['quote'].symbol, market_cost_track['cost'] ) market_cost_track['cost'] = final_amount_cost break # exchange preserves x*y # buying subtracts from that side of the pool # selling adds to that side of the pool ################## lots of repeating code in this section, needs cleanup pool_cost_track = {'invariant': data['invariant']} if data['buy_or_sell'] == 'buy': if selected_asset == data['assets'][0]: # creates local variable for balance x reference_x = self.amount_x.amount # gets difference of what user wants vs pool difference_of_x = reference_x - data['amount'] # calculates new y balance by keeping invariant constant new_y_balance = data['invariant'] / difference_of_x # uses function to get correct precision cost output_amount = self.correct_pool_amount(new_y_balance, self.amount_y.amount, unselected_asset) # assigns asset and correct cost to pool tracker variable pool_cost_track['pool_cost'] = output_amount pool_cost_track['asset'] = unselected_asset else: reference_y = self.amount_y.amount difference_of_y = reference_y - data['amount'] new_x_balance = data['invariant'] / difference_of_y output_amount = self.correct_pool_amount(new_x_balance, self.amount_x.amount, unselected_asset) pool_cost_track['pool_cost'] = output_amount pool_cost_track['asset'] = unselected_asset else: if selected_asset == data['assets'][0]: reference_x = self.amount_x.amount addition_to_x = reference_x + data['amount'] new_y_balance = data['invariant'] / addition_to_x output_amount = self.correct_pool_amount(self.amount_y.amount, new_y_balance, unselected_asset) pool_cost_track['pool_cost'] = output_amount pool_cost_track['asset'] = unselected_asset else: reference_y = self.amount_y.amount addition_to_y = reference_y + data['amount'] new_x_balance = data['invariant'] / addition_to_y output_amount = self.correct_pool_amount(self.amount_x.amount, new_x_balance, unselected_asset) pool_cost_track['pool_cost'] = output_amount pool_cost_track['asset'] = unselected_asset pub.sendMessage('update_trading_prices', data={ 'market': '{} {}'.format(market_cost_track['cost'], order['base'].symbol), 'pool': '{} {}'.format(pool_cost_track['pool_cost'], pool_cost_track['asset']) })
class Parser(): def __init__(self, sett, **kwargs): """ Инициализация класса, рынков и получение цены BTS :param set sett: настройки класса str quote - актив, стоимость которого считаем str base - актив, в котором считаем стоимость list additional_assets - дополнительные рынки для расчета, кроме BTS list usdt_assets - дополнительные рынки, стоимость которых равна стоимости актива base float base_depth - глубина расчета цены в стаканах в активе base float history_depth - глубина расчета цены совершенных сделок в активе base int price_precision - количество знаков после запятой, для отображения цен int orderbook_limit - максимальное количество сделок из стакана получаемое от ноды int history_limit - максимальное количество сделок получаемое из истории от ноды int history_period - максимальное количество дней, за которые берется история set viz_account - данные аккаунта для публикации в блокчейне VIZ """ self.sett = sett self.quote_market = Market(self.sett['quote'] + ':BTS') self.base_market = Market('BTS:' + self.sett['base']) book = self.base_market.orderbook(limit=1) self.price = {} self.price['BTS'] = (book['asks'][0]['price'] + book['bids'][0]['price']) / 2 self.bids = [] self.asks = [] def check_ask(self, base, core): """ Функция для создания нового "виртуального" ордера в формате пары self.sett['quote'] / BTS Возвращает True в случае попадания этого ордера в выборку и False в противном случае :param bitshares.price.Order base: ордер на продажу из пары self.sett['quote'] / BTS :param bitshares.price.Order core: ордер на продажу из пары BTS / self.sett['base'] Функция проверяет объемы в ордерах base и core и создает новый на основе меньшего из них """ base_amount = base['base']['amount'] core_amount = core['quote']['amount'] if base_amount >= core_amount: new_base = base.copy() new_base['quote'] = Amount( core_amount / base['price'], base['quote']['asset'] ) new_base['base'] = core['quote'] order = Order(new_base['quote'], core['base']) else: new_core = core.copy() new_core['base'] = Amount( base_amount * core['price'], core['base']['asset'] ) new_core['quote'] = base['base'] order = Order(base['quote'], new_core['base']) return self.create_asks([order]) def check_bid(self, base, core): """ Функция для создания нового "виртуального" ордера в формате пары self.sett['quote'] / BTS Возвращает True в случае попадания этого ордера в выборку и False в противном случае :param bitshares.price.Order base: ордер на покупку из пары self.sett['quote'] / BTS :param bitshares.price.Order core: ордер на покупку из пары BTS / self.sett['base'] Функция проверяет объемы в ордерах base и core и создает новый на основе меньшего из них """ base_amount = base['base']['amount'] core_amount = core['quote']['amount'] if base_amount >= core_amount: new_base = base.copy() new_base['quote'] = Amount( core_amount / base['price'], base['quote']['asset'] ) new_base['base'] = core['quote'] order = Order(new_base['quote'], core['base']) else: new_core = core.copy() new_core['base'] = Amount( base_amount * core['price'], core['base']['asset'] ) new_core['quote'] = base['base'] order = Order(base['quote'], new_core['base']) return self.create_bids([order]) def create_asks(self, asks): """ Функция для формирования выборки ордеров на продажу. Возвращает True в случае попадания первого ордера в выборку и False в противном случае :param list(bitshares.price.Order) asks: список ордеров на продажу в формате пары self.sett['quote'] / BTS Функция сортирует ордера в порядке увеличения цены и отсекает все, которые не вписываются в параметр self.sett['base_depth'] """ tmp_asks = self.asks tmp_asks.extend(asks) tmp_asks.sort() self.asks = [] asks_amount = 0 result = False for ask in tmp_asks: self.asks.append(ask) if ask == asks[0]: result = True amount = ask['base']['amount'] * self.price['BTS'] asks_amount += amount if asks_amount > self.sett['base_depth']: break return result def create_bids(self, bids): """ Функция для формирования выборки ордеров на покупку. Возвращает True в случае попадания первого ордера в выборку и False в противном случае :param list(bitshares.price.Order) bids: список ордеров на покупку в формате пары self.sett['quote'] / BTS Функция сортирует ордера в порядке уменьшения цены и отсекает все, которые не вписываются в параметр self.sett['base_depth'] """ tmp_bids = self.bids tmp_bids.extend(bids) tmp_bids.sort(reverse=True) self.bids = [] bids_amount = 0 result = False for bid in tmp_bids: self.bids.append(bid) if bid == bids[0]: result = True amount = bid['base']['amount'] * self.price['BTS'] bids_amount += amount if bids_amount > self.sett['base_depth']: break return result def get_additional_orderbook(self): """ Функция для проверки ордеров в стаканах пар указанные в параметре self.sett['additional_assets'] Функция получает из сети BitShares данные из всех стаканов указанных в параметре self.sett['additional_assets'] и формирует выборку на основе этих данных. Результаты ее работы сохраняются в переменных класса self.bids и self.asks """ for asset in self.sett['additional_assets']: market_base = Market(self.sett['quote'] + ':' + asset) market_core = Market(asset + ':BTS') book_base = market_base.orderbook( limit=self.sett['orderbook_limit'] ) book_core = market_core.orderbook( limit=self.sett['orderbook_limit'] ) for bid_base in book_base['bids']: check = False base_amount = bid_base['base']['amount'] bid_core = book_core['bids'][0] while base_amount > 0: core_amount = bid_core['quote']['amount'] check = self.check_bid(bid_base, bid_core) if base_amount >= core_amount: bid_base['quote'] -= Amount( core_amount / bid_base['price'], bid_base['quote']['asset'] ) bid_base['base'] -= bid_core['quote'] book_core['bids'].pop(0) bid_core = book_core['bids'][0] else: bid_core['base'] -= Amount( base_amount * bid_core['price'], bid_core['base']['asset'] ) bid_core['quote'] -= bid_base['base'] break if not check: base_amount = 0 else: base_amount = bid_base['base']['amount'] if not check: break for ask_base in book_base['asks']: check = False base_amount = ask_base['base']['amount'] ask_core = book_core['asks'][0] while base_amount > 0: core_amount = ask_core['quote']['amount'] check = self.check_ask(ask_base, ask_core) if base_amount >= core_amount: ask_base['quote'] -= Amount( core_amount / ask_base['price'], ask_base['quote']['asset'] ) ask_base['base'] -= ask_core['quote'] book_core['asks'].pop(0) ask_core = book_core['asks'][0] else: ask_core['base'] -= Amount( base_amount * ask_core['price'], ask_core['base']['asset'] ) ask_core['quote'] -= ask_base['base'] break if not check: base_amount = 0 else: base_amount = ask_base['base']['amount'] if not check: break def get_history_depth(self): """ Функция для рассчета средней цены совершенных сделок Функция собирает все данные из истории, сортирует их по дате, приводит цены к self.sett['base'] и отсекает все сделки выходящие за пределы self.sett['history_depth']. Результаты сохраняет в переменных класса self.history_amount и self.average_history_price """ history = [] sum = 0 start_time = datetime.now() - timedelta( days=self.sett['history_period'] ) for trade in self.quote_market.trades( limit=self.sett['history_limit'], start=start_time ): amount = trade['base']['amount'] * self.price['BTS'] history.append(trade) sum += amount if sum > self.sett['history_depth']: break history.sort(key=self.sortByTime, reverse=True) assets = self.sett['additional_assets'].copy() assets.extend(self.sett['usdt_assets']) for asset in assets: market = Market(asset + ':BTS') book = market.orderbook(limit=1) self.price[asset] = (book['asks'][0]['price'] + book['bids'][0]['price']) / 2*self.price['BTS'] market = Market(self.sett['quote'] + ':' + asset) for trade in market.trades( limit=self.sett['history_limit'], start=start_time ): history.append(trade) history.sort(key=self.sortByTime, reverse=True) amount = trade['base']['amount'] * self.price[asset] sum += amount break_bool = False while sum >= self.sett['history_depth']: last = history.pop() last_amount = (last['base']['amount'] * self.price[last['base']['symbol']]) if last_amount > sum - self.sett['history_depth']: history.append(last) break else: sum -= last_amount if (last['quote']['symbol'] == trade['quote']['symbol'] and last['base']['symbol'] == trade['base']['symbol']): if (collections.Counter(last) == collections.Counter(trade)): break_bool = True break if break_bool: break sum = sum_quote = 0 for h in history: sum += h['base']['amount'] * self.price[h['base']['symbol']] sum_quote += h['quote']['amount'] if sum > self.sett['history_depth']: last = history.pop() ratio = sum / self.sett['history_depth'] sum_quote = sum_quote / ratio sum = self.sett['history_depth'] self.history_amount = sum_quote self.average_history_price = sum / sum_quote def get_market_depth(self): """ Основная функция для расчета средней цены ордеров в стакане Функция поочередно вызывает дочерние функции self.get_orderbook(), self.get_additional_orderbook(), self.get_usdt_orderbook() для сбора ордеров из всех пар. А затем расчитывает среднюю цену и сохраняет данные в переменных класса self.average_bid_price и self.average_ask_price """ self.get_orderbook() self.get_additional_orderbook() self.get_usdt_orderbook() quote = base = sum = 0 for bid in self.bids: amount = bid['base']['amount'] * self.price['BTS'] if sum + amount <= self.sett['base_depth']: quote += bid['quote']['amount'] base += bid['base']['amount'] sum += amount else: diff = self.sett['base_depth'] - sum ratio = diff / amount quote += bid['quote']['amount'] * ratio base += bid['base']['amount'] * ratio sum += diff self.average_bid_price = base / quote * self.price['BTS'] quote = base = sum = 0 for ask in self.asks: amount = ask['base']['amount'] * self.price['BTS'] if sum + amount <= self.sett['base_depth']: quote += ask['quote']['amount'] base += ask['base']['amount'] sum += amount else: diff = self.sett['base_depth'] - sum ratio = diff / amount quote += ask['quote']['amount'] * ratio base += ask['base']['amount'] * ratio sum += diff self.average_ask_price = base / quote * self.price['BTS'] def get_orderbook(self): """ Функция получает ордера из пары self.sett['quote'] / BTS """ orderbook = self.quote_market.orderbook( limit=self.sett['orderbook_limit'] ) self.create_bids(orderbook['bids']) self.create_asks(orderbook['asks']) def get_usdt_orderbook(self): """ Функция для проверки ордеров в стаканах пар указанные в параметре self.sett['usdt_assets'] Функция получает из сети BitShares данные из всех стаканов указанных в параметре self.sett['usdt_assets'] и формирует выборку на основе этих данных. Результаты ее работы сохраняются в переменных класса self.bids и self.asks """ for asset in self.sett['usdt_assets']: market = Market(self.sett['quote'] + ':' + asset) book = market.orderbook( limit=self.sett['orderbook_limit'] ) for bid in book['bids']: amount = bid['base']['amount'] bid = Order( bid['quote'], Amount(amount / self.price['BTS'], 'BTS') ) if not self.create_bids([bid]): break for ask in book['asks']: amount = ask['base']['amount'] ask = Order( ask['quote'], Amount(amount / self.price['BTS'], 'BTS') ) if not self.create_asks([ask]): break def sortByTime(self, input): """ Вспомогательная функция для сортировки """ return input['time']