problem handling conversations when creating an automated trading bot using python- telegram-bot and metatrader5 library

i have been trying to create a bot that i forward a certain message to it and it will start trading when the requirements are met
bot in the trading process it wont handle any incoming keyboard markup or update when i tell it to stop trading or even cancel trading before the trading even began

when the bot receives and matches the signals the conversation state changes to SIGNAL_RECIVED and it runs an asyncio task and starts a function called Update_Price_And_Place_order
the said function contains a while loop that updates the market prices
now my problem is that the keyboard buttons for cancel trading does not work in mentioned function

# Import necessary libraries and modules
import logging
import nest_asyncio
import asyncio
import re
import MetaTrader5 as mt5
import threading
from threading import Thread
from multiprocessing import Process
from datetime import datetime
import telegram
from telegram import Update, ReplyKeyboardMarkup, ReplyKeyboardRemove, User
from telegram.ext import (
    Application,
    CommandHandler,
    MessageHandler,
    ConversationHandler,
    CallbackContext,
    filters,
)


nest_asyncio.apply()


# Enable logging
logging.basicConfig(
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
)
logger = logging.getLogger(__name__)

# Bot token
TOKEN = 

# Define states for the conversation
LOGIN, LOGGED_OUT, LOGGED_IN, WAITING_FOR_SIGNAL, SIGNAL_RECIVED, ORDER_PLACED = range(
    6
)


# last ask and bid prices
Matching_Symbol = ""
Last_signal_time = 0
trading_active = False
get_tick = False
Buy_placed_at_top = False
Buy_placed_at_buttom = False
Buy_placed_at_instatly = False
sell_placed_at_top = False
sell_placed_at_buttom = False
sell_placed_instatly = False
Ask = 0
Bid = 0
last_Ask = 0
Last_Bid = 0
lot_size = 0.01


# define the signal dictionary to store the signal data
signal = {}


# Define the regex pattern to match the format of the message
Signal_pattern = re.compile(
    r"([A-Z]+)\s+([A-Z]+)\s+(\d+_\d+)\s*"
    r"TP1:\s*(\d+)\s*"
    r"TP2:\s*(\d+)\s*"
    r"TP3:\s*(\d+)\s*"
    r"TP4:\s*(\d+)\s*"
    r"SL:\s*(\d+)"
)


# Define the start command that shows the Start button
async def start(update: Update, context: CallbackContext) -> int:
    await update.message.reply_text(
        "Welcome to the bot! Please click 'login' to begin.",
        reply_markup=ReplyKeyboardMarkup(
            [["Login"]], one_time_keyboard=True, resize_keyboard=True
        ),
    )
    return LOGGED_OUT


# Define the login function
async def login_to_mt5(update: Update, context: CallbackContext) -> int:
    # Initialize MetaTrader 5
    if "mt5_login" not in context.user_data:
        # Ask for MetaTrader 5 login number
        await update.message.reply_text(
            "Please enter your MetaTrader 5 login number:",
            reply_markup=ReplyKeyboardMarkup(
                [["Cancel"]], one_time_keyboard=True, resize_keyboard=True
            ),
        )
        context.user_data["state"] = "ask_mt5_login"
        return LOGIN

    elif "mt5_password" not in context.user_data:
        # Ask for MetaTrader 5 password
        # Store login number
        context.user_data["mt5_login"] = update.message.text
        await update.message.reply_text(
            "Please enter your MetaTrader 5 password:",
            reply_markup=ReplyKeyboardMarkup(
                [["Cancel"]], one_time_keyboard=True, resize_keyboard=True
            ),
        )
        context.user_data["state"] = "ask_mt5_password"
        return LOGIN

    elif "mt5_server" not in context.user_data:
        # Ask for MetaTrader 5 server
        # Store password
        context.user_data["mt5_password"] = update.message.text
        await update.message.reply_text(
            "Please enter your MetaTrader 5 server:",
            reply_markup=ReplyKeyboardMarkup(
                [["Cancel"]], one_time_keyboard=True, resize_keyboard=True
            ),
        )
        context.user_data["state"] = "ask_mt5_server"
        return LOGIN

    else:
        if "mt5_server" not in context.user_data:
            # Store server
            context.user_data["mt5_server"] = update.message.text
        mt5_login = int(context.user_data["mt5_login"])
        mt5_password = context.user_data["mt5_password"]
        mt5_server = context.user_data["mt5_server"]

    # Initialize MetaTrader 5
    if not mt5.initialize():
        await update.message.reply_text("Failed to initialize MetaTrader 5.")
        logger.error("MT5 initialization failed")
        return LOGGED_OUT

    # Attempt to login
    if not mt5.login(login=mt5_login, password=mt5_password, server=mt5_server):
        await update.message.reply_text(
            "MetaTrader 5 login failed. Please check your credentials."
        )
        logger.error(
            "MT5 login failed",
            reply_markup=ReplyKeyboardMarkup(
                [["Login"]], one_time_keyboard=True, resize_keyboard=True
            ),
        )

        # Clear saved credentials to ask again
        context.user_data.pop("mt5_login", None)
        context.user_data.pop("mt5_password", None)
        context.user_data.pop("mt5_server", None)
        return LOGGED_OUT

    # Get and send account information
    account_info = mt5.account_info()
    if account_info is None:
        await update.message.reply_text(
            "Failed to retrieve MetaTrader 5 account information.",
            reply_markup=ReplyKeyboardMarkup(
                [["login"]], one_time_keyboard=True, resize_keyboard=True
            ),
        )
        logger.error("Failed to retrieve account information")
        return LOGGED_OUT

    if account_info is not None:
        await update.message.reply_text(
            "successfully retrieved MetaTrader 5 account information",
            reply_markup=ReplyKeyboardMarkup(
                [
                    [
                        "Start Trading",
                        "get account info",
                        "Get XAUUSD market info",
                        "Change Lot Size",
                        "Logout",
                    ]
                ],
            ),
        )
        return LOGGED_IN


# get account information
async def get_account_info(update: Update, context: CallbackContext):
    """Get and send account information."""
    account_info = mt5.account_info()
    account_info_message = (
        f"Account Information:\n"
        f"name: {account_info.name}\n"
        f"Balance: {account_info.balance}\n"
        f"Equity: {account_info.equity}\n"
        f"Profit: {account_info.profit}\n"
        f"Currency: {account_info.currency}\n"
        f"Leverage: {account_info.leverage}\n"
    )
    await update.message.reply_text(
        account_info_message,
        reply_markup=ReplyKeyboardMarkup(
            [
                [
                    "Start Trading",
                    "get account info",
                    "Get XAUUSD market info",
                    "Change Lot Size",
                    "Logout",
                ]
            ],
        ),
    )

    context.user_data["account_info"] = account_info_message
    # Successful login
    logger.info("MT5 login and account info retrieval successful")
    return LOGGED_IN


# Modify the start_trading function to wait for the message, check the format, and store it in the signal dictionary
async def start_trading(update: Update, context: CallbackContext) -> int:
    global trading_active, get_tick
    trading_active = True
    get_tick = True
    await update.message.reply_text(
        "Trading started. Please send your signal message in the correct format.",
        reply_markup=ReplyKeyboardMarkup(
            [
                [
                    "stop Trading",
                    "Logout",
                ]
            ]
        ),
    )
    return WAITING_FOR_SIGNAL


# Handle the Stop Trading button
async def stop_trading(update: Update, context: CallbackContext) -> int:
    global trading_active, get_tick, monitor_task
    trading_active = False
    get_tick = False
    if monitor_task:
        monitor_task.cancel()  # Gracefully stop the monitoring task

    await update.message.reply_text(
        "Trading stopped.",
        reply_markup=ReplyKeyboardMarkup(
            [
                [
                    "Start Trading",
                    "get account info",
                    "Get XAUUSD market info",
                    "Change Lot Size",
                    "Logout",
                ]
            ]
        ),
    )
    return LOGGED_IN


# get current gold market price
async def Get_XAUUSD_market_info(update: Update, context: CallbackContext) -> int:
    global Matching_Symbol
    Get_All_Symbols = mt5.symbols_get()
    for symbol in Get_All_Symbols:
        if "XAUUSD" in symbol.name:
            Matching_Symbol = symbol.name
            symbol_info = mt5.symbol_info(Matching_Symbol)
            break
    symbol_info_massage = (
        f"Gold market info:\n"
        f"Symbol: {Matching_Symbol}\n"
        f"Ask Price: {symbol_info.ask}\n"
        f"Bid Price: {symbol_info.bid}\n"
        f"currency: {symbol_info.currency_base}\n"
        f"description: {symbol_info.description}\n"
    )
    await update.message.reply_text(
        symbol_info_massage,
        reply_markup=ReplyKeyboardMarkup(
            [
                [
                    "Start Trading",
                    "get account info",
                    "Get XAUUSD market info",
                    "Change Lot Size",
                    "Logout",
                ]
            ]
        ),
    )
    return LOGGED_IN


# Change the lot size
async def change_lot_size(update: Update, context: CallbackContext):
    global Lot_Size
    await update.message.reply_text("Enter the desired Lot Size")
    Lot_Size = int(update.message.text)
    await update.message.reply_text(
        f"Lot Size changed to {Lot_Size}.",
        reply_markup=ReplyKeyboardMarkup(
            [
                [
                    "Start Trading",
                    "get account info",
                    "Get XAUUSD market info",
                    "Change Lot Size",
                    "Logout",
                ]
            ]
        ),
    )
    return LOGGED_IN


# Handle the incoming message in TRADING state
async def handle_signal_message(update: Update, context: CallbackContext) -> int:
    global Signal_pattern, Last_signal_time, signal

    # Check if 'signal' already exists in context.user_data, otherwise initialize it as a dictionary
    if "signal" not in context.user_data:
        context.user_data["signal"] = {}

    # Get the user's message
    user_message = update.message.text
    user_message = user_message.upper()
    user_message = user_message.encode("ascii", "ignore").decode()
    user_message = re.sub(r"\s+\s+", "\n", user_message)

    print(f"Received message: \n {user_message}")

    # Try to match the message format
    match = Signal_pattern.match(user_message)

    print(f"Match: {match}")

    if match:
        # Extract the values from the message
        symbol = match.group(1)
        Order_type = match.group(2)
        price_range = match.group(3)
        tp1 = int(match.group(4))
        tp2 = int(match.group(5))
        tp3 = int(match.group(6))
        tp4 = int(match.group(7))
        sl = int(match.group(8))

        # Store the extracted information in the signal dictionary
        signal_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        Last_signal_time = signal_time
        signal = {
            signal_time: {
                "symbol": symbol,
                "Order_Type": Order_type,
                "Price_range": price_range,
                "Take_Profit": tp1,
                "Stop_Loss": sl,
                "Lot_Size": lot_size,
            }
        }
        # Save it to the user's context data
        context.user_data["signal"].update(signal)
        if "BUY" in Order_type.upper():
            order_massage = "📈Order Type: Buy"
        if "SELL" in Order_type.upper():
            order_massage = "📈Order Type: Sell"
        # Respond with confirmation (fixed string concatenation)
        response_message = (
            f"Signal received and stored waiting for the conditions:\n"
            f"🕕Time: {signal_time}\n"
            f"💰Symbol: {symbol}\n"
            f"{order_massage}\n"
            f"💵Price Range: {price_range}\n"
            f"✅Take Profit: {tp1}\n"
            f"🛑Stop Loss: {sl}\n"
            f"🧮Lot Size: {lot_size}"
        )
        await update.message.reply_text(
            response_message,
            reply_markup=ReplyKeyboardMarkup(
                [
                    [
                        "cancel trade",
                        "Get XAUUSD market info",
                    ]
                ]
            ),
        )

        global monitor_task
        monitor_task = asyncio.create_task(
            Update_Price_And_Place_order(
                update, context, Order_type, price_range, tp1, sl, lot_size)
        )
        if monitor_task:
            result = (
                await monitor_task
            )  # This will wait for the task to complete and get the result
            if result == ORDER_PLACED:
                return ORDER_PLACED  # Pass it to the conversation handler
            if result == LOGGED_IN:
                stop_trading(update, context)
                return LOGGED_IN  # Pass it to the conversation

        return SIGNAL_RECIVED

    else:
        # If the message format is incorrect, notify the user
        await update.message.reply_text(
            "Invalid format. Please send the message in the correct format.",
            reply_markup=ReplyKeyboardMarkup(
                [
                    [
                        "stop Trading",
                        "Logout",
                    ]
                ]
            ),
        )
        return WAITING_FOR_SIGNAL


# Define the logout function
async def logout(update: Update, context: CallbackContext) -> int:
    """Logout from MetaTrader 5."""
    global trading_active, get_tick
    trading_active = False
    get_tick = False
    # Check if user is logged in
    if "mt5_login" in context.user_data:
        # Terminate MetaTrader 5 session
        mt5.shutdown()
        context.user_data.pop("mt5_login", None)
        context.user_data.pop("mt5_password", None)
        context.user_data.pop("mt5_server", None)

        await update.message.reply_text(
            "You have successfully logged out from MetaTrader 5.",
            reply_markup=ReplyKeyboardMarkup(
                [["Login"]], one_time_keyboard=True, resize_keyboard=True
            ),
        )
        logger.info("MT5 logout successful")
    else:
        context.user_data.pop("mt5_login", None)
        context.user_data.pop("mt5_password", None)
        context.user_data.pop("mt5_server", None)
        await update.message.reply_text(
            "You are not logged in to MetaTrader 5.",
            reply_markup=ReplyKeyboardMarkup(
                [["Login"]], one_time_keyboard=True, resize_keyboard=True
            ),
        )
        logger.warning("MT5 logout attempted without being logged in")

    return LOGGED_OUT


# Cancel command to exit the conversation
async def cancel_login(update: Update, context: CallbackContext) -> int:
    await update.message.reply_text(
        "Login process has been canceled.",
        reply_markup=ReplyKeyboardMarkup(
            [["Login"]], one_time_keyboard=True, resize_keyboard=True
        ),
    )
    context.user_data.pop("mt5_login", None)
    context.user_data.pop("mt5_password", None)
    context.user_data.pop("mt5_server", None)
    return LOGGED_OUT


# setup the connection to metatrader 5 and update the prices
async def Update_Price_And_Place_order(update: Update, context: CallbackContext, Order_type, price_range, TP, SL, lot_size):
    global Ask, Bid, Matching_Symbol, get_tick, last_Ask, Last_Bid

    # Get market information
    Get_All_Symbols = mt5.symbols_get()
    for symbol in Get_All_Symbols:
        if "XAUUSD" in symbol.name:
            Matching_Symbol = symbol.name
            mt5.symbol_select(symbol.name, True)
            break
    
    

    # Continuously update prices
    while get_tick:
        await asyncio.sleep(0.01)
        
        tick = mt5.symbol_info_tick(Matching_Symbol)
        if tick:
            if Ask != tick.ask or Bid != tick.bid:
                Ask = tick.ask
                Bid = tick.bid
                logger.info(f"prices updated Bid: {Bid}, Ask: {Ask}")
                await update.message.reply_text(
                    f"prices updated Bid: {Bid}, Ask: {Ask}",
                    reply_markup=ReplyKeyboardMarkup(
                        [
                            [
                                "cancel trade",
                            ]
                        ]
                    ),
                )
                logger.info(conv_handler.check_update(update))
                if last_Ask == 0 or Last_Bid == 0:
                    last_Ask = Ask
                    Last_Bid = Bid

                Price1, Price2 = int(price_range.split("_")[0]), int(
                    price_range.split("_")[1]
                )
                Price_Handled = await Handle_Price_Update(
                    update,
                    context,
                    last_Ask,
                    Last_Bid,
                    Order_type,
                    Ask,
                    Bid,
                    TP,
                    SL,
                    lot_size,
                    Price1,
                    Price2,
                )
                if Price_Handled == ORDER_PLACED:
                    return ORDER_PLACED  # Propagate ORDER_PLACED


async def Handle_Price_Update(
    update: Update,
    context: CallbackContext,
    last_Ask,
    Last_Bid,
    Order_type,
    Ask,
    Bid,
    TP,
    SL,
    lot_size,
    Price1,
    Price2,
):
    global Buy_placed_at_top, Buy_placed_at_buttom, Buy_placed_at_instatly, sell_placed_at_top, sell_placed_at_buttom, sell_placed_instatly

    if "BUY" in Order_type.upper():
        if last_Ask < min(
            Price1, Price2
        ):  # ask price is under the price range == buy at min price
            if Buy_placed_at_buttom == False and (
                max(Price1, Price2) >= Ask >= min(Price1, Price2)
            ):  # ask price has hit the price range from below
                Buy_placed_at_buttom = await Buy(int(TP), int(SL), int(lot_size), Ask)
                logger.info("trying to place a buy at min price")
                if Buy_placed_at_buttom == ORDER_PLACED:
                    return ORDER_PLACED  # Propagate ORDER_PLACED
                last_Ask = Ask

        elif last_Ask > max(
            Price1, Price2
        ):  # ask price is above the price range == buy at max price and buy at min price
            if (max(Price1, Price2) >= Ask >= min(Price1, Price2)) and (
                Buy_placed_at_top == False
            ):  # ask price has hit the price range from above
                Buy_placed_at_top = await Buy(int(TP), int(SL), int(lot_size), Ask)
                logger.info("trying to place a buy at max price")
                if Buy_placed_at_top == ORDER_PLACED:
                    return ORDER_PLACED  # Propagate ORDER_PLACED

            if (min(Price1, Price2) >= Ask) and (
                Buy_placed_at_buttom == False
            ):  # ask price has hit the minimum price
                Buy_placed_at_buttom = await Buy(int(TP), int(SL), int(lot_size), Ask)
                logger.info("trying to place a buy at min price")
                if Buy_placed_at_buttom == ORDER_PLACED:
                    return ORDER_PLACED  # Propagate ORDER_PLACED
                last_Ask = Ask

        elif (
            min(Price1, Price2) <= last_Ask <= max(Price1, Price2)
        ):  # ask price is between the price range == instant buy and buy at min price
            if Buy_placed_at_instatly == False:
                Buy_placed_at_instatly = await Buy(int(TP), int(SL), int(lot_size), Ask)
                logger.info("trying to place a buy instantly")
                if Buy_placed_at_instatly == ORDER_PLACED:
                    return ORDER_PLACED  # Propagate ORDER_PLACED

            if min(Price1, Price2) >= Ask and Buy_placed_at_buttom == False:
                Buy_placed_at_buttom = await Buy(int(TP), int(SL), int(lot_size), Ask)
                logger.info("trying to place a buy at low price")
                if Buy_placed_at_buttom == ORDER_PLACED:
                    return ORDER_PLACED  # Propagate ORDER_PLACED
                last_Ask = Ask

    elif "SELL" in Order_type.upper():
        if Last_Bid < min(
            Price1, Price2
        ):  # bid price is under the price range == sell at min price and sell at max price
            if sell_placed_at_buttom == False and (
                max(Price1, Price2) >= Bid >= min(Price1, Price2)
            ):
                sell_placed_at_buttom = await Sell(int(TP), int(SL), int(lot_size), Bid)
                logger.info("Trying to place a sell at min price")
                if sell_placed_at_buttom == ORDER_PLACED:
                    return ORDER_PLACED  # Propagate ORDER_PLACED

            if sell_placed_at_top == False and (
                max(Price1, Price2) <= Bid
            ):
                sell_placed_at_top = await Sell(int(TP), int(SL), int(lot_size), Bid)
                logger.info("Trying to place a sell at min price")
                if sell_placed_at_top == ORDER_PLACED:
                    return ORDER_PLACED  # Propagate ORDER_PLACED
                Last_Bid = Bid  # Update the last bid price

        elif Last_Bid > max(
            Price1, Price2
        ):  # bid price is above the price range == sell at max price
            if (max(Price1, Price2) >= Bid >= min(Price1, Price2)) and (
                sell_placed_at_top == False
            ):
                sell_placed_at_top = await Sell(int(TP), int(SL), int(lot_size), Bid)
                logger.info("Trying to place a sell at peak price")
                if sell_placed_at_top == ORDER_PLACED:
                    return ORDER_PLACED  # Propagate ORDER_PLACED
                Last_Bid = Bid

        elif (
            min(Price1, Price2) <= Last_Bid <= max(Price1, Price2)
        ):  # bid price is between the price range == instant sell and sell at peak price
            if sell_placed_instatly == False:
                sell_placed_instatly = await Sell(int(TP), int(SL), int(lot_size), Bid)
                if sell_placed_instatly == ORDER_PLACED:
                    return ORDER_PLACED  # Propagate ORDER_PLACED
                logger.info("Trying to place a sell instantly")

            if max(Price1, Price2) <= Bid and sell_placed_at_top == False:
                sell_placed_at_top = await Sell(int(TP), int(SL), int(lot_size), Bid)
                logger.info("Trying to place a sell instantly")
                if sell_placed_at_top == ORDER_PLACED:
                    return ORDER_PLACED  # Propagate ORDER_PLACED
                Last_Bid = Bid


async def Buy(update: Update, context: CallbackContext, TP, SL, symbol):
    request = {
        "action": mt5.TRADE_ACTION_DEAL,
        "symbol": symbol,
        "volume": int(lot_size),
        "type": mt5.ORDER_TYPE_BUY,
        "price": Ask,
        "sl": int(SL),
        "tp": int(TP),
        "deviation": 20,
        "magic": 234000,
        "comment": "python script open",
        "type_time": mt5.ORDER_TIME_GTC,
        "type_filling": mt5.ORDER_FILLING_RETURN,
    }

    try:
        result = mt5.order_send(request)
        logger.info(result)
        if result.retcode != mt5.TRADE_RETCODE_DONE:
            await update.message.reply_text(
                f"Failed to place buy order for {
                    symbol}. Error: {result.retcode}"
            )
            return False
        else:
            await update.message.reply_text(
                f"Buy order placed successfully for {
                    symbol} at price {context.user_data['Ask']}!"
            )
            return ORDER_PLACED
    except Exception as e:
        await update.message.reply_text(
            f"An error occurred while placing the buy order: {str(e)}"
        )
        logger.error(f"Error in Buy function: {e}")
        return False


async def Sell(update: Update, context: CallbackContext, TP, SL, symbol):
    request = {
        "action": mt5.TRADE_ACTION_DEAL,
        "symbol": symbol,
        "volume": int(lot_size),
        "type": mt5.ORDER_TYPE_SELL,
        "price": Bid,
        "sl": int(SL),
        "tp": int(TP),
        "deviation": 20,
        "magic": 234000,
        "comment": "python script open",
        "type_time": mt5.ORDER_TIME_GTC,
        "type_filling": mt5.ORDER_FILLING_RETURN,
    }

    try:
        result = mt5.order_send(request)
        logger.info(result)
        if result.retcode != mt5.TRADE_RETCODE_DONE:
            await update.message.reply_text(
                f"Failed to place sell order for {
                    symbol}. Error: {result.retcode}"
            )
            return False
        else:
            await update.message.reply_text(
                f"Sell order placed successfully for {
                    symbol} at price {context.user_data['Bid']}!"
            )
            return ORDER_PLACED
    except Exception as e:
        await update.message.reply_text(
            f"An error occurred while placing the sell order: {str(e)}"
        )
        logger.error(f"Error in Sell function: {e}")
        return False


async def close_all_trades(update: Update, context: CallbackContext) -> int:
    global trading_active, get_tick, Buy_placed_at_top, Buy_placed_at_buttom
    global Buy_placed_at_instatly, sell_placed_at_top, sell_placed_at_buttom
    global sell_placed_instatly, Ask, Bid, last_Ask, Last_Bid, lot_size
    global monitor_task

    # Stop price monitoring
    if monitor_task:
        monitor_task.cancel()
        monitor_task = None

    # Close all open positions
    open_positions = mt5.positions_get()
    if open_positions is None or len(open_positions) == 0:
        await update.message.reply_text("No trades to close.")
    else:
        for position in open_positions:
            close_request = {
                "action": mt5.TRADE_ACTION_DEAL,
                "symbol": position.symbol,
                "volume": position.volume,
                "type": (
                    mt5.ORDER_TYPE_SELL
                    if position.type == mt5.ORDER_TYPE_BUY
                    else mt5.ORDER_TYPE_BUY
                ),
                "position": position.ticket,
                "price": (
                    mt5.symbol_info_tick(position.symbol).bid
                    if position.type == mt5.ORDER_TYPE_BUY
                    else mt5.symbol_info_tick(position.symbol).ask
                ),
                "deviation": 20,
                "magic": 234000,
                "comment": "Close all trades",
                "type_time": mt5.ORDER_TIME_GTC,
                "type_filling": mt5.ORDER_FILLING_RETURN,
            }
            result = mt5.order_send(close_request)
            if result.retcode != mt5.TRADE_RETCODE_DONE:
                await update.message.reply_text(
                    f"Failed to close trade for {
                        position.symbol}. Error: {result.retcode}"
                )
            else:
                await update.message.reply_text(f"Closed trade for {position.symbol}.")

    # Reset global variables
    trading_active = False
    get_tick = False
    Buy_placed_at_top = False
    Buy_placed_at_buttom = False
    Buy_placed_at_instatly = False
    sell_placed_at_top = False
    sell_placed_at_buttom = False
    sell_placed_instatly = False
    Ask = 0
    Bid = 0
    last_Ask = 0
    Last_Bid = 0
    lot_size = 0.01

    # Respond with confirmation
    await update.message.reply_text(
        "All trades closed and system reset.",
        reply_markup=ReplyKeyboardMarkup(
            [
                [
                    "Start Trading",
                    "get account info",
                    "Get XAUUSD market info",
                    "Change Lot Size",
                    "Logout",
                ]
            ],
            resize_keyboard=True,
        ),
    )
    return LOGGED_IN


# Set up the conversation handler with states and transitions
def main():
    # Replace 'YOUR_BOT_TOKEN' with the token you got from the BotFather
    global conv_handler, application
    application = Application.builder().token(TOKEN).build()

    # Conversation handler to manage the login flow
    conv_handler = ConversationHandler(
        entry_points=[
            CommandHandler("start", login_to_mt5),
            MessageHandler(filters.Regex("(?i)^Start$"), start),
        ],
        states={
            LOGIN: [
                MessageHandler(filters.Regex("(?i)^Login$"), login_to_mt5),
                MessageHandler(filters.Regex("(?i)^Cancel$"), cancel_login),
            ],
            LOGGED_IN: [
                MessageHandler(filters.Regex("(?i)^Logout$"), logout),
                MessageHandler(filters.Regex(
                    "(?i)^Start Trading$"), start_trading),
                MessageHandler(
                    filters.Regex("(?i)^Get XAUUSD market info$"),
                    Get_XAUUSD_market_info,
                ),
                MessageHandler(
                    filters.Regex("(?i)^get account info$"), get_account_info
                ),
                MessageHandler(filters.Regex(
                    "(?i)^Change Lot Size$"), change_lot_size),
            ],
            WAITING_FOR_SIGNAL: [
                MessageHandler(filters.Regex(
                    "(?i)^stop Trading$"), stop_trading),
                MessageHandler(filters.Regex("(?i)^Logout$"), logout),
                MessageHandler(filters.TEXT & ~filters.COMMAND,
                               handle_signal_message),
            ],
            SIGNAL_RECIVED: [
                MessageHandler(filters.Regex(
                    "(?i)^cancel trade$"), stop_trading),
                MessageHandler(
                    filters.Regex("(?i)^Get XAUUSD market info$"),
                    Get_XAUUSD_market_info,
                ),
            ],
            ORDER_PLACED: [
                MessageHandler(
                    filters.Regex("(?i)^Close All Trades$"), close_all_trades
                ),
                MessageHandler(
                    filters.Regex("(?i)^\\+\\d+pip"), close_all_trades
                ),  # Pip message handler
            ],
            LOGGED_OUT: [
                MessageHandler(filters.Regex("(?i)^Login$"), login_to_mt5),
            ],
        },
        fallbacks=[CommandHandler("cancel", cancel_login)],
    )
    # Add the conversation handler to the application
    application.add_handler(conv_handler)

    # Start the bot
    application.run_polling()


if __name__ == "__main__":
    asyncio.run(main())