Files
AlphaFlow-MT5-ML-DL-Trading…/notebooks/strategies/ml/live_trading/multi_bar_classification.ipynb
T

142 KiB

One-Symbol Version

In [ ]:
# LIVE TRADING CODE FOR MULTI-BAR CLASSIFICATION

import sys
import os
import warnings
from pathlib import Path

# ---------------------------------------------------------------------------
# 1) SET PROJECT ROOT AND UPDATE PATH/WORKING DIRECTORY
# ---------------------------------------------------------------------------
project_root = Path.cwd().parent.parent  # Adjust if your notebook is in notebooks/time_series
sys.path.append(str(project_root))
os.chdir(str(project_root))
warnings.filterwarnings("ignore")

import warnings
warnings.filterwarnings("ignore")
import MetaTrader5 as mt5
import pandas as pd
import numpy as np
import ta
from datetime import datetime, timedelta
import time
import logging
import joblib

# Setup logging
logging.basicConfig(
    filename='models/saved_models/trading_app1.log',
    level=logging.INFO,
    format='%(asctime)s %(levelname)s:%(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)

def log_and_print(message, is_error=False):
    """
    Logs and prints a message.
    If is_error=True, logs at the ERROR level; otherwise logs at INFO level.
    """
    if is_error:
        logging.error(message)
    else:
        logging.info(message)
    print(message)

# Update the login credentials and server information accordingly
#name = 66677507
#key = 'ST746$nG38'
#serv = 'ICMarketsSC-Demo'

# Global variables
SYMBOL = "JP225"
LOT_SIZE = 0.1
TIMEFRAME = mt5.TIMEFRAME_H4  # 1 hour timeframe
N_BARS = 1000
MAGIC_NUMBER = 234003
SLEEP_TIME = 14400  # 4 hours in seconds
COMMENT_ML = "RFFV-D"

# If you still need feature selection, you can keep this helper function:
def select_features_rf_reg(X, y, estimator, max_features=20):
    """
    Example helper function for feature selection using RandomForest.
    """
    from sklearn.feature_selection import SelectFromModel
    selector = SelectFromModel(estimator=estimator, threshold=-np.inf, max_features=max_features).fit(X, y)
    X_transformed = selector.transform(X)
    selected_features_mask = selector.get_support()
    return X_transformed, selected_features_mask

class TradingApp:
    def __init__(self, symbol, lot_size, magic_number):
        self.symbol = symbol
        self.lot_size = lot_size
        self.magic_number = magic_number
        self.pipeline = None  # We'll store the loaded classification pipeline here
        self.last_retrain_time = None

    def get_data(self, symbol, n, timeframe):
        """
        Fetch 'n' bars of historical data for the given symbol and timeframe.
        """
        rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, n)
        rates_frame = pd.DataFrame(rates)
        rates_frame['time'] = pd.to_datetime(rates_frame['time'], unit='s')
        rates_frame.set_index('time', inplace=True)
        return rates_frame

    def add_all_ta_features(self, df):
        """
        Add technical analysis features to the DataFrame using the 'ta' library.
        """
        df = ta.add_all_ta_features(
            df, open="open", high="high", low="low", close="close", volume="tick_volume", fillna=True
        )
        return df

    def load_pipeline(self, pipeline_path):
        """
        Loads a pre-trained classification pipeline (either a Pipeline or a dict).
        """
        pipeline_loaded = joblib.load(pipeline_path)

        # If it's a dict, extract the model
        if isinstance(pipeline_loaded, dict):
            self.pipeline = pipeline_loaded["model"]
        else:
            self.pipeline = pipeline_loaded

        logging.info(f"Loaded pipeline from {pipeline_path}")
        log_and_print(f"Loaded pipeline from {pipeline_path}")


    def ml_signal_generation(self, symbol, n_bars, timeframe):
        """
        Generate buy/sell signals using the loaded classification pipeline.
        The pipeline outputs SHIFTED labels in {0,1,2} => we SHIFT them back to {-1,0,+1}.
        We'll interpret +1 => buy, -1 => sell, 0 => no trade.
        """
        if self.pipeline is None:
            logging.error("No pipeline loaded. Call load_pipeline(...) first.")
            return False, False, True, True

        # 1) Fetch new data
        df = self.get_data(symbol, n_bars, timeframe)

        # 2) Add TA features
        df = self.add_all_ta_features(df)
        df.fillna(method='ffill', inplace=True)

        # 3) Prepare the features
        X_new = df  # The pipeline must handle columns in the correct order.

        # 4) Predict SHIFTED classes
        preds_shifted = self.pipeline.predict(X_new)
        # SHIFT them back: 0->-1, 1->0, 2->+1
        preds = preds_shifted - 1

        # Get the latest predicted class
        latest_pred = preds[-1]
        # If latest_pred == +1 => buy signal
        # If latest_pred == -1 => sell signal
        # If 0 => do nothing
        buy_signal = (latest_pred == 1)
        sell_signal = (latest_pred == -1)

        return buy_signal, sell_signal, not buy_signal, not sell_signal

    def orders(self, symbol, lot, is_buy=True, id_position=None, sl=None, tp=None):
        """
        Place an order (BUY or SELL) for the specified symbol and lot size.
        """
        symbol_info = mt5.symbol_info(symbol)
        if symbol_info is None:
            log_and_print(f"Symbol {symbol} not found, can't place order.", is_error=True)
            return "Symbol not found"

        # Make sure symbol is visible
        if not symbol_info.visible:
            if not mt5.symbol_select(symbol, True):
                log_and_print(f"Failed to select symbol {symbol}", is_error=True)
                return "Symbol not visible or could not be selected."

        tick_info = mt5.symbol_info_tick(symbol)
        if tick_info is None:
            log_and_print(f"Could not get tick info for {symbol}.", is_error=True)
            return "Tick info unavailable"

        # Check for valid bid/ask
        if tick_info.bid <= 0 or tick_info.ask <= 0:
            log_and_print(
                f"Zero or invalid bid/ask for {symbol}: bid={tick_info.bid}, ask={tick_info.ask}",
                is_error=True
            )
            return "Invalid prices"

        # LOT SIZE VALIDATION
        lot = max(lot, symbol_info.volume_min)
        step = symbol_info.volume_step
        if step > 0:
            remainder = lot % step
            if remainder != 0:
                lot = lot - remainder + step
        if lot > symbol_info.volume_max:
            lot = symbol_info.volume_max

        log_and_print(
            f"Adjusted lot size to {lot} (min={symbol_info.volume_min}, "
            f"step={symbol_info.volume_step}, max={symbol_info.volume_max})"
        )

        # Force ORDER_FILLING_IOC
        filling_mode = 1  # ORDER_FILLING_IOC

        order_type = mt5.ORDER_TYPE_BUY if is_buy else mt5.ORDER_TYPE_SELL
        order_price = tick_info.ask if is_buy else tick_info.bid
        deviation = 20

        request = {
            "action": mt5.TRADE_ACTION_DEAL,
            "symbol": symbol,
            "volume": lot,
            "type": order_type,
            "deviation": deviation,
            "magic": self.magic_number,
            "comment": COMMENT_ML,
            "type_time": mt5.ORDER_TIME_GTC,
            "type_filling": filling_mode,
        }

        if sl is not None:
            request["sl"] = sl
        if tp is not None:
            request["tp"] = tp
        if id_position is not None:
            request["position"] = id_position

        log_and_print(f"Sending order request: {request}")
        result = mt5.order_send(request)

        order_type_str = "BUY" if is_buy else "SELL"
        if result is None or result.retcode != mt5.TRADE_RETCODE_DONE:
            error_message = f"Order failed for {symbol}"
            if result:
                error_message += f", retcode={result.retcode}, comment={result.comment}"
            additional_info = (
                f"Date/Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
                f"Order Type: {order_type_str}\n"
                f"Lot Size: {lot}\n"
                f"SL: {sl if sl else 'None'}\n"
                f"TP: {tp if tp else 'None'}\n"
                f"Comment: {COMMENT_ML}\n"
                f"Request: {request}\n"
                f"Result: {result}"
            )
            # If you want notifications, you could log or handle them differently here.
            log_and_print(f"Order failed details: {additional_info}", is_error=True)
        else:
            success_message = f"Order successful for {symbol}, comment={result.comment}"
            additional_info = (
                f"Date/Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
                f"Order Type: {order_type_str}\n"
                f"Lot Size: {lot}\n"
                f"SL: {sl if sl else 'None'}\n"
                f"TP: {tp if tp else 'None'}\n"
                f"Comment: {COMMENT_ML}"
            )
            # If you want notifications, you could log or handle them differently here.
            log_and_print(success_message)

    def get_positions_by_magic(self, symbol, magic_number):
        """
        Retrieve positions for a specific symbol and magic number.
        """
        all_positions = mt5.positions_get(symbol=symbol)
        if not all_positions:
            log_and_print("No positions found.", is_error=False)
            return []
        return [pos for pos in all_positions if pos.magic == magic_number]

    def run_strategy(self, symbol, lot, buy_signal, sell_signal):
        """
        Run the trading strategy logic based on buy/sell signals.
        """
        log_and_print("------------------------------------------------------------------")
        log_and_print(
            f"Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}, "
            f"SYMBOL: {symbol}, BUY SIGNAL: {buy_signal}, SELL SIGNAL: {sell_signal}"
        )

        positions = self.get_positions_by_magic(symbol, self.magic_number)
        has_buy = any(pos.type == mt5.POSITION_TYPE_BUY for pos in positions)
        has_sell = any(pos.type == mt5.POSITION_TYPE_SELL for pos in positions)

        if buy_signal and not has_buy:
            if has_sell:
                log_and_print("Existing sell positions found. Attempting to close...")
                if self.close_position(symbol, is_buy=True):
                    log_and_print("Sell positions closed. Placing new buy order.")
                    self.orders(symbol, lot, is_buy=True)
                else:
                    log_and_print("Failed to close sell positions.")
            else:
                self.orders(symbol, lot, is_buy=True)
        elif sell_signal and not has_sell:
            if has_buy:
                log_and_print("Existing buy positions found. Attempting to close...")
                if self.close_position(symbol, is_buy=False):
                    log_and_print("Buy positions closed. Placing new sell order.")
                    self.orders(symbol, lot, is_buy=False)
                else:
                    log_and_print("Failed to close buy positions.")
            else:
                self.orders(symbol, lot, is_buy=False)
        else:
            log_and_print("Appropriate position already exists or no signal to act on.")

    def close_position(self, symbol, is_buy):
        """
        Closes positions of the opposite type (BUY/SELL) for this app's magic number.
        """
        positions = mt5.positions_get(symbol=symbol)
        if not positions:
            log_and_print(f"No positions to close for symbol: {symbol}")
            return False

        initial_balance = mt5.account_info().balance
        closed_any = False

        for position in positions:
            # Close positions of the opposite type with the same magic number
            if position.magic == self.magic_number and (
                (is_buy and position.type == mt5.POSITION_TYPE_SELL) or
                (not is_buy and position.type == mt5.POSITION_TYPE_BUY)
            ):
                close_request = {
                    "action": mt5.TRADE_ACTION_DEAL,
                    "symbol": symbol,
                    "volume": position.volume,
                    "type": mt5.ORDER_TYPE_BUY if position.type == mt5.POSITION_TYPE_SELL else mt5.ORDER_TYPE_SELL,
                    "position": position.ticket,
                    "deviation": 20,
                    "magic": self.magic_number,
                    "comment": COMMENT_ML,
                    "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:
                    error_message = f"Failed to close position {position.ticket} for {symbol}: {result.retcode}"
                    log_and_print(error_message, is_error=True)
                    # If you want notifications, you could log or handle them differently here.
                else:
                    log_and_print(f"Successfully closed position {position.ticket} for {symbol}")
                    closed_any = True

        if closed_any:
            final_balance = mt5.account_info().balance
            profit = final_balance - initial_balance
            success_message = f"Closed positions successfully, Profit: {profit}"
            log_and_print(success_message)
            return True

        return False

    def check_and_execute_trades(self):
        """
        Convenience method to perform the entire flow:
        generate signals, run strategy, and deselect symbol.
        """
        mt5.symbol_select(self.symbol, True)
        buy, sell, _, _ = self.ml_signal_generation(self.symbol, N_BARS, TIMEFRAME)
        self.run_strategy(self.symbol, self.lot_size, buy, sell)
        mt5.symbol_select(self.symbol, False)
        log_and_print("Waiting for new signals...")

def is_market_open():
    """
    Check if the current time is within the typical Forex trading session, adjusted for CET/CEST.
    Market closes at Friday 10:00 PM CET and opens at Sunday 11:00 PM CET. 
    It is closed all day Saturday.
    """
    current_time_utc = datetime.utcnow()
    # Adjust for Central European Time (UTC+1) or Central European Summer Time (UTC+2)
    current_time_cet = (
        current_time_utc + timedelta(hours=2) 
        if time.localtime().tm_isdst 
        else current_time_utc + timedelta(hours=1)
    )

    # Friday after 10 PM CET
    if current_time_cet.weekday() == 4 and current_time_cet.hour >= 22:
        return False
    # Sunday before 11 PM CET
    elif current_time_cet.weekday() == 6 and current_time_cet.hour < 23:
        return False
    # All day Saturday
    elif current_time_cet.weekday() == 5:
        return False
    return True

if __name__ == "__main__":
    try:
        if not mt5.initialize():
            log_and_print("Failed to initialize MetaTrader 5", is_error=True)
            exit()

        app = TradingApp(symbol=SYMBOL, lot_size=LOT_SIZE, magic_number=MAGIC_NUMBER)

        # 1) Load the classification pipeline
        pipeline_path = "models/simple_models/JP225_best_model.pkl"
        app.load_pipeline(pipeline_path)

        while True:
            log_and_print("Checking market status...")
            if is_market_open():
                log_and_print("Market is open. Executing trades...")

                # 2) Generate signals using the loaded pipeline
                #    This pipeline is classification-based => SHIFTED labels [0,1,2]
                #    ml_signal_generation() SHIFTs them back to [-1,0,+1] for signals
                buy_signal, sell_signal, _, _ = app.ml_signal_generation(
                    symbol=app.symbol,
                    n_bars=N_BARS,
                    timeframe=TIMEFRAME
                )

                # 3) Run strategy
                app.run_strategy(app.symbol, app.lot_size, buy_signal, sell_signal)
            else:
                log_and_print("Market is closed. No actions performed.")

            time.sleep(SLEEP_TIME)

    except KeyboardInterrupt:
        log_and_print("Shutdown signal received.")
        # If you need a notification here, handle it (e.g., log, email, etc.).
    except Exception as e:
        error_message = f"An error occurred: {e}"
        log_and_print(error_message, is_error=True)
        # If you need a notification here, handle it (e.g., log, email, etc.).
    finally:
        mt5.shutdown()
        log_and_print("MetaTrader 5 shutdown completed.")
        # If you need a notification here, handle it (e.g., log, email, etc.).
Loaded pipeline from models/simple_models/JP225_best_model.pkl
Checking market status...
Market is open. Executing trades...
------------------------------------------------------------------
Date: 2025-04-22 21:45:06, SYMBOL: JP225, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
Adjusted lot size to 1.0 (min=1.0, step=1.0, max=250.0)
Sending order request: {'action': 1, 'symbol': 'JP225', 'volume': 1.0, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order successful for JP225, comment=Request executed

Multi-Symbol Version

In [ ]:
# LIVE TRADING CODE FOR MULTI-BAR CLASSIFICATION

import sys
import os
import warnings
from pathlib import Path

# ---------------------------------------------------------------------------
# 1) SET PROJECT ROOT AND UPDATE PATH/WORKING DIRECTORY
# ---------------------------------------------------------------------------
project_root = Path.cwd().parent.parent  # Adjust if your notebook is in notebooks/time_series
sys.path.append(str(project_root))
os.chdir(str(project_root))
warnings.filterwarnings("ignore")

import warnings
warnings.filterwarnings("ignore")
import MetaTrader5 as mt5
import pandas as pd
import numpy as np
import ta
from datetime import datetime, timedelta
import time
import logging
import joblib

# Setup logging
logging.basicConfig(
    filename='models/saved_models/trading_app1.log',
    level=logging.INFO,
    format='%(asctime)s %(levelname)s:%(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)

def log_and_print(message, is_error=False):
    """
    Logs and prints a message.
    If is_error=True, logs at the ERROR level; otherwise logs at INFO level.
    """
    if is_error:
        logging.error(message)
    else:
        logging.info(message)
    print(message)

# Update the login credentials and server information accordingly
#name = 66677507
#key = 'ST746$nG38'
#serv = 'ICMarketsSC-Demo'

# Global variables
symbols = [
    "EURUSD", "USDJPY", "AUDUSD", "GBPUSD", "USDCHF", "EURGBP",
    "MSFT.NAS", "TSLA.NAS", "NVDA.NAS", "AMZN.NAS", "GOOG.NAS", "NFLX.NAS", "AAPL.NAS",
    "BABA.NYSE", "JPM.NYSE", "XOM.NYSE", "BA.NYSE", "DIS.NYSE", "NKE.NYSE","JP225"
]

lot_sizes = {
  
    "US500": 0.1,
    "JP225": 1.00,

}

# Add Forex and Stocks with 0.01 lot size
for symbol in symbols:
    if symbol not in lot_sizes:
        lot_sizes[symbol] = 0.01

model_paths = {
    symbol: f"models/h1_models/{symbol}_H1_best_model.pkl" for symbol in symbols
}


TIMEFRAME = mt5.TIMEFRAME_H1
N_BARS = 1000
MAGIC_NUMBER = 234003
SLEEP_TIME = 3600  # 1 hour
COMMENT_ML = "RFFV-D"

success_count = 0
fail_count = 0
retry_queue = []
# Global setting for whether to close open positions on flat (neutral) signal
CLOSE_ON_FLAT = True


# If you still need feature selection, you can keep this helper function:
def select_features_rf_reg(X, y, estimator, max_features=20):
    """
    Example helper function for feature selection using RandomForest.
    """
    from sklearn.feature_selection import SelectFromModel
    selector = SelectFromModel(estimator=estimator, threshold=-np.inf, max_features=max_features).fit(X, y)
    X_transformed = selector.transform(X)
    selected_features_mask = selector.get_support()
    return X_transformed, selected_features_mask

def is_us_stock(symbol):
    return symbol.endswith(".NAS") or symbol.endswith(".NYSE")

def is_us_market_open():
    """
    Check if US stock market is open based on Switzerland time (CET/CEST).
    """
    now = datetime.now()

    if now.weekday() >= 5:  # Saturday or Sunday
        return False

    market_open = now.replace(hour=15, minute=30, second=0, microsecond=0)
    market_close = now.replace(hour=22, minute=0, second=0, microsecond=0)

    return market_open <= now <= market_close




class TradingApp:
    def __init__(self, symbol, lot_size, magic_number):
        self.symbol = symbol
        self.lot_size = lot_size
        self.magic_number = magic_number
        self.pipeline = None  # We'll store the loaded classification pipeline here
        self.last_retrain_time = None

    def get_data(self, symbol, n, timeframe):
        """
        Fetch 'n' bars of historical data for the given symbol and timeframe.
        """
        rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, n)
        rates_frame = pd.DataFrame(rates)
        rates_frame['time'] = pd.to_datetime(rates_frame['time'], unit='s')
        rates_frame.set_index('time', inplace=True)
        return rates_frame

    def add_all_ta_features(self, df):
        """
        Add technical analysis features to the DataFrame using the 'ta' library.
        """
        df = ta.add_all_ta_features(
            df, open="open", high="high", low="low", close="close", volume="tick_volume", fillna=True
        )
        return df

    def load_pipeline(self, pipeline_path):
        """
        Loads a pre-trained classification pipeline (either a Pipeline or a dict).
        """
        pipeline_loaded = joblib.load(pipeline_path)

        # If it's a dict, extract the model
        if isinstance(pipeline_loaded, dict):
            self.pipeline = pipeline_loaded["model"]
        else:
            self.pipeline = pipeline_loaded

        logging.info(f"Loaded pipeline from {pipeline_path}")
        log_and_print(f"Loaded pipeline from {pipeline_path}")


    def ml_signal_generation(self, symbol, n_bars, timeframe):
        """
        Generate buy/sell signals using the loaded classification pipeline.
        The pipeline outputs SHIFTED labels in {0,1,2} => we SHIFT them back to {-1,0,+1}.
        We'll interpret +1 => buy, -1 => sell, 0 => no trade.
        """
        if self.pipeline is None:
            logging.error("No pipeline loaded. Call load_pipeline(...) first.")
            return False, False, True, True

        # 1) Fetch new data
        df = self.get_data(symbol, n_bars, timeframe)

        # 2) Add TA features
        df = self.add_all_ta_features(df)
        df.fillna(method='ffill', inplace=True)

        # 3) Prepare the features
        X_new = df  # The pipeline must handle columns in the correct order.

        # 4) Predict SHIFTED classes
        preds_shifted = self.pipeline.predict(X_new)
        # SHIFT them back: 0->-1, 1->0, 2->+1
        preds = preds_shifted - 1

        # Get the latest predicted class
        latest_pred = preds[-1]
        # If latest_pred == +1 => buy signal
        # If latest_pred == -1 => sell signal
        # If 0 => do nothing
        buy_signal = (latest_pred == 1)
        sell_signal = (latest_pred == -1)

        return buy_signal, sell_signal, not buy_signal, not sell_signal

    def orders(self, symbol, lot, is_buy=True, id_position=None, sl=None, tp=None):
        """
        Place an order (BUY or SELL) for the specified symbol and lot size.
        """
        global success_count, fail_count, retry_queue

        symbol_info = mt5.symbol_info(symbol)
        if symbol_info is None:
            log_and_print(f"Symbol {symbol} not found, can't place order.", is_error=True)
            fail_count += 1
            return "Symbol not found"

        # Make sure symbol is visible
        if not symbol_info.visible:
            if not mt5.symbol_select(symbol, True):
                log_and_print(f"Failed to select symbol {symbol}", is_error=True)
                fail_count += 1
                return "Symbol not visible or could not be selected."

        tick_info = mt5.symbol_info_tick(symbol)
        if tick_info is None:
            log_and_print(f"Could not get tick info for {symbol}.", is_error=True)
            fail_count += 1
            return "Tick info unavailable"

        # Check for valid bid/ask
        if tick_info.bid <= 0 or tick_info.ask <= 0:
            log_and_print(
                f"Zero or invalid bid/ask for {symbol}: bid={tick_info.bid}, ask={tick_info.ask}",
                is_error=True
            )
            fail_count += 1
            return "Invalid prices"

        # LOT SIZE VALIDATION
        lot = max(lot, symbol_info.volume_min)
        step = symbol_info.volume_step
        if step > 0:
            remainder = lot % step
            if remainder != 0:
                lot = lot - remainder + step
        if lot > symbol_info.volume_max:
            lot = symbol_info.volume_max

        log_and_print(
            f"Adjusted lot size to {lot} (min={symbol_info.volume_min}, "
            f"step={symbol_info.volume_step}, max={symbol_info.volume_max})"
        )

        # Force ORDER_FILLING_IOC
        filling_mode = 1  # ORDER_FILLING_IOC

        order_type = mt5.ORDER_TYPE_BUY if is_buy else mt5.ORDER_TYPE_SELL
        order_price = tick_info.ask if is_buy else tick_info.bid
        deviation = 20

        request = {
            "action": mt5.TRADE_ACTION_DEAL,
            "symbol": symbol,
            "volume": lot,
            "type": order_type,
            "deviation": deviation,
            "magic": self.magic_number,
            "comment": COMMENT_ML,
            "type_time": mt5.ORDER_TIME_GTC,
            "type_filling": filling_mode,
        }

        if sl is not None:
            request["sl"] = sl
        if tp is not None:
            request["tp"] = tp
        if id_position is not None:
            request["position"] = id_position

        log_and_print(f"Sending order request: {request}")
        result = mt5.order_send(request)

        order_type_str = "BUY" if is_buy else "SELL"

        if result is None or result.retcode != mt5.TRADE_RETCODE_DONE:
            fail_count += 1
            error_message = f"Order failed for {symbol}"
            if result:
                error_message += f", retcode={result.retcode}, comment={result.comment}"
            additional_info = (
                f"Date/Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
                f"Order Type: {order_type_str}\n"
                f"Lot Size: {lot}\n"
                f"SL: {sl if sl else 'None'}\n"
                f"TP: {tp if tp else 'None'}\n"
                f"Comment: {COMMENT_ML}\n"
                f"Request: {request}\n"
                f"Result: {result}"
            )
            log_and_print(f"Order failed details: {additional_info}", is_error=True)

            # If market closed or only closing allowed => add to retry queue
            if result is not None and result.retcode in [10018, 10044]:
                retry_queue.append((symbol, datetime.now() + timedelta(minutes=15)))
                log_and_print(f"Symbol {symbol} added to retry queue for later attempt.", is_error=False)

        else:
            success_count += 1
            success_message = f"Order successful for {symbol}, comment={result.comment}"
            additional_info = (
                f"Date/Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
                f"Order Type: {order_type_str}\n"
                f"Lot Size: {lot}\n"
                f"SL: {sl if sl else 'None'}\n"
                f"TP: {tp if tp else 'None'}\n"
                f"Comment: {COMMENT_ML}"
            )
            log_and_print(success_message)


    def get_positions_by_magic(self, symbol, magic_number):
        """
        Retrieve positions for a specific symbol and magic number.
        """
        all_positions = mt5.positions_get(symbol=symbol)
        if not all_positions:
            log_and_print("No positions found.", is_error=False)
            return []
        return [pos for pos in all_positions if pos.magic == magic_number]

    def run_strategy(self, symbol, lot, buy_signal, sell_signal):
        """
        Run the trading strategy logic based on buy/sell signals, including flat signals.
        """
        log_and_print("------------------------------------------------------------------")
        log_and_print(
            f"🟡 Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}, "
            f"SYMBOL: {symbol}, BUY SIGNAL: {buy_signal}, SELL SIGNAL: {sell_signal}"
        )

        positions = self.get_positions_by_magic(symbol, self.magic_number)
        has_buy = any(pos.type == mt5.POSITION_TYPE_BUY for pos in positions)
        has_sell = any(pos.type == mt5.POSITION_TYPE_SELL for pos in positions)

        if buy_signal and not has_buy:
            if has_sell:
                log_and_print(f"🔄 {symbol}: Existing SELL position found. Attempting to close it...")
                if self.close_position(symbol, is_buy=True):
                    log_and_print(f"{symbol}: Closed SELL. Placing new BUY order.")
                    self.orders(symbol, lot, is_buy=True)
                else:
                    log_and_print(f"{symbol}: Failed to close SELL position.")
            else:
                log_and_print(f"🟢 {symbol}: Placing new BUY order.")
                self.orders(symbol, lot, is_buy=True)

        elif sell_signal and not has_sell:
            if has_buy:
                log_and_print(f"🔄 {symbol}: Existing BUY position found. Attempting to close it...")
                if self.close_position(symbol, is_buy=False):
                    log_and_print(f"{symbol}: Closed BUY. Placing new SELL order.")
                    self.orders(symbol, lot, is_buy=False)
                else:
                    log_and_print(f"{symbol}: Failed to close BUY position.")
            else:
                log_and_print(f"🔴 {symbol}: Placing new SELL order.")
                self.orders(symbol, lot, is_buy=False)

        elif not buy_signal and not sell_signal:
            if has_buy or has_sell:
                if CLOSE_ON_FLAT:
                    log_and_print(f"{symbol}: Flat signal. CLOSE_ON_FLAT is True, attempting to close open position.")
                    success = self.close_position(symbol, is_buy=has_sell)
                    if success:
                        log_and_print(f"{symbol}: Flat signal - Position closed.")
                    else:
                        log_and_print(f"{symbol}: Flat signal - Failed to close position.")
                else:
                    log_and_print(f"{symbol}: Flat signal but CLOSE_ON_FLAT is False. Holding current position.")
            else:
                log_and_print(f"🟤 {symbol}: Flat signal. No position open.")



    def close_position(self, symbol, is_buy):
        """
        Closes positions of the opposite type (BUY/SELL) for this app's magic number.
        """
        positions = mt5.positions_get(symbol=symbol)
        if not positions:
            log_and_print(f"No positions to close for symbol: {symbol}")
            return False

        initial_balance = mt5.account_info().balance
        closed_any = False

        for position in positions:
            if position.magic == self.magic_number and (
                (is_buy and position.type == mt5.POSITION_TYPE_SELL) or
                (not is_buy and position.type == mt5.POSITION_TYPE_BUY)
            ):
                # First try ORDER_FILLING_RETURN
                close_request = {
                    "action": mt5.TRADE_ACTION_DEAL,
                    "symbol": symbol,
                    "volume": position.volume,
                    "type": mt5.ORDER_TYPE_BUY if position.type == mt5.POSITION_TYPE_SELL else mt5.ORDER_TYPE_SELL,
                    "position": position.ticket,
                    "deviation": 20,
                    "magic": self.magic_number,
                    "comment": COMMENT_ML,
                    "type_time": mt5.ORDER_TIME_GTC,
                    "type_filling": mt5.ORDER_FILLING_RETURN,  # Try RETURN first
                }
                result = mt5.order_send(close_request)

                if result is None or result.retcode != mt5.TRADE_RETCODE_DONE:
                    # Retry WITH ORDER_FILLING_IOC instead of removing filling type
                    log_and_print(f"⚠️ Filling mode error for {symbol} position {position.ticket}, retrying with ORDER_FILLING_IOC...")
                    
                    close_request["type_filling"] = mt5.ORDER_FILLING_IOC  # Force IOC
                    result_retry = mt5.order_send(close_request)

                    if result_retry is None or result_retry.retcode != mt5.TRADE_RETCODE_DONE:
                        log_and_print(f"❌ Retry failed to close {symbol} — retcode: {result_retry.retcode}, comment: {result_retry.comment}", is_error=True)
                    else:
                        log_and_print(f"✅ Retry succeeded in closing {symbol} position {position.ticket}")
                        closed_any = True
                else:
                    log_and_print(f"✅ Successfully closed position {position.ticket} for {symbol}")
                    closed_any = True

        if closed_any:
            final_balance = mt5.account_info().balance
            profit = final_balance - initial_balance
            log_and_print(f"✅ Closed positions successfully, Profit: {profit}")
            return True
        else:
            return False





    def check_and_execute_trades(self):
        """
        Convenience method to perform the entire flow:
        generate signals, run strategy, and deselect symbol.
        """
        mt5.symbol_select(self.symbol, True)
        buy, sell, _, _ = self.ml_signal_generation(self.symbol, N_BARS, TIMEFRAME)
        self.run_strategy(self.symbol, self.lot_size, buy, sell)
        mt5.symbol_select(self.symbol, False)
        log_and_print("Waiting for new signals...")

def is_market_open():
    """
    Check if the current time is within the typical Forex trading session, adjusted for CET/CEST.
    Market closes at Friday 10:00 PM CET and opens at Sunday 11:00 PM CET. 
    It is closed all day Saturday.
    """
    current_time_utc = datetime.utcnow()
    # Adjust for Central European Time (UTC+1) or Central European Summer Time (UTC+2)
    current_time_cet = (
        current_time_utc + timedelta(hours=2) 
        if time.localtime().tm_isdst 
        else current_time_utc + timedelta(hours=1)
    )

    # Friday after 10 PM CET
    if current_time_cet.weekday() == 4 and current_time_cet.hour >= 22:
        return False
    # Sunday before 11 PM CET
    elif current_time_cet.weekday() == 6 and current_time_cet.hour < 23:
        return False
    # All day Saturday
    elif current_time_cet.weekday() == 5:
        return False
    return True


if __name__ == "__main__":
    try:
        if not mt5.initialize():
            log_and_print("Failed to initialize MetaTrader 5", is_error=True)
            exit()

        # 1) Create a TradingApp per symbol
        apps = {}
        for symbol in symbols:
            app = TradingApp(symbol=symbol, lot_size=lot_sizes[symbol], magic_number=MAGIC_NUMBER)
            app.load_pipeline(model_paths[symbol])
            apps[symbol] = app

        # 2) Initialize tracking variables
        success_count = 0
        fail_count = 0
        retry_queue = []

        while True:
            log_and_print("Checking market status...")
            if is_market_open():
                log_and_print("Market is open. Executing trades...")

                # Handle retry queue
                now = datetime.now()
                retry_symbols_ready = [item for item in retry_queue if item[1] <= now]
                retry_queue = [item for item in retry_queue if item[1] > now]

                symbols_to_process = set(apps.keys())

                # Add retry symbols first
                symbols_ready_to_retry = [item[0] for item in retry_symbols_ready]
                if symbols_ready_to_retry:
                    log_and_print(f"🔁 Retrying symbols: {symbols_ready_to_retry}")
                    symbols_to_process = set(symbols_ready_to_retry) | symbols_to_process

                for symbol in symbols_to_process:
                    app = apps[symbol]

                    try:
                        # Skip US stock symbols if US market is closed
                        if is_us_stock(symbol) and not is_us_market_open():
                            log_and_print(f"🟠 Skipping {symbol}: US market not open yet.")
                            continue

                        log_and_print(f"🔵 Checking Symbol: {symbol}")
                        buy_signal, sell_signal, _, _ = app.ml_signal_generation(
                            symbol=app.symbol,
                            n_bars=N_BARS,
                            timeframe=TIMEFRAME
                        )
                        app.run_strategy(app.symbol, app.lot_size, buy_signal, sell_signal)

                    except Exception as e:
                        log_and_print(f"⚠️ Error processing {symbol}: {e}", is_error=True)

                # After the trading round, log results
                log_and_print(f"✅ Successful Orders: {success_count}")
                log_and_print(f"❌ Failed Orders: {fail_count}")
                log_and_print(f"⏳ Retry Queue: {[item[0] for item in retry_queue]}")

            else:
                log_and_print("Market is closed. Waiting...")

            time.sleep(SLEEP_TIME)

    except KeyboardInterrupt:
        log_and_print("Shutdown signal received.")

    except Exception as e:
        error_message = f"An error occurred: {e}"
        log_and_print(error_message, is_error=True)

    finally:
        mt5.shutdown()
        log_and_print("MetaTrader 5 shutdown completed.")

Loaded pipeline from models/h1_models/EURUSD_H1_best_model.pkl
Loaded pipeline from models/h1_models/USDJPY_H1_best_model.pkl
Loaded pipeline from models/h1_models/AUDUSD_H1_best_model.pkl
Loaded pipeline from models/h1_models/GBPUSD_H1_best_model.pkl
Loaded pipeline from models/h1_models/USDCHF_H1_best_model.pkl
Loaded pipeline from models/h1_models/EURGBP_H1_best_model.pkl
Loaded pipeline from models/h1_models/MSFT.NAS_H1_best_model.pkl
Loaded pipeline from models/h1_models/TSLA.NAS_H1_best_model.pkl
Loaded pipeline from models/h1_models/NVDA.NAS_H1_best_model.pkl
Loaded pipeline from models/h1_models/AMZN.NAS_H1_best_model.pkl
Loaded pipeline from models/h1_models/GOOG.NAS_H1_best_model.pkl
Loaded pipeline from models/h1_models/NFLX.NAS_H1_best_model.pkl
Loaded pipeline from models/h1_models/AAPL.NAS_H1_best_model.pkl
Loaded pipeline from models/h1_models/BABA.NYSE_H1_best_model.pkl
Loaded pipeline from models/h1_models/JPM.NYSE_H1_best_model.pkl
Loaded pipeline from models/h1_models/XOM.NYSE_H1_best_model.pkl
Loaded pipeline from models/h1_models/BA.NYSE_H1_best_model.pkl
Loaded pipeline from models/h1_models/DIS.NYSE_H1_best_model.pkl
Loaded pipeline from models/h1_models/NKE.NYSE_H1_best_model.pkl
Loaded pipeline from models/h1_models/US500_H1_best_model.pkl
Loaded pipeline from models/h1_models/US2000_H1_best_model.pkl
Loaded pipeline from models/h1_models/UK100_H1_best_model.pkl
Loaded pipeline from models/h1_models/JP225_H1_best_model.pkl
Loaded pipeline from models/h1_models/XAUUSD_H1_best_model.pkl
Loaded pipeline from models/h1_models/DE40_H1_best_model.pkl
Checking market status...
Market is open. Executing trades...
🟠 Skipping NKE.NYSE: US market not open yet.
🟠 Skipping NVDA.NAS: US market not open yet.
🔵 Checking Symbol: XAUUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 07:09:26, SYMBOL: XAUUSD, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
🔴 XAUUSD: Placing new SELL order.
Adjusted lot size to 0.01 (min=0.01, step=0.01, max=100.0)
Sending order request: {'action': 1, 'symbol': 'XAUUSD', 'volume': 0.01, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order successful for XAUUSD, comment=Request executed
🔵 Checking Symbol: US2000
------------------------------------------------------------------
🟡 Date: 2025-05-01 07:09:27, SYMBOL: US2000, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 US2000: Flat signal. No position open.
🔵 Checking Symbol: USDJPY
------------------------------------------------------------------
🟡 Date: 2025-05-01 07:09:27, SYMBOL: USDJPY, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: GBPUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 07:09:28, SYMBOL: GBPUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 GBPUSD: Flat signal. No position open.
🟠 Skipping NFLX.NAS: US market not open yet.
🟠 Skipping TSLA.NAS: US market not open yet.
🟠 Skipping AAPL.NAS: US market not open yet.
🟠 Skipping XOM.NYSE: US market not open yet.
🔵 Checking Symbol: EURGBP
------------------------------------------------------------------
🟡 Date: 2025-05-01 07:09:28, SYMBOL: EURGBP, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 EURGBP: Flat signal. No position open.
🔵 Checking Symbol: US500
------------------------------------------------------------------
🟡 Date: 2025-05-01 07:09:29, SYMBOL: US500, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
🔴 US500: Placing new SELL order.
Adjusted lot size to 0.1 (min=0.1, step=0.1, max=250.0)
Sending order request: {'action': 1, 'symbol': 'US500', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order successful for US500, comment=Request executed
🔵 Checking Symbol: USDCHF
------------------------------------------------------------------
🟡 Date: 2025-05-01 07:09:30, SYMBOL: USDCHF, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 USDCHF: Flat signal. No position open.
🔵 Checking Symbol: EURUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 07:09:30, SYMBOL: EURUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 EURUSD: Flat signal. No position open.
🟠 Skipping MSFT.NAS: US market not open yet.
🔵 Checking Symbol: AUDUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 07:09:31, SYMBOL: AUDUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 AUDUSD: Flat signal. No position open.
🟠 Skipping BA.NYSE: US market not open yet.
🟠 Skipping JPM.NYSE: US market not open yet.
🟠 Skipping DIS.NYSE: US market not open yet.
🔵 Checking Symbol: DE40
------------------------------------------------------------------
🟡 Date: 2025-05-01 07:09:31, SYMBOL: DE40, BUY SIGNAL: False, SELL SIGNAL: False
🟤 DE40: Flat signal. No position open.
🔵 Checking Symbol: JP225
------------------------------------------------------------------
🟡 Date: 2025-05-01 07:09:32, SYMBOL: JP225, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
🔴 JP225: Placing new SELL order.
Adjusted lot size to 1.0 (min=1.0, step=1.0, max=250.0)
Sending order request: {'action': 1, 'symbol': 'JP225', 'volume': 1.0, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order successful for JP225, comment=Request executed
🟠 Skipping AMZN.NAS: US market not open yet.
🔵 Checking Symbol: UK100
------------------------------------------------------------------
🟡 Date: 2025-05-01 07:09:33, SYMBOL: UK100, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
🔴 UK100: Placing new SELL order.
Adjusted lot size to 0.1 (min=0.1, step=0.1, max=250.0)
Sending order request: {'action': 1, 'symbol': 'UK100', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order successful for UK100, comment=Request executed
🟠 Skipping GOOG.NAS: US market not open yet.
🟠 Skipping BABA.NYSE: US market not open yet.
✅ Successful Orders: 4
❌ Failed Orders: 0
⏳ Retry Queue: []
Checking market status...
Market is open. Executing trades...
🟠 Skipping NKE.NYSE: US market not open yet.
🟠 Skipping NVDA.NAS: US market not open yet.
🔵 Checking Symbol: XAUUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 08:09:34, SYMBOL: XAUUSD, BUY SIGNAL: False, SELL SIGNAL: True
🔴 XAUUSD: Placing new SELL order.
Adjusted lot size to 0.01 (min=0.01, step=0.01, max=100.0)
Sending order request: {'action': 1, 'symbol': 'XAUUSD', 'volume': 0.01, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order successful for XAUUSD, comment=Request executed
🔵 Checking Symbol: US2000
------------------------------------------------------------------
🟡 Date: 2025-05-01 08:09:35, SYMBOL: US2000, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 US2000: Flat signal. No position open.
🔵 Checking Symbol: USDJPY
------------------------------------------------------------------
🟡 Date: 2025-05-01 08:09:36, SYMBOL: USDJPY, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: GBPUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 08:09:37, SYMBOL: GBPUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 GBPUSD: Flat signal. No position open.
🟠 Skipping NFLX.NAS: US market not open yet.
🟠 Skipping TSLA.NAS: US market not open yet.
🟠 Skipping AAPL.NAS: US market not open yet.
🟠 Skipping XOM.NYSE: US market not open yet.
🔵 Checking Symbol: EURGBP
------------------------------------------------------------------
🟡 Date: 2025-05-01 08:09:38, SYMBOL: EURGBP, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 EURGBP: Flat signal. No position open.
🔵 Checking Symbol: US500
------------------------------------------------------------------
🟡 Date: 2025-05-01 08:09:39, SYMBOL: US500, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
🔴 US500: Placing new SELL order.
Adjusted lot size to 0.1 (min=0.1, step=0.1, max=250.0)
Sending order request: {'action': 1, 'symbol': 'US500', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order successful for US500, comment=Request executed
🔵 Checking Symbol: USDCHF
------------------------------------------------------------------
🟡 Date: 2025-05-01 08:09:40, SYMBOL: USDCHF, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 USDCHF: Flat signal. No position open.
🔵 Checking Symbol: EURUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 08:09:41, SYMBOL: EURUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 EURUSD: Flat signal. No position open.
🟠 Skipping MSFT.NAS: US market not open yet.
🔵 Checking Symbol: AUDUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 08:09:42, SYMBOL: AUDUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 AUDUSD: Flat signal. No position open.
🟠 Skipping BA.NYSE: US market not open yet.
🟠 Skipping JPM.NYSE: US market not open yet.
🟠 Skipping DIS.NYSE: US market not open yet.
🔵 Checking Symbol: DE40
------------------------------------------------------------------
🟡 Date: 2025-05-01 08:09:42, SYMBOL: DE40, BUY SIGNAL: False, SELL SIGNAL: False
🟤 DE40: Flat signal. No position open.
🔵 Checking Symbol: JP225
------------------------------------------------------------------
🟡 Date: 2025-05-01 08:09:43, SYMBOL: JP225, BUY SIGNAL: False, SELL SIGNAL: True
🟠 Skipping AMZN.NAS: US market not open yet.
🔵 Checking Symbol: UK100
------------------------------------------------------------------
🟡 Date: 2025-05-01 08:09:44, SYMBOL: UK100, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
🔴 UK100: Placing new SELL order.
Adjusted lot size to 0.1 (min=0.1, step=0.1, max=250.0)
Sending order request: {'action': 1, 'symbol': 'UK100', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order successful for UK100, comment=Request executed
🟠 Skipping GOOG.NAS: US market not open yet.
🟠 Skipping BABA.NYSE: US market not open yet.
✅ Successful Orders: 7
❌ Failed Orders: 0
⏳ Retry Queue: []
Checking market status...
Market is open. Executing trades...
🟠 Skipping NKE.NYSE: US market not open yet.
🟠 Skipping NVDA.NAS: US market not open yet.
🔵 Checking Symbol: XAUUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 09:09:45, SYMBOL: XAUUSD, BUY SIGNAL: False, SELL SIGNAL: True
🔴 XAUUSD: Placing new SELL order.
Adjusted lot size to 0.01 (min=0.01, step=0.01, max=100.0)
Sending order request: {'action': 1, 'symbol': 'XAUUSD', 'volume': 0.01, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order successful for XAUUSD, comment=Request executed
🔵 Checking Symbol: US2000
------------------------------------------------------------------
🟡 Date: 2025-05-01 09:09:47, SYMBOL: US2000, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 US2000: Flat signal. No position open.
🔵 Checking Symbol: USDJPY
------------------------------------------------------------------
🟡 Date: 2025-05-01 09:09:48, SYMBOL: USDJPY, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: GBPUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 09:09:49, SYMBOL: GBPUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 GBPUSD: Flat signal. No position open.
🟠 Skipping NFLX.NAS: US market not open yet.
🟠 Skipping TSLA.NAS: US market not open yet.
🟠 Skipping AAPL.NAS: US market not open yet.
🟠 Skipping XOM.NYSE: US market not open yet.
🔵 Checking Symbol: EURGBP
------------------------------------------------------------------
🟡 Date: 2025-05-01 09:09:50, SYMBOL: EURGBP, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 EURGBP: Flat signal. No position open.
🔵 Checking Symbol: US500
------------------------------------------------------------------
🟡 Date: 2025-05-01 09:09:51, SYMBOL: US500, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: USDCHF
------------------------------------------------------------------
🟡 Date: 2025-05-01 09:09:52, SYMBOL: USDCHF, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 USDCHF: Flat signal. No position open.
🔵 Checking Symbol: EURUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 09:09:53, SYMBOL: EURUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 EURUSD: Flat signal. No position open.
🟠 Skipping MSFT.NAS: US market not open yet.
🔵 Checking Symbol: AUDUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 09:09:54, SYMBOL: AUDUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 AUDUSD: Flat signal. No position open.
🟠 Skipping BA.NYSE: US market not open yet.
🟠 Skipping JPM.NYSE: US market not open yet.
🟠 Skipping DIS.NYSE: US market not open yet.
🔵 Checking Symbol: DE40
------------------------------------------------------------------
🟡 Date: 2025-05-01 09:09:55, SYMBOL: DE40, BUY SIGNAL: False, SELL SIGNAL: False
🟤 DE40: Flat signal. No position open.
🔵 Checking Symbol: JP225
------------------------------------------------------------------
🟡 Date: 2025-05-01 09:09:56, SYMBOL: JP225, BUY SIGNAL: False, SELL SIGNAL: True
🟠 Skipping AMZN.NAS: US market not open yet.
🔵 Checking Symbol: UK100
------------------------------------------------------------------
🟡 Date: 2025-05-01 09:09:57, SYMBOL: UK100, BUY SIGNAL: False, SELL SIGNAL: True
🟠 Skipping GOOG.NAS: US market not open yet.
🟠 Skipping BABA.NYSE: US market not open yet.
✅ Successful Orders: 8
❌ Failed Orders: 0
⏳ Retry Queue: []
Checking market status...
Market is open. Executing trades...
🟠 Skipping NKE.NYSE: US market not open yet.
🟠 Skipping NVDA.NAS: US market not open yet.
🔵 Checking Symbol: XAUUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 10:09:58, SYMBOL: XAUUSD, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: US2000
------------------------------------------------------------------
🟡 Date: 2025-05-01 10:09:59, SYMBOL: US2000, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 US2000: Flat signal. No position open.
🔵 Checking Symbol: USDJPY
------------------------------------------------------------------
🟡 Date: 2025-05-01 10:09:59, SYMBOL: USDJPY, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: GBPUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 10:10:00, SYMBOL: GBPUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 GBPUSD: Flat signal. No position open.
🟠 Skipping NFLX.NAS: US market not open yet.
🟠 Skipping TSLA.NAS: US market not open yet.
🟠 Skipping AAPL.NAS: US market not open yet.
🟠 Skipping XOM.NYSE: US market not open yet.
🔵 Checking Symbol: EURGBP
------------------------------------------------------------------
🟡 Date: 2025-05-01 10:10:00, SYMBOL: EURGBP, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 EURGBP: Flat signal. No position open.
🔵 Checking Symbol: US500
------------------------------------------------------------------
🟡 Date: 2025-05-01 10:10:01, SYMBOL: US500, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: USDCHF
------------------------------------------------------------------
🟡 Date: 2025-05-01 10:10:02, SYMBOL: USDCHF, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 USDCHF: Flat signal. No position open.
🔵 Checking Symbol: EURUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 10:10:02, SYMBOL: EURUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 EURUSD: Flat signal. No position open.
🟠 Skipping MSFT.NAS: US market not open yet.
🔵 Checking Symbol: AUDUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 10:10:03, SYMBOL: AUDUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 AUDUSD: Flat signal. No position open.
🟠 Skipping BA.NYSE: US market not open yet.
🟠 Skipping JPM.NYSE: US market not open yet.
🟠 Skipping DIS.NYSE: US market not open yet.
🔵 Checking Symbol: DE40
------------------------------------------------------------------
🟡 Date: 2025-05-01 10:10:03, SYMBOL: DE40, BUY SIGNAL: False, SELL SIGNAL: False
🟤 DE40: Flat signal. No position open.
🔵 Checking Symbol: JP225
------------------------------------------------------------------
🟡 Date: 2025-05-01 10:10:04, SYMBOL: JP225, BUY SIGNAL: False, SELL SIGNAL: True
🟠 Skipping AMZN.NAS: US market not open yet.
🔵 Checking Symbol: UK100
------------------------------------------------------------------
🟡 Date: 2025-05-01 10:10:04, SYMBOL: UK100, BUY SIGNAL: False, SELL SIGNAL: True
🟠 Skipping GOOG.NAS: US market not open yet.
🟠 Skipping BABA.NYSE: US market not open yet.
✅ Successful Orders: 8
❌ Failed Orders: 0
⏳ Retry Queue: []
Checking market status...
Market is open. Executing trades...
🟠 Skipping NKE.NYSE: US market not open yet.
🟠 Skipping NVDA.NAS: US market not open yet.
🔵 Checking Symbol: XAUUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 11:10:05, SYMBOL: XAUUSD, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: US2000
------------------------------------------------------------------
🟡 Date: 2025-05-01 11:10:05, SYMBOL: US2000, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 US2000: Flat signal. No position open.
🔵 Checking Symbol: USDJPY
------------------------------------------------------------------
🟡 Date: 2025-05-01 11:10:06, SYMBOL: USDJPY, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: GBPUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 11:10:06, SYMBOL: GBPUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 GBPUSD: Flat signal. No position open.
🟠 Skipping NFLX.NAS: US market not open yet.
🟠 Skipping TSLA.NAS: US market not open yet.
🟠 Skipping AAPL.NAS: US market not open yet.
🟠 Skipping XOM.NYSE: US market not open yet.
🔵 Checking Symbol: EURGBP
------------------------------------------------------------------
🟡 Date: 2025-05-01 11:10:07, SYMBOL: EURGBP, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 EURGBP: Flat signal. No position open.
🔵 Checking Symbol: US500
------------------------------------------------------------------
🟡 Date: 2025-05-01 11:10:07, SYMBOL: US500, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: USDCHF
------------------------------------------------------------------
🟡 Date: 2025-05-01 11:10:08, SYMBOL: USDCHF, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 USDCHF: Flat signal. No position open.
🔵 Checking Symbol: EURUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 11:10:08, SYMBOL: EURUSD, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
🔴 EURUSD: Placing new SELL order.
Adjusted lot size to 0.01 (min=0.01, step=0.01, max=200.0)
Sending order request: {'action': 1, 'symbol': 'EURUSD', 'volume': 0.01, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order successful for EURUSD, comment=Request executed
🟠 Skipping MSFT.NAS: US market not open yet.
🔵 Checking Symbol: AUDUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 11:10:09, SYMBOL: AUDUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 AUDUSD: Flat signal. No position open.
🟠 Skipping BA.NYSE: US market not open yet.
🟠 Skipping JPM.NYSE: US market not open yet.
🟠 Skipping DIS.NYSE: US market not open yet.
🔵 Checking Symbol: DE40
------------------------------------------------------------------
🟡 Date: 2025-05-01 11:10:09, SYMBOL: DE40, BUY SIGNAL: False, SELL SIGNAL: False
🟤 DE40: Flat signal. No position open.
🔵 Checking Symbol: JP225
------------------------------------------------------------------
🟡 Date: 2025-05-01 11:10:10, SYMBOL: JP225, BUY SIGNAL: False, SELL SIGNAL: True
🟠 Skipping AMZN.NAS: US market not open yet.
🔵 Checking Symbol: UK100
------------------------------------------------------------------
🟡 Date: 2025-05-01 11:10:10, SYMBOL: UK100, BUY SIGNAL: False, SELL SIGNAL: True
🟠 Skipping GOOG.NAS: US market not open yet.
🟠 Skipping BABA.NYSE: US market not open yet.
✅ Successful Orders: 9
❌ Failed Orders: 0
⏳ Retry Queue: []
Checking market status...
Market is open. Executing trades...
🟠 Skipping NKE.NYSE: US market not open yet.
🟠 Skipping NVDA.NAS: US market not open yet.
🔵 Checking Symbol: XAUUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 12:10:11, SYMBOL: XAUUSD, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: US2000
------------------------------------------------------------------
🟡 Date: 2025-05-01 12:10:12, SYMBOL: US2000, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 US2000: Flat signal. No position open.
🔵 Checking Symbol: USDJPY
------------------------------------------------------------------
🟡 Date: 2025-05-01 12:10:12, SYMBOL: USDJPY, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: GBPUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 12:10:13, SYMBOL: GBPUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 GBPUSD: Flat signal. No position open.
🟠 Skipping NFLX.NAS: US market not open yet.
🟠 Skipping TSLA.NAS: US market not open yet.
🟠 Skipping AAPL.NAS: US market not open yet.
🟠 Skipping XOM.NYSE: US market not open yet.
🔵 Checking Symbol: EURGBP
------------------------------------------------------------------
🟡 Date: 2025-05-01 12:10:14, SYMBOL: EURGBP, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 EURGBP: Flat signal. No position open.
🔵 Checking Symbol: US500
------------------------------------------------------------------
🟡 Date: 2025-05-01 12:10:14, SYMBOL: US500, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: USDCHF
------------------------------------------------------------------
🟡 Date: 2025-05-01 12:10:15, SYMBOL: USDCHF, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 USDCHF: Flat signal. No position open.
🔵 Checking Symbol: EURUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 12:10:15, SYMBOL: EURUSD, BUY SIGNAL: False, SELL SIGNAL: True
🟠 Skipping MSFT.NAS: US market not open yet.
🔵 Checking Symbol: AUDUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 12:10:16, SYMBOL: AUDUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 AUDUSD: Flat signal. No position open.
🟠 Skipping BA.NYSE: US market not open yet.
🟠 Skipping JPM.NYSE: US market not open yet.
🟠 Skipping DIS.NYSE: US market not open yet.
🔵 Checking Symbol: DE40
------------------------------------------------------------------
🟡 Date: 2025-05-01 12:10:17, SYMBOL: DE40, BUY SIGNAL: False, SELL SIGNAL: False
🟤 DE40: Flat signal. No position open.
🔵 Checking Symbol: JP225
------------------------------------------------------------------
🟡 Date: 2025-05-01 12:10:17, SYMBOL: JP225, BUY SIGNAL: False, SELL SIGNAL: True
🟠 Skipping AMZN.NAS: US market not open yet.
🔵 Checking Symbol: UK100
------------------------------------------------------------------
🟡 Date: 2025-05-01 12:10:18, SYMBOL: UK100, BUY SIGNAL: False, SELL SIGNAL: True
🟠 Skipping GOOG.NAS: US market not open yet.
🟠 Skipping BABA.NYSE: US market not open yet.
✅ Successful Orders: 9
❌ Failed Orders: 0
⏳ Retry Queue: []
Checking market status...
Market is open. Executing trades...
🟠 Skipping NKE.NYSE: US market not open yet.
🟠 Skipping NVDA.NAS: US market not open yet.
🔵 Checking Symbol: XAUUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 13:10:19, SYMBOL: XAUUSD, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
🔴 XAUUSD: Placing new SELL order.
Adjusted lot size to 0.01 (min=0.01, step=0.01, max=100.0)
Sending order request: {'action': 1, 'symbol': 'XAUUSD', 'volume': 0.01, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order successful for XAUUSD, comment=Request executed
🔵 Checking Symbol: US2000
------------------------------------------------------------------
🟡 Date: 2025-05-01 13:10:20, SYMBOL: US2000, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 US2000: Flat signal. No position open.
🔵 Checking Symbol: USDJPY
------------------------------------------------------------------
🟡 Date: 2025-05-01 13:10:20, SYMBOL: USDJPY, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: GBPUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 13:10:21, SYMBOL: GBPUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 GBPUSD: Flat signal. No position open.
🟠 Skipping NFLX.NAS: US market not open yet.
🟠 Skipping TSLA.NAS: US market not open yet.
🟠 Skipping AAPL.NAS: US market not open yet.
🟠 Skipping XOM.NYSE: US market not open yet.
🔵 Checking Symbol: EURGBP
------------------------------------------------------------------
🟡 Date: 2025-05-01 13:10:21, SYMBOL: EURGBP, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 EURGBP: Flat signal. No position open.
🔵 Checking Symbol: US500
------------------------------------------------------------------
🟡 Date: 2025-05-01 13:10:22, SYMBOL: US500, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: USDCHF
------------------------------------------------------------------
🟡 Date: 2025-05-01 13:10:22, SYMBOL: USDCHF, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 USDCHF: Flat signal. No position open.
🔵 Checking Symbol: EURUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 13:10:23, SYMBOL: EURUSD, BUY SIGNAL: False, SELL SIGNAL: False
⚪ EURUSD: Flat signal. CLOSE_ON_FLAT is True, attempting to close open position.
⚠️ Filling mode error for EURUSD position 1117275715, retrying with ORDER_FILLING_IOC...
✅ Retry succeeded in closing EURUSD position 1117275715
✅ Closed positions successfully, Profit: -0.7900000000000205
✅ EURUSD: Flat signal - Position closed.
🟠 Skipping MSFT.NAS: US market not open yet.
🔵 Checking Symbol: AUDUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 13:10:24, SYMBOL: AUDUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 AUDUSD: Flat signal. No position open.
🟠 Skipping BA.NYSE: US market not open yet.
🟠 Skipping JPM.NYSE: US market not open yet.
🟠 Skipping DIS.NYSE: US market not open yet.
🔵 Checking Symbol: DE40
------------------------------------------------------------------
🟡 Date: 2025-05-01 13:10:24, SYMBOL: DE40, BUY SIGNAL: False, SELL SIGNAL: False
🟤 DE40: Flat signal. No position open.
🔵 Checking Symbol: JP225
------------------------------------------------------------------
🟡 Date: 2025-05-01 13:10:25, SYMBOL: JP225, BUY SIGNAL: False, SELL SIGNAL: True
🟠 Skipping AMZN.NAS: US market not open yet.
🔵 Checking Symbol: UK100
------------------------------------------------------------------
🟡 Date: 2025-05-01 13:10:25, SYMBOL: UK100, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
🔴 UK100: Placing new SELL order.
Adjusted lot size to 0.1 (min=0.1, step=0.1, max=250.0)
Sending order request: {'action': 1, 'symbol': 'UK100', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order successful for UK100, comment=Request executed
🟠 Skipping GOOG.NAS: US market not open yet.
🟠 Skipping BABA.NYSE: US market not open yet.
✅ Successful Orders: 11
❌ Failed Orders: 0
⏳ Retry Queue: []
Checking market status...
Market is open. Executing trades...
🟠 Skipping NKE.NYSE: US market not open yet.
🟠 Skipping NVDA.NAS: US market not open yet.
🔵 Checking Symbol: XAUUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 14:10:26, SYMBOL: XAUUSD, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
🔴 XAUUSD: Placing new SELL order.
Adjusted lot size to 0.01 (min=0.01, step=0.01, max=100.0)
Sending order request: {'action': 1, 'symbol': 'XAUUSD', 'volume': 0.01, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order successful for XAUUSD, comment=Request executed
🔵 Checking Symbol: US2000
------------------------------------------------------------------
🟡 Date: 2025-05-01 14:10:28, SYMBOL: US2000, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 US2000: Flat signal. No position open.
🔵 Checking Symbol: USDJPY
------------------------------------------------------------------
🟡 Date: 2025-05-01 14:10:28, SYMBOL: USDJPY, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: GBPUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 14:10:29, SYMBOL: GBPUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 GBPUSD: Flat signal. No position open.
🟠 Skipping NFLX.NAS: US market not open yet.
🟠 Skipping TSLA.NAS: US market not open yet.
🟠 Skipping AAPL.NAS: US market not open yet.
🟠 Skipping XOM.NYSE: US market not open yet.
🔵 Checking Symbol: EURGBP
------------------------------------------------------------------
🟡 Date: 2025-05-01 14:10:30, SYMBOL: EURGBP, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 EURGBP: Flat signal. No position open.
🔵 Checking Symbol: US500
------------------------------------------------------------------
🟡 Date: 2025-05-01 14:10:31, SYMBOL: US500, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: USDCHF
------------------------------------------------------------------
🟡 Date: 2025-05-01 14:10:32, SYMBOL: USDCHF, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 USDCHF: Flat signal. No position open.
🔵 Checking Symbol: EURUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 14:10:33, SYMBOL: EURUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 EURUSD: Flat signal. No position open.
🟠 Skipping MSFT.NAS: US market not open yet.
🔵 Checking Symbol: AUDUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 14:10:34, SYMBOL: AUDUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 AUDUSD: Flat signal. No position open.
🟠 Skipping BA.NYSE: US market not open yet.
🟠 Skipping JPM.NYSE: US market not open yet.
🟠 Skipping DIS.NYSE: US market not open yet.
🔵 Checking Symbol: DE40
------------------------------------------------------------------
🟡 Date: 2025-05-01 14:10:35, SYMBOL: DE40, BUY SIGNAL: False, SELL SIGNAL: False
🟤 DE40: Flat signal. No position open.
🔵 Checking Symbol: JP225
------------------------------------------------------------------
🟡 Date: 2025-05-01 14:10:36, SYMBOL: JP225, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
🔴 JP225: Placing new SELL order.
Adjusted lot size to 1.0 (min=1.0, step=1.0, max=250.0)
Sending order request: {'action': 1, 'symbol': 'JP225', 'volume': 1.0, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order successful for JP225, comment=Request executed
🟠 Skipping AMZN.NAS: US market not open yet.
🔵 Checking Symbol: UK100
------------------------------------------------------------------
🟡 Date: 2025-05-01 14:10:37, SYMBOL: UK100, BUY SIGNAL: False, SELL SIGNAL: True
🟠 Skipping GOOG.NAS: US market not open yet.
🟠 Skipping BABA.NYSE: US market not open yet.
✅ Successful Orders: 13
❌ Failed Orders: 0
⏳ Retry Queue: []
Checking market status...
Market is open. Executing trades...
🟠 Skipping NKE.NYSE: US market not open yet.
🟠 Skipping NVDA.NAS: US market not open yet.
🔵 Checking Symbol: XAUUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 15:10:38, SYMBOL: XAUUSD, BUY SIGNAL: False, SELL SIGNAL: True
🔴 XAUUSD: Placing new SELL order.
Adjusted lot size to 0.01 (min=0.01, step=0.01, max=100.0)
Sending order request: {'action': 1, 'symbol': 'XAUUSD', 'volume': 0.01, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order successful for XAUUSD, comment=Request executed
🔵 Checking Symbol: US2000
------------------------------------------------------------------
🟡 Date: 2025-05-01 15:10:39, SYMBOL: US2000, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 US2000: Flat signal. No position open.
🔵 Checking Symbol: USDJPY
------------------------------------------------------------------
🟡 Date: 2025-05-01 15:10:40, SYMBOL: USDJPY, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: GBPUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 15:10:41, SYMBOL: GBPUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 GBPUSD: Flat signal. No position open.
🟠 Skipping NFLX.NAS: US market not open yet.
🟠 Skipping TSLA.NAS: US market not open yet.
🟠 Skipping AAPL.NAS: US market not open yet.
🟠 Skipping XOM.NYSE: US market not open yet.
🔵 Checking Symbol: EURGBP
------------------------------------------------------------------
🟡 Date: 2025-05-01 15:10:42, SYMBOL: EURGBP, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 EURGBP: Flat signal. No position open.
🔵 Checking Symbol: US500
------------------------------------------------------------------
🟡 Date: 2025-05-01 15:10:43, SYMBOL: US500, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: USDCHF
------------------------------------------------------------------
🟡 Date: 2025-05-01 15:10:43, SYMBOL: USDCHF, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 USDCHF: Flat signal. No position open.
🔵 Checking Symbol: EURUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 15:10:44, SYMBOL: EURUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 EURUSD: Flat signal. No position open.
🟠 Skipping MSFT.NAS: US market not open yet.
🔵 Checking Symbol: AUDUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 15:10:45, SYMBOL: AUDUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 AUDUSD: Flat signal. No position open.
🟠 Skipping BA.NYSE: US market not open yet.
🟠 Skipping JPM.NYSE: US market not open yet.
🟠 Skipping DIS.NYSE: US market not open yet.
🔵 Checking Symbol: DE40
------------------------------------------------------------------
🟡 Date: 2025-05-01 15:10:46, SYMBOL: DE40, BUY SIGNAL: False, SELL SIGNAL: False
🟤 DE40: Flat signal. No position open.
🔵 Checking Symbol: JP225
------------------------------------------------------------------
🟡 Date: 2025-05-01 15:10:47, SYMBOL: JP225, BUY SIGNAL: False, SELL SIGNAL: True
🟠 Skipping AMZN.NAS: US market not open yet.
🔵 Checking Symbol: UK100
------------------------------------------------------------------
🟡 Date: 2025-05-01 15:10:47, SYMBOL: UK100, BUY SIGNAL: False, SELL SIGNAL: True
🟠 Skipping GOOG.NAS: US market not open yet.
🟠 Skipping BABA.NYSE: US market not open yet.
✅ Successful Orders: 14
❌ Failed Orders: 0
⏳ Retry Queue: []
Checking market status...
Market is open. Executing trades...
🔵 Checking Symbol: NKE.NYSE
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:10:49, SYMBOL: NKE.NYSE, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: NVDA.NAS
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:10:50, SYMBOL: NVDA.NAS, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: XAUUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:10:51, SYMBOL: XAUUSD, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
🔴 XAUUSD: Placing new SELL order.
Adjusted lot size to 0.01 (min=0.01, step=0.01, max=100.0)
Sending order request: {'action': 1, 'symbol': 'XAUUSD', 'volume': 0.01, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order failed details: Date/Time: 2025-05-01 16:10:51
Order Type: SELL
Lot Size: 0.01
SL: None
TP: None
Comment: RFFV-D
Request: {'action': 1, 'symbol': 'XAUUSD', 'volume': 0.01, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Result: OrderSendResult(retcode=10031, deal=0, order=0, volume=0.0, price=0.0, bid=0.0, ask=0.0, comment='Request rejected due to absence of network connection', request_id=0, retcode_external=0, request=TradeRequest(action=1, magic=234003, order=0, symbol='XAUUSD', volume=0.01, price=0.0, stoplimit=0.0, sl=0.0, tp=0.0, deviation=20, type=1, type_filling=1, type_time=0, expiration=0, comment='RFFV-D', position=0, position_by=0))
🔵 Checking Symbol: US2000
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:10:52, SYMBOL: US2000, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 US2000: Flat signal. No position open.
🔵 Checking Symbol: USDJPY
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:10:53, SYMBOL: USDJPY, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
🔴 USDJPY: Placing new SELL order.
Adjusted lot size to 0.01 (min=0.01, step=0.01, max=200.0)
Sending order request: {'action': 1, 'symbol': 'USDJPY', 'volume': 0.01, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order failed details: Date/Time: 2025-05-01 16:10:53
Order Type: SELL
Lot Size: 0.01
SL: None
TP: None
Comment: RFFV-D
Request: {'action': 1, 'symbol': 'USDJPY', 'volume': 0.01, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Result: OrderSendResult(retcode=10031, deal=0, order=0, volume=0.0, price=0.0, bid=0.0, ask=0.0, comment='Request rejected due to absence of network connection', request_id=0, retcode_external=0, request=TradeRequest(action=1, magic=234003, order=0, symbol='USDJPY', volume=0.01, price=0.0, stoplimit=0.0, sl=0.0, tp=0.0, deviation=20, type=1, type_filling=1, type_time=0, expiration=0, comment='RFFV-D', position=0, position_by=0))
🔵 Checking Symbol: GBPUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:10:54, SYMBOL: GBPUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 GBPUSD: Flat signal. No position open.
🔵 Checking Symbol: NFLX.NAS
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:10:55, SYMBOL: NFLX.NAS, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: TSLA.NAS
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:10:56, SYMBOL: TSLA.NAS, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: AAPL.NAS
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:10:57, SYMBOL: AAPL.NAS, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
🔴 AAPL.NAS: Placing new SELL order.
Adjusted lot size to 0.1 (min=0.1, step=0.1, max=1000.0)
Sending order request: {'action': 1, 'symbol': 'AAPL.NAS', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order failed details: Date/Time: 2025-05-01 16:10:57
Order Type: SELL
Lot Size: 0.1
SL: None
TP: None
Comment: RFFV-D
Request: {'action': 1, 'symbol': 'AAPL.NAS', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Result: OrderSendResult(retcode=10044, deal=0, order=0, volume=0.0, price=0.0, bid=0.0, ask=0.0, comment='Only position closing is allowed', request_id=0, retcode_external=0, request=TradeRequest(action=1, magic=234003, order=0, symbol='AAPL.NAS', volume=0.1, price=0.0, stoplimit=0.0, sl=0.0, tp=0.0, deviation=20, type=1, type_filling=1, type_time=0, expiration=0, comment='RFFV-D', position=0, position_by=0))
Symbol AAPL.NAS added to retry queue for later attempt.
🔵 Checking Symbol: XOM.NYSE
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:10:59, SYMBOL: XOM.NYSE, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
🔴 XOM.NYSE: Placing new SELL order.
Zero or invalid bid/ask for XOM.NYSE: bid=0.0, ask=0.0
🔵 Checking Symbol: EURGBP
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:10:59, SYMBOL: EURGBP, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 EURGBP: Flat signal. No position open.
🔵 Checking Symbol: US500
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:11:00, SYMBOL: US500, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: USDCHF
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:11:01, SYMBOL: USDCHF, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 USDCHF: Flat signal. No position open.
🔵 Checking Symbol: EURUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:11:02, SYMBOL: EURUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 EURUSD: Flat signal. No position open.
🔵 Checking Symbol: MSFT.NAS
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:11:04, SYMBOL: MSFT.NAS, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
🔴 MSFT.NAS: Placing new SELL order.
Zero or invalid bid/ask for MSFT.NAS: bid=0.0, ask=0.0
🔵 Checking Symbol: AUDUSD
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:11:04, SYMBOL: AUDUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
🟤 AUDUSD: Flat signal. No position open.
🔵 Checking Symbol: BA.NYSE
⚠️ Error processing BA.NYSE: 'time'
🔵 Checking Symbol: JPM.NYSE
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:11:07, SYMBOL: JPM.NYSE, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: DIS.NYSE
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:11:08, SYMBOL: DIS.NYSE, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
🔴 DIS.NYSE: Placing new SELL order.
Zero or invalid bid/ask for DIS.NYSE: bid=0.0, ask=0.0
🔵 Checking Symbol: DE40
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:11:09, SYMBOL: DE40, BUY SIGNAL: False, SELL SIGNAL: False
🟤 DE40: Flat signal. No position open.
🔵 Checking Symbol: JP225
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:11:10, SYMBOL: JP225, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: AMZN.NAS
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:11:11, SYMBOL: AMZN.NAS, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
🔴 AMZN.NAS: Placing new SELL order.
Zero or invalid bid/ask for AMZN.NAS: bid=0.0, ask=0.0
🔵 Checking Symbol: UK100
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:11:12, SYMBOL: UK100, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: GOOG.NAS
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:11:13, SYMBOL: GOOG.NAS, BUY SIGNAL: False, SELL SIGNAL: True
🔵 Checking Symbol: BABA.NYSE
------------------------------------------------------------------
🟡 Date: 2025-05-01 16:11:14, SYMBOL: BABA.NYSE, BUY SIGNAL: False, SELL SIGNAL: True
✅ Successful Orders: 14
❌ Failed Orders: 7
⏳ Retry Queue: ['AAPL.NAS']
In [ ]:
# LIVE TRADING CODE FOR MULTI-BAR CLASSIFICATION

import sys
import os
import warnings
from pathlib import Path

# ---------------------------------------------------------------------------
# 1) SET PROJECT ROOT AND UPDATE PATH/WORKING DIRECTORY
# ---------------------------------------------------------------------------
project_root = Path.cwd().parent.parent  # Adjust if your notebook is in notebooks/time_series
sys.path.append(str(project_root))
os.chdir(str(project_root))
warnings.filterwarnings("ignore")

import warnings
warnings.filterwarnings("ignore")
import MetaTrader5 as mt5
import pandas as pd
import numpy as np
import ta
from datetime import datetime, timedelta
import time
import logging
import joblib

# Setup logging
logging.basicConfig(
    filename='models/saved_models/trading_app1.log',
    level=logging.INFO,
    format='%(asctime)s %(levelname)s:%(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)

def log_and_print(message, is_error=False):
    """
    Logs and prints a message.
    If is_error=True, logs at the ERROR level; otherwise logs at INFO level.
    """
    if is_error:
        logging.error(message)
    else:
        logging.info(message)
    print(message)

# Update the login credentials and server information accordingly
#name = 66677507
#key = 'ST746$nG38'
#serv = 'ICMarketsSC-Demo'

# Global variables
symbols = [
    "EURUSD", "USDJPY", "AUDUSD", "GBPUSD", "USDCHF", "EURGBP",
    "MSFT.NAS", "TSLA.NAS", "NVDA.NAS", "AMZN.NAS", "GOOG.NAS", "NFLX.NAS", "AAPL.NAS",
    "BABA.NYSE", "JPM.NYSE", "XOM.NYSE", "BA.NYSE", "DIS.NYSE", "NKE.NYSE",
    "JP225", "US500", "UK100"
]

lot_sizes = {
    "JP225": 1,
    "US500": 0.1,
    "UK100": 0.1
}

# Add Forex and Stocks with 0.01 lot size
for symbol in symbols:
    if symbol not in lot_sizes:
        lot_sizes[symbol] = 0.01

model_paths = {
    symbol: f"models/simple_models/{symbol}_best_model.pkl" for symbol in symbols
}


TIMEFRAME = mt5.TIMEFRAME_H4
N_BARS = 1000
MAGIC_NUMBER = 234003
SLEEP_TIME = 14400  # 4 hours
COMMENT_ML = "RFFV-D"

# If you still need feature selection, you can keep this helper function:
def select_features_rf_reg(X, y, estimator, max_features=20):
    """
    Example helper function for feature selection using RandomForest.
    """
    from sklearn.feature_selection import SelectFromModel
    selector = SelectFromModel(estimator=estimator, threshold=-np.inf, max_features=max_features).fit(X, y)
    X_transformed = selector.transform(X)
    selected_features_mask = selector.get_support()
    return X_transformed, selected_features_mask

class TradingApp:
    def __init__(self, symbol, lot_size, magic_number):
        self.symbol = symbol
        self.lot_size = lot_size
        self.magic_number = magic_number
        self.pipeline = None  # We'll store the loaded classification pipeline here
        self.last_retrain_time = None

    def get_data(self, symbol, n, timeframe):
        """
        Fetch 'n' bars of historical data for the given symbol and timeframe.
        """
        rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, n)
        rates_frame = pd.DataFrame(rates)
        rates_frame['time'] = pd.to_datetime(rates_frame['time'], unit='s')
        rates_frame.set_index('time', inplace=True)
        return rates_frame

    def add_all_ta_features(self, df):
        """
        Add technical analysis features to the DataFrame using the 'ta' library.
        """
        df = ta.add_all_ta_features(
            df, open="open", high="high", low="low", close="close", volume="tick_volume", fillna=True
        )
        return df

    def load_pipeline(self, pipeline_path):
        """
        Loads a pre-trained classification pipeline (either a Pipeline or a dict).
        """
        pipeline_loaded = joblib.load(pipeline_path)

        # If it's a dict, extract the model
        if isinstance(pipeline_loaded, dict):
            self.pipeline = pipeline_loaded["model"]
        else:
            self.pipeline = pipeline_loaded

        logging.info(f"Loaded pipeline from {pipeline_path}")
        log_and_print(f"Loaded pipeline from {pipeline_path}")


    def ml_signal_generation(self, symbol, n_bars, timeframe):
        """
        Generate buy/sell signals using the loaded classification pipeline.
        The pipeline outputs SHIFTED labels in {0,1,2} => we SHIFT them back to {-1,0,+1}.
        We'll interpret +1 => buy, -1 => sell, 0 => no trade.
        """
        if self.pipeline is None:
            logging.error("No pipeline loaded. Call load_pipeline(...) first.")
            return False, False, True, True

        # 1) Fetch new data
        df = self.get_data(symbol, n_bars, timeframe)

        # 2) Add TA features
        df = self.add_all_ta_features(df)
        df.fillna(method='ffill', inplace=True)

        # 3) Prepare the features
        X_new = df  # The pipeline must handle columns in the correct order.

        # 4) Predict SHIFTED classes
        preds_shifted = self.pipeline.predict(X_new)
        # SHIFT them back: 0->-1, 1->0, 2->+1
        preds = preds_shifted - 1

        # Get the latest predicted class
        latest_pred = preds[-1]
        # If latest_pred == +1 => buy signal
        # If latest_pred == -1 => sell signal
        # If 0 => do nothing
        buy_signal = (latest_pred == 1)
        sell_signal = (latest_pred == -1)

        return buy_signal, sell_signal, not buy_signal, not sell_signal

    def orders(self, symbol, lot, is_buy=True, id_position=None, sl=None, tp=None):
        """
        Place an order (BUY or SELL) for the specified symbol and lot size.
        """
        symbol_info = mt5.symbol_info(symbol)
        if symbol_info is None:
            log_and_print(f"Symbol {symbol} not found, can't place order.", is_error=True)
            return "Symbol not found"

        # Make sure symbol is visible
        if not symbol_info.visible:
            if not mt5.symbol_select(symbol, True):
                log_and_print(f"Failed to select symbol {symbol}", is_error=True)
                return "Symbol not visible or could not be selected."

        tick_info = mt5.symbol_info_tick(symbol)
        if tick_info is None:
            log_and_print(f"Could not get tick info for {symbol}.", is_error=True)
            return "Tick info unavailable"

        # Check for valid bid/ask
        if tick_info.bid <= 0 or tick_info.ask <= 0:
            log_and_print(
                f"Zero or invalid bid/ask for {symbol}: bid={tick_info.bid}, ask={tick_info.ask}",
                is_error=True
            )
            return "Invalid prices"

        # LOT SIZE VALIDATION
        lot = max(lot, symbol_info.volume_min)
        step = symbol_info.volume_step
        if step > 0:
            remainder = lot % step
            if remainder != 0:
                lot = lot - remainder + step
        if lot > symbol_info.volume_max:
            lot = symbol_info.volume_max

        log_and_print(
            f"Adjusted lot size to {lot} (min={symbol_info.volume_min}, "
            f"step={symbol_info.volume_step}, max={symbol_info.volume_max})"
        )

        # Force ORDER_FILLING_IOC
        filling_mode = 1  # ORDER_FILLING_IOC

        order_type = mt5.ORDER_TYPE_BUY if is_buy else mt5.ORDER_TYPE_SELL
        order_price = tick_info.ask if is_buy else tick_info.bid
        deviation = 20

        request = {
            "action": mt5.TRADE_ACTION_DEAL,
            "symbol": symbol,
            "volume": lot,
            "type": order_type,
            "deviation": deviation,
            "magic": self.magic_number,
            "comment": COMMENT_ML,
            "type_time": mt5.ORDER_TIME_GTC,
            "type_filling": filling_mode,
        }

        if sl is not None:
            request["sl"] = sl
        if tp is not None:
            request["tp"] = tp
        if id_position is not None:
            request["position"] = id_position

        log_and_print(f"Sending order request: {request}")
        result = mt5.order_send(request)

        order_type_str = "BUY" if is_buy else "SELL"
        if result is None or result.retcode != mt5.TRADE_RETCODE_DONE:
            error_message = f"Order failed for {symbol}"
            if result:
                error_message += f", retcode={result.retcode}, comment={result.comment}"
            additional_info = (
                f"Date/Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
                f"Order Type: {order_type_str}\n"
                f"Lot Size: {lot}\n"
                f"SL: {sl if sl else 'None'}\n"
                f"TP: {tp if tp else 'None'}\n"
                f"Comment: {COMMENT_ML}\n"
                f"Request: {request}\n"
                f"Result: {result}"
            )
            # If you want notifications, you could log or handle them differently here.
            log_and_print(f"Order failed details: {additional_info}", is_error=True)
        else:
            success_message = f"Order successful for {symbol}, comment={result.comment}"
            additional_info = (
                f"Date/Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
                f"Order Type: {order_type_str}\n"
                f"Lot Size: {lot}\n"
                f"SL: {sl if sl else 'None'}\n"
                f"TP: {tp if tp else 'None'}\n"
                f"Comment: {COMMENT_ML}"
            )
            # If you want notifications, you could log or handle them differently here.
            log_and_print(success_message)

    def get_positions_by_magic(self, symbol, magic_number):
        """
        Retrieve positions for a specific symbol and magic number.
        """
        all_positions = mt5.positions_get(symbol=symbol)
        if not all_positions:
            log_and_print("No positions found.", is_error=False)
            return []
        return [pos for pos in all_positions if pos.magic == magic_number]

    def run_strategy(self, symbol, lot, buy_signal, sell_signal):
        """
        Run the trading strategy logic based on buy/sell signals.
        """
        log_and_print("------------------------------------------------------------------")
        log_and_print(
            f"Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}, "
            f"SYMBOL: {symbol}, BUY SIGNAL: {buy_signal}, SELL SIGNAL: {sell_signal}"
        )

        positions = self.get_positions_by_magic(symbol, self.magic_number)
        has_buy = any(pos.type == mt5.POSITION_TYPE_BUY for pos in positions)
        has_sell = any(pos.type == mt5.POSITION_TYPE_SELL for pos in positions)

        if buy_signal and not has_buy:
            if has_sell:
                log_and_print("Existing sell positions found. Attempting to close...")
                if self.close_position(symbol, is_buy=True):
                    log_and_print("Sell positions closed. Placing new buy order.")
                    self.orders(symbol, lot, is_buy=True)
                else:
                    log_and_print("Failed to close sell positions.")
            else:
                self.orders(symbol, lot, is_buy=True)
        elif sell_signal and not has_sell:
            if has_buy:
                log_and_print("Existing buy positions found. Attempting to close...")
                if self.close_position(symbol, is_buy=False):
                    log_and_print("Buy positions closed. Placing new sell order.")
                    self.orders(symbol, lot, is_buy=False)
                else:
                    log_and_print("Failed to close buy positions.")
            else:
                self.orders(symbol, lot, is_buy=False)
        else:
            log_and_print("Appropriate position already exists or no signal to act on.")

    def close_position(self, symbol, is_buy):
        """
        Closes positions of the opposite type (BUY/SELL) for this app's magic number.
        """
        positions = mt5.positions_get(symbol=symbol)
        if not positions:
            log_and_print(f"No positions to close for symbol: {symbol}")
            return False

        initial_balance = mt5.account_info().balance
        closed_any = False

        for position in positions:
            # Close positions of the opposite type with the same magic number
            if position.magic == self.magic_number and (
                (is_buy and position.type == mt5.POSITION_TYPE_SELL) or
                (not is_buy and position.type == mt5.POSITION_TYPE_BUY)
            ):
                close_request = {
                    "action": mt5.TRADE_ACTION_DEAL,
                    "symbol": symbol,
                    "volume": position.volume,
                    "type": mt5.ORDER_TYPE_BUY if position.type == mt5.POSITION_TYPE_SELL else mt5.ORDER_TYPE_SELL,
                    "position": position.ticket,
                    "deviation": 20,
                    "magic": self.magic_number,
                    "comment": COMMENT_ML,
                    "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:
                    error_message = f"Failed to close position {position.ticket} for {symbol}: {result.retcode}"
                    log_and_print(error_message, is_error=True)
                    # If you want notifications, you could log or handle them differently here.
                else:
                    log_and_print(f"Successfully closed position {position.ticket} for {symbol}")
                    closed_any = True

        if closed_any:
            final_balance = mt5.account_info().balance
            profit = final_balance - initial_balance
            success_message = f"Closed positions successfully, Profit: {profit}"
            log_and_print(success_message)
            return True

        return False

    def check_and_execute_trades(self):
        """
        Convenience method to perform the entire flow:
        generate signals, run strategy, and deselect symbol.
        """
        mt5.symbol_select(self.symbol, True)
        buy, sell, _, _ = self.ml_signal_generation(self.symbol, N_BARS, TIMEFRAME)
        self.run_strategy(self.symbol, self.lot_size, buy, sell)
        mt5.symbol_select(self.symbol, False)
        log_and_print("Waiting for new signals...")

def is_market_open():
    """
    Check if the current time is within the typical Forex trading session, adjusted for CET/CEST.
    Market closes at Friday 10:00 PM CET and opens at Sunday 11:00 PM CET. 
    It is closed all day Saturday.
    """
    current_time_utc = datetime.utcnow()
    # Adjust for Central European Time (UTC+1) or Central European Summer Time (UTC+2)
    current_time_cet = (
        current_time_utc + timedelta(hours=2) 
        if time.localtime().tm_isdst 
        else current_time_utc + timedelta(hours=1)
    )

    # Friday after 10 PM CET
    if current_time_cet.weekday() == 4 and current_time_cet.hour >= 22:
        return False
    # Sunday before 11 PM CET
    elif current_time_cet.weekday() == 6 and current_time_cet.hour < 23:
        return False
    # All day Saturday
    elif current_time_cet.weekday() == 5:
        return False
    return True


if __name__ == "__main__":
    try:
        if not mt5.initialize():
            log_and_print("Failed to initialize MetaTrader 5", is_error=True)
            exit()

        # 1) Create a TradingApp per symbol
        apps = {}
        for symbol in symbols:
            app = TradingApp(symbol=symbol, lot_size=lot_sizes[symbol], magic_number=MAGIC_NUMBER)
            app.load_pipeline(model_paths[symbol])
            apps[symbol] = app

        while True:
            log_and_print("Checking market status...")
            if is_market_open():
                log_and_print("Market is open. Executing trades...")

                for symbol, app in apps.items():
                    try:
                        log_and_print(f"🔵 Checking Symbol: {symbol}")
                        buy_signal, sell_signal, _, _ = app.ml_signal_generation(
                            symbol=app.symbol,
                            n_bars=N_BARS,
                            timeframe=TIMEFRAME
                        )
                        app.run_strategy(app.symbol, app.lot_size, buy_signal, sell_signal)
                    except Exception as e:
                        log_and_print(f"⚠️ Error processing {symbol}: {e}", is_error=True)


            time.sleep(SLEEP_TIME)

    except KeyboardInterrupt:
        log_and_print("Shutdown signal received.")

    except Exception as e:
        error_message = f"An error occurred: {e}"
        log_and_print(error_message, is_error=True)

    finally:
        mt5.shutdown()
        log_and_print("MetaTrader 5 shutdown completed.")
Loaded pipeline from models/simple_models/EURUSD_best_model.pkl
Loaded pipeline from models/simple_models/USDJPY_best_model.pkl
Loaded pipeline from models/simple_models/AUDUSD_best_model.pkl
Loaded pipeline from models/simple_models/GBPUSD_best_model.pkl
Loaded pipeline from models/simple_models/USDCHF_best_model.pkl
Loaded pipeline from models/simple_models/EURGBP_best_model.pkl
Loaded pipeline from models/simple_models/MSFT.NAS_best_model.pkl
Loaded pipeline from models/simple_models/TSLA.NAS_best_model.pkl
Loaded pipeline from models/simple_models/NVDA.NAS_best_model.pkl
Loaded pipeline from models/simple_models/AMZN.NAS_best_model.pkl
Loaded pipeline from models/simple_models/GOOG.NAS_best_model.pkl
Loaded pipeline from models/simple_models/NFLX.NAS_best_model.pkl
Loaded pipeline from models/simple_models/AAPL.NAS_best_model.pkl
Loaded pipeline from models/simple_models/BABA.NYSE_best_model.pkl
Loaded pipeline from models/simple_models/JPM.NYSE_best_model.pkl
Loaded pipeline from models/simple_models/XOM.NYSE_best_model.pkl
Loaded pipeline from models/simple_models/BA.NYSE_best_model.pkl
Loaded pipeline from models/simple_models/DIS.NYSE_best_model.pkl
Loaded pipeline from models/simple_models/NKE.NYSE_best_model.pkl
Loaded pipeline from models/simple_models/JP225_best_model.pkl
Loaded pipeline from models/simple_models/US500_best_model.pkl
Loaded pipeline from models/simple_models/UK100_best_model.pkl
Checking market status...
Market is open. Executing trades...
🔵 Checking Symbol: EURUSD
------------------------------------------------------------------
Date: 2025-04-28 15:01:46, SYMBOL: EURUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
Appropriate position already exists or no signal to act on.
🔵 Checking Symbol: USDJPY
------------------------------------------------------------------
Date: 2025-04-28 15:01:47, SYMBOL: USDJPY, BUY SIGNAL: False, SELL SIGNAL: True
Appropriate position already exists or no signal to act on.
🔵 Checking Symbol: AUDUSD
------------------------------------------------------------------
Date: 2025-04-28 15:01:48, SYMBOL: AUDUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
Appropriate position already exists or no signal to act on.
🔵 Checking Symbol: GBPUSD
------------------------------------------------------------------
Date: 2025-04-28 15:01:51, SYMBOL: GBPUSD, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
Appropriate position already exists or no signal to act on.
🔵 Checking Symbol: USDCHF
------------------------------------------------------------------
Date: 2025-04-28 15:01:55, SYMBOL: USDCHF, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
Appropriate position already exists or no signal to act on.
🔵 Checking Symbol: EURGBP
------------------------------------------------------------------
Date: 2025-04-28 15:01:58, SYMBOL: EURGBP, BUY SIGNAL: False, SELL SIGNAL: True
Appropriate position already exists or no signal to act on.
🔵 Checking Symbol: MSFT.NAS
------------------------------------------------------------------
Date: 2025-04-28 15:01:59, SYMBOL: MSFT.NAS, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
Adjusted lot size to 0.1 (min=0.1, step=0.1, max=1000.0)
Sending order request: {'action': 1, 'symbol': 'MSFT.NAS', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order failed details: Date/Time: 2025-04-28 15:01:59
Order Type: SELL
Lot Size: 0.1
SL: None
TP: None
Comment: RFFV-D
Request: {'action': 1, 'symbol': 'MSFT.NAS', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Result: OrderSendResult(retcode=10044, deal=0, order=0, volume=0.0, price=0.0, bid=0.0, ask=0.0, comment='Only position closing is allowed', request_id=0, retcode_external=0, request=TradeRequest(action=1, magic=234003, order=0, symbol='MSFT.NAS', volume=0.1, price=0.0, stoplimit=0.0, sl=0.0, tp=0.0, deviation=20, type=1, type_filling=1, type_time=0, expiration=0, comment='RFFV-D', position=0, position_by=0))
🔵 Checking Symbol: TSLA.NAS
  File "c:\Users\moham\miniconda3\envs\ml\Lib\site-packages\joblib\externals\loky\backend\context.py", line 257, in _count_physical_cores
    cpu_info = subprocess.run(
               ^^^^^^^^^^^^^^^
  File "c:\Users\moham\miniconda3\envs\ml\Lib\subprocess.py", line 548, in run
    with Popen(*popenargs, **kwargs) as process:
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\moham\miniconda3\envs\ml\Lib\subprocess.py", line 1026, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "c:\Users\moham\miniconda3\envs\ml\Lib\subprocess.py", line 1538, in _execute_child
    hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
------------------------------------------------------------------
Date: 2025-04-28 15:02:01, SYMBOL: TSLA.NAS, BUY SIGNAL: True, SELL SIGNAL: False
No positions found.
Adjusted lot size to 0.1 (min=0.1, step=0.1, max=1000.0)
Sending order request: {'action': 1, 'symbol': 'TSLA.NAS', 'volume': 0.1, 'type': 0, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order failed details: Date/Time: 2025-04-28 15:02:01
Order Type: BUY
Lot Size: 0.1
SL: None
TP: None
Comment: RFFV-D
Request: {'action': 1, 'symbol': 'TSLA.NAS', 'volume': 0.1, 'type': 0, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Result: OrderSendResult(retcode=10018, deal=0, order=0, volume=0.0, price=0.0, bid=0.0, ask=0.0, comment='Market closed', request_id=753743240, retcode_external=0, request=TradeRequest(action=1, magic=234003, order=0, symbol='TSLA.NAS', volume=0.1, price=0.0, stoplimit=0.0, sl=0.0, tp=0.0, deviation=20, type=0, type_filling=1, type_time=0, expiration=0, comment='RFFV-D', position=0, position_by=0))
🔵 Checking Symbol: NVDA.NAS
------------------------------------------------------------------
Date: 2025-04-28 15:02:02, SYMBOL: NVDA.NAS, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
Adjusted lot size to 0.1 (min=0.1, step=0.1, max=1000.0)
Sending order request: {'action': 1, 'symbol': 'NVDA.NAS', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order failed details: Date/Time: 2025-04-28 15:02:02
Order Type: SELL
Lot Size: 0.1
SL: None
TP: None
Comment: RFFV-D
Request: {'action': 1, 'symbol': 'NVDA.NAS', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Result: OrderSendResult(retcode=10018, deal=0, order=0, volume=0.0, price=0.0, bid=0.0, ask=0.0, comment='Market closed', request_id=753743241, retcode_external=0, request=TradeRequest(action=1, magic=234003, order=0, symbol='NVDA.NAS', volume=0.1, price=0.0, stoplimit=0.0, sl=0.0, tp=0.0, deviation=20, type=1, type_filling=1, type_time=0, expiration=0, comment='RFFV-D', position=0, position_by=0))
🔵 Checking Symbol: AMZN.NAS
------------------------------------------------------------------
Date: 2025-04-28 15:02:03, SYMBOL: AMZN.NAS, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
Adjusted lot size to 0.1 (min=0.1, step=0.1, max=1000.0)
Sending order request: {'action': 1, 'symbol': 'AMZN.NAS', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order failed details: Date/Time: 2025-04-28 15:02:03
Order Type: SELL
Lot Size: 0.1
SL: None
TP: None
Comment: RFFV-D
Request: {'action': 1, 'symbol': 'AMZN.NAS', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Result: OrderSendResult(retcode=10044, deal=0, order=0, volume=0.0, price=0.0, bid=0.0, ask=0.0, comment='Only position closing is allowed', request_id=0, retcode_external=0, request=TradeRequest(action=1, magic=234003, order=0, symbol='AMZN.NAS', volume=0.1, price=0.0, stoplimit=0.0, sl=0.0, tp=0.0, deviation=20, type=1, type_filling=1, type_time=0, expiration=0, comment='RFFV-D', position=0, position_by=0))
🔵 Checking Symbol: GOOG.NAS
------------------------------------------------------------------
Date: 2025-04-28 15:02:04, SYMBOL: GOOG.NAS, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
Adjusted lot size to 0.1 (min=0.1, step=0.1, max=1000.0)
Sending order request: {'action': 1, 'symbol': 'GOOG.NAS', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order failed details: Date/Time: 2025-04-28 15:02:04
Order Type: SELL
Lot Size: 0.1
SL: None
TP: None
Comment: RFFV-D
Request: {'action': 1, 'symbol': 'GOOG.NAS', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Result: OrderSendResult(retcode=10018, deal=0, order=0, volume=0.0, price=0.0, bid=0.0, ask=0.0, comment='Market closed', request_id=753743242, retcode_external=0, request=TradeRequest(action=1, magic=234003, order=0, symbol='GOOG.NAS', volume=0.1, price=0.0, stoplimit=0.0, sl=0.0, tp=0.0, deviation=20, type=1, type_filling=1, type_time=0, expiration=0, comment='RFFV-D', position=0, position_by=0))
🔵 Checking Symbol: NFLX.NAS
------------------------------------------------------------------
Date: 2025-04-28 15:02:05, SYMBOL: NFLX.NAS, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
Adjusted lot size to 0.1 (min=0.1, step=0.1, max=1000.0)
Sending order request: {'action': 1, 'symbol': 'NFLX.NAS', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order failed details: Date/Time: 2025-04-28 15:02:05
Order Type: SELL
Lot Size: 0.1
SL: None
TP: None
Comment: RFFV-D
Request: {'action': 1, 'symbol': 'NFLX.NAS', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Result: OrderSendResult(retcode=10018, deal=0, order=0, volume=0.0, price=0.0, bid=0.0, ask=0.0, comment='Market closed', request_id=753743243, retcode_external=0, request=TradeRequest(action=1, magic=234003, order=0, symbol='NFLX.NAS', volume=0.1, price=0.0, stoplimit=0.0, sl=0.0, tp=0.0, deviation=20, type=1, type_filling=1, type_time=0, expiration=0, comment='RFFV-D', position=0, position_by=0))
🔵 Checking Symbol: AAPL.NAS
------------------------------------------------------------------
Date: 2025-04-28 15:02:06, SYMBOL: AAPL.NAS, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
Adjusted lot size to 0.1 (min=0.1, step=0.1, max=1000.0)
Sending order request: {'action': 1, 'symbol': 'AAPL.NAS', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order failed details: Date/Time: 2025-04-28 15:02:06
Order Type: SELL
Lot Size: 0.1
SL: None
TP: None
Comment: RFFV-D
Request: {'action': 1, 'symbol': 'AAPL.NAS', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Result: OrderSendResult(retcode=10044, deal=0, order=0, volume=0.0, price=0.0, bid=0.0, ask=0.0, comment='Only position closing is allowed', request_id=0, retcode_external=0, request=TradeRequest(action=1, magic=234003, order=0, symbol='AAPL.NAS', volume=0.1, price=0.0, stoplimit=0.0, sl=0.0, tp=0.0, deviation=20, type=1, type_filling=1, type_time=0, expiration=0, comment='RFFV-D', position=0, position_by=0))
🔵 Checking Symbol: BABA.NYSE
------------------------------------------------------------------
Date: 2025-04-28 15:02:07, SYMBOL: BABA.NYSE, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
Adjusted lot size to 0.1 (min=0.1, step=0.1, max=1000.0)
Sending order request: {'action': 1, 'symbol': 'BABA.NYSE', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order failed details: Date/Time: 2025-04-28 15:02:07
Order Type: SELL
Lot Size: 0.1
SL: None
TP: None
Comment: RFFV-D
Request: {'action': 1, 'symbol': 'BABA.NYSE', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Result: OrderSendResult(retcode=10018, deal=0, order=0, volume=0.0, price=0.0, bid=0.0, ask=0.0, comment='Market closed', request_id=753743244, retcode_external=0, request=TradeRequest(action=1, magic=234003, order=0, symbol='BABA.NYSE', volume=0.1, price=0.0, stoplimit=0.0, sl=0.0, tp=0.0, deviation=20, type=1, type_filling=1, type_time=0, expiration=0, comment='RFFV-D', position=0, position_by=0))
🔵 Checking Symbol: JPM.NYSE
------------------------------------------------------------------
Date: 2025-04-28 15:02:09, SYMBOL: JPM.NYSE, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
Adjusted lot size to 0.1 (min=0.1, step=0.1, max=1000.0)
Sending order request: {'action': 1, 'symbol': 'JPM.NYSE', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order failed details: Date/Time: 2025-04-28 15:02:09
Order Type: SELL
Lot Size: 0.1
SL: None
TP: None
Comment: RFFV-D
Request: {'action': 1, 'symbol': 'JPM.NYSE', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Result: OrderSendResult(retcode=10018, deal=0, order=0, volume=0.0, price=0.0, bid=0.0, ask=0.0, comment='Market closed', request_id=753743245, retcode_external=0, request=TradeRequest(action=1, magic=234003, order=0, symbol='JPM.NYSE', volume=0.1, price=0.0, stoplimit=0.0, sl=0.0, tp=0.0, deviation=20, type=1, type_filling=1, type_time=0, expiration=0, comment='RFFV-D', position=0, position_by=0))
🔵 Checking Symbol: XOM.NYSE
------------------------------------------------------------------
Date: 2025-04-28 15:02:11, SYMBOL: XOM.NYSE, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
Appropriate position already exists or no signal to act on.
🔵 Checking Symbol: BA.NYSE
------------------------------------------------------------------
Date: 2025-04-28 15:02:14, SYMBOL: BA.NYSE, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
Adjusted lot size to 0.1 (min=0.1, step=0.1, max=1000.0)
Sending order request: {'action': 1, 'symbol': 'BA.NYSE', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order failed details: Date/Time: 2025-04-28 15:02:14
Order Type: SELL
Lot Size: 0.1
SL: None
TP: None
Comment: RFFV-D
Request: {'action': 1, 'symbol': 'BA.NYSE', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Result: OrderSendResult(retcode=10044, deal=0, order=0, volume=0.0, price=0.0, bid=0.0, ask=0.0, comment='Only position closing is allowed', request_id=0, retcode_external=0, request=TradeRequest(action=1, magic=234003, order=0, symbol='BA.NYSE', volume=0.1, price=0.0, stoplimit=0.0, sl=0.0, tp=0.0, deviation=20, type=1, type_filling=1, type_time=0, expiration=0, comment='RFFV-D', position=0, position_by=0))
🔵 Checking Symbol: DIS.NYSE
------------------------------------------------------------------
Date: 2025-04-28 15:02:16, SYMBOL: DIS.NYSE, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
Adjusted lot size to 0.1 (min=0.1, step=0.1, max=1000.0)
Sending order request: {'action': 1, 'symbol': 'DIS.NYSE', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order failed details: Date/Time: 2025-04-28 15:02:16
Order Type: SELL
Lot Size: 0.1
SL: None
TP: None
Comment: RFFV-D
Request: {'action': 1, 'symbol': 'DIS.NYSE', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Result: OrderSendResult(retcode=10044, deal=0, order=0, volume=0.0, price=0.0, bid=0.0, ask=0.0, comment='Only position closing is allowed', request_id=0, retcode_external=0, request=TradeRequest(action=1, magic=234003, order=0, symbol='DIS.NYSE', volume=0.1, price=0.0, stoplimit=0.0, sl=0.0, tp=0.0, deviation=20, type=1, type_filling=1, type_time=0, expiration=0, comment='RFFV-D', position=0, position_by=0))
🔵 Checking Symbol: NKE.NYSE
------------------------------------------------------------------
Date: 2025-04-28 15:02:17, SYMBOL: NKE.NYSE, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
Adjusted lot size to 0.1 (min=0.1, step=0.1, max=1000.0)
Sending order request: {'action': 1, 'symbol': 'NKE.NYSE', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order failed details: Date/Time: 2025-04-28 15:02:17
Order Type: SELL
Lot Size: 0.1
SL: None
TP: None
Comment: RFFV-D
Request: {'action': 1, 'symbol': 'NKE.NYSE', 'volume': 0.1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Result: OrderSendResult(retcode=10018, deal=0, order=0, volume=0.0, price=0.0, bid=0.0, ask=0.0, comment='Market closed', request_id=753743246, retcode_external=0, request=TradeRequest(action=1, magic=234003, order=0, symbol='NKE.NYSE', volume=0.1, price=0.0, stoplimit=0.0, sl=0.0, tp=0.0, deviation=20, type=1, type_filling=1, type_time=0, expiration=0, comment='RFFV-D', position=0, position_by=0))
🔵 Checking Symbol: JP225
------------------------------------------------------------------
Date: 2025-04-28 15:02:18, SYMBOL: JP225, BUY SIGNAL: False, SELL SIGNAL: True
No positions found.
Adjusted lot size to 1 (min=1.0, step=1.0, max=250.0)
Sending order request: {'action': 1, 'symbol': 'JP225', 'volume': 1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Order failed details: Date/Time: 2025-04-28 15:02:18
Order Type: SELL
Lot Size: 1
SL: None
TP: None
Comment: RFFV-D
Request: {'action': 1, 'symbol': 'JP225', 'volume': 1, 'type': 1, 'deviation': 20, 'magic': 234003, 'comment': 'RFFV-D', 'type_time': 0, 'type_filling': 1}
Result: None
🔵 Checking Symbol: US500
------------------------------------------------------------------
Date: 2025-04-28 15:02:19, SYMBOL: US500, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
Appropriate position already exists or no signal to act on.
🔵 Checking Symbol: UK100
------------------------------------------------------------------
Date: 2025-04-28 15:02:20, SYMBOL: UK100, BUY SIGNAL: False, SELL SIGNAL: False
No positions found.
Appropriate position already exists or no signal to act on.