예제 #1
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
예제 #2
0
    def update_paper_limit_orders(self):
        """Process paper limit orders

		"""

        socket = CronJobs.zmqContext.socket(zmq.REQ)
        socket.connect("tcp://candle-server:6900")
        socket.setsockopt(zmq.LINGER, 3)
        poller = zmq.Poller()
        poller.register(socket, zmq.POLLIN)

        try:
            for accountId in self.accountProperties:
                if "customer" in self.accountProperties[accountId]:
                    for exchange in self.accountProperties[accountId][
                            "paperTrader"]:
                        if exchange in ["globalLastReset", "globalResetCount"]:
                            continue
                        paper = self.accountProperties[accountId][
                            "paperTrader"][exchange]

                        for order in list(paper["openOrders"]):
                            paperRequest = pickle.loads(
                                zlib.decompress(order["request"]))
                            ticker = paperRequest.get_ticker()
                            exchange = paperRequest.get_exchange()

                            if paperRequest.currentPlatform == "CCXT":
                                levelText = Utils.format_price(
                                    exchange.properties, ticker.symbol,
                                    order["price"])
                            elif paperRequest.currentPlatform == "IEXC" or paperRequest.currentPlatform == "Quandl":
                                levelText = "{:,.5f}".format(order["price"])
                            else:
                                levelText = "{:,.0f}".format(order["price"])

                            socket.send_multipart(
                                [b"cronjob", b"candle", order["request"]])
                            responses = poller.poll(5 * 1000)

                            if len(responses) != 0:
                                response = socket.recv()
                                payload, responseText = pickle.loads(
                                    zlib.decompress(response))

                                if payload is None:
                                    if responseText is not None:
                                        print("Paper order request error",
                                              responseText)
                                        if os.environ["PRODUCTION_MODE"]:
                                            self.logging.report(responseText)
                                    return

                                for candle in reversed(payload["candles"]):
                                    if candle[0] < order["timestamp"] / 1000:
                                        break
                                    if candle[3] < order["price"] < candle[2]:
                                        baseOrder = paper["balance"][
                                            ticker.base]
                                        quoteOrder = paper["balance"][
                                            ticker.quote]

                                        execAmount = order["amount"]
                                        isPricePercent, isLimitOrder, reduceOnly = order[
                                            "parameters"]
                                        if reduceOnly and (
                                            (order["orderType"] == "buy"
                                             and baseOrder["amount"] >= 0) or
                                            (order["orderType"] == "sell"
                                             and baseOrder["amount"] <= 0)):
                                            order["status"] = "canceled"
                                            paper["openOrders"].remove(order)

                                        if exchange.id == "bitmex":
                                            averageEntry = (
                                                baseOrder["entry"] *
                                                baseOrder["amount"] +
                                                order["price"] * execAmount
                                            ) / (
                                                baseOrder["amount"] +
                                                execAmount
                                            ) if baseOrder[
                                                "amount"] + execAmount != 0 else 0
                                            quoteValue = (
                                                abs(execAmount) *
                                                (-1 if reduceOnly else 1)
                                            ) / (averageEntry
                                                 if averageEntry != 0 else
                                                 baseOrder["entry"]) / leverage
                                            roi = (
                                                (order["price"] -
                                                 baseOrder["entry"]) *
                                                0.000001 if ticker.symbol
                                                == "ETH/USD" else
                                                (1 / baseOrder["entry"] - 1 /
                                                 order["price"])) * baseOrder[
                                                     "amount"] if baseOrder[
                                                         "entry"] != 0 else 0
                                            orderFee = execAmount * exchange.properties.markets[
                                                ticker.
                                                symbol]["maker" if isLimitOrder
                                                        else "taker"]

                                            if order[
                                                    "orderType"] == "buy" or order[
                                                        "orderType"] == "sell":
                                                baseOrder[
                                                    "entry"] = averageEntry
                                                baseOrder[
                                                    "amount"] += execAmount
                                            elif order[
                                                    "orderType"] == "stop-buy" or order[
                                                        "orderType"] == "stop-sell":
                                                quoteOrder["amount"] += round(
                                                    roi -
                                                    (quoteValue + abs(orderFee)
                                                     / order["price"]), 8)
                                                baseOrder[
                                                    "entry"] = averageEntry
                                                baseOrder[
                                                    "amount"] += execAmount
                                        else:
                                            if order["orderType"] == "buy":
                                                if reduceOnly:
                                                    execAmount = min(
                                                        abs(quoteOrder[
                                                            "amount"]),
                                                        order["price"] *
                                                        execAmount
                                                    ) / order["price"]
                                                orderFee = execAmount * exchange.properties.markets[
                                                    ticker.symbol]["maker"]

                                                baseOrder[
                                                    "amount"] += execAmount - orderFee
                                            elif order["orderType"] == "sell":
                                                if reduceOnly:
                                                    execAmount = min(
                                                        abs(baseOrder["amount"]
                                                            ), execAmount)
                                                orderFee = execAmount * exchange.properties.markets[
                                                    ticker.symbol]["maker"]

                                                quoteOrder["amount"] += (
                                                    execAmount -
                                                    orderFee) * order["price"]
                                            elif order[
                                                    "orderType"] == "stop-buy":
                                                if reduceOnly:
                                                    execAmount = min(
                                                        abs(quoteOrder[
                                                            "amount"]),
                                                        order["price"] *
                                                        execAmount
                                                    ) / order["price"]
                                                orderFee = execAmount * exchange.properties.markets[
                                                    ticker.symbol]["taker"]

                                                baseOrder[
                                                    "amount"] += execAmount - orderFee
                                                quoteOrder["amount"] -= order[
                                                    "price"] * execAmount
                                            elif order[
                                                    "orderType"] == "stop-sell":
                                                if reduceOnly:
                                                    execAmount = min(
                                                        abs(baseOrder["amount"]
                                                            ), execAmount)
                                                orderFee = execAmount * exchange.properties.markets[
                                                    ticker.symbol]["taker"]

                                                baseOrder[
                                                    "amount"] -= execAmount
                                                quoteOrder["amount"] += (
                                                    execAmount -
                                                    orderFee) * order["price"]

                                        paper["openOrders"].remove(order)
                                        order["status"] = "filled"
                                        paper["history"].append(order)
                                        database.document("accounts/{}".format(
                                            accountId)).set(
                                                {
                                                    "paperTrader": {
                                                        exchange.id: paper
                                                    }
                                                },
                                                merge=True)

                                        if self.server.accountProperties[
                                                accountId]["oauth"][
                                                    "discord"].get(
                                                        "userId") is not None:
                                            database.document(
                                                "discord/properties/messages/{}"
                                                .format(str(uuid.uuid4()))
                                            ).set({
                                                "title":
                                                "Paper {} order of {} {} on {} at {} was successfully executed."
                                                .format(
                                                    order["orderType"].replace(
                                                        "-", " "),
                                                    Utils.format_amount(
                                                        exchange.properties,
                                                        ticker.symbol,
                                                        order["amount"]),
                                                    order["base"],
                                                    exchange.name,
                                                    order["price"]),
                                                "subtitle":
                                                "Alpha Paper Trader",
                                                "description":
                                                None,
                                                "color":
                                                6765239,
                                                "user":
                                                self.server.
                                                accountProperties[accountId]
                                                ["oauth"]["discord"]["userId"],
                                                "channel":
                                                "611107823111372810"
                                            })

        except (KeyboardInterrupt, SystemExit):
            pass
        except Exception:
            print(traceback.format_exc())
            if os.environ["PRODUCTION_MODE"]: self.logging.report_exception()
예제 #3
0
    def check_price_alert(self, authorId, accountId, reference, alert):
        socket = CronJobs.zmqContext.socket(zmq.REQ)
        socket.connect("tcp://candle-server:6900")
        socket.setsockopt(zmq.LINGER, 3)
        poller = zmq.Poller()
        poller.register(socket, zmq.POLLIN)

        try:
            alertRequest = pickle.loads(zlib.decompress(alert["request"]))
            alertRequest.timestamp = time.time()
            ticker = alertRequest.get_ticker()
            exchange = alertRequest.get_exchange()

            if alertRequest.currentPlatform == "CCXT":
                levelText = Utils.format_price(exchange.properties,
                                               ticker.symbol, alert["level"])
            elif alertRequest.currentPlatform == "IEXC" or alertRequest.currentPlatform == "Quandl":
                levelText = "{:,.5f}".format(alert["level"])
            else:
                levelText = "{:,.0f}".format(alert["level"])

            if alert["timestamp"] < time.time() - 86400 * 30.5 * 6:
                if os.environ["PRODUCTION_MODE"]:
                    database.document("discord/properties/messages/{}".format(
                        str(uuid.uuid4())
                    )).set({
                        "title":
                        "Price alert for {} ({}) at {} {} expired.".format(
                            ticker.base, alertRequest.currentPlatform
                            if exchange is None else exchange.name, levelText,
                            ticker.quote),
                        "subtitle":
                        "Alpha Price Alerts",
                        "description":
                        "Price alerts automatically cancel after 6 months. If you'd like to keep your alert, you'll have to schedule it again.",
                        "color":
                        6765239,
                        "user":
                        authorId,
                        "channel":
                        alert["channel"]
                    })

                    reference.delete()

                else:
                    print(
                        "{}: price alert for {} ({}) at {} {} expired.".format(
                            accountId, ticker.base,
                            alertRequest.currentPlatform if exchange is None
                            else exchange.name, levelText, ticker.quote))

            else:
                socket.send_multipart([
                    b"cronjob", b"candle",
                    zlib.compress(pickle.dumps(alertRequest, -1))
                ])
                responses = poller.poll(30 * 1000)

                if len(responses) != 0:
                    response = socket.recv()
                    payload, responseText = pickle.loads(
                        zlib.decompress(response))

                    if payload is None:
                        if responseText is not None:
                            print("Alert request error", responseText)
                            if os.environ["PRODUCTION_MODE"]:
                                self.logging.report(responseText)
                        return

                    alertRequest.set_current(platform=payload["platform"])
                    for candle in reversed(payload["candles"]):
                        if candle[0] < alert["timestamp"]: break
                        if (candle[3] <= alert["level"] and alert["placement"]
                                == "below") or (alert["level"] <= candle[2] and
                                                alert["placement"] == "above"):
                            if os.environ["PRODUCTION_MODE"]:
                                database.document(
                                    "discord/properties/messages/{}".format(
                                        str(uuid.uuid4()))
                                ).set({
                                    "title":
                                    "Price of {} ({}) hit {} {}.".format(
                                        ticker.base,
                                        alertRequest.currentPlatform
                                        if exchange is None else exchange.name,
                                        levelText, ticker.quote),
                                    "subtitle":
                                    "Alpha Price Alerts",
                                    "description":
                                    None,
                                    "color":
                                    6765239,
                                    "user":
                                    authorId,
                                    "channel":
                                    alert["channel"]
                                })

                                reference.delete()

                            else:
                                print("{}: price of {} ({}) hit {} {}.".format(
                                    accountId, ticker.base,
                                    alertRequest.currentPlatform
                                    if exchange is None else exchange.name,
                                    levelText, ticker.quote))
                            break

        except (KeyboardInterrupt, SystemExit):
            pass
        except Exception:
            print(traceback.format_exc())
            if os.environ["PRODUCTION_MODE"]: self.logging.report_exception()
        socket.close()
예제 #4
0
    def process_trade(self, paper, orderType, request, payload):
        outputTitle = None
        outputMessage = None

        exchange = request.get_exchange()
        ticker = request.get_ticker()
        isLimitOrder = request.find_parameter_in_list("isLimitOrder",
                                                      request.get_filters(),
                                                      default=False)
        isAmountPercent = request.find_parameter_in_list("isAmountPercent",
                                                         request.get_filters(),
                                                         default=False)
        isPricePercent = request.find_parameter_in_list("isPricePercent",
                                                        request.get_filters(),
                                                        default=False)
        reduceOnly = request.find_parameter_in_list(
            "isReduceOnlyMode", request.get_filters(),
            default=False) or "stop" in orderType
        if not isLimitOrder:
            execPrice = payload["quotePrice"]
        elif isLimitOrder and len(request.get_numerical_parameters()) != 2:
            outputTitle = "Execution price was not provided."
            outputMessage = "A limit order execution price must be provided."
            return outputTitle, outputMessage, paper, None
        else:
            execPrice = request.get_numerical_parameters()[1]
        execAmount = request.get_numerical_parameters()[0]
        inverseOrderType = "sell" if "buy" in orderType else "buy"

        if exchange.id not in paper:
            paper[exchange.id] = {
                "balance":
                copy.deepcopy(PaperTrader.startingBalance[exchange.id]),
                "openOrders": [],
                "history": []
            }

        if isLimitOrder and len(paper[exchange.id]["openOrders"]) >= 1000:
            outputTitle = "Too many open paper orders"
            outputMessage = "Only up to 1000 open paper orders are allowed."
            return outputTitle, outputMessage, paper, None

        base = ticker.name if exchange.id in ["bitmex"] else ticker.base
        quote = "BTC" if exchange.id in ["bitmex"] else ticker.quote
        if base not in paper[exchange.id]["balance"]:
            paper[exchange.id]["balance"][base] = {"entry": 0.0, "amount": 0.0}
        if quote not in paper[exchange.id]["balance"]:
            paper[exchange.id]["balance"][quote] = {
                "entry": 0.0,
                "amount": 0.0
            }

        baseOrder = paper[exchange.id]["balance"][base]
        quoteOrder = paper[exchange.id]["balance"][quote]

        if orderType.endswith("buy"):
            if isPricePercent:
                execPrice = payload["quotePrice"] * (1 - execPrice / 100)
            execAmount = (
                (abs(quoteOrder["amount"]) * execPrice if exchange.id
                 in ["bitmex"] else abs(quoteOrder["amount"]) / execPrice) *
                (execAmount / 100)) if isAmountPercent else execAmount
        elif orderType.endswith("sell"):
            if isPricePercent:
                execPrice = payload["quotePrice"] * (1 + execPrice / 100)
            execAmount = (
                (quoteOrder["amount"] * execPrice
                 if exchange.id in ["bitmex"] else baseOrder["amount"]) *
                (execAmount / 100)) if isAmountPercent else execAmount
            if exchange.id in ["bitmex"]: execAmount *= -1

        execPriceText = Utils.format_price(exchange.properties, ticker.symbol,
                                           execPrice)
        execPrice = float(execPriceText.replace(",", ""))
        execAmountText = Utils.format_amount(exchange.properties,
                                             ticker.symbol, execAmount)
        execAmount = float(execAmountText.replace(",", ""))

        if exchange.id in ["bitmex"]:
            baseValue = execAmount / execPrice
            quoteValue = execAmount
            amountPrecision = exchange.properties.markets[
                ticker.symbol]["precision"]["amount"]
            amountLimits = exchange.properties.markets[
                ticker.symbol]["limits"]["cost"]

            if execAmount < 1:
                outputTitle = "Insuficient paper order size"
                outputMessage = "Order size of {:,.0f} contract is less than the minimum required size of 1 contract.".format(
                    execAmount)
                return outputTitle, outputMessage, paper, None
            elif execAmount > amountLimits["max"]:
                outputTitle = "Paper order size exeeds maximum allowed order size"
                outputMessage = "Order size must not exceed {:,.0f} {}.".format(
                    amountLimits["max"], base)

            elif not reduceOnly and (
                (orderType.endswith("sell")
                 and baseValue > baseOrder["amount"]) or
                (orderType.endswith("buy")
                 and quoteValue / execPrice > quoteOrder["amount"])):
                outputTitle = "Insuficient paper wallet balance"
                outputMessage = "Order size of {} {} exeeds your paper wallet balance of {:,.8f} {}.".format(
                    execAmountText, base, quoteOrder["amount"]
                    if orderType.endswith("buy") else baseOrder["amount"],
                    quote if orderType.endswith("buy") else base)
                return outputTitle, outputMessage, paper, None
            elif (orderType.endswith("buy") and quoteOrder["amount"] == 0) or (
                    orderType.endswith("sell") and baseOrder["amount"] == 0):
                outputTitle = "Insuficient paper wallet balance"
                outputMessage = "Your {} balance is empty.".format(
                    quote if orderType.endswith("buy") else base)
                return outputTitle, outputMessage, paper, None

            newOrder = {
                "id":
                str(uuid.uuid4()),
                "orderType":
                orderType,
                "request":
                zlib.compress(pickle.dumps(request, -1)),
                "amount":
                execAmount,
                "price":
                request.get_numerical_parameters()[0]
                if isPricePercent else execPrice,
                "highest":
                execPrice,
                "timestamp":
                int(time.time() * 1000),
                "status":
                "placed",
                "parameters": [isPricePercent, isLimitOrder, reduceOnly]
            }
            priceText = "{:,.2f} %".format(request.get_numerical_parameters(
            )[0]) if isPricePercent else "{} {}".format(
                execPriceText, ticker.quote)
            conversionText = None if isPricePercent else "{} contracts ≈ {:,.6f} {}".format(
                execAmountText, baseValue, ticker.base)
            return None, None, paper, Order(newOrder,
                                            request,
                                            priceText=priceText,
                                            conversionText=conversionText,
                                            amountText=execAmountText)
        else:
            baseValue = execAmount
            quoteValue = execAmount * execPrice
            amountPrecision = exchange.properties.markets[
                ticker.symbol]["precision"]["amount"]
            amountLimits = exchange.properties.markets[
                ticker.symbol]["limits"]["amount"]

            if execAmount < amountLimits["min"]:
                outputTitle = "Insuficient paper order size"
                outputMessage = (
                    "Order size of {:,.%df} {} is less than the minimum required size of {:,.%df} {}."
                    % (amountPrecision, amountPrecision)).format(
                        execAmount, quote, amountLimits["min"], base)
                return outputTitle, outputMessage, paper, None
            elif execAmount > amountLimits["max"]:
                outputTitle = "Paper order size exeeds maximum allowed order size"
                outputMessage = ("Order size must not exceed {:,.%df} {}." %
                                 (amountPrecision)).format(
                                     amountLimits["max"], base)
                return outputTitle, outputMessage, paper, None
            elif not reduceOnly and ((orderType.endswith("sell")
                                      and baseValue > baseOrder["amount"]) or
                                     (orderType.endswith("buy")
                                      and quoteValue > quoteOrder["amount"])):
                outputTitle = "Insuficient paper wallet balance"
                outputMessage = "Order size of {} {} exeeds your paper wallet balance of {:,.8f} {}.".format(
                    execAmountText, base, quoteOrder["amount"]
                    if orderType.endswith("buy") else baseOrder["amount"],
                    quote if orderType.endswith("buy") else base)
                return outputTitle, outputMessage, paper, None
            elif (orderType.endswith("buy") and quoteOrder["amount"] == 0) or (
                    orderType.endswith("sell") and baseOrder["amount"] == 0):
                outputTitle = "Insuficient paper wallet balance"
                outputMessage = "Your {} balance is empty.".format(
                    quote if orderType.endswith("buy") else base)
                return outputTitle, outputMessage, paper, None

            newOrder = {
                "id":
                str(uuid.uuid4()),
                "orderType":
                orderType,
                "request":
                zlib.compress(pickle.dumps(request, -1)),
                "amount":
                execAmount,
                "price":
                request.get_numerical_parameters()[0]
                if isPricePercent else execPrice,
                "highest":
                execPrice,
                "timestamp":
                int(time.time() * 1000),
                "status":
                "placed",
                "parameters": [isPricePercent, isLimitOrder, reduceOnly]
            }
            priceText = "{:,.2f} %".format(request.get_numerical_parameters(
            )[0]) if isPricePercent else "{} {}".format(
                execPriceText, ticker.quote)
            conversionText = None if isPricePercent else "{} {} ≈ {:,.6f} {}".format(
                execAmountText, ticker.base, quoteValue, ticker.quote)
            return None, None, paper, Order(newOrder,
                                            request,
                                            priceText=priceText,
                                            conversionText=conversionText,
                                            amountText=execAmountText)
예제 #5
0
    def check_paper_order(self, authorId, accountId, reference, order):
        socket = CronJobs.zmqContext.socket(zmq.REQ)
        socket.connect("tcp://candle-server:6900")
        socket.setsockopt(zmq.LINGER, 3)
        poller = zmq.Poller()
        poller.register(socket, zmq.POLLIN)

        try:
            paperRequest = pickle.loads(zlib.decompress(order["request"]))
            paperRequest.timestamp = time.time()
            ticker = paperRequest.get_ticker()
            exchange = paperRequest.get_exchange()

            if paperRequest.currentPlatform == "CCXT":
                levelText = Utils.format_price(exchange.properties,
                                               ticker.symbol, order["price"])
            elif paperRequest.currentPlatform == "IEXC":
                levelText = "{:,.5f}".format(order["price"])
            else:
                levelText = "{:,.0f}".format(order["price"])

            if order["timestamp"] < time.time() - 86400 * 30.5 * 6:
                if os.environ["PRODUCTION_MODE"]:
                    database.document("discord/properties/messages/{}".format(
                        str(uuid.uuid4())
                    )).set({
                        "title":
                        "Paper {} order of {} {} on {} at {} {} expired.".
                        format(
                            order["orderType"].replace("-", " "),
                            Utils.format_amount(exchange.properties,
                                                ticker.symbol,
                                                order["amount"]), ticker.base,
                            paperRequest.currentPlatform if exchange is None
                            else exchange.name, order["price"], ticker.quote),
                        "subtitle":
                        "Alpha Paper Trader",
                        "description":
                        "Paper orders automatically cancel after 6 months. If you'd like to keep your order, you'll have to set it again.",
                        "color":
                        6765239,
                        "user":
                        authorId,
                        "channel":
                        order["channel"]
                    })
                    reference.delete()

                else:
                    print("{}: paper {} order of {} {} on {} at {} expired".
                          format(
                              order["orderType"].replace("-", " "),
                              Utils.format_amount(exchange.properties,
                                                  ticker.symbol,
                                                  order["amount"]),
                              ticker.base, paperRequest.currentPlatform
                              if exchange is None else exchange.name,
                              order["price"], ticker.quote))

            else:
                socket.send_multipart([
                    b"cronjob", b"candle",
                    zlib.compress(pickle.dumps(paperRequest, -1))
                ])
                responses = poller.poll(30 * 1000)

                if len(responses) != 0:
                    response = socket.recv()
                    payload, responseText = pickle.loads(
                        zlib.decompress(response))

                    if payload is None:
                        if responseText is not None:
                            print("Paper order request error", responseText)
                            if os.environ["PRODUCTION_MODE"]:
                                self.logging.report(responseText)
                        return

                    paperRequest.set_current(platform=payload["platform"])
                    for candle in reversed(payload["candles"]):
                        if candle[0] < order["timestamp"]: break
                        if (candle[3] <= order["level"] and order["placement"]
                                == "below") or (order["level"] <= candle[2] and
                                                order["placement"] == "above"):
                            loop = asyncio.get_event_loop()
                            accountProperties = loop.run_until_complete(
                                self.accountProperties.get(accountId))

                            if os.environ["PRODUCTION_MODE"]:
                                if "paperTrader" in accountProperties:
                                    paper = accountProperties["paperTrader"]
                                    baseOrder = paper.get(ticker.base, 0)
                                    quoteOrder = paper.get(ticker.quote, 0)

                                    execAmount = order["amount"]
                                    isPricePercent, isLimitOrder, reduceOnly = order[
                                        "parameters"]
                                    if reduceOnly and (
                                        (order["orderType"] == "buy"
                                         and baseOrder["amount"] >= 0) or
                                        (order["orderType"] == "sell"
                                         and baseOrder["amount"] <= 0)):
                                        order["status"] = "canceled"
                                        database.document(
                                            "discord/properties/messages/{}".
                                            format(str(uuid.uuid4()))
                                        ).set({
                                            "title":
                                            "Paper {} order of {} {} on {} at {} {} expired."
                                            .format(
                                                order["orderType"].replace(
                                                    "-", " "),
                                                Utils.format_amount(
                                                    exchange.properties,
                                                    ticker.symbol,
                                                    execAmount), ticker.base,
                                                paperRequest.currentPlatform
                                                if exchange is None else
                                                exchange.name, order["price"],
                                                ticker.quote),
                                            "subtitle":
                                            "Alpha Paper Trader",
                                            "description":
                                            "Paper orders automatically cancel after 6 months. If you'd like to keep your order, you'll have to set it again.",
                                            "color":
                                            6765239,
                                            "user":
                                            authorId,
                                            "channel":
                                            order["channel"]
                                        })
                                        reference.delete()

                                    else:
                                        if order["orderType"] == "buy":
                                            if reduceOnly:
                                                execAmount = min(
                                                    abs(quoteOrder["amount"]),
                                                    order["price"] * execAmount
                                                ) / order["price"]
                                            orderFee = execAmount * exchange.properties.markets[
                                                ticker.symbol]["maker"]

                                            baseOrder[
                                                "amount"] += execAmount - orderFee
                                        elif order["orderType"] == "sell":
                                            if reduceOnly:
                                                execAmount = min(
                                                    abs(baseOrder["amount"]),
                                                    execAmount)
                                            orderFee = execAmount * exchange.properties.markets[
                                                ticker.symbol]["maker"]

                                            quoteOrder["amount"] += (
                                                execAmount -
                                                orderFee) * order["price"]
                                        elif order["orderType"] == "stop-buy":
                                            if reduceOnly:
                                                execAmount = min(
                                                    abs(quoteOrder["amount"]),
                                                    order["price"] * execAmount
                                                ) / order["price"]
                                            orderFee = execAmount * exchange.properties.markets[
                                                ticker.symbol]["taker"]

                                            baseOrder[
                                                "amount"] += execAmount - orderFee
                                            quoteOrder["amount"] -= order[
                                                "price"] * execAmount
                                        elif order["orderType"] == "stop-sell":
                                            if reduceOnly:
                                                execAmount = min(
                                                    abs(baseOrder["amount"]),
                                                    execAmount)
                                            orderFee = execAmount * exchange.properties.markets[
                                                ticker.symbol]["taker"]

                                            baseOrder["amount"] -= execAmount
                                            quoteOrder["amount"] += (
                                                execAmount -
                                                orderFee) * order["price"]

                                        order["status"] = "filled"
                                        database.document(
                                            "details/paperOrderHistory/{}/{}".
                                            format(accountId, str(
                                                uuid.uuid4()))).set(order)
                                        database.document("accounts/{}".format(
                                            accountId)).set(
                                                {
                                                    "paperTrader": {
                                                        exchange.id: paper
                                                    }
                                                },
                                                merge=True)

                                        database.document(
                                            "discord/properties/messages/{}".
                                            format(str(uuid.uuid4()))
                                        ).set({
                                            "title":
                                            "Paper {} order of {} {} on {} at {} {} was successfully executed."
                                            .format(
                                                order["orderType"].replace(
                                                    "-", " "),
                                                Utils.format_amount(
                                                    exchange.properties,
                                                    ticker.symbol,
                                                    execAmount), ticker.base,
                                                paperRequest.currentPlatform
                                                if exchange is None else
                                                exchange.name, order["price"],
                                                ticker.quote),
                                            "subtitle":
                                            "Alpha Paper Trader",
                                            "description":
                                            None,
                                            "color":
                                            6765239,
                                            "user":
                                            authorId,
                                            "channel":
                                            order["channel"]
                                        })
                                        reference.delete()

                                else:
                                    print(
                                        "{}: paper {} order of {} {} on {} at {} {} was successfully executed"
                                        .format(
                                            order["orderType"].replace(
                                                "-", " "),
                                            Utils.format_amount(
                                                exchange.properties,
                                                ticker.symbol,
                                                order["amount"]), ticker.base,
                                            paperRequest.currentPlatform
                                            if exchange is None else
                                            exchange.name, order["price"],
                                            ticker.quote))
                            break

        except (KeyboardInterrupt, SystemExit):
            pass
        except Exception:
            print(traceback.format_exc())
            if os.environ["PRODUCTION_MODE"]: self.logging.report_exception()