Exemplo n.º 1
0
def update_btb(update: Update, _: CallbackContext) -> int:
    logger.info(f"Updating Binance Trade Bot. ({update.message.text})")

    keyboard = [["OK 👌"]]
    reply_markup = ReplyKeyboardMarkup(keyboard, resize_keyboard=True)

    if update.message.text != "Cancel update":
        message = ("The bot has been stopped and is now updating\.\n"
                   "Wait a few seconds, then restart manually\.")
        update.message.reply_text(message,
                                  reply_markup=reply_markup,
                                  parse_mode="MarkdownV2")
        try:
            find_and_kill_binance_trade_bot_process()
            subprocess.call(
                f"cd {settings.ROOT_PATH} && "
                f"git pull && "
                f"$(which python3) -m pip install -r requirements.txt --upgrade",
                shell=True,
            )
        except Exception as e:
            logger.error(f"Unable to update Binance Trade Bot: {e}")
            message = "Unable to update Binance Trade Bot"
            update.message.reply_text(message,
                                      reply_markup=reply_markup,
                                      parse_mode="MarkdownV2")
    else:
        message = "👌 Exited without changes\.\n" "Binance Trade Bot was *not* updated\."
        update.message.reply_text(message,
                                  reply_markup=reply_markup,
                                  parse_mode="MarkdownV2")

    return MENU
Exemplo n.º 2
0
def delete_db(update: Update, _: CallbackContext) -> int:
    logger.info(
        f"Asking if the user really wants to delete the db. ({update.message.text})"
    )

    if update.message.text != "Go back":
        message = "✔ Successfully deleted database file\."
        db_file_path = os.path.join(settings.ROOT_PATH,
                                    "data/crypto_trading.db")
        log_file_path = os.path.join(settings.ROOT_PATH,
                                     "logs/crypto_trading.log")
        try:
            copyfile(db_file_path, f"{db_file_path}.backup")
            os.remove(db_file_path)
        except Exception as e:
            logger.error(f"❌ Unable to delete database file: {e}")
            message = "❌ Unable to delete database file\."
        try:
            with open(log_file_path, "w") as f:
                f.truncate()
        except Exception as e:
            logger.error(f"❌ Unable to clear log file: {e}")
            message = "❌ Unable to clear log file\."

    else:
        message = "👌 Exited without changes\.\n" "Your database was *not* deleted\."

    keyboard = [["OK"]]
    reply_markup = ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
    update.message.reply_text(message,
                              reply_markup=reply_markup,
                              parse_mode="MarkdownV2")

    return MENU
Exemplo n.º 3
0
def update_tg_bot(update: Update, _: CallbackContext) -> int:
    logger.info(f"Updating BTB Manager Telegram. ({update.message.text})")

    if update.message.text != "Cancel update":
        message = ("The bot is updating\.\n"
                   "Wait a few seconds then start the bot again with /start")
        keyboard = [["/start"]]
        reply_markup = ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
        update.message.reply_text(message,
                                  reply_markup=reply_markup,
                                  parse_mode="MarkdownV2")
        try:
            subprocess.call(
                f"git pull && $(which python3) -m pip install -r requirements.txt --upgrade && "
                f'$(which python3) -m btb_manager_telegram -p "{settings.ROOT_PATH}" &',
                shell=True,
            )
            kill_btb_manager_telegram_process()
        except Exception as e:
            logger.error(f"❌ Unable to update BTB Manager Telegram: {e}")
            message = "Unable to update BTB Manager Telegram"
            update.message.reply_text(message,
                                      reply_markup=reply_markup,
                                      parse_mode="MarkdownV2")
    else:
        message = ("👌 Exited without changes\.\n"
                   "BTB Manager Telegram was *not* updated\.")
        keyboard = [["OK 👌"]]
        reply_markup = ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
        update.message.reply_text(message,
                                  reply_markup=reply_markup,
                                  parse_mode="MarkdownV2")

    return MENU
Exemplo n.º 4
0
def edit_coin(update: Update, _: CallbackContext) -> int:
    logger.info(f"Editing coin list. ({update.message.text})")

    if update.message.text != "/stop":
        message = (f"✔ Successfully edited coin list file to:\n\n"
                   f"```\n"
                   f"{update.message.text}\n"
                   f"```".replace(".", "\."))
        coin_file_path = os.path.join(settings.ROOT_PATH,
                                      "supported_coin_list")
        try:
            copyfile(coin_file_path, f"{coin_file_path}.backup")
            with open(coin_file_path, "w") as f:
                f.write(update.message.text + "\n")
        except Exception as e:
            logger.error(f"❌ Unable to edit coin list file: {e}",
                         exc_info=True)
            message = "❌ Unable to edit coin list file\."
    else:
        message = "👌 Exited without changes\.\nYour `supported_coin_list` file was *not* modified\."

    keyboard = [["Go back"]]
    reply_markup = ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
    update.message.reply_text(message,
                              reply_markup=reply_markup,
                              parse_mode="MarkdownV2")

    return MENU
Exemplo n.º 5
0
def edit_user_config(update: Update, _: CallbackContext) -> int:
    logger.info(f"Editing user configuration. ({update.message.text})")

    if update.message.text != "/stop":
        message = (f"✔ Successfully edited user configuration file to:\n\n"
                   f"```\n"
                   f"{update.message.text}\n"
                   f"```".replace(".", "\."))
        user_cfg_file_path = os.path.join(settings.ROOT_PATH, "user.cfg")
        try:
            copyfile(user_cfg_file_path, f"{user_cfg_file_path}.backup")
            with open(user_cfg_file_path, "w") as f:
                f.write(update.message.text + "\n\n\n")
        except Exception as e:
            logger.error(f"❌ Unable to edit user configuration file: {e}")
            message = "❌ Unable to edit user configuration file\."
    else:
        message = ("👌 Exited without changes\.\n"
                   "Your `user.cfg` file was *not* modified\.")

    keyboard = [["Go back"]]
    reply_markup = ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
    update.message.reply_text(message,
                              reply_markup=reply_markup,
                              parse_mode="MarkdownV2")

    return MENU
Exemplo n.º 6
0
def check_progress():
    logger.info("Progress button pressed.")

    db_file_path = os.path.join(settings.ROOT_PATH, "data/crypto_trading.db")
    message = [f"⚠ Unable to find database file at `{db_file_path}`\."]
    if os.path.exists(db_file_path):
        try:
            con = sqlite3.connect(db_file_path)
            cur = con.cursor()

            # Get progress information
            try:
                cur.execute(
                    """SELECT th1.alt_coin_id AS coin, th1.alt_trade_amount AS amount, th1.crypto_trade_amount AS priceInUSD,(th1.alt_trade_amount - ( SELECT th2.alt_trade_amount FROM trade_history th2 WHERE th2.state = 'COMPLETE' AND th2.alt_coin_id = th1.alt_coin_id AND th1.datetime > th2.datetime AND th2.selling = 0 ORDER BY th2.datetime DESC LIMIT 1)) AS change, (SELECT th2.datetime FROM trade_history th2 WHERE th2.state = 'COMPLETE' AND th2.alt_coin_id = th1.alt_coin_id AND th1.datetime > th2.datetime AND th2.selling = 0 ORDER BY th2.datetime DESC LIMIT 1) AS pre_last_trade_date, datetime FROM trade_history th1 WHERE th1.state = 'COMPLETE' AND th1.selling = 0 ORDER BY th1.datetime DESC LIMIT 15"""
                )
                query = cur.fetchall()

                # Generate message
                m_list = ["Current coin amount progress:\n\n"]
                for coin in query:
                    last_trade_date = datetime.strptime(
                        coin[5], "%Y-%m-%d %H:%M:%S.%f")
                    if coin[4] is None:
                        pre_last_trade_date = datetime.strptime(
                            coin[5], "%Y-%m-%d %H:%M:%S.%f")
                    else:
                        pre_last_trade_date = datetime.strptime(
                            coin[4], "%Y-%m-%d %H:%M:%S.%f")

                    time_passed = last_trade_date - pre_last_trade_date
                    last_trade_date = last_trade_date.strftime(
                        "%H:%M:%S %d/%m/%Y")
                    m_list.append(
                        f"*{coin[0]}*\n"
                        f"\t\- Amount: `{format_float(coin[1])}` *{coin[0]}*\n"
                        f"\t\- Price: `{round(coin[2]*0.71, 2)}` *GBP*\n"
                        f"\t\- Price: `{round(coin[2], 2)}` *USD*\n"
                        f"\t\- Change: {f'`{format_float(coin[3])}` *{coin[0]}* `{round(coin[3] / (coin[1] - coin[3]) * 100, 2)}` *%* in {time_passed.days} days, {time_passed.seconds // 3600} hours' if coin[3] is not None else f'`{coin[3]}`'}\n"
                        f"\t\- Trade datetime: `{last_trade_date}`\n\n".
                        replace(".", "\."))

                message = telegram_text_truncator(m_list)
                con.close()
            except Exception as e:
                logger.error(
                    f"❌ Unable to fetch progress information from database: {e}",
                    exc_info=True,
                )
                con.close()
                return [
                    "❌ Unable to fetch progress information from database\."
                ]
        except Exception as e:
            logger.error(f"❌ Unable to perform actions on the database: {e}",
                         exc_info=True)
            message = ["❌ Unable to perform actions on the database\."]
    return message
Exemplo n.º 7
0
def is_tg_bot_update_available():
    try:
        proc = subprocess.Popen(
            ["bash", "-c", "git remote update && git status -uno"],
            stdout=subprocess.PIPE,
        )
        output, _ = proc.communicate()
        re = "Your branch is behind" in str(output)
    except Exception as e:
        logger.error(e, exc_info=True)
        re = None
    return re
Exemplo n.º 8
0
def next_coin():
    logger.info("Next coin button pressed.")

    db_file_path = os.path.join(settings.ROOT_PATH, "data/crypto_trading.db")
    user_cfg_file_path = os.path.join(settings.ROOT_PATH, "user.cfg")
    message = [f"⚠ Unable to find database file at `{db_file_path}`\."]
    if os.path.exists(db_file_path):
        try:
            # Get bridge currency symbol
            with open(user_cfg_file_path) as cfg:
                config = ConfigParser()
                config.read_file(cfg)
                bridge = config.get("binance_user_config", "bridge")
                scout_multiplier = config.get("binance_user_config",
                                              "scout_multiplier")

            con = sqlite3.connect(db_file_path)
            cur = con.cursor()

            # Get prices and percentages for a jump to the next coin
            try:
                cur.execute(
                    f"""SELECT p.to_coin_id as other_coin, sh.other_coin_price, (current_coin_price - 0.001 * '{scout_multiplier}' * current_coin_price) / sh.target_ratio AS 'price_needs_to_drop_to', ((current_coin_price - 0.001 * '{scout_multiplier}' * current_coin_price) / sh.target_ratio) / sh.other_coin_price as 'percentage' FROM scout_history sh JOIN pairs p ON p.id = sh.pair_id WHERE p.from_coin_id = (SELECT alt_coin_id FROM trade_history ORDER BY datetime DESC LIMIT 1) ORDER BY sh.datetime DESC, percentage DESC LIMIT (SELECT count(DISTINCT pairs.to_coin_id) FROM pairs JOIN coins ON coins.symbol = pairs.to_coin_id WHERE coins.enabled = 1 AND pairs.from_coin_id=(SELECT alt_coin_id FROM trade_history ORDER BY datetime DESC LIMIT 1));"""
                )
                query = cur.fetchall()

                m_list = []
                for coin in query:
                    percentage = round(coin[3] * 100, 2)
                    m_list.append(
                        f"*{coin[0]} \(`{format_float(percentage)}`%\)*\n"
                        f"\t\- Current Price: `{format_float(round(coin[1], 8))}` {bridge}\n"
                        f"\t\- Target Price: `{format_float(round(coin[2], 8))}` {bridge}\n\n"
                        .replace(".", "\."))

                message = telegram_text_truncator(m_list)
                con.close()
            except Exception as e:
                logger.error(
                    f"❌ Something went wrong, unable to generate next coin at this time: {e}",
                    exc_info=True,
                )
                con.close()
                return [
                    "❌ Something went wrong, unable to generate next coin at this time\.",
                    "⚠ Please make sure logging for _Binance Trade Bot_ is enabled\.",
                ]
        except Exception as e:
            logger.error(f"❌ Unable to perform actions on the database: {e}",
                         exc_info=True)
            message = ["❌ Unable to perform actions on the database\."]
    return message
Exemplo n.º 9
0
def is_btb_bot_update_available():
    try:
        proc = subprocess.Popen(
            [
                "bash",
                "-c",
                f"cd {settings.ROOT_PATH} && git remote update && git status -uno",
            ],
            stdout=subprocess.PIPE,
        )
        output, _ = proc.communicate()
        re = "Your branch is behind" in str(output)
    except Exception as e:
        logger.error(e)
        re = None
    return re
Exemplo n.º 10
0
def trade_history():
    logger.info("Trade history button pressed.")

    db_file_path = os.path.join(settings.ROOT_PATH, "data/crypto_trading.db")
    message = [f"⚠ Unable to find database file at `{db_file_path}`\."]
    if os.path.exists(db_file_path):
        try:
            con = sqlite3.connect(db_file_path)
            cur = con.cursor()

            # Get last 10 trades
            try:
                cur.execute(
                    """SELECT alt_coin_id, crypto_coin_id, selling, state, alt_trade_amount, crypto_trade_amount, datetime FROM trade_history ORDER BY datetime DESC LIMIT 10;"""
                )
                query = cur.fetchall()

                m_list = [
                    f"Last **{10 if len(query) > 10 else len(query)}** trades:\n\n"
                ]
                for trade in query:
                    if trade[4] is None:
                        continue
                    date = datetime.strptime(trade[6], "%Y-%m-%d %H:%M:%S.%f")
                    m_list.append(
                        f"`{date.strftime('%H:%M:%S %d/%m/%Y')}`\n"
                        f"*{'Sold' if trade[2] else 'Bought'}* `{format_float(trade[4])}` *{trade[0]}*{f' for `{format_float(trade[5])}` *{trade[1]}*' if trade[5] is not None else ''}\n"
                        f"Status: _*{trade[3]}*_\n\n".replace(".", "\.")
                    )

                message = telegram_text_truncator(m_list)
                con.close()
            except Exception as e:
                logger.error(
                    f"❌ Something went wrong, unable to generate trade history at this time: {e}",
                    exc_info=True,
                )
                con.close()
                return [
                    "❌ Something went wrong, unable to generate trade history at this time\."
                ]
        except Exception as e:
            logger.error(
                f"❌ Unable to perform actions on the database: {e}", exc_info=True
            )
            message = ["❌ Unable to perform actions on the database\."]
    return message
Exemplo n.º 11
0
def execute_custom_script(update: Update, _: CallbackContext) -> int:
    logger.info(f"Going to 🤖 execute custom script. ({update.message.text})")

    keyboard = [["OK 👌"]]
    reply_markup = ReplyKeyboardMarkup(keyboard, resize_keyboard=True)

    custom_scripts_path = "./config/custom_scripts.json"
    if update.message.text != "Cancel":
        with open(custom_scripts_path) as f:
            scripts = json.load(f)

            try:
                command = ["bash", "-c", str(scripts[update.message.text])]
            except Exception as e:
                logger.error(
                    f"Unable to find script named {update.message.text} in custom_scripts.json file: {e}",
                    exc_info=True,
                )
                message = f"Unable to find script named `{escape_markdown(update.message.text, version=2)}` in `custom_scripts.json` file\."
                update.message.reply_text(message,
                                          reply_markup=reply_markup,
                                          parse_mode="MarkdownV2")

            try:
                proc = subprocess.Popen(
                    command,
                    stdout=subprocess.PIPE,
                )
                output, _ = proc.communicate()
                message_list = telegram_text_truncator(
                    escape_markdown(output.decode("utf-8"), version=2),
                    padding_chars_head="```\n",
                    padding_chars_tail="```",
                )
                for message in message_list:
                    update.message.reply_text(message,
                                              reply_markup=reply_markup,
                                              parse_mode="MarkdownV2")
            except Exception as e:
                logger.error(f"Error during script execution: {e}",
                             exc_info=True)
                message = "Error during script execution\."
                update.message.reply_text(message,
                                          reply_markup=reply_markup,
                                          parse_mode="MarkdownV2")

    return MENU
Exemplo n.º 12
0
def setup_telegram_constants():
    logger.info("Retrieving Telegram token and chat_id from apprise.yml file.")
    telegram_url = None
    yaml_file_path = os.path.join(settings.ROOT_PATH, "config/apprise.yml")
    if os.path.exists(yaml_file_path):
        with open(yaml_file_path) as f:
            try:
                parsed_urls = yaml.load(f, Loader=yaml.FullLoader)["urls"]
            except Exception:
                logger.error(
                    "Unable to correctly read apprise.yml file. Make sure it is correctly set up. Aborting."
                )
                exit(-1)
            for url in parsed_urls:
                if url.startswith("tgram"):
                    telegram_url = url.split("//")[1]
        if not telegram_url:
            logger.error(
                "No telegram configuration was found in your apprise.yml file. Aborting."
            )
            exit(-1)
    else:
        logger.error(
            f'Unable to find apprise.yml file at "{yaml_file_path}". Aborting.'
        )
        exit(-1)
    try:
        settings.TOKEN = telegram_url.split("/")[0]
        settings.CHAT_ID = telegram_url.split("/")[1]
        logger.info(
            f"Successfully retrieved Telegram configuration. "
            f"The bot will only respond to user in the chat with chat_id {settings.CHAT_ID}"
        )
    except Exception:
        logger.error(
            "No chat_id has been set in the yaml configuration, anyone would be able to control your bot. Aborting."
        )
        exit(-1)
Exemplo n.º 13
0
def panic_btn():
    logger.info("🚨 Panic Button button pressed.")

    # Check if open orders / not in usd
    db_file_path = os.path.join(settings.ROOT_PATH, "data/crypto_trading.db")
    if not os.path.exists(db_file_path):
        return ["ERROR: Database file not found\.", -1]

    user_cfg_file_path = os.path.join(settings.ROOT_PATH, "user.cfg")
    if not os.path.exists(user_cfg_file_path):
        return ["ERROR: `user.cfg` file not found\.", -1]

    try:
        con = sqlite3.connect(db_file_path)
        cur = con.cursor()

        # Get last trade
        try:
            cur.execute(
                """SELECT alt_coin_id, crypto_coin_id, selling, state, alt_trade_amount, crypto_trade_amount FROM trade_history ORDER BY datetime DESC LIMIT 1;"""
            )
            (
                alt_coin_id,
                crypto_coin_id,
                selling,
                state,
                alt_trade_amount,
                crypto_trade_amount,
            ) = cur.fetchone()

            if not selling:
                price_old = crypto_trade_amount / alt_trade_amount
                price_now = get_current_price(alt_coin_id, crypto_coin_id)
                if state == "COMPLETE":
                    return [
                        f"You are currently holding `{round(alt_trade_amount, 6)}` *{alt_coin_id}* bought for `{round(crypto_trade_amount, 2)}` *{crypto_coin_id}*.\n\n"
                        f"Exchange rate when bought:\n"
                        f"`{round(price_old, 4)}` *{crypto_coin_id}*/*{alt_coin_id}*\n\n"
                        f"Current exchange rate:\n"
                        f"`{round(price_now, 4)}` *{crypto_coin_id}*/*{alt_coin_id}*\n\n"
                        f"Current value:\n"
                        f"`{round(price_now * alt_trade_amount, 4)}` *{crypto_coin_id}*\n\n"
                        f"Change:\n"
                        f"`{round((price_now - price_old) / price_old * 100, 2)}` *%*\n\n"
                        f"Would you like to stop _Binance Trade Bot_ and sell at market price?"
                        .replace(".", "\."),
                        BOUGHT,
                    ]
                else:
                    return [
                        f"You have an open buy order of `{alt_trade_amount}` *{alt_coin_id}* for `{crypto_trade_amount}` *{crypto_coin_id}*.\n\n"
                        f"Limit buy at price:\n"
                        f"`{round(price_old, 4)}` *{crypto_coin_id}*/*{alt_coin_id}*\n\n"
                        f"Current exchange rate:\n"
                        f"`{round(price_now, 4)}` *{crypto_coin_id}*/*{alt_coin_id}*\n\n"
                        f"Change:\n"
                        f"`{round((price_now - price_old) / price_old * 100, 2)}` *%*\n\n"
                        f"Would you like to stop _Binance Trade Bot_ and cancel the open order?"
                        .replace(".", "\."),
                        BUYING,
                    ]
            else:
                if state == "COMPLETE":
                    return [
                        f"Your balance is already in *{crypto_coin_id}*.\n\n"
                        f"Would you like to stop _Binance Trade Bot_?".replace(
                            ".", "\."),
                        SOLD,
                    ]
                else:
                    price_old = crypto_trade_amount / alt_trade_amount
                    price_now = get_current_price(alt_coin_id, crypto_coin_id)
                    return [
                        f"You have an open sell order of `{alt_trade_amount}` *{alt_coin_id}* for `{crypto_trade_amount}` *{crypto_coin_id}*.\n\n"
                        f"Limit sell at price:\n"
                        f"`{round(price_old, 4)}` *{crypto_coin_id}*/*{alt_coin_id}*\n\n"
                        f"Current exchange rate:\n"
                        f"`{round(price_now, 4)}` *{crypto_coin_id}*/*{alt_coin_id}*\n\n"
                        f"Change:\n"
                        f"`{round((price_now - price_old) / price_old * 100, 2)}` *%*\n\n"
                        f"Would you like to stop _Binance Trade Bot_ and cancel the open order?"
                        .replace(".", "\."),
                        SELLING,
                    ]

            con.close()
        except Exception as e:
            con.close()
            logger.error(
                f"❌ Something went wrong, the panic button is not working at this time: {e}",
                exc_info=True,
            )
            return [
                "❌ Something went wrong, the panic button is not working at this time\.",
                -1,
            ]
    except Exception as e:
        logger.error(f"❌ Unable to perform actions on the database: {e}",
                     exc_info=True)
        return ["❌ Unable to perform actions on the database\.", -1]
Exemplo n.º 14
0
def current_ratios():
    logger.info("Current ratios button pressed.")

    db_file_path = os.path.join(settings.ROOT_PATH, "data/crypto_trading.db")
    user_cfg_file_path = os.path.join(settings.ROOT_PATH, "user.cfg")
    message = [f"⚠ Unable to find database file at `{db_file_path}`\."]
    if os.path.exists(db_file_path):
        try:
            # Get bridge currency symbol
            with open(user_cfg_file_path) as cfg:
                config = ConfigParser()
                config.read_file(cfg)
                bridge = config.get("binance_user_config", "bridge")
                scout_multiplier = config.get("binance_user_config",
                                              "scout_multiplier")

            con = sqlite3.connect(db_file_path)
            cur = con.cursor()

            # Get current coin symbol
            try:
                cur.execute(
                    """SELECT alt_coin_id FROM trade_history ORDER BY datetime DESC LIMIT 1;"""
                )
                current_coin = cur.fetchone()[0]
                if current_coin is None:
                    raise Exception()
            except Exception as e:
                logger.error(
                    f"❌ Unable to fetch current coin from database: {e}",
                    exc_info=True)
                con.close()
                return ["❌ Unable to fetch current coin from database\."]

            # Get prices and ratios of all alt coins
            try:
                cur.execute(
                    f"""SELECT sh.datetime, p.to_coin_id, sh.other_coin_price, ( ( ( current_coin_price / other_coin_price ) - 0.001 * '{scout_multiplier}' * ( current_coin_price / other_coin_price ) ) - sh.target_ratio ) AS 'ratio_dict' FROM scout_history sh JOIN pairs p ON p.id = sh.pair_id WHERE p.from_coin_id='{current_coin}' AND p.from_coin_id = ( SELECT alt_coin_id FROM trade_history ORDER BY datetime DESC LIMIT 1) ORDER BY sh.datetime DESC LIMIT ( SELECT count(DISTINCT pairs.to_coin_id) FROM pairs JOIN coins ON coins.symbol = pairs.to_coin_id WHERE coins.enabled = 1 AND pairs.from_coin_id='{current_coin}');"""
                )
                query = cur.fetchall()

                # Generate message
                last_update = datetime.strptime(query[0][0],
                                                "%Y-%m-%d %H:%M:%S.%f")
                query = sorted(query, key=lambda k: k[-1], reverse=True)

                m_list = [
                    f"\nLast update: `{last_update.strftime('%H:%M:%S %d/%m/%Y')}`\n\n"
                    f"*Coin ratios compared to {current_coin} in decreasing order:*\n"
                    .replace(".", "\.")
                ]
                for coin in query:
                    m_list.append(
                        f"*{coin[1]}*:\n"
                        f"\t\- Price: `{coin[2]}` {bridge}\n"
                        f"\t\- Ratio: `{format_float(coin[3])}`\n\n".replace(
                            ".", "\."))

                message = telegram_text_truncator(m_list)
                con.close()
            except Exception as e:
                logger.error(
                    f"❌ Something went wrong, unable to generate ratios at this time: {e}",
                    exc_info=True,
                )
                con.close()
                return [
                    "❌ Something went wrong, unable to generate ratios at this time\.",
                    "⚠ Please make sure logging for _Binance Trade Bot_ is enabled\.",
                ]
        except Exception as e:
            logger.error(f"❌ Unable to perform actions on the database: {e}",
                         exc_info=True)
            message = ["❌ Unable to perform actions on the database\."]
    return message
Exemplo n.º 15
0
def current_value():
    logger.info("Current value button pressed.")

    db_file_path = os.path.join(settings.ROOT_PATH, "data/crypto_trading.db")
    message = [f"⚠ Unable to find database file at `{db_file_path}`\."]
    if os.path.exists(db_file_path):
        try:
            con = sqlite3.connect(db_file_path)
            cur = con.cursor()

            # Get current coin symbol, bridge symbol, order state, order size, initial buying price
            try:
                cur.execute(
                    """SELECT alt_coin_id, crypto_coin_id, state, alt_trade_amount, crypto_starting_balance, crypto_trade_amount FROM trade_history ORDER BY datetime DESC LIMIT 1;"""
                )
                (
                    current_coin,
                    bridge,
                    state,
                    alt_amount,
                    order_size,
                    buy_price,
                ) = cur.fetchone()
                if current_coin is None:
                    raise Exception()
                if state == "ORDERED":
                    return [
                        f"A buy order of `{format_float(order_size)}` *{bridge}* is currently placed on coin *{current_coin}*.\n\n"
                        f"_Waiting for buy order to complete_.".replace(
                            ".", "\.")
                    ]
            except Exception as e:
                logger.error(
                    f"❌ Unable to fetch current coin from database: {e}",
                    exc_info=True)
                con.close()
                return ["❌ Unable to fetch current coin from database\."]

            # Get balance, current coin price in USD, current coin price in BTC
            try:
                cur.execute(f"""SELECT balance, usd_price, btc_price, datetime
                        FROM 'coin_value'
                        WHERE coin_id = '{current_coin}'
                        ORDER BY datetime DESC LIMIT 1;""")
                query = cur.fetchone()

                cur.execute("""SELECT cv.balance, cv.usd_price
                        FROM coin_value as cv
                        WHERE cv.coin_id = (SELECT th.alt_coin_id FROM trade_history as th WHERE th.datetime > DATETIME ('now', '-1 day') AND th.selling = 0 ORDER BY th.datetime ASC LIMIT 1)
                        AND cv.datetime > (SELECT th.datetime FROM trade_history as th WHERE th.datetime > DATETIME ('now', '-1 day') AND th.selling = 0 ORDER BY th.datetime ASC LIMIT 1)
                        ORDER BY cv.datetime ASC LIMIT 1;""")
                query_1_day = cur.fetchone()

                cur.execute("""SELECT cv.balance, cv.usd_price
                        FROM coin_value as cv
                        WHERE cv.coin_id = (SELECT th.alt_coin_id FROM trade_history as th WHERE th.datetime > DATETIME ('now', '-7 day') AND th.selling = 0 ORDER BY th.datetime ASC LIMIT 1)
                        AND cv.datetime > (SELECT th.datetime FROM trade_history as th WHERE th.datetime > DATETIME ('now', '-7 day') AND th.selling = 0 ORDER BY th.datetime ASC LIMIT 1)
                        ORDER BY cv.datetime ASC LIMIT 1;""")
                query_7_day = cur.fetchone()

                if query is None:
                    return [
                        f"❌ No information about *{current_coin}* available in the database\.",
                        "⚠ If you tried using the `Current value` button during a trade please try again after the trade has been completed\.",
                    ]

                balance, usd_price, btc_price, last_update = query
                if balance is None:
                    balance = 0
                if usd_price is None:
                    usd_price = 0
                if btc_price is None:
                    btc_price = 0
                last_update = datetime.strptime(last_update,
                                                "%Y-%m-%d %H:%M:%S.%f")

                return_rate_1_day, return_rate_7_day = 0, 0
                balance_1_day, usd_price_1_day, balance_7_day, usd_price_7_day = (
                    0,
                    0,
                    0,
                    0,
                )

                if (query_1_day is not None
                        and all(elem is not None for elem in query_1_day)
                        and usd_price != 0):
                    balance_1_day, usd_price_1_day = query_1_day
                    return_rate_1_day = round(
                        (balance * usd_price - balance_1_day * usd_price_1_day)
                        / (balance_1_day * usd_price_1_day) * 100,
                        2,
                    )

                if (query_7_day is not None
                        and all(elem is not None for elem in query_7_day)
                        and usd_price != 0):
                    balance_7_day, usd_price_7_day = query_7_day
                    return_rate_7_day = round(
                        (balance * usd_price - balance_7_day * usd_price_7_day)
                        / (balance_7_day * usd_price_7_day) * 100,
                        2,
                    )
            except Exception as e:
                logger.error(
                    f"❌ Unable to fetch current coin information from database: {e}",
                    exc_info=True,
                )
                con.close()
                return [
                    "❌ Unable to fetch current coin information from database\.",
                    "⚠ If you tried using the `Current value` button during a trade please try again after the trade has been completed\.",
                ]

            # Generate message
            try:
                m_list = [
                    f"\nLast update: `{last_update.strftime('%H:%M:%S %d/%m/%Y')}`\n\n"
                    f"*Current coin {current_coin}:*\n"
                    f"\t\- Balance: `{format_float(balance)}` *{current_coin}*\n"
                    f"\t\- Exchange rate purchased: `{format_float(buy_price / alt_amount)}` *{bridge}*/*{current_coin}* \n"
                    f"\t\- Exchange rate now: `{format_float(usd_price)}` *USD*/*{current_coin}*\n"
                    f"\t\- Change in value: `{round((balance * usd_price - buy_price) / buy_price * 100, 2)}` *%*\n"
                    f"\t\- Value in *GBP*: `{round((balance * usd_price)*0.71, 2)}` *GBP*\n"
                    f"\t\- Value in *USD*: `{round(balance * usd_price, 2)}` *USD*\n"
                    f"\t\- Value in *BTC*: `{format_float(balance * btc_price)}` *BTC*\n\n"
                    f"_Bought for_ `{round(buy_price, 2)}` *{bridge}* / `{round(buy_price*0.71, 2)}` *GBP*\n"
                    f"_*1 day* value change USD_: `{return_rate_1_day}` *%*\n"
                    f"_*7 days* value change USD_: `{return_rate_7_day}` *%*\n"
                ]
                message = telegram_text_truncator(m_list)
                con.close()
            except Exception as e:
                logger.error(
                    f"❌ Something went wrong, unable to generate value at this time: {e}",
                    exc_info=True,
                )
                con.close()
                return [
                    "❌ Something went wrong, unable to generate value at this time\."
                ]
        except Exception as e:
            logger.error(f"❌ Unable to perform actions on the database: {e}",
                         exc_info=True)
            message = ["❌ Unable to perform actions on the database\."]
    return message
Exemplo n.º 16
0
def current_value():
    logger.info("Current value button pressed.")

    db_file_path = os.path.join(settings.ROOT_PATH, "data/crypto_trading.db")
    message = [f"⚠ Unable to find database file at `{db_file_path}`\."]
    if os.path.exists(db_file_path):
        try:
            con = sqlite3.connect(db_file_path)
            cur = con.cursor()

            # Get current coin symbol, bridge symbol, order state, order size, initial buying price
            try:
                cur.execute(
                    """SELECT alt_coin_id, crypto_coin_id, state, alt_trade_amount, crypto_starting_balance, crypto_trade_amount FROM trade_history ORDER BY datetime DESC LIMIT 1;"""
                )
                (
                    current_coin,
                    bridge,
                    state,
                    alt_amount,
                    order_size,
                    buy_price,
                ) = cur.fetchone()
                if current_coin is None:
                    raise Exception()
                if state == "ORDERED":
                    return [
                        f"A buy order of `{format_float(order_size)}` *{bridge}* is currently placed on coin *{current_coin}*.\n\n"
                        f"_Waiting for buy order to complete_.".replace(".", "\.")
                    ]
            except Exception as e:
                logger.error(
                    f"❌ Unable to fetch current coin from database: {e}", exc_info=True
                )
                con.close()
                return ["❌ Unable to fetch current coin from database\."]

            # Get balance, current coin price in USD, current coin price in BTC
            try:
                cur.execute(
                    f"""SELECT balance, usd_price, btc_price, datetime FROM 'coin_value' WHERE coin_id = '{current_coin}' ORDER BY datetime DESC LIMIT 1;"""
                )
                query = cur.fetchone()
                if query is None:
                    return [
                        f"❌ No information about *{current_coin}* available in the database\.",
                        "⚠ If you tried using the `Current value` button during a trade please try again after the trade has been completed\.",
                    ]
                balance, usd_price, btc_price, last_update = query
                if balance is None:
                    balance = 0
                if usd_price is None:
                    usd_price = 0
                if btc_price is None:
                    btc_price = 0
                last_update = datetime.strptime(last_update, "%Y-%m-%d %H:%M:%S.%f")
            except Exception as e:
                logger.error(
                    f"❌ Unable to fetch current coin information from database: {e}",
                    exc_info=True,
                )
                con.close()
                return [
                    "❌ Unable to fetch current coin information from database\.",
                    "⚠ If you tried using the `Current value` button during a trade please try again after the trade has been completed\.",
                ]

            # Generate message
            try:
                m_list = [
                    f"\nLast update: `{last_update.strftime('%H:%M:%S %d/%m/%Y')}`\n\n"
                    f"*Current coin {current_coin}:*\n"
                    f"\t\- Balance: `{format_float(balance)}` *{current_coin}*\n"
                    f"\t\- Current coin exchange rate: `{format_float(usd_price)}` *USD*/*{current_coin}*\n"
                    f"\t\- Value in *USD*: `{round(balance * usd_price, 2)}` *USD*\n"
                    f"\t\- Value in *BTC*: `{format_float(balance * btc_price)}` *BTC*\n\n"
                    f"_Initially bought for_ `{round(buy_price, 2)}` *{bridge}*\n"
                    f"_Exchange rate when purchased:_ `{format_float(buy_price / alt_amount)}` *{bridge}*/*{current_coin}*\n"
                    f"{f'*Change in value*: `{round((balance * usd_price - buy_price) / buy_price * 100, 2)}` *%*' if bridge in ['USDT', 'BUSD'] else ''}".replace(
                        ".", "\."
                    )
                ]
                message = telegram_text_truncator(m_list)
                con.close()
            except Exception as e:
                logger.error(
                    f"❌ Something went wrong, unable to generate value at this time: {e}",
                    exc_info=True,
                )
                con.close()
                return [
                    "❌ Something went wrong, unable to generate value at this time\."
                ]
        except Exception as e:
            logger.error(
                f"❌ Unable to perform actions on the database: {e}", exc_info=True
            )
            message = ["❌ Unable to perform actions on the database\."]
    return message