Esempio n. 1
0
	def refresh_iexc_index():
		try:
			stockSymbols = get_symbols(token=os.environ["IEXC_KEY"])
			for index, stock in stockSymbols.iterrows():
				if stock["exchange"] not in TickerParserServer.exchanges:
					TickerParserServer.exchanges[stock["exchange"]] = Exchange(stock["exchange"])
				tickerId = stock["symbol"] if stock["iexId"] is None else stock["iexId"]
				TickerParserServer.iexcStocksIndex[stock["symbol"]] = {"id": tickerId, "name": stock["name"], "base": stock["symbol"], "quote": stock["currency"], "exchange": stock["exchange"]}
				TickerParserServer.exchanges[stock["exchange"]].properties.symbols.append(stock["symbol"])
			
			forexSymbols = requests.get("https://cloud.iexapis.com/stable/ref-data/fx/symbols?token={}".format(os.environ["IEXC_KEY"])).json()
			derivedCurrencies = set()
			for pair in forexSymbols["pairs"]:
				derivedCurrencies.add(pair["fromCurrency"])
				derivedCurrencies.add(pair["toCurrency"])
				TickerParserServer.iexcForexIndex[pair["symbol"]] = {"id": pair["symbol"], "name": pair["symbol"], "base": pair["fromCurrency"], "quote": pair["toCurrency"], "reversed": False}
				TickerParserServer.iexcForexIndex[pair["toCurrency"] + pair["fromCurrency"]] = {"id": pair["symbol"], "name": pair["toCurrency"] + pair["fromCurrency"], "base": pair["toCurrency"], "quote": pair["fromCurrency"], "reversed": True}
			for fromCurrency in derivedCurrencies:
				for toCurrency in derivedCurrencies:
					symbol = fromCurrency + toCurrency
					if fromCurrency != toCurrency and symbol not in TickerParserServer.iexcForexIndex:
						TickerParserServer.iexcForexIndex[symbol] = {"id": symbol, "name": symbol, "base": fromCurrency, "quote": toCurrency, "reversed": False}

			otcSymbols = requests.get("https://cloud.iexapis.com/stable/ref-data/otc/symbols?token={}".format(os.environ["IEXC_KEY"])).json()
			for stock in otcSymbols:
				if stock["exchange"] not in TickerParserServer.exchanges:
					TickerParserServer.exchanges[stock["exchange"]] = Exchange(stock["exchange"])
				tickerId = stock["symbol"] if stock["iexId"] is None else stock["iexId"]
				TickerParserServer.iexcOtcIndex[stock["symbol"]] = {"id": tickerId, "name": stock["name"], "base": stock["symbol"], "quote": stock["currency"], "exchange": stock["exchange"]}

		except Exception:
			print(traceback.format_exc())
Esempio n. 2
0
    def request_ccxt_depth(self, request):
        ticker = request.get_ticker()
        exchange = request.get_exchange()

        imageStyle = request.get_image_style()
        forceMode = "force" in imageStyle and request.authorId == 361916376069439490
        uploadMode = "upload" in imageStyle and request.authorId == 361916376069439490

        try:
            if exchange is None: return None, None
            exchange = Exchange(exchange.id, "crypto")

            try:
                depthData = exchange.properties.fetch_order_book(ticker.symbol)
                bestBid = depthData["bids"][0]
                bestAsk = depthData["asks"][0]
                lastPrice = (bestBid[0] + bestAsk[0]) / 2
            except:
                return None, None

            imageData = self.generate_depth_image(depthData, bestBid, bestAsk,
                                                  lastPrice)
            if uploadMode:
                bucket.blob("uploads/{}.png".format(int(
                    time.time() * 1000))).upload_from_string(
                        base64.decodebytes(imageData))

            return imageData, None
        except Exception:
            print(traceback.format_exc())
            if os.environ["PRODUCTION_MODE"]:
                self.logging.report_exception(user=ticker.id)
            return None, None
Esempio n. 3
0
	def request_ccxt_candles(self, request):
		ticker = request.get_ticker()
		exchange = request.get_exchange()

		try:
			if exchange is None: return None, None
			exchange = Exchange(exchange.id, "crypto")

			try:
				rawData = exchange.properties.fetch_ohlcv(ticker.symbol, timeframe="1m", limit=3)
				if len(rawData) == 0 or rawData[-1][4] is None or rawData[0][1] is None: return None, None
			except:
				return None, None

			payload = {
				"candles": [],
				"title": ticker.name,
				"baseTicker": "USD" if ticker.base in CandleProcessor.stableCoinTickers else ticker.base,
				"quoteTicker": "USD" if ticker.quote in CandleProcessor.stableCoinTickers else ticker.quote,
				"sourceText": "on {}".format(exchange.name),
				"platform": "CCXT"
			}

			for e in rawData:
				timestamp = e[0] / 1000
				if ticker.isReversed:
					payload["candles"].append([timestamp, 1 / e[1], 1 / e[2], 1 / e[3], 1 / e[4]])
				else:
					payload["candles"].append([timestamp, e[1], e[2], e[3], e[4]])

			return payload, None
		except Exception:
			print(traceback.format_exc())
			if os.environ["PRODUCTION_MODE"]: self.logging.report_exception(user=ticker.id)
			return None, None
Esempio n. 4
0
	def refresh_ccxt_index(self):
		difference = set(ccxt.exchanges).symmetric_difference(supported.ccxtExchanges)
		newExchanges = []
		newSupportedExchanges = []
		unsupportedCryptoExchanges = []
		for e in difference:
			try:
				ex = getattr(ccxt, e)()
			except:
				unsupportedCryptoExchanges.append(e)
				continue
			if e not in supported.ccxtExchanges:
				if ex.has['fetchOHLCV'] != False and ex.has['fetchOrderBook'] != False and ex.timeframes is not None and len(ex.timeframes) != 0: newSupportedExchanges.append(e)
				else: newExchanges.append(e)
		if len(newSupportedExchanges) != 0: print("New supported CCXT exchanges: {}".format(newSupportedExchanges))
		if len(newExchanges) != 0: print("New partially unsupported CCXT exchanges: {}".format(newExchanges))
		if len(unsupportedCryptoExchanges) != 0: print("New deprecated CCXT exchanges: {}".format(unsupportedCryptoExchanges))

		completedTasks = set()
		sortedIndexReference = {}

		for platform in supported.cryptoExchanges:
			if platform not in sortedIndexReference: sortedIndexReference[platform] = {}
			for exchange in supported.cryptoExchanges[platform]:
				if exchange not in completedTasks:
					if exchange not in self.exchanges: self.exchanges[exchange] = Exchange(exchange, "crypto" if exchange in ccxt.exchanges else "traditional")
					try: self.exchanges[exchange].properties.load_markets()
					except: continue
					completedTasks.add(exchange)

				for symbol in self.exchanges[exchange].properties.symbols:
					if '.' not in symbol and (self.exchanges[exchange].properties.markets[symbol].get("active") is None or self.exchanges[exchange].properties.markets[symbol].get("active")):
						base = self.exchanges[exchange].properties.markets[symbol]["base"]
						quote = self.exchanges[exchange].properties.markets[symbol]["quote"]
						marketPair = symbol.split("/")

						if base != marketPair[0] or quote != marketPair[-1]:
							if marketPair[0] != marketPair[-1]: base, quote = marketPair[0], marketPair[-1]
							else: continue

						isIdentifiable = quote in self.coinGeckoIndex and self.coinGeckoIndex[quote]["market_cap_rank"] is not None

						if base not in sortedIndexReference[platform]:
							sortedIndexReference[platform][base] = {}
						if quote not in sortedIndexReference[platform][base]:
							if isIdentifiable:
								sortedIndexReference[platform][base][quote] = self.coinGeckoIndex[quote]["market_cap_rank"]
							else:
								sortedIndexReference[platform][base][quote] = MAXSIZE

		for platform in sortedIndexReference:
			self.ccxtIndex[platform] = {}
			for base in sortedIndexReference[platform]:
				if base not in self.ccxtIndex[platform]: self.ccxtIndex[platform][base] = []
				self.ccxtIndex[platform][base] = sorted(sortedIndexReference[platform][base].keys(), key=lambda quote: sortedIndexReference[platform][base][quote])
				try: self.ccxtIndex[platform][base].insert(0, self.ccxtIndex[platform][base].pop(self.ccxtIndex[platform][base].index("USDT")))
				except: pass
				try: self.ccxtIndex[platform][base].insert(0, self.ccxtIndex[platform][base].pop(self.ccxtIndex[platform][base].index("USD")))
				except: pass
Esempio n. 5
0
	def request_ccxt_quote(self, request):
		ticker = request.get_ticker()
		exchange = request.get_exchange()

		try:
			if exchange is None: return None, None
			exchange = Exchange(exchange.id)

			tf, limitTimestamp, candleOffset = Utils.get_highest_supported_timeframe(exchange.properties, datetime.datetime.now().astimezone(pytz.utc))
			try:
				rawData = exchange.properties.fetch_ohlcv(ticker.symbol, timeframe=tf.lower(), since=limitTimestamp, limit=300)
				if len(rawData) == 0 or rawData[-1][4] is None or rawData[0][1] is None: return None, None
			except:
				print(traceback.format_exc())
				return None, None

			price = [rawData[-1][4], rawData[0][1]] if len(rawData) < candleOffset else [rawData[-1][4], rawData[-candleOffset][1]]
			if ticker.isReversed: price = [1 / price[0], 1 / price[1]]
			volume = None if price[0] is None else sum([candle[5] for candle in rawData if int(candle[0] / 1000) >= int(exchange.properties.milliseconds() / 1000) - 86400]) / (price[0] if exchange.id in ["bitmex", "binancefutures"] else 1)
			priceChange = 0 if tf == "1m" or price[1] == 0 else (price[0] / price[1]) * 100 - 100

			payload = {
				"quotePrice": "{:,.8f}".format(price[0]) if ticker.isReversed else Utils.format_price(exchange.properties, ticker.symbol, price[0]),
				"quoteVolume": volume,
				"quoteConvertedPrice": "≈ ${:,.6f}".format(price[0] * self.lastBitcoinQuote["quotePrice"][0]) if ticker.quote == "BTC" else None,
				"quoteConvertedVolume": "≈ ${:,.4f}".format(volume * self.lastBitcoinQuote["quotePrice"][0]) if ticker.quote == "BTC" else None,
				"title": ticker.name,
				"baseTicker": "USD" if ticker.base in QuoteProcessor.stableCoinTickers else ticker.base,
				"quoteTicker": "USD" if ticker.quote in QuoteProcessor.stableCoinTickers else ticker.quote,
				"change": priceChange,
				"thumbnailUrl": TickerParser.get_coingecko_image(ticker.base),
				"messageColor": "amber" if priceChange == 0 else ("green" if priceChange > 0 else "red"),
				"sourceText": "on {}".format(exchange.name),
				"platform": "CCXT",
				"raw": {
					"quotePrice": [price[0]] if tf == "1m" else price[:1],
					"quoteVolume": volume,
					"ticker": ticker,
					"exchange": exchange,
					"timestamp": time.time()
				}
			}
			return payload, None
		except Exception:
			print(traceback.format_exc())
			if os.environ["PRODUCTION_MODE"]: self.logging.report_exception()
			return None, None
Esempio n. 6
0
    def request_ccxt_depth(self, request):
        ticker = request.get_ticker()
        exchange = request.get_exchange()

        try:
            if exchange is None: return None, None
            exchange = Exchange(exchange.id)

            try:
                depthData = exchange.properties.fetch_order_book(ticker.symbol)
                bestBid = depthData["bids"][0]
                bestAsk = depthData["asks"][0]
                lastPrice = (bestBid[0] + bestAsk[0]) / 2
            except:
                return None, None

            imageData = self.generate_depth_image(depthData, bestBid, bestAsk,
                                                  lastPrice)

            return imageData, None
        except Exception:
            print(traceback.format_exc())
            if os.environ["PRODUCTION_MODE"]: self.logging.report_exception()
            return None, None
Esempio n. 7
0
	def refresh_iexc_index(self):
		try:
			def get_url(url):
				while True:
					try:
						return get(url).json()
					except:
						print(format_exc())
						sleep(10)


			iexcExchanges = set()
			exchanges = get_url("https://cloud.iexapis.com/stable/ref-data/market/us/exchanges?token={}".format(environ["IEXC_KEY"]))
			suffixMap = {}

			for exchange in exchanges:
				if exchange["refId"] == "": continue
				exchangeId = exchange["refId"]
				iexcExchanges.add(exchangeId.lower())
				self.exchanges[exchangeId.lower()] = Exchange(exchangeId, "traditional", exchange["longName"], region="us")
			exchanges = get_url("https://cloud.iexapis.com/stable/ref-data/exchanges?token={}".format(environ["IEXC_KEY"]))
			for exchange in exchanges:
				exchangeId = exchange["exchange"].replace("Euronext Euronext", "Euronext")
				if exchangeId.lower() in iexcExchanges: continue
				iexcExchanges.add(exchangeId.lower())
				self.exchanges[exchangeId.lower()] = Exchange(exchangeId, "traditional", exchange["description"], region=exchange["region"])
				suffixMap[exchangeId.lower()] = exchange["exchangeSuffix"]

			difference = set(iexcExchanges).symmetric_difference(supported.iexcExchanges)
			newSupportedExchanges = []
			unsupportedCryptoExchanges = []
			for exchangeId in difference:
				if exchangeId not in supported.iexcExchanges:
					newSupportedExchanges.append(exchangeId)
				else:
					unsupportedCryptoExchanges.append(exchangeId)
			if len(newSupportedExchanges) != 0: print("New supported IEXC exchanges: {}".format(newSupportedExchanges))
			if len(unsupportedCryptoExchanges) != 0: print("New deprecated IEXC exchanges: {}".format(unsupportedCryptoExchanges))

			for exchangeId in supported.traditionalExchanges["IEXC"]:
				symbols = get_url("https://cloud.iexapis.com/stable/ref-data/exchange/{}/symbols?token={}".format(self.exchanges[exchangeId].id, environ["IEXC_KEY"]))
				if len(symbols) == 0: print("No symbols found on {}".format(exchangeId))
				for symbol in symbols:
					suffix = suffixMap.get(exchangeId, "")
					tickerId = symbol["symbol"]
					if tickerId not in self.iexcStocksIndex:
						self.iexcStocksIndex[tickerId] = {"id": tickerId.removesuffix(suffix), "name": symbol["name"], "base": tickerId.removesuffix(suffix), "quote": symbol["currency"]}
					self.exchanges[exchangeId].properties.symbols.append(tickerId)

			forexSymbols = get_url("https://cloud.iexapis.com/stable/ref-data/fx/symbols?token={}".format(environ["IEXC_KEY"]))
			derivedCurrencies = set()
			for pair in forexSymbols["pairs"]:
				derivedCurrencies.add(pair["fromCurrency"])
				derivedCurrencies.add(pair["toCurrency"])
				self.iexcForexIndex[pair["symbol"]] = {"id": pair["symbol"], "name": pair["symbol"], "base": pair["fromCurrency"], "quote": pair["toCurrency"], "reversed": False}
				self.iexcForexIndex[pair["toCurrency"] + pair["fromCurrency"]] = {"id": pair["symbol"], "name": pair["toCurrency"] + pair["fromCurrency"], "base": pair["toCurrency"], "quote": pair["fromCurrency"], "reversed": True}
			for fromCurrency in derivedCurrencies:
				for toCurrency in derivedCurrencies:
					symbol = fromCurrency + toCurrency
					if fromCurrency != toCurrency and symbol not in self.iexcForexIndex:
						self.iexcForexIndex[symbol] = {"id": symbol, "name": symbol, "base": fromCurrency, "quote": toCurrency, "reversed": False}

		except Exception:
			print(format_exc())
Esempio n. 8
0
    def request_lld_quote(self, request):
        ticker = request.get_ticker()
        exchange = request.get_exchange()
        filters = request.get_filters()
        action = request.find_parameter_in_list("lld", filters)

        try:
            if exchange is not None: exchange = Exchange(exchange.id, "crypto")

            if action == "funding":
                if exchange.id in ["bitmex"]:
                    try:
                        rawData = exchange.properties.public_get_instrument(
                            {"symbol": ticker.id})[0]
                    except:
                        return None, "Requested funding data for `{}` is not available.".format(
                            ticker.name)

                    if rawData["fundingTimestamp"] is not None:
                        fundingDate = datetime.datetime.strptime(
                            rawData["fundingTimestamp"],
                            "%Y-%m-%dT%H:%M:00.000Z").replace(tzinfo=pytz.utc)
                    else:
                        fundingDate = datetime.datetime.now().replace(
                            tzinfo=pytz.utc)
                    indicativeFundingTimestamp = datetime.datetime.timestamp(
                        fundingDate) + 28800
                    indicativeFundingDate = datetime.datetime.utcfromtimestamp(
                        indicativeFundingTimestamp).replace(tzinfo=pytz.utc)
                    deltaFunding = fundingDate - datetime.datetime.now(
                    ).astimezone(pytz.utc)
                    deltaIndicative = indicativeFundingDate - datetime.datetime.now(
                    ).astimezone(pytz.utc)

                    hours1, seconds1 = divmod(
                        deltaFunding.days * 86400 + deltaFunding.seconds, 3600)
                    minutes1 = int(seconds1 / 60)
                    hoursFunding = "{:d} {} ".format(
                        hours1, "hours"
                        if hours1 > 1 else "hour") if hours1 > 0 else ""
                    minutesFunding = "{:d} {}".format(
                        minutes1 if hours1 > 0 or minutes1 > 0 else seconds1,
                        "{}".format("minute" if minutes1 == 1 else "minutes")
                        if hours1 > 0 or minutes1 > 0 else
                        ("second" if seconds1 == 1 else "seconds"))
                    deltaFundingText = "{}{}".format(hoursFunding,
                                                     minutesFunding)

                    hours2, seconds2 = divmod(
                        deltaIndicative.days * 86400 + deltaIndicative.seconds,
                        3600)
                    minutes2 = int(seconds2 / 60)
                    hoursIndicative = "{:d} {} ".format(
                        hours2, "hours"
                        if hours2 > 1 else "hour") if hours2 > 0 else ""
                    minutesIndicative = "{:d} {}".format(
                        minutes2 if hours2 > 0 or minutes2 > 0 else seconds2,
                        "{}".format("minute" if minutes2 == 1 else "minutes")
                        if hours2 > 0 or minutes2 > 0 else
                        ("second" if seconds2 == 1 else "seconds"))
                    deltaIndicativeText = "{}{}".format(
                        hoursIndicative, minutesIndicative)

                    fundingRate = float(rawData["fundingRate"]) * 100
                    predictedFundingRate = float(
                        rawData["indicativeFundingRate"]) * 100
                    averageFundingRate = (fundingRate +
                                          predictedFundingRate) / 2

                    payload = {
                        "quotePrice":
                        "Funding Rate: {:+.4f} % *(in {})*\nPredicted Rate: {:+.4f} % *(in {})*"
                        .format(fundingRate, deltaFundingText,
                                predictedFundingRate, deltaIndicativeText),
                        "title":
                        ticker.name,
                        "baseTicker":
                        ticker.base,
                        "quoteTicker":
                        ticker.quote,
                        "thumbnailUrl":
                        TickerParser.get_coingecko_image(ticker.base),
                        "messageColor":
                        "yellow" if averageFundingRate == 0.01 else
                        ("light green"
                         if averageFundingRate < 0.01 else "deep orange"),
                        "sourceText":
                        "Contract details on {}".format(exchange.name),
                        "platform":
                        "LLD",
                        "raw": {
                            "quotePrice": [fundingRate, predictedFundingRate],
                            "ticker": ticker,
                            "exchange": exchange,
                            "timestamp": time.time()
                        }
                    }
                    return payload, None
                return None, "Funding data is only available on BitMEX."
            elif action == "oi":
                if exchange.id in ["bitmex"]:
                    try:
                        rawData = exchange.properties.public_get_instrument(
                            {"symbol": ticker.id})[0]
                    except:
                        return None, "Requested open interest data for `{}` is not available.".format(
                            ticker.name)

                    payload = {
                        "quotePrice":
                        "Open interest: {:,.0f} {}\nOpen value: {:,.4f} XBT".
                        format(float(rawData["openInterest"]),
                               "USD" if ticker.id == "XBTUSD" else "contracts",
                               float(rawData["openValue"]) / 100000000),
                        "title":
                        ticker.name,
                        "baseTicker":
                        ticker.base,
                        "quoteTicker":
                        ticker.quote,
                        "thumbnailUrl":
                        TickerParser.get_coingecko_image(ticker.base),
                        "messageColor":
                        "deep purple",
                        "sourceText":
                        "Contract details on {}".format(exchange.name),
                        "platform":
                        "LLD",
                        "raw": {
                            "quotePrice": [
                                float(rawData["openInterest"]),
                                float(rawData["openValue"]) / 100000000
                            ],
                            "ticker":
                            ticker,
                            "exchange":
                            exchange,
                            "timestamp":
                            time.time()
                        }
                    }
                    return payload, None
                return None, "Open interest and open value data is only available on BitMEX."
            elif action == "ls":
                if exchange.id in ["bitfinex2"]:
                    try:
                        longs = exchange.properties.publicGetStats1KeySizeSymbolLongLast(
                            {
                                "key": "pos.size",
                                "size": "1m",
                                "symbol": "t{}".format(ticker.id),
                                "side": "long",
                                "section": "last"
                            })
                        shorts = exchange.properties.publicGetStats1KeySizeSymbolShortLast(
                            {
                                "key": "pos.size",
                                "size": "1m",
                                "symbol": "t{}".format(ticker.id),
                                "side": "long",
                                "section": "last"
                            })
                        ratio = longs[1] / (longs[1] + shorts[1]) * 100
                    except:
                        return None, None

                    payload = {
                        "quotePrice":
                        "{:.1f} % longs / {:.1f} % shorts".format(
                            ratio, 100 - ratio),
                        "title":
                        "{} longs/shorts ratio".format(ticker.name),
                        "baseTicker":
                        ticker.base,
                        "quoteTicker":
                        ticker.quote,
                        "thumbnailUrl":
                        TickerParser.get_coingecko_image(ticker.base),
                        "messageColor":
                        "deep purple",
                        "sourceText":
                        "Data on {}".format(exchange.name),
                        "platform":
                        "LLD",
                        "raw": {
                            "quotePrice": [longs[1], shorts[1]],
                            "ticker": ticker,
                            "exchange": exchange,
                            "timestamp": time.time()
                        }
                    }
                    return payload, None
                return None, "Longs and shorts data is only available on Bitfinex."
            elif action == "sl":
                if exchange.id in ["bitfinex2"]:
                    try:
                        longs = exchange.properties.publicGetStats1KeySizeSymbolLongLast(
                            {
                                "key": "pos.size",
                                "size": "1m",
                                "symbol": "t{}".format(ticker.id),
                                "side": "short",
                                "section": "last"
                            })
                        shorts = exchange.properties.publicGetStats1KeySizeSymbolShortLast(
                            {
                                "key": "pos.size",
                                "size": "1m",
                                "symbol": "t{}".format(ticker.id),
                                "side": "short",
                                "section": "last"
                            })
                        ratio = shorts[1] / (longs[1] + shorts[1]) * 100
                    except:
                        return None, None

                    payload = {
                        "quotePrice":
                        "{:.1f} % shorts / {:.1f} % longs".format(
                            ratio, 100 - ratio),
                        "title":
                        "{} shorts/longs ratio".format(ticker.name),
                        "baseTicker":
                        ticker.base,
                        "quoteTicker":
                        ticker.quote,
                        "thumbnailUrl":
                        TickerParser.get_coingecko_image(ticker.base),
                        "messageColor":
                        "deep purple",
                        "sourceText":
                        "Data on {}".format(exchange.name),
                        "platform":
                        "LLD",
                        "raw": {
                            "quotePrice": [longs[1], shorts[1]],
                            "ticker": ticker,
                            "exchange": exchange,
                            "timestamp": time.time()
                        }
                    }
                    return payload, None
                return None, "Longs and shorts data is only available on Bitfinex."
            elif action == "dom":
                try:
                    rawData = self.coinGecko.get_global()
                except:
                    return None, "Requested dominance data for `{}` is not available.".format(
                        ticker.name)
                if ticker.base.lower() not in rawData["market_cap_percentage"]:
                    return None, "Dominance for {} does not exist.".format(
                        ticker.base)
                coinDominance = rawData["market_cap_percentage"][
                    ticker.base.lower()]

                payload = {
                    "quotePrice":
                    "{} dominance: {:,.2f} %".format(ticker.base,
                                                     coinDominance),
                    "title":
                    "Market Dominance",
                    "baseTicker":
                    ticker.base,
                    "quoteTicker":
                    ticker.quote,
                    "thumbnailUrl":
                    TickerParser.get_coingecko_image(ticker.base),
                    "messageColor":
                    "deep purple",
                    "sourceText":
                    "Market information from CoinGecko",
                    "platform":
                    "LLD",
                    "raw": {
                        "quotePrice": coinDominance,
                        "ticker": ticker,
                        "timestamp": time.time()
                    }
                }
                return payload, None
            else:
                return None, None
        except Exception:
            print(traceback.format_exc())
            if os.environ["PRODUCTION_MODE"]:
                self.logging.report_exception(user=ticker.id)
            return None, None
Esempio n. 9
0
	def request_depth_visualization(self, request):
		ticker = request.get_ticker()
		exchange = request.get_exchange()

		try:
			if exchange is None: return None, "Data for {} isn't available.".format(ticker.name)
			exchange = Exchange(exchange.id)

			try:
				depthData = exchange.properties.fetch_order_book(ticker.symbol)
				bestBid = depthData["bids"][0]
				bestAsk = depthData["asks"][0]
				lastPrice = (bestBid[0] + bestAsk[0]) / 2
			except:
				return None, None

			bidTotal = 0
			xBids = [bestBid[0]]
			yBids = [0]
			for bid in depthData['bids']:
				if len(xBids) < 10 or bid[0] > lastPrice * 0.9:
					bidTotal += bid[1]
					xBids.append(bid[0])
					yBids.append(bidTotal)

			askTotal = 0
			xAsks = [bestAsk[0]]
			yAsks = [0]
			for ask in depthData['asks']:
				if len(xAsks) < 10 or ask[0] < lastPrice * 1.1:
					askTotal += ask[1]
					xAsks.append(ask[0])
					yAsks.append(askTotal)

			fig = plt.figure(facecolor="#131722")
			ax = fig.add_subplot(1, 1, 1)
			ax.tick_params(color="#787878", labelcolor="#D9D9D9")
			ax.step(xBids, yBids, where="post", color="#27A59A")
			ax.step(xAsks, yAsks, where="post", color="#EF534F")
			ax.fill_between(xBids, yBids, 0, facecolor="#27A59A", interpolate=True, step="post", alpha=0.33, zorder=2)
			ax.fill_between(xAsks, yAsks, 0, facecolor="#EF534F", interpolate=True, step="post", alpha=0.33, zorder=2)
			plt.axvline(x=lastPrice, color="#758696", linestyle="--")

			ax.set_facecolor("#131722")
			for spine in ax.spines.values():
				spine.set_edgecolor("#787878")
			ax.autoscale(enable=True, axis="both", tight=True)

			def on_draw(event):
				bboxes = []
				for label in ax.get_yticklabels():
					bbox = label.get_window_extent()
					bboxi = bbox.transformed(fig.transFigure.inverted())
					bboxes.append(bboxi)

				bbox = mtransforms.Bbox.union(bboxes)
				if fig.subplotpars.left < bbox.width:
					fig.subplots_adjust(left=1.1 * bbox.width)
					fig.canvas.draw()
				return False

			ax.yaxis.set_major_formatter(tkr.FuncFormatter(lambda x, p: format(int(x), ',')))
			plt.setp(ax.get_xticklabels(), rotation=45, horizontalalignment='right')
			lastPriceLabel = bestAsk[0] if bestAsk[1] >= bestBid[1] else bestBid[0]
			xLabels = list(plt.xticks()[0][1:])
			yLabels = list(plt.yticks()[0][1:])
			for label in xLabels:
				plt.axvline(x=label, color="#363C4F", linewidth=1, zorder=1)
			for label in yLabels:
				plt.axhline(y=label, color="#363C4F", linewidth=1, zorder=1)
			diffLabels = 1 - xLabels[0] / xLabels[1]
			bottomBound, topBound = lastPriceLabel * (1 - diffLabels * (1/4)), lastPriceLabel * (1 + diffLabels * (1/4))
			xLabels = [l for l in xLabels if not (bottomBound <= l <= topBound)]

			plt.xticks(xLabels + [lastPriceLabel])
			plt.yticks(yLabels)
			ax.set_xlim([xBids[-1], xAsks[-1]])
			ax.set_ylim([0, max(bidTotal, askTotal)])

			fig.canvas.mpl_connect("draw_event", on_draw)
			plt.tight_layout()

			rawImageData = BytesIO()
			plt.savefig(rawImageData, format="png", edgecolor="none")
			rawImageData.seek(0)

			imageBuffer = BytesIO()
			chartImage = Image.new("RGBA", (1600, 1200))
			chartImage.paste(Image.open(rawImageData))
			chartImage = Image.alpha_composite(chartImage, self.imageOverlays["Alpha depth"])
			chartImage.save(imageBuffer, format="png")
			imageData = base64.b64encode(imageBuffer.getvalue())
			imageBuffer.close()

			return imageData, None
		except Exception:
			print(traceback.format_exc())
			if os.environ["PRODUCTION_MODE"]: self.logging.report_exception()
			return None, None