コード例 #1
0
    def request_candles(cls, request):
        ticker = request.get("ticker")
        exchange = Exchange.from_dict(ticker.get("exchange"))

        if exchange is None: return [{}, ""]

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

        payload = {
            "candles": [],
            "title": ticker.get("name"),
            "sourceText": "Data from {}".format(exchange.name),
            "platform": "CCXT"
        }

        for e in rawData:
            timestamp = e[0] / 1000
            if ticker.get("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, ""]
コード例 #2
0
	def _request_depth(cls, request, ticker):
		exchange = Exchange.from_dict(ticker.get("exchange"))

		preferences = request.get("preferences")
		forceMode = {"id": "force", "value": "force"} in preferences
		uploadMode = {"id": "upload", "value": "upload"} in preferences

		if exchange is None: return [{}, ""]

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

		imageBuffer = BytesIO()
		chartImage = Image.new("RGBA", (1600, 1200))
		chartImage.paste(CCXT._generate_depth_image(depthData, bestBid, bestAsk, lastPrice))
		chartImage = Image.alpha_composite(chartImage, CCXT.chartOverlay["normal"])
		chartImage.save(imageBuffer, format="png")
		imageData = b64encode(imageBuffer.getvalue())
		imageBuffer.close()
		# if uploadMode:
		# 	bucket.blob("uploads/{}.png".format(int(time() * 1000))).upload_from_string(decodebytes(imageData))

		payload = {
			"data": imageData.decode(),
			"platform": "CCXT"
		}

		return [payload, ""]
コード例 #3
0
    def _request_forex(cls, request, ticker):
        exchange = Exchange.from_dict(ticker.get("exchange"))

        try:
            if exchange is not None: return [{}, ""]
            rawData = get(
                "https://cloud.iexapis.com/stable/fx/latest?symbols={}&token={}"
                .format(ticker.get("id"), environ["IEXC_KEY"])).json()
            if rawData is None or type(rawData) is not list or len(
                    rawData) == 0:
                return [{}, ""]
        except:
            return [{}, ""]

        price = rawData[0]["rate"]
        if price is None: return [{}, ""]
        if ticker.get("isReversed"): price = 1 / price

        payload = {
            "quotePrice": "{:,.5f} {}".format(price, ticker.get("quote")),
            "title": ticker.get("name"),
            "thumbnailUrl": static_storage.icon,
            "messageColor": "deep purple",
            "sourceText": "Data provided by IEX Cloud",
            "platform": "IEXC",
            "raw": {
                "quotePrice": [price],
                "timestamp": time()
            }
        }
        return [payload, ""]
コード例 #4
0
    def _request_depth(cls, request, ticker):
        exchange = Exchange.from_dict(ticker.get("exchange"))

        preferences = request.get("preferences")
        forceMode = {"id": "force", "value": "force"} in preferences
        uploadMode = {"id": "upload", "value": "upload"} in preferences

        try:
            stock = Stock(ticker.get("symbol"), token=environ["IEXC_KEY"])
            depthData = stock.get_book()[ticker.get("symbol")]
            rawData = stock.get_quote().loc[ticker.get("symbol")]
            if ticker.get("quote") is None and exchange is not None:
                return [
                    {},
                    "Orderbook visualization for `{}` is not available on {}.".
                    format(ticker.get("name"), exchange.get("name"))
                ]
            lastPrice = (depthData["bids"][0]["price"] +
                         depthData["asks"][0]["price"]) / 2
            depthData = {
                "bids": [[e.get("price"), e.get("size")]
                         for e in depthData["bids"]
                         if e.get("price") >= lastPrice * 0.75],
                "asks": [[e.get("price"), e.get("size")]
                         for e in depthData["asks"]
                         if e.get("price") <= lastPrice * 1.25]
            }
            bestBid = depthData["bids"][0]
            bestAsk = depthData["asks"][0]
        except:
            return [{}, ""]

        imageBuffer = BytesIO()
        chartImage = Image.new("RGBA", (1600, 1200))
        chartImage.paste(
            IEXC._generate_depth_image(depthData, bestBid, bestAsk, lastPrice))
        chartImage = Image.alpha_composite(chartImage,
                                           IEXC.chartOverlay["normal"])
        chartImage.save(imageBuffer, format="png")
        imageData = b64encode(imageBuffer.getvalue())
        imageBuffer.close()
        # if uploadMode:
        # 	bucket.blob("uploads/{}.png".format(int(time() * 1000))).upload_from_string(decodebytes(imageData))

        payload = {"data": imageData.decode(), "platform": "IEXC"}

        return [payload, ""]
コード例 #5
0
	def request_candles(cls, request):
		ticker = request.get("ticker")
		exchange = Exchange.from_dict(ticker.get("exchange"))

		try:
			stock = Stock(ticker.get("id"), token=environ["IEXC_KEY"])
			rawData = stock.get_intraday_prices(chartLast=3)
			if len(rawData) == 0: return [{}, ""]
			if ticker.get("quote") is None and exchange is not None: return [{}, "Price for `{}` is not available on {}.".format(ticker.get("name"), exchange.get("name"))]
		except:
			return [{}, ""]

		payload = {
			"candles": [],
			"title": ticker.get("name"),
			"sourceText": "Data provided by IEX Cloud",
			"platform": "IEXC"
		}

		for index, e in rawData.iterrows():
			parsedDatetime = None
			try: parsedDatetime = datetime.strptime(index, "%Y-%m-%d %I:%M %p")
			except: pass
			try: parsedDatetime = datetime.strptime(index, "%Y-%m-%d %I %p")
			except: pass
			try: parsedDatetime = datetime.strptime(index, "%Y-%m-%d None")
			except: pass

			if parsedDatetime is None:
				raise Exception("timestamp formatting mismatch: {}".format(index))

			timestamp = timezone('US/Eastern').localize(parsedDatetime, is_dst=None).timestamp()

			if ticker.get("isReversed"):
				if "marketClose" in e:
					payload["candles"].append([timestamp, 1 / e.marketOpen, 1 / e.marketHigh, 1 / e.marketLow, 1 / e.marketClose])
				else:
					payload["candles"].append([timestamp, 1 / e.open, 1 / e.high, 1 / e.low, 1 / e.close])
			else:
				if "marketClose" in e:
					payload["candles"].append([timestamp, e.marketOpen, e.marketHigh, e.marketLow, e.marketClose])
				else:
					payload["candles"].append([timestamp, e.open, e.high, e.low, e.close])

		return [payload, ""]
コード例 #6
0
	def _request_quote(cls, request, ticker):
		exchange = Exchange.from_dict(ticker.get("exchange"))

		if exchange is None: return [{}, ""]

		tf, limitTimestamp, candleOffset = CCXT.get_highest_supported_timeframe(exchange.properties, datetime.now().astimezone(utc))
		try:
			rawData = exchange.properties.fetch_ohlcv(ticker.get("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 [{}, ""]
		except:
			return [{}, ""]

		price = [rawData[-1][4], rawData[0][1]] if len(rawData) < candleOffset else [rawData[-1][4], rawData[-candleOffset][1]]
		if ticker.get("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 == "bitmex" else 1)
		priceChange = 0 if tf == "1m" or price[1] == 0 else (price[0] / price[1]) * 100 - 100
		coinThumbnail = static_storage.icon if ticker.get("image") is None else ticker.get("image")

		base = "USD" if ticker.get("base") in AbstractProvider.stableCoinTickers else ticker.get("base")
		quote = "USD" if ticker.get("quote") in AbstractProvider.stableCoinTickers else ticker.get("quote")
		payload = {
			"quotePrice": "{:,.10f}".format(price[0]).rstrip('0').rstrip('.') + " " + quote,
			"quoteVolume": "{:,.4f}".format(volume).rstrip('0').rstrip('.') + " " + base,
			"title": ticker.get("name"),
			"change": "{:+.2f} %".format(priceChange),
			"thumbnailUrl": coinThumbnail,
			"messageColor": "amber" if priceChange == 0 else ("green" if priceChange > 0 else "red"),
			"sourceText": "Data from {}".format(exchange.name),
			"platform": CCXT.name,
			"raw": {
				"quotePrice": [price[0]] if tf == "1m" else price[:1],
				"quoteVolume": [volume],
				"timestamp": time()
			}
		}
		if ticker.get("quote") == "BTC":
			payload["quoteConvertedPrice"] = "≈ ${:,.6f}".format(price[0] * CoinGecko.lastBitcoinQuote)
			payload["quoteConvertedVolume"] = "≈ ${:,.4f}".format(volume * CoinGecko.lastBitcoinQuote)

		return [payload, ""]
コード例 #7
0
	def request_lld(cls, request):
		ticker = request.get("ticker")
		exchange = Exchange.from_dict(ticker.get("exchange"))
		preferences = request.get("preferences")
		action = [e.get("value") for e in preferences if e.get("id") == "lld"]
		if len(action) == 0: return [{}, ""]
		action = action[0]

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

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

				coinThumbnail = static_storage.icon if ticker.get("image") is None else ticker.get("image")

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

				coinThumbnail = static_storage.icon if ticker.get("image") is None else ticker.get("image")

				payload = {
					"quotePrice": "Open interest: {:,.0f} contracts".format(float(rawData["openInterest"])),
					"quoteConvertedPrice": "Open value: {:,.4f} XBT".format(float(rawData["openValue"]) / 100000000),
					"title": ticker.get("name"),
					"thumbnailUrl": coinThumbnail,
					"messageColor": "deep purple",
					"sourceText": "Open interest on {}".format(exchange.name),
					"platform": CCXT.name,
					"raw": {
						"quotePrice": [float(rawData["openInterest"]), float(rawData["openValue"]) / 100000000],
						"timestamp": time()
					}
				}
				return [payload, ""]
			return [{}, "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.get("id")), "side": "long", "section": "last"})
					shorts = exchange.properties.publicGetStats1KeySizeSymbolShortLast({"key": "pos.size", "size": "1m", "symbol": "t{}".format(ticker.get("id")), "side": "long", "section": "last"})
					ratio = longs[1] / (longs[1] + shorts[1]) * 100
				except:
					return [{}, ""]

				coinThumbnail = static_storage.icon if ticker.get("image") is None else ticker.get("image")

				payload = {
					"quotePrice": "{:.1f} % longs / {:.1f} % shorts".format(ratio, 100 - ratio),
					"title": ticker.get("name"),
					"change": "in {}".format(deltaFundingText),
					"thumbnailUrl": coinThumbnail,
					"messageColor": "deep purple",
					"sourceText": "Longs/shorts on {}".format(exchange.name),
					"platform": CCXT.name,
					"raw": {
						"quotePrice": [longs[1], shorts[1]],
						"timestamp": time()
					}
				}
				return [payload, ""]
			return [{}, "Longs and shorts data is only available on Bitfinex."]
		elif action == "dom":
			try: rawData = CoinGecko.connection.get_global()
			except: return [{}, "Requested dominance data for `{}` is not available.".format(ticker.get("name"))]
			if ticker.get("base").lower() not in rawData["market_cap_percentage"]: return [{}, "Dominance for {} does not exist.".format(ticker.get("base"))]
			coinDominance = rawData["market_cap_percentage"][ticker.get("base").lower()]

			coinThumbnail = static_storage.icon if ticker.get("image") is None else ticker.get("image")

			payload = {
				"quotePrice": "{} dominance: {:,.2f} %".format(ticker.get("base"), coinDominance),
				"title": "Market Dominance",
				"thumbnailUrl": coinThumbnail,
				"messageColor": "deep purple",
				"sourceText": "Market information from CoinGecko",
				"platform": CCXT.name,
				"raw": {
					"quotePrice": [coinDominance],
					"timestamp": time()
				}
			}
			return [payload, ""]
		else:
			return [{}, ""]
コード例 #8
0
    def _request_stocks(cls, request, ticker):
        exchange = Exchange.from_dict(ticker.get("exchange"))

        try:
            stock = Stock(ticker.get("symbol"), token=environ["IEXC_KEY"])
            rawData = stock.get_quote().loc[ticker.get("symbol")]
            if ticker.get("quote") is None and exchange is not None:
                return [{}, "Price for `{}` is not available on {}.".format(
                    ticker.get("name"), exchange.get("name"))]
            if rawData is None or (rawData["latestPrice"] is None
                                   and rawData["delayedPrice"] is None):
                return [{}, ""]
        except:
            return [{}, ""]

        try:
            coinThumbnail = stock.get_logo().loc[ticker.get("symbol")]["url"]
        except:
            coinThumbnail = static_storage.icon

        latestPrice = rawData["delayedPrice"] if rawData[
            "latestPrice"] is None else rawData["latestPrice"]
        price = float(
            latestPrice if "isUSMarketOpen" not in rawData
            or rawData["isUSMarketOpen"] or "extendedPrice" not in rawData
            or rawData["extendedPrice"] is None else rawData["extendedPrice"])
        if ticker.get("isReversed"): price = 1 / price
        priceChange = (
            (1 / float(rawData["change"]) if ticker.get("isReversed")
             and float(rawData["change"]) != 0 else float(rawData["change"])) /
            price * 100
        ) if "change" in rawData and rawData["change"] is not None else 0

        payload = {
            "quotePrice":
            "{:,.10f}".format(price).rstrip('0').rstrip('.') +
            ("" if ticker.get("isReversed") else
             (" USD" if ticker.get("quote") is None else
              (" " + ticker.get("quote")))),
            "title":
            ticker.get("name"),
            "change":
            "{:+.2f} %".format(priceChange),
            "thumbnailUrl":
            coinThumbnail,
            "messageColor":
            "amber" if priceChange == 0 else
            ("green" if priceChange > 0 else "red"),
            "sourceText":
            "Data provided by IEX Cloud",
            "platform":
            "IEXC",
            "raw": {
                "quotePrice": [price],
                "timestamp": time()
            }
        }

        if "latestVolume" in rawData:
            volume = float(rawData["latestVolume"])
            payload["quoteVolume"] = "{:,.4f}".format(volume).rstrip(
                '0').rstrip('.') + " " + ticker.get("base")
            payload["raw"]["quoteVolume"] = [volume]

        return [payload, ""]