예제 #1
0
    def get(self):
        # token_data = jwt.decode(request.headers.get('AccessToken'), os.environ['SECRET_KEY'])
        users = list(app.db.users.find())
        if users:
            resp = jsonResp_message(users, 200)
        else:
            resp = jsonResp_message("No users found", 200)

        return resp
예제 #2
0
    def add(self):
        data = request.json
        expected_data = {
            "email": data["email"].lower(),
            "password": data["password"],
        }
        # Merge the posted data with the default user attributes
        self.defaults.update(expected_data)
        user = self.defaults
        # Encrypt the password
        user["password"] = pbkdf2_sha256.encrypt(
            user["password"], rounds=20000, salt_size=16
        )
        # Make sure there isn"t already a user with this email address
        existing_email = app.db.users.find_one({"email": user["email"]})

        if existing_email:
            resp = jsonResp_message(
                {
                    "message": "There's already an account with this email address",
                },
                200,
            )

        else:
            insertion = app.db.users.insert(user)
            if insertion:

                # Log the user in (create and return tokens)
                access_token = encodeAccessToken(user["password"], user["email"])
                refresh_token = encodeRefreshToken(user["password"], user["email"])

                app.db.users.update_one(
                    {"_id": user["_id"]}, {"$set": {"refresh_token": refresh_token}}
                )

                resp = jsonResp_message(
                    {
                        "_id": user["_id"],
                        "email": user["email"],
                        "access_token": access_token,
                        "refresh_token": refresh_token,
                    },
                    200,
                )

            else:
                resp = jsonResp_message("User could not be added", 200)
        return resp
예제 #3
0
    def get_open_orders(self):
        timestamp = int(round(tm.time() * 1000))
        url = self.open_orders
        params = [("timestamp", timestamp), ("recvWindow", self.recvWindow)]
        headers = {"X-MBX-APIKEY": self.key}

        # Prepare request for signing
        r = requests.Request(url=url, params=params, headers=headers)
        prepped = r.prepare()
        query_string = urlparse(prepped.url).query
        total_params = query_string

        # Generate and append signature
        signature = hmac.new(self.secret.encode("utf-8"),
                             total_params.encode("utf-8"),
                             hashlib.sha256).hexdigest()
        params.append(("signature", signature))

        res = requests.get(url=url, params=params, headers=headers)
        handle_error(res)
        data = res.json()

        if len(data) > 0:
            resp = jsonResp({
                "message": "Open orders found!",
                "data": data
            }, 200)
        else:
            resp = jsonResp_message("No open orders found!", 200)
        return resp
예제 #4
0
파일: account.py 프로젝트: carkod/binbot
 def get_symbol_info(self):
     symbols = self._exchange_info()["symbols"]
     pair = request.view_args["pair"]
     symbol = next((s for s in symbols if s["symbol"] == pair), None)
     if symbol:
         return jsonResp({"data": symbol}, 200)
     else:
         return jsonResp_message("Pair not found", 200)
예제 #5
0
 def block_response(self):
     """
     Scanning already in progress
     """
     global poll_percentage
     resp = jsonResp_message(
         f"Pearson correlation scanning is in progress {poll_percentage}%",
         200)
     return resp
예제 #6
0
    def close_deals(self):
        """
        Close all deals
        - Deals should be stored as an array of orderIds
        - Delete (cancel) endpoint, with symbold and orderId
        """
        deals = self.active_bot["deals"]

        for d in deals:
            if "deal_type" in d and (
                d["status"] == "NEW" or d["status"] == "PARTIALLY_FILLED"
            ):
                order_id = d["order_id"]
                res = requests.delete(
                    url=f'{self.bb_close_order_url}/{self.active_bot["pair"]}/{order_id}'
                )

                if isinstance(handle_error(res), Response):
                    return handle_error(res)

        # Sell everything
        pair = self.active_bot["pair"]
        base_asset = self.find_baseAsset(pair)
        balance = self.get_balances().json
        qty = round_numbers(
            float(next((s for s in symbols if s["symbol"] == symbol), None)["free"]),
            self.qty_precision,
        )
        book_order = Book_Order(pair)
        price = float(book_order.matching_engine(True, qty))

        if price:
            order = {
                "pair": pair,
                "qty": qty,
                "price": supress_notation(price, self.price_precision),
            }
            res = requests.post(url=self.bb_sell_order_url, json=order)
        else:
            order = {
                "pair": pair,
                "qty": qty,
            }
            res = requests.post(url=self.bb_sell_market_order_url, json=order)

        if isinstance(handle_error(res), Response):
            return handle_error(res)

        response = jsonResp_message("Deals closed successfully", 200)
        return response
예제 #7
0
def handle_error(req):
    try:
        req.raise_for_status()

        if isinstance(json.loads(req.content), dict):
            # Binance code errors
            if "code" in json.loads(req.content).keys():

                response = req.json()
                if response["code"] == -2010:
                    return jsonResp({
                        "message": "Not enough funds",
                        "error": 1
                    }, 200)

                # Uknown orders ignored, they are used as a trial an error endpoint to close orders (close deals)
                if response["code"] == -2011:
                    return

                return jsonResp_message(json.loads(req.content), 200)

    except requests.exceptions.HTTPError as err:
        if err:
            print(req.json())
            return jsonResp_message(req.json(), 200)
        else:
            return err
    except requests.exceptions.Timeout:
        # Maybe set up for a retry, or continue in a retry loop
        return jsonResp_message("handle_error: Timeout", 408)
    except requests.exceptions.TooManyRedirects:
        # Tell the user their URL was bad and try a different one
        return jsonResp_message("handle_error: Too many Redirects", 429)
    except requests.exceptions.RequestException as e:
        # catastrophic error. bail.
        return jsonResp_message(f"Catastrophic error: {e}", 500)
예제 #8
0
    def logout(self):
        try:
            tokenData = jwt.decode(
                request.headers.get("AccessToken"), os.environ["SECRET_KEY"]
            )
            app.db.users.update(
                {"id": tokenData["userid"]}, {"$unset": {"access_token": ""}}
            )
            # Note: At some point I need to implement Token Revoking/Blacklisting
            # General info here: https://flask-jwt-extended.readthedocs.io/en/latest/blacklist_and_token_revoking.html
        except:
            pass

        resp = jsonResp_message("User logged out", 200)

        return resp
예제 #9
0
    def delete_all_orders(self):
        """
        Delete All orders by symbol
        - Optimal for open orders table
        """
        symbol = request.args["symbol"]
        timestamp = int(round(tm.time() * 1000))
        url = self.open_orders
        # query params -> args
        # path params -> view_args
        symbol = request.args["symbol"]
        params = [
            ("symbol", symbol),
            ("timestamp", timestamp),
            ("recvWindow", self.recvWindow),
        ]

        headers = {"X-MBX-APIKEY": self.key}

        # Prepare request for signing
        r = requests.Request(url=url, params=params, headers=headers)
        prepped = r.prepare()
        query_string = urlparse(prepped.url).query
        total_params = query_string

        # Generate and append signature
        signature = hmac.new(self.secret.encode("utf-8"),
                             total_params.encode("utf-8"),
                             hashlib.sha256).hexdigest()
        params.append(("signature", signature))

        # Response after request
        res = requests.delete(url=url, params=params, headers=headers)
        handle_error(res)
        data = res.json()

        if len(data) > 0:
            resp = jsonResp({"message": "Orders deleted", "data": data}, 200)
        else:
            resp = jsonResp_message("No open orders found!", 200)
        return resp
예제 #10
0
    def short_stop_limit_order(self):
        """
        Part I of Short bot order: Stop loss (sell all)
        After safety orders are executed, if price keeps going down, execute Stop Loss order
        """
        pair = self.active_bot["pair"]
        base_asset = self.find_baseAsset(pair)
        base_order_deal = next(
            (
                bo_deal
                for bo_deal in self.active_bot["deals"]
                if bo_deal["deal_type"] == "base_order"
            ),
            None,
        )
        price = float(base_order_deal["price"])
        stop_loss = price * int(self.active_bot["stop_loss"]) / 100
        stop_loss_price = price - stop_loss
        self.asset_qty = next(
            (b["free"] for b in self.get_balances().json if b["asset"] == base_asset),
            None,
        )

        # Validations
        if price:
            if price <= float(self.MIN_PRICE):
                return jsonResp_message("[Short stop loss order] Price too low", 200)
        # Avoid common rate limits
        if float(self.asset_qty) <= float(self.MIN_QTY):
            return jsonResp_message("[Short stop loss order] Quantity too low", 200)
        if price * float(self.asset_qty) <= float(self.MIN_NOTIONAL):
            return jsonResp_message(
                "[Short stop loss order] Price x Quantity too low", 200
            )

        order = {
            "pair": pair,
            "qty": self.asset_qty,
            "price": supress_notation(
                stop_loss_price, self.price_precision
            ),  # Theoretically stop_price, as we don't have book orders
            "stop_price": supress_notation(stop_loss_price, self.price_precision),
        }
        res = requests.post(url=self.bb_stop_sell_order_url, json=order)
        if isinstance(handle_error(res), Response):
            return handle_error(res)

        stop_limit_order = res.json()

        stop_limit_order = {
            "deal_type": "stop_limit",
            "order_id": stop_limit_order["orderId"],
            "strategy": "long",  # change accordingly
            "pair": stop_limit_order["symbol"],
            "order_side": stop_limit_order["side"],
            "order_type": stop_limit_order["type"],
            "price": stop_limit_order["price"],
            "qty": stop_limit_order["origQty"],
            "fills": stop_limit_order["fills"],
            "time_in_force": stop_limit_order["timeInForce"],
            "status": stop_limit_order["status"],
        }

        self.active_bot["deals"].append(stop_limit_order)
        botId = app.db.bots.update_one(
            {"_id": self.active_bot["_id"]}, {"$push": {"deals": stop_limit_order}}
        )
        if not botId:
            resp = jsonResp(
                {
                    "message": "Failed to save short order stop_limit deal in the bot",
                    "botId": str(self.active_bot["_id"]),
                },
                200,
            )
            return resp
예제 #11
0
 def response(self):
     """
     Start scanning
     """
     resp = jsonResp_message("Pearson correlation scanning started", 200)
     return resp
예제 #12
0
    def update_take_profit(self, order_id):
        """
        Update take profit after websocket order endpoint triggered
        - Close current opened take profit order
        - Create new take profit order
        - Update database by replacing old take profit deal with new take profit deal
        """
        bot = self.active_bot
        for deal in bot["deals"]:
            if deal["order_id"] == order_id:
                so_deal_price = deal["price"]
                # Create new take profit order
                new_tp_price = float(so_deal_price) + (
                    float(so_deal_price) * float(bot["take_profit"]) / 100)
                asset = self.find_baseAsset(bot["pair"])

                # First cancel old order to unlock balance
                close_order_params = {
                    "symbol": bot["pair"],
                    "orderId": order_id
                }
                cancel_response = requests.post(url=self.bb_close_order_url,
                                                params=close_order_params)
                if cancel_response.status_code != 200:
                    print("Take profit order not found, no need to cancel")
                else:
                    print("Old take profit order cancelled")

                qty = round_numbers(self.get_one_balance(asset),
                                    self.qty_precision)

                # Validations
                if new_tp_price:
                    if new_tp_price <= float(self.MIN_PRICE):
                        return jsonResp_message(
                            "[Take profit order error] Price too low", 200)
                if qty <= float(self.MIN_QTY):
                    return jsonResp_message(
                        "[Take profit order error] Quantity too low", 200)
                if new_tp_price * qty <= float(self.MIN_NOTIONAL):
                    return jsonResp_message(
                        "[Take profit order error] Price x Quantity too low",
                        200)

                new_tp_order = {
                    "pair": bot["pair"],
                    "qty": qty,
                    "price": supress_notation(new_tp_price,
                                              self.price_precision),
                }
                res = requests.post(url=self.bb_sell_order_url,
                                    json=new_tp_order)
                if isinstance(handle_error(res), Response):
                    return handle_error(res)

                # New take profit order successfully created
                order = res.json()

                # Replace take_profit order
                take_profit_order = {
                    "deal_type": "take_profit",
                    "order_id": order["orderId"],
                    "strategy": "long",  # change accordingly
                    "pair": order["symbol"],
                    "order_side": order["side"],
                    "order_type": order["type"],
                    "price": order["price"],
                    "qty": order["origQty"],
                    "fills": order["fills"],
                    "time_in_force": order["timeInForce"],
                    "status": order["status"],
                }
                # Build new deals list
                new_deals = []
                for d in bot["deals"]:
                    if d["deal_type"] != "take_profit":
                        new_deals.append(d)

                # Append now new take_profit deal
                new_deals.append(take_profit_order)
                self.active_bot["orders"] = new_deals
                botId = app.db.bots.update_one(
                    {"_id": self.active_bot["_id"]},
                    {"$push": {
                        "orders": take_profit_order
                    }},
                )
                if not botId:
                    print(f"Failed to update take_profit deal: {botId}")
                else:
                    print(
                        f"New take_profit deal successfully updated: {botId}")
                return