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 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 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 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
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 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