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
def find_and_kill_binance_trade_bot_process(): try: binance_trade_bot_process = get_binance_trade_bot_process() binance_trade_bot_process.terminate() binance_trade_bot_process.wait() except Exception as e: logger.info(f"ERROR: {e}")
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
def edit_user_cfg(): logger.info("Edit user configuration button pressed.") message = "β Please stop Binance Trade Bot before editing user configuration file\." edit = False user_cfg_file_path = os.path.join(settings.ROOT_PATH, "user.cfg") if not get_binance_trade_bot_process(): if os.path.exists(user_cfg_file_path): with open(user_cfg_file_path) as f: message = ( f"Current configuration file is:\n\n" f"```\n" f"{f.read()}\n" f"```\n\n" f"_*Please reply with a message containing the updated configuration*_.\n\n" f"Write /stop to stop editing and exit without changes.".replace( ".", "\." ) ) edit = True else: message = f"β Unable to find user configuration file at `{user_cfg_file_path}`.".replace( ".", "\." ) return [message, edit]
def get_custom_scripts_keyboard(): logger.info("Getting list of custom scripts.") custom_scripts_path = "./config/custom_scripts.json" keyboard = [] custom_script_exist = False message = "No custom script was found inside *BTB\-manager\-telegram*'s `/config/custom_scripts.json` file\." if os.path.exists(custom_scripts_path): with open(custom_scripts_path) as f: scripts = json.load(f) for script_name in scripts: keyboard.append([script_name]) if len(keyboard) >= 1: custom_script_exist = True message = "Select one of your custom scripts to execute it\." else: logger.warning( "Unable to find custom_scripts.json file inside BTB-manager-telegram's config/ directory." ) message = "Unable to find `custom_scripts.json` file inside *BTB\-manager\-telegram*'s `config/` directory\." keyboard.append(["Cancel"]) return keyboard, custom_script_exist, message
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: 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
def check_status(): logger.info("Check status button pressed.") message = "β Binance Trade Bot is not running." if get_binance_trade_bot_process(): message = "β Binance Trade Bot is running." return message
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
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
def cancel(update: Update, _: CallbackContext) -> int: logger.info("Conversation canceled.") update.message.reply_text( "Bye! I hope we can talk again some day.", reply_markup=ReplyKeyboardRemove(), ) return ConversationHandler.END
def kill_btb_manager_telegram_process(): try: btb_manager_telegram_pid = os.getpid() btb_manager_telegram_process = psutil.Process(btb_manager_telegram_pid) btb_manager_telegram_process.kill() btb_manager_telegram_process.wait() except Exception as e: logger.info(f"ERROR: {e}")
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
def update_reminder(self, message): logger.info(f"Reminding user: {message}") bot = Bot(settings.TOKEN) bot.send_message(settings.CHAT_ID, message, parse_mode="MarkdownV2") scheduler.enter( 60 * 60 * 12, 1, update_reminder, )
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
def stop_bot(): logger.info("Stop bot button pressed.") message = "β Binance Trade Bot is not running." if get_binance_trade_bot_process(): find_and_kill_binance_trade_bot_process() if not get_binance_trade_bot_process(): message = "β Successfully stopped the bot." else: message = ( "β Unable to stop Binance Trade Bot.\n\n" "If you are running the telegram bot on Windows make sure to run with administrator privileges." ) return message
def export_db(): logger.info("Export database button pressed.") message = "β Please stop Binance Trade Bot before exporting the database file\." db_file_path = os.path.join(settings.ROOT_PATH, "data/crypto_trading.db") fil = None if not get_binance_trade_bot_process(): if os.path.exists(db_file_path): with open(db_file_path, "rb") as db: fil = db.read() message = "Here is your database file:" else: message = "β Unable to Export the database file\." return [message, fil]
def read_log(): logger.info("Read log button pressed.") log_file_path = os.path.join(settings.ROOT_PATH, "logs/crypto_trading.log") message = f"β Unable to find log file at `{log_file_path}`.".replace( ".", "\.") if os.path.exists(log_file_path): with open(log_file_path) as f: file_content = f.read().replace(".", "\.")[-4000:] message = (f"Last *4000* characters in log file:\n\n" f"```\n" f"{file_content}\n" f"```") return message
def update_btb(): logger.info("β¬ Update Binance Trade Bot button pressed.") message = "Your Binance Trade Bot installation is already up to date\." upd = False to_update = is_btb_bot_update_available() if to_update is not None: if to_update: upd = True message = ("An update for Binance Trade Bot is available\.\n" "Would you like to update now?") else: message = "Error while trying to fetch Binance Trade Bot version information\." return [message, upd]
def delete_db(): logger.info("Delete database button pressed.") message = "β Please stop Binance Trade Bot before deleting the database file\." delete = False db_file_path = os.path.join(settings.ROOT_PATH, "data/crypto_trading.db") if not get_binance_trade_bot_process(): if os.path.exists(db_file_path): message = "Are you sure you want to delete the database file?" delete = True else: message = f"β Unable to find database file at `{db_file_path}`.".replace( ".", "\." ) return [message, delete]
def update_tg_bot(): logger.info("β¬ Update Telegram Bot button pressed.") message = "Your BTB Manager Telegram installation is already up to date\." upd = False to_update = is_tg_bot_update_available() if to_update is not None: if to_update: message = ("An update for BTB Manager Telegram is available\.\n" "Would you like to update now?") upd = True else: message = ( "Error while trying to fetch BTB Manager Telegram version information\." ) return [message, upd]
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
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
def start_bot(): logger.info("Start bot button pressed.") message = "β Binance Trade Bot is already running\." if not get_binance_trade_bot_process(): if os.path.exists(os.path.join(settings.ROOT_PATH, "binance_trade_bot/")): subprocess.call( f"cd {settings.ROOT_PATH} && $(which python3) -m binance_trade_bot &", shell=True, ) if get_binance_trade_bot_process(): message = "β Binance Trade Bot successfully started\." else: message = "β Unable to start Binance Trade Bot\." else: message = ( f"β Unable to find _Binance Trade Bot_ installation at {settings.ROOT_PATH}\.\n" f"Make sure the `binance-trade-bot` and `BTB-manager-telegram` are in the same parent directory\." ) return message
def edit_coin(): logger.info("Edit coin list button pressed.") message = "β Please stop Binance Trade Bot before editing the coin list\." edit = False coin_file_path = os.path.join(settings.ROOT_PATH, "supported_coin_list") if not get_binance_trade_bot_process(): if os.path.exists(coin_file_path): with open(coin_file_path) as f: message = ( f"Current coin list is:\n\n" f"```\n{f.read()}\n```\n\n" f"_*Please reply with a message containing the updated coin list*_.\n\n" f"Write /stop to stop editing and exit without changes.". replace(".", "\.")) edit = True else: message = f"β Unable to find coin list file at `{coin_file_path}`.".replace( ".", "\.") return [message, edit]
def start(update: Update, _: CallbackContext) -> int: logger.info("Started conversation.") keyboard = [["Begin"]] message = ( f"Hi *{escape_markdown(update.message.from_user.first_name)}*\!\n" f"Welcome to _Binace Trade Bot Manager Telegram_\.\n\n" f"This Telegram bot was developed by @lorcalhost\.\n" f"Find out more about the project [here](https://github.com/lorcalhost/BTB-manager-telegram)\.\n\n" f"If you like the bot please [consider supporting the project π»](https://www.buymeacoffee.com/lorcalhost)\." ) reply_markup = ReplyKeyboardMarkup(keyboard, one_time_keyboard=True, resize_keyboard=True) update.message.reply_text( message, reply_markup=reply_markup, parse_mode="MarkdownV2", disable_web_page_preview=True, ) return MENU
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)
def update_checker(): logger.info("Checking for updates.") if settings.TG_UPDATE_BROADCASTED_BEFORE is False: if is_tg_bot_update_available(): logger.info("BTB Manager Telegram update found.") message = ( "Γ’Ε‘Β An update for _BTB Manager Telegram_ is available\.\n\n" "Please update by going to *Γ°ΕΈβΊΒ Maintenance* and pressing the *Γ’Β¬β Update Telegram Bot* button\." ) settings.TG_UPDATE_BROADCASTED_BEFORE = True bot = Bot(settings.TOKEN) bot.send_message(settings.CHAT_ID, message, parse_mode="MarkdownV2") sleep(1) bot.close() sleep(1) scheduler.enter( 60 * 60 * 12, 1, update_reminder, ("_*Reminder*_:\n\n" + message, ), ) if settings.BTB_UPDATE_BROADCASTED_BEFORE is False: if is_btb_bot_update_available(): logger.info("Binance Trade Bot update found.") message = ( "Γ’Ε‘Β An update for _Binance Trade Bot_ is available\.\n\n" "Please update by going to *Γ°ΕΈβΊΒ Maintenance* and pressing the *Update Binance Trade Bot* button\." ) settings.BTB_UPDATE_BROADCASTED_BEFORE = True bot = Bot(settings.TOKEN) bot.send_message(settings.CHAT_ID, message, parse_mode="MarkdownV2") sleep(1) bot.close() sleep(1) scheduler.enter( 60 * 60 * 12, 1, update_reminder, ("_*Reminder*_:\n\n" + message, ), ) if (settings.TG_UPDATE_BROADCASTED_BEFORE is False or settings.BTB_UPDATE_BROADCASTED_BEFORE is False): sleep(1) scheduler.enter( 60 * 60, 1, update_checker, )
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") 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: 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 * 5 * ( 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 WHERE 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}:*\n".replace(".", "\.") ] for coin in query: m_list.append( f"*{coin[1]}*:\n" f"\t\- Price: `{coin[2]}` {bridge}\n" f"\t\- Ratio: `{round(coin[3], 6)}`\n\n".replace(".", "\.") ) message = telegram_text_truncator(m_list) con.close() except Exception: 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: message = ["β Unable to perform actions on the database\."] return message
def setup_root_path_constant(): if settings.ROOT_PATH is None: logger.info("No root_path was specified. Aborting.") exit(-1) else: settings.ROOT_PATH = os.path.join(settings.ROOT_PATH, "")
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 `{round(order_size, 2)}` *{bridge}* is currently placed on coin *{current_coin}*.\n\n" f"_Waiting for buy order to complete_.".replace(".", "\.") ] except Exception: 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: 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: `{round(balance, 6)}` *{current_coin}*\n" f"\t\- Current coin exchange ratio: `{round(usd_price, 6)}` *USD*/*{current_coin}*\n" f"\t\- Value in *USD*: `{round((balance * usd_price), 2)}` *USD*\n" f"\t\- Value in *BTC*: `{round((balance * btc_price), 6)}` *BTC*\n\n" f"_Initially bought for_ {round(buy_price, 2)} *{bridge}*\n" f"_Exchange ratio when purchased:_ `{round((buy_price / alt_amount), 6)}` *{bridge}*/*{current_coin}*".replace( ".", "\." ) ] message = telegram_text_truncator(m_list) con.close() except Exception: con.close() return [ "β Something went wrong, unable to generate value at this time\." ] except Exception: message = ["β Unable to perform actions on the database\."] return message