From 4c6c8c4688c9077194ba6345f091afb0ba7d18a7 Mon Sep 17 00:00:00 2001 From: kleinpanic Date: Thu, 6 Mar 2025 21:05:12 +0000 Subject: [PATCH] changed name --- .../LSTM-python/backups/LSTMDQNbadreward.py | 871 ++++++++++++++++++ .../LSTM-python/src/.python-version | 2 +- .../LSTM-python/src/LSTMDQN.py | 10 +- .../__pycache__/args.cpython-39.pyc | Bin 0 -> 1522 bytes .../data_processing.cpython-39.pyc | Bin 0 -> 4891 bytes .../__pycache__/dqn_callbacks.cpython-39.pyc | Bin 0 -> 2101 bytes .../__pycache__/dqn_training.cpython-39.pyc | Bin 0 -> 2480 bytes .../__pycache__/environment.cpython-39.pyc | Bin 0 -> 3552 bytes .../__pycache__/lstm_model.cpython-39.pyc | Bin 0 -> 1329 bytes .../__pycache__/resources.cpython-39.pyc | Bin 0 -> 2388 bytes .../LSTM-python/src/output/LSTMDQN.log | 106 +++ .../LSTM-python/src/requirements.txt | 93 +- 12 files changed, 990 insertions(+), 92 deletions(-) create mode 100644 src/Machine-Learning/LSTM-python/backups/LSTMDQNbadreward.py create mode 100644 src/Machine-Learning/LSTM-python/src/modular_version/__pycache__/args.cpython-39.pyc create mode 100644 src/Machine-Learning/LSTM-python/src/modular_version/__pycache__/data_processing.cpython-39.pyc create mode 100644 src/Machine-Learning/LSTM-python/src/modular_version/__pycache__/dqn_callbacks.cpython-39.pyc create mode 100644 src/Machine-Learning/LSTM-python/src/modular_version/__pycache__/dqn_training.cpython-39.pyc create mode 100644 src/Machine-Learning/LSTM-python/src/modular_version/__pycache__/environment.cpython-39.pyc create mode 100644 src/Machine-Learning/LSTM-python/src/modular_version/__pycache__/lstm_model.cpython-39.pyc create mode 100644 src/Machine-Learning/LSTM-python/src/modular_version/__pycache__/resources.cpython-39.pyc create mode 100644 src/Machine-Learning/LSTM-python/src/output/LSTMDQN.log diff --git a/src/Machine-Learning/LSTM-python/backups/LSTMDQNbadreward.py b/src/Machine-Learning/LSTM-python/backups/LSTMDQNbadreward.py new file mode 100644 index 0000000..ee948ae --- /dev/null +++ b/src/Machine-Learning/LSTM-python/backups/LSTMDQNbadreward.py @@ -0,0 +1,871 @@ +import os +import sys +import argparse +import numpy as np +import pandas as pd +import logging +from tabulate import tabulate +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +import seaborn as sns +import psutil +import GPUtil +import tensorflow as tf +from tensorflow.keras.models import Sequential, load_model +from tensorflow.keras.layers import LSTM, Dense, Dropout, Bidirectional +from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau +from tensorflow.keras.losses import Huber +from tensorflow.keras.regularizers import l2 +from tensorflow.keras.optimizers import Adam, Nadam + +from sklearn.preprocessing import MinMaxScaler +from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score +import joblib + +import optuna +from optuna.integration import KerasPruningCallback + +import gym +from gym import spaces +from stable_baselines3 import DQN +from stable_baselines3.common.vec_env import DummyVecEnv +from stable_baselines3.common.callbacks import BaseCallback + +from multiprocessing import Pool, cpu_count +import threading +import time + +# Suppress TensorFlow logs beyond errors +os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' + +# ============================================================================= +# GLOBAL LOCK FOR DQN TRAINING (to force one-at-a-time usage of the shared LSTM) +# ============================================================================= +dqn_lock = threading.Lock() + +# ============================ +# Resource Detection Functions +# ============================ +def get_cpu_info(): + cpu_count = psutil.cpu_count(logical=False) # Physical cores + cpu_count_logical = psutil.cpu_count(logical=True) # Logical cores + cpu_percent = psutil.cpu_percent(interval=1, percpu=True) + return { + 'physical_cores': cpu_count, + 'logical_cores': cpu_count_logical, + 'cpu_percent': cpu_percent + } + +def get_gpu_info(): + gpus = GPUtil.getGPUs() + gpu_info = [] + for gpu in gpus: + gpu_info.append({ + 'id': gpu.id, + 'name': gpu.name, + 'load': gpu.load * 100, # Convert to percentage + 'memory_total': gpu.memoryTotal, + 'memory_used': gpu.memoryUsed, + 'memory_free': gpu.memoryFree, + 'temperature': gpu.temperature + }) + return gpu_info + +def configure_tensorflow(cpu_stats, gpu_stats): + logical_cores = cpu_stats['logical_cores'] + os.environ["OMP_NUM_THREADS"] = str(logical_cores) + os.environ["TF_NUM_INTRAOP_THREADS"] = str(logical_cores) + os.environ["TF_NUM_INTEROP_THREADS"] = str(logical_cores) + + if gpu_stats: + gpus = tf.config.list_physical_devices('GPU') + if gpus: + try: + for gpu in gpus: + tf.config.experimental.set_memory_growth(gpu, True) + logging.info(f"Enabled memory growth for {len(gpus)} GPU(s).") + except RuntimeError as e: + logging.error(f"TensorFlow GPU configuration error: {e}") + else: + tf.config.threading.set_intra_op_parallelism_threads(logical_cores) + tf.config.threading.set_inter_op_parallelism_threads(logical_cores) + logging.info("Configured TensorFlow to use CPU with optimized thread settings.") + +# ============================ +# Resource Monitoring Function (Optional) +# ============================ +def monitor_resources(interval=60): + while True: + cpu = psutil.cpu_percent(interval=1, percpu=True) + gpu = get_gpu_info() + logging.info(f"CPU Usage per Core: {cpu}%") + if gpu: + for gpu_stat in gpu: + logging.info(f"GPU {gpu_stat['id']} - {gpu_stat['name']}: Load: {gpu_stat['load']}%, " + f"Memory Used: {gpu_stat['memory_used']}MB / {gpu_stat['memory_total']}MB, " + f"Temperature: {gpu_stat['temperature']}°C") + else: + logging.info("No GPUs detected.") + logging.info("-" * 50) + time.sleep(interval) + +# ============================ +# Data Loading & Technical Indicators +# ============================ +def load_data(file_path): + logging.info(f"Loading data from: {file_path}") + try: + df = pd.read_csv(file_path, parse_dates=['time']) + except FileNotFoundError: + logging.error(f"File not found: {file_path}") + sys.exit(1) + except pd.errors.ParserError as e: + logging.error(f"Error parsing CSV file: {e}") + sys.exit(1) + except Exception as e: + logging.error(f"Unexpected error: {e}") + sys.exit(1) + + rename_mapping = { + 'time': 'Date', + 'open': 'Open', + 'high': 'High', + 'low': 'Low', + 'close': 'Close' + } + df.rename(columns=rename_mapping, inplace=True) + logging.info(f"Data columns after renaming: {df.columns.tolist()}") + df.sort_values('Date', inplace=True) + df.reset_index(drop=True, inplace=True) + logging.info("Data loaded and sorted successfully.") + return df + +def compute_rsi(series, window=14): + delta = series.diff() + gain = delta.where(delta > 0, 0).rolling(window=window).mean() + loss = -delta.where(delta < 0, 0).rolling(window=window).mean() + RS = gain / (loss + 1e-9) + return 100 - (100 / (1 + RS)) + +def compute_macd(series, span_short=12, span_long=26, span_signal=9): + ema_short = series.ewm(span=span_short, adjust=False).mean() + ema_long = series.ewm(span=span_long, adjust=False).mean() + macd_line = ema_short - ema_long + signal_line = macd_line.ewm(span=span_signal, adjust=False).mean() + return macd_line - signal_line # histogram + +def compute_obv(df): + signed_volume = (np.sign(df['Close'].diff()) * df['Volume']).fillna(0) + return signed_volume.cumsum() + +def compute_adx(df, window=14): + df['H-L'] = df['High'] - df['Low'] + df['H-Cp'] = (df['High'] - df['Close'].shift(1)).abs() + df['L-Cp'] = (df['Low'] - df['Close'].shift(1)).abs() + tr = df[['H-L','H-Cp','L-Cp']].max(axis=1) + tr_rolling = tr.rolling(window=window).mean() + adx_placeholder = tr_rolling / (df['Close'] + 1e-9) + df.drop(['H-L','H-Cp','L-Cp'], axis=1, inplace=True) + return adx_placeholder + +def compute_bollinger_bands(series, window=20, num_std=2): + sma = series.rolling(window=window).mean() + std = series.rolling(window=window).std() + upper = sma + num_std * std + lower = sma - num_std * std + bandwidth = (upper - lower) / (sma + 1e-9) + return upper, lower, bandwidth + +def compute_mfi(df, window=14): + typical_price = (df['High'] + df['Low'] + df['Close']) / 3 + money_flow = typical_price * df['Volume'] + prev_tp = typical_price.shift(1) + flow_pos = money_flow.where(typical_price > prev_tp, 0) + flow_neg = money_flow.where(typical_price < prev_tp, 0) + pos_sum = flow_pos.rolling(window=window).sum() + neg_sum = flow_neg.rolling(window=window).sum() + mfi = 100 - (100 / (1 + pos_sum / (neg_sum + 1e-9))) + return mfi + +def calculate_technical_indicators(df): + logging.info("Calculating technical indicators...") + df['RSI'] = compute_rsi(df['Close'], 14) + df['MACD'] = compute_macd(df['Close']) + df['OBV'] = compute_obv(df) + df['ADX'] = compute_adx(df) + + up, lo, bw = compute_bollinger_bands(df['Close'], 20, 2) + df['BB_Upper'] = up + df['BB_Lower'] = lo + df['BB_Width'] = bw + + df['MFI'] = compute_mfi(df, 14) + df['SMA_5'] = df['Close'].rolling(5).mean() + df['SMA_10'] = df['Close'].rolling(10).mean() + df['EMA_5'] = df['Close'].ewm(span=5, adjust=False).mean() + df['EMA_10'] = df['Close'].ewm(span=10, adjust=False).mean() + df['STDDEV_5'] = df['Close'].rolling(5).std() + + df.dropna(inplace=True) + logging.info("Technical indicators calculated successfully.") + return df + +# ============================ +# Argument Parsing +# ============================ +def parse_arguments(): + parser = argparse.ArgumentParser(description='All-in-One: LSTM + DQN (with LSTM predictions) + Tuning.') + parser.add_argument('csv_path', type=str, + help='Path to CSV data with columns [time, open, high, low, close, volume].') + parser.add_argument('--lstm_window_size', type=int, default=15, + help='Sequence window size for LSTM. Default=15.') + parser.add_argument('--dqn_total_timesteps', type=int, default=50000, + help='Total timesteps to train each DQN candidate. Default=50000.') + parser.add_argument('--dqn_eval_episodes', type=int, default=1, + help='Number of episodes to evaluate DQN in the tuning step. Default=1 (entire dataset once).') + parser.add_argument('--n_trials_lstm', type=int, default=30, + help='Number of Optuna trials for LSTM. Default=30.') + # The following arguments are no longer used in sequential DQN training: + parser.add_argument('--n_trials_dqn', type=int, default=20, + help='(Unused in sequential DQN training)') + parser.add_argument('--max_parallel_trials', type=int, default=None, + help='(Unused in sequential DQN training)') + parser.add_argument('--preprocess_workers', type=int, default=None, + help='Number of worker processes for data preprocessing. Defaults to (logical cores - 2).') + parser.add_argument('--monitor_resources', action='store_true', + help='Enable real-time resource monitoring.') + return parser.parse_args() + +# ============================ +# Custom DQN Callback: Log Actions + Rewards +# ============================ +class ActionLoggingCallback(BaseCallback): + """ + Logs distribution of actions and average reward after each rollout. + For off-policy (DQN), "rollout" can be a bit different than on-policy, + but stable-baselines3 still calls `_on_rollout_end` periodically. + """ + def __init__(self, verbose=0): + super(ActionLoggingCallback, self).__init__(verbose) + self.action_buffer = [] + self.reward_buffer = [] + + def _on_training_start(self): + self.action_buffer = [] + self.reward_buffer = [] + + def _on_step(self): + action = self.locals.get('action', None) + reward = self.locals.get('reward', None) + if action is not None: + self.action_buffer.append(action) + if reward is not None: + self.reward_buffer.append(reward) + return True + + def _on_rollout_end(self): + import numpy as np + actions = np.array(self.action_buffer) + rewards = np.array(self.reward_buffer) + if len(actions) > 0: + unique, counts = np.unique(actions, return_counts=True) + total = len(actions) + distr_str = [] + for act, c in zip(unique, counts): + distr_str.append(f"Action {act}: {c} times ({100 * c / total:.2f}%)") + logging.info(" -- DQN Rollout End -- ") + logging.info(" " + ", ".join(distr_str)) + logging.info(f" Avg Reward this rollout: {rewards.mean():.4f} (min={rewards.min():.4f}, max={rewards.max():.4f})") + self.action_buffer = [] + self.reward_buffer = [] + +# ============================ +# Data Preprocessing with Controlled Parallelization +# ============================ +def parallel_feature_engineering(row): + """ + Placeholder function for feature engineering. Modify as needed. + Args: + row (pd.Series): A row from the DataFrame. + Returns: + pd.Series: Processed row. + """ + # Implement any additional feature engineering here if necessary + return row + +def feature_engineering_parallel(df, num_workers): + """ + Applies feature engineering in parallel using multiprocessing. + Args: + df (pd.DataFrame): DataFrame to process. + num_workers (int): Number of worker processes. + Returns: + pd.DataFrame: Processed DataFrame. + """ + logging.info(f"Starting parallel feature engineering with {num_workers} workers...") + with Pool(processes=num_workers) as pool: + processed_rows = pool.map(parallel_feature_engineering, [row for _, row in df.iterrows()]) + df_processed = pd.DataFrame(processed_rows) + logging.info("Parallel feature engineering completed.") + return df_processed + +# ============================ +# LSTM Model Construction & Training (Including Optuna Tuning) +# ============================ +def build_lstm(input_shape, hyperparams): + model = Sequential() + num_layers = hyperparams['num_lstm_layers'] + units = hyperparams['lstm_units'] + drop = hyperparams['dropout_rate'] + for i in range(num_layers): + return_seqs = (i < num_layers - 1) + model.add(Bidirectional( + LSTM(units, return_sequences=return_seqs, kernel_regularizer=l2(1e-4)), + input_shape=input_shape if i == 0 else None + )) + model.add(Dropout(drop)) + model.add(Dense(1, activation='linear')) + + opt_name = hyperparams['optimizer'] + lr = hyperparams['learning_rate'] + decay = hyperparams['decay'] + if opt_name == 'Adam': + opt = Adam(learning_rate=lr, decay=decay) + elif opt_name == 'Nadam': + opt = Nadam(learning_rate=lr) + else: + opt = Adam(learning_rate=lr) + + model.compile(loss=Huber(), optimizer=opt, metrics=['mae']) + return model + +# NOTE: The following lstm_objective is now defined as an inner function in main, +# so that it can access X_train, y_train, X_val, y_val. + +# ============================ +# Custom Gym Environment with LSTM Predictions +# ============================ +class StockTradingEnvWithLSTM(gym.Env): + """ + A custom OpenAI Gym environment for stock trading that integrates LSTM model predictions. + Observation includes technical indicators, account information, and predicted next close price. + """ + metadata = {'render.modes': ['human']} + + def __init__(self, df, feature_columns, lstm_model, scaler_features, scaler_target, + window_size=15, initial_balance=10000, transaction_cost=0.001): + super(StockTradingEnvWithLSTM, self).__init__() + self.df = df.reset_index(drop=True) + self.feature_columns = feature_columns + self.lstm_model = lstm_model + self.scaler_features = scaler_features + self.scaler_target = scaler_target + self.window_size = window_size + + self.initial_balance = initial_balance + self.balance = initial_balance + self.net_worth = initial_balance + self.transaction_cost = transaction_cost + + self.max_steps = len(df) + self.current_step = 0 + self.shares_held = 0 + self.cost_basis = 0 + + # Raw array of features + self.raw_features = df[feature_columns].values + + # Action space: 0=Sell, 1=Hold, 2=Buy + self.action_space = spaces.Discrete(3) + + # Observation space: [technical indicators, balance, shares, cost_basis, predicted_next_close] + self.observation_space = spaces.Box( + low=0, high=1, + shape=(len(feature_columns) + 3 + 1,), + dtype=np.float32 + ) + # Forced lock for LSTM predictions + self.lstm_lock = threading.Lock() + + def reset(self): + self.balance = self.initial_balance + self.net_worth = self.initial_balance + self.current_step = 0 + self.shares_held = 0 + self.cost_basis = 0 + return self._get_obs() + + def _get_obs(self): + row = self.raw_features[self.current_step] + row_max = np.max(row) if np.max(row) != 0 else 1.0 + row_norm = row / row_max + + # Account info + additional = np.array([ + self.balance / self.initial_balance, + self.shares_held / 100.0, # Assuming max 100 shares for normalization + self.cost_basis / (self.initial_balance + 1e-9) + ], dtype=np.float32) + + # LSTM prediction + if self.current_step < self.window_size: + predicted_close = 0.0 + else: + seq = self.raw_features[self.current_step - self.window_size: self.current_step] + seq_scaled = self.scaler_features.transform(seq) + seq_scaled = np.expand_dims(seq_scaled, axis=0) # shape (1, window_size, #features) + with self.lstm_lock: + pred_scaled = self.lstm_model.predict(seq_scaled, verbose=0).flatten()[0] + pred_scaled = np.clip(pred_scaled, 0, 1) + unscaled = self.scaler_target.inverse_transform([[pred_scaled]])[0, 0] + predicted_close = unscaled / 1000.0 # Adjust normalization as needed + + obs = np.concatenate([row_norm, additional, [predicted_close]]).astype(np.float32) + return obs + + def step(self, action): + prev_net_worth = self.net_worth + current_price = self.df.loc[self.current_step, 'Close'] + + if action == 2: # BUY + shares_bought = int(self.balance // current_price) + if shares_bought > 0: + cost = shares_bought * current_price + fee = cost * self.transaction_cost + self.balance -= (cost + fee) + old_shares = self.shares_held + self.shares_held += shares_bought + self.cost_basis = ((self.cost_basis * old_shares) + (shares_bought * current_price)) / self.shares_held + + elif action == 0: # SELL + if self.shares_held > 0: + revenue = self.shares_held * current_price + fee = revenue * self.transaction_cost + self.balance += (revenue - fee) + self.shares_held = 0 + self.cost_basis = 0 + + self.net_worth = self.balance + self.shares_held * current_price + self.current_step += 1 + done = (self.current_step >= self.max_steps - 1) + reward = self.net_worth - self.initial_balance + obs = self._get_obs() + return obs, reward, done, {} + + def render(self, mode='human'): + profit = self.net_worth - self.initial_balance + print(f"Step: {self.current_step}, Balance={self.balance:.2f}, Shares={self.shares_held}, NetWorth={self.net_worth:.2f}, Profit={profit:.2f}") + +# ============================ +# DQN Training & Evaluation Functions (Sequential Loop) +# ============================ +def evaluate_dqn_networth(model, env, n_episodes=1): + """ + Evaluates the trained DQN model by simulating trading over a specified number of episodes. + Args: + model (DQN): Trained DQN model. + env (gym.Env): Trading environment instance. + n_episodes (int): Number of episodes to run for evaluation. + Returns: + float: Average final net worth across episodes. + """ + final_net_worths = [] + for _ in range(n_episodes): + obs = env.reset() + done = False + while not done: + action, _ = model.predict(obs, deterministic=True) + obs, reward, done, info = env.step(action) + final_net_worths.append(env.net_worth) + return np.mean(final_net_worths) + +def train_and_evaluate_dqn(hyperparams, env_params, total_timesteps, eval_episodes): + """ + Trains a single DQN agent on an environment (using the frozen LSTM) with given hyperparameters, + then evaluates its final net worth. + Args: + hyperparams (dict): Hyperparameters for the DQN model. + env_params (dict): Parameters to create the StockTradingEnvWithLSTM. + total_timesteps (int): Total timesteps for training. + eval_episodes (int): Number of episodes for evaluation. + Returns: + agent, final_net_worth + """ + env = StockTradingEnvWithLSTM(**env_params) + vec_env = DummyVecEnv([lambda: env]) + with dqn_lock: + agent = DQN( + 'MlpPolicy', + vec_env, + verbose=1, + learning_rate=hyperparams['lr'], + gamma=hyperparams['gamma'], + exploration_fraction=hyperparams['exploration_fraction'], + buffer_size=hyperparams['buffer_size'], + batch_size=hyperparams['batch_size'], + train_freq=4, + target_update_interval=1000 + ) + agent.learn(total_timesteps=total_timesteps, callback=ActionLoggingCallback(verbose=0)) + final_net_worth = evaluate_dqn_networth(agent, env, n_episodes=eval_episodes) + return agent, final_net_worth + +# ============================ +# MAIN FUNCTION WITH ENHANCED OPTIMIZATIONS +# ============================ +def main(): + args = parse_arguments() + csv_path = args.csv_path + lstm_window_size = args.lstm_window_size + dqn_total_timesteps = args.dqn_total_timesteps + dqn_eval_episodes = args.dqn_eval_episodes + n_trials_lstm = args.n_trials_lstm + preprocess_workers = args.preprocess_workers + enable_resource_monitor = args.monitor_resources + + # ----------------------------- + # Setup Logging + # ----------------------------- + logging.basicConfig(level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s', + handlers=[logging.FileHandler("LSTMDQN.log"), logging.StreamHandler(sys.stdout)]) + + # ----------------------------- + # Resource Detection & Logging + # ----------------------------- + cpu_stats = get_cpu_info() + gpu_stats = get_gpu_info() + + logging.info("===== Resource Statistics =====") + logging.info(f"Physical CPU Cores: {cpu_stats['physical_cores']}") + logging.info(f"Logical CPU Cores: {cpu_stats['logical_cores']}") + logging.info(f"CPU Usage per Core: {cpu_stats['cpu_percent']}%") + if gpu_stats: + logging.info("GPU Statistics:") + for gpu in gpu_stats: + logging.info(f"GPU {gpu['id']} - {gpu['name']}: Load: {gpu['load']}%, Memory Used: {gpu['memory_used']}MB / {gpu['memory_total']}MB, Temperature: {gpu['temperature']}°C") + else: + logging.info("No GPUs detected.") + logging.info("=================================") + + # ----------------------------- + # Configure TensorFlow + # ----------------------------- + configure_tensorflow(cpu_stats, gpu_stats) + + # ----------------------------- + # Start Resource Monitoring (Optional) + # ----------------------------- + if enable_resource_monitor: + logging.info("Starting real-time resource monitoring...") + resource_monitor_thread = threading.Thread(target=monitor_resources, args=(60,), daemon=True) + resource_monitor_thread.start() + + ########################################## + # A) LSTM PART: LOAD, PREPROCESS, TUNE + ########################################## + # 1) LOAD & preprocess + df = load_data(csv_path) + df = calculate_technical_indicators(df) + + feature_columns = [ + 'SMA_5','SMA_10','EMA_5','EMA_10','STDDEV_5', + 'RSI','MACD','ADX','OBV','Volume','Open','High','Low', + 'BB_Upper','BB_Lower','BB_Width','MFI' + ] + target_column = 'Close' + df = df[['Date'] + feature_columns + [target_column]].dropna() + + # 2) Controlled Parallel Data Preprocessing + if preprocess_workers is None: + preprocess_workers = max(1, cpu_stats['logical_cores'] - 2) + else: + preprocess_workers = min(preprocess_workers, cpu_stats['logical_cores']) + df = feature_engineering_parallel(df, num_workers=preprocess_workers) + + scaler_features = MinMaxScaler() + scaler_target = MinMaxScaler() + + X_all = df[feature_columns].values + y_all = df[[target_column]].values + + X_scaled = scaler_features.fit_transform(X_all) + y_scaled = scaler_target.fit_transform(y_all).flatten() + + # 3) Create sequences for LSTM + def create_sequences(features, target, window_size): + X_seq, y_seq = [], [] + for i in range(len(features) - window_size): + X_seq.append(features[i:i+window_size]) + y_seq.append(target[i+window_size]) + return np.array(X_seq), np.array(y_seq) + + X, y = create_sequences(X_scaled, y_scaled, lstm_window_size) + + # 4) Split into train/val/test + train_size = int(len(X) * 0.7) + val_size = int(len(X) * 0.15) + test_size = len(X) - train_size - val_size + + X_train, y_train = X[:train_size], y[:train_size] + X_val, y_val = X[train_size: train_size + val_size], y[train_size: train_size + val_size] + X_test, y_test = X[train_size + val_size:], y[train_size + val_size:] + + logging.info(f"Scaled training features shape: {X_train.shape}") + logging.info(f"Scaled validation features shape: {X_val.shape}") + logging.info(f"Scaled testing features shape: {X_test.shape}") + logging.info(f"Scaled training target shape: {y_train.shape}") + logging.info(f"Scaled validation target shape: {y_val.shape}") + logging.info(f"Scaled testing target shape: {y_test.shape}") + + # 5) Define the LSTM objective function here (so it has access to X_train, y_train, X_val, y_val) + def lstm_objective(trial): + num_lstm_layers = trial.suggest_int('num_lstm_layers', 1, 3) + lstm_units = trial.suggest_categorical('lstm_units', [32, 64, 96, 128]) + dropout_rate = trial.suggest_float('dropout_rate', 0.1, 0.5) + learning_rate = trial.suggest_float('learning_rate', 1e-5, 1e-2, log=True) + optimizer_name = trial.suggest_categorical('optimizer', ['Adam', 'Nadam']) + decay = trial.suggest_float('decay', 0.0, 1e-4) + + hyperparams = { + 'num_lstm_layers': num_lstm_layers, + 'lstm_units': lstm_units, + 'dropout_rate': dropout_rate, + 'learning_rate': learning_rate, + 'optimizer': optimizer_name, + 'decay': decay + } + + model_ = build_lstm((X_train.shape[1], X_train.shape[2]), hyperparams) + early_stop = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True) + lr_reduce = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=5, min_lr=1e-6) + cb_prune = KerasPruningCallback(trial, 'val_loss') + + history = model_.fit( + X_train, y_train, + epochs=100, + batch_size=16, + validation_data=(X_val, y_val), + callbacks=[early_stop, lr_reduce, cb_prune], + verbose=0 + ) + val_mae = min(history.history['val_mae']) + return val_mae + + # 6) Hyperparameter Optimization with Optuna for the LSTM + logging.info(f"Starting LSTM hyperparameter optimization with Optuna using {cpu_stats['logical_cores']-2} parallel trials...") + study_lstm = optuna.create_study(direction='minimize') + study_lstm.optimize(lstm_objective, n_trials=n_trials_lstm, n_jobs=cpu_stats['logical_cores']-2) + best_lstm_params = study_lstm.best_params + logging.info(f"Best LSTM Hyperparameters: {best_lstm_params}") + + # 7) Train final LSTM with best hyperparameters + final_lstm = build_lstm((X_train.shape[1], X_train.shape[2]), best_lstm_params) + early_stop_final = EarlyStopping(monitor='val_loss', patience=20, restore_best_weights=True) + lr_reduce_final = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=5, min_lr=1e-6) + logging.info("Training best LSTM model with optimized hyperparameters...") + hist = final_lstm.fit( + X_train, y_train, + epochs=300, + batch_size=16, + validation_data=(X_val, y_val), + callbacks=[early_stop_final, lr_reduce_final], + verbose=1 + ) + + # 8) Evaluate LSTM + def evaluate_final_lstm(model, X_test, y_test): + logging.info("Evaluating final LSTM model...") + y_pred_scaled = model.predict(X_test).flatten() + y_pred_scaled = np.clip(y_pred_scaled, 0, 1) + y_pred = scaler_target.inverse_transform(y_pred_scaled.reshape(-1, 1)).flatten() + y_test_actual = scaler_target.inverse_transform(y_test.reshape(-1, 1)).flatten() + + mse_ = mean_squared_error(y_test_actual, y_pred) + rmse_ = np.sqrt(mse_) + mae_ = mean_absolute_error(y_test_actual, y_pred) + r2_ = r2_score(y_test_actual, y_pred) + + direction_actual = np.sign(np.diff(y_test_actual)) + direction_pred = np.sign(np.diff(y_pred)) + directional_accuracy = np.mean(direction_actual == direction_pred) + + logging.info(f"Test MSE: {mse_:.4f}") + logging.info(f"Test RMSE: {rmse_:.4f}") + logging.info(f"Test MAE: {mae_:.4f}") + logging.info(f"Test R2 Score: {r2_:.4f}") + logging.info(f"Directional Accuracy: {directional_accuracy:.4f}") + + plt.figure(figsize=(14, 7)) + plt.plot(y_test_actual, label='Actual Price') + plt.plot(y_pred, label='Predicted Price') + plt.title('LSTM: Actual vs Predicted Closing Prices') + plt.legend() + plt.grid(True) + plt.savefig('lstm_actual_vs_pred.png') + plt.close() + + table = [] + limit = min(40, len(y_test_actual)) + for i in range(limit): + table.append([i, round(y_test_actual[i], 2), round(y_pred[i], 2)]) + headers = ["Index", "Actual Price", "Predicted Price"] + print("\nFirst 40 Actual vs. Predicted Prices:") + print(tabulate(table, headers=headers, tablefmt="pretty")) + return r2_, directional_accuracy + + _r2, _diracc = evaluate_final_lstm(final_lstm, X_test, y_test) + + # 9) Save final LSTM model and scalers + final_lstm.save('best_lstm_model.h5') + joblib.dump(scaler_features, 'scaler_features.pkl') + joblib.dump(scaler_target, 'scaler_target.pkl') + logging.info("Saved best LSTM model and scaler objects (best_lstm_model.h5, scaler_features.pkl, scaler_target.pkl).") + + ############################################################ + # B) DQN PART: BUILD ENV THAT USES THE FROZEN LSTM + FORECAST + ############################################################ + # (StockTradingEnvWithLSTM is defined above) + + ################################### + # C) SEQUENTIAL DQN TRAINING WITH LSTM INTEGRATION + ################################### + env_params = { + 'df': df, + 'feature_columns': feature_columns, + 'lstm_model': final_lstm, # Use the frozen, best LSTM model + 'scaler_features': scaler_features, + 'scaler_target': scaler_target, + 'window_size': lstm_window_size, + 'initial_balance': 10000, + 'transaction_cost': 0.001 + } + + # Base DQN hyperparameters (adjust as needed) + base_hyperparams = { + 'lr': 1e-3, + 'gamma': 0.95, + 'exploration_fraction': 0.1, + 'buffer_size': 10000, + 'batch_size': 64 + } + + # Define performance threshold (final net worth must be above this) + PERFORMANCE_THRESHOLD = 10500.0 + current_hyperparams = base_hyperparams.copy() + max_attempts = 10 + best_agent = None + + for attempt in range(max_attempts): + logging.info(f"Training DQN agent: Attempt {attempt+1} with hyperparameters: {current_hyperparams}") + agent, net_worth = train_and_evaluate_dqn(current_hyperparams, env_params, + total_timesteps=dqn_total_timesteps, + eval_episodes=dqn_eval_episodes) + logging.info(f"Agent achieved final net worth: ${net_worth:.2f}") + if net_worth >= PERFORMANCE_THRESHOLD: + logging.info("Agent meets performance criteria!") + best_agent = agent + best_agent.save("best_dqn_model_lstm.zip") + break + else: + logging.info("Performance below threshold. Adjusting hyperparameters and retrying...") + current_hyperparams['lr'] *= 0.9 # decrease learning rate by 10% + current_hyperparams['exploration_fraction'] = min(current_hyperparams['exploration_fraction'] + 0.02, 0.3) + + if best_agent is None: + logging.warning("Failed to train a satisfactory DQN agent after multiple attempts. Using last trained model") + best_agent = agent + else: + logging.info("Final DQN agent trained and saved.") + + ################################### + # D) FINAL INFERENCE & LOG RESULTS + ################################### + logging.info("Running final inference with the trained DQN model...") + + env_test = StockTradingEnvWithLSTM(**env_params) + obs = env_test.reset() + done = False + total_reward = 0.0 + step_data = [] + step_count = 0 + + while not done: + step_count += 1 + action, _ = best_agent.predict(obs, deterministic=True) + obs, reward, done, info = env_test.step(action) + total_reward += reward + step_data.append({ + "Step": step_count, + "Action": int(action), + "Reward": reward, + "Balance": env_test.balance, + "Shares": env_test.shares_held, + "NetWorth": env_test.net_worth + }) + + final_net_worth = env_test.net_worth + final_profit = final_net_worth - env_test.initial_balance + + print("\n=== Final DQN Inference ===") + print(f"Total Steps: {step_count}") + print(f"Final Net Worth: {final_net_worth:.2f}") + print(f"Final Profit: {final_profit:.2f}") + print(f"Sum of Rewards: {total_reward:.2f}") + + buy_count = sum(1 for x in step_data if x["Action"] == 2) + sell_count = sum(1 for x in step_data if x["Action"] == 0) + hold_count = sum(1 for x in step_data if x["Action"] == 1) + print(f"Actions Taken -> BUY: {buy_count}, SELL: {sell_count}, HOLD: {hold_count}") + + # Show last 15 steps + last_n = step_data[-15:] if len(step_data) > 15 else step_data + rows = [] + for d in last_n: + rows.append([ + d["Step"], + d["Action"], + f"{d['Reward']:.2f}", + f"{d['Balance']:.2f}", + d["Shares"], + f"{d['NetWorth']:.2f}" + ]) + headers = ["Step", "Action", "Reward", "Balance", "Shares", "NetWorth"] + print(f"\n== Last 15 Steps ==") + print(tabulate(rows, headers=headers, tablefmt="pretty")) + + logging.info("Final inference completed. Results logged and displayed.") + + ################################### + # E) OPTIONAL: RETRY LOOP IF NET WORTH < THRESHOLD + ################################### + if final_net_worth < PERFORMANCE_THRESHOLD: + logging.warning(f"Final net worth (${final_net_worth:.2f}) is below ${PERFORMANCE_THRESHOLD:.2f}. Retraining the same DQN model to learn from mistakes...") + + additional_timesteps = 50000 + logging.info(f"Retraining the existing DQN model for an additional {additional_timesteps} timesteps (keeping old experiences).") + best_agent.learn( + total_timesteps=additional_timesteps, + reset_num_timesteps=False, # Keep replay buffer + internal step counter + callback=ActionLoggingCallback(verbose=1) + ) + + obs = env_test.reset() + done = False + second_total_reward = 0.0 + while not done: + action, _ = best_agent.predict(obs, deterministic=True) + obs, reward, done, info = env_test.step(action) + second_total_reward += reward + + second_net_worth = env_test.net_worth + second_profit = second_net_worth - env_test.initial_balance + logging.info(f"After additional training, new final net worth=${second_net_worth:.2f}, profit=${second_profit:.2f}") + + if second_net_worth < PERFORMANCE_THRESHOLD: + logging.warning("Even after continued training, net worth is still below threshold. Consider a deeper hyperparameter search or analyzing the environment settings.") + +if __name__ == "__main__": + main() + diff --git a/src/Machine-Learning/LSTM-python/src/.python-version b/src/Machine-Learning/LSTM-python/src/.python-version index bd28b9c..21af950 100644 --- a/src/Machine-Learning/LSTM-python/src/.python-version +++ b/src/Machine-Learning/LSTM-python/src/.python-version @@ -1 +1 @@ -3.9 +3.9.13 diff --git a/src/Machine-Learning/LSTM-python/src/LSTMDQN.py b/src/Machine-Learning/LSTM-python/src/LSTMDQN.py index 6357e14..f9858d2 100644 --- a/src/Machine-Learning/LSTM-python/src/LSTMDQN.py +++ b/src/Machine-Learning/LSTM-python/src/LSTMDQN.py @@ -709,7 +709,7 @@ def main(): plt.title('LSTM: Actual vs Predicted Closing Prices') plt.legend() plt.grid(True) - plt.savefig(os.path.join(output_dir, 'lstm_actual_vs_pred.png') + plt.savefig(os.path.join(output_dir, 'lstm_actual_vs_pred.png')) plt.close() table = [] @@ -724,9 +724,9 @@ def main(): _r2, _diracc = evaluate_final_lstm(final_lstm, X_test, y_test) # 9) Save final LSTM model and scalers - final_lstm.save(os.path.join(output_dir, 'best_lstm_model.h5') - joblib.dump(scaler_features, os.path.join(output_dir, 'scaler_features.pkl') - joblib.dump(scaler_target, os.path.join(output_dir, 'scaler_target.pkl') + final_lstm.save(os.path.join(output_dir, 'best_lstm_model.h5')) + joblib.dump(scaler_features, os.path.join(output_dir, 'scaler_features.pkl')) + joblib.dump(scaler_target, os.path.join(output_dir, 'scaler_target.pkl')) logging.info("Saved best LSTM model and scaler objects (best_lstm_model.h5, scaler_features.pkl, scaler_target.pkl).") ############################################################ @@ -772,7 +772,7 @@ def main(): if net_worth >= PERFORMANCE_THRESHOLD: logging.info("Agent meets performance criteria!") best_agent = agent - best_agent.save(os.path.join(output_dir, "best_dqn_model_lstm.zip") + best_agent.save(os.path.join(output_dir, "best_dqn_model_lstm.zip")) break else: logging.info("Performance below threshold. Adjusting hyperparameters and retrying...") diff --git a/src/Machine-Learning/LSTM-python/src/modular_version/__pycache__/args.cpython-39.pyc b/src/Machine-Learning/LSTM-python/src/modular_version/__pycache__/args.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..003d73d428a8f7dda11c02b316475dfb98c51741 GIT binary patch literal 1522 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 I0m`RL0K&l|NB{r; literal 0 HcmV?d00001 diff --git a/src/Machine-Learning/LSTM-python/src/modular_version/__pycache__/dqn_training.cpython-39.pyc b/src/Machine-Learning/LSTM-python/src/modular_version/__pycache__/dqn_training.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6341cf53326cfbc440fcd85186615db919308c1c GIT binary patch literal 2480 zcmYe~<>g{vU|{G}J({k}$-wX!#6iZ)3=9ko3=9m#X$%YuDGVu$ISf${nlXwA%x8{b zPGLx4%3;Z6jbdd4$uZ}!<+4YygV`)O9J!oPoM1L<4p%OB6gMM7D)R!Kg$z-=DcmXS zDI6_~QG6+!DO@cKQT!>4!3>%_FF`Kw(`3BG>=Fo~xLrzfb1TDAlU?)5G#PJ+2bbh0 zXNMFerex-&yXKXJXO?961c&%)GTst(OfJdH&-2MoPtVLtcTUX7NlHx4e#ywdz>o~` z3dmp(26>v5fq}spoGxPHxW(1{{losV7 zxi&2)Ke5D0!Lcm0C^0=%AuTg6F-IXUwM3yjzo;ZbAu+iqzqlC9ziuI#jJJ4GQcF^c zax?QXi%T+-H92mv7A5ATr`}>MN-a(;xy4>kl$w&6Tyl%0xFogU7F%LLL26#gEzZ2u zl6bJux0vz@Zn5O1Cgy2!-C_j?+AZePys}$d2tP&%fZY=h*HnCqG5!{Fep2x*mX!Rw z)LU$c;Iwy(tthoTu_)yhOJ-hL{z`@-Nd^XnU*-B4`MIh3xtS@6#rnP=G9)!QBQHNE zKRq+G*wfD$Q&7LSC|Tb(F*zeMFICqkHL)l!GcR2ql+bkxDoZl*^S}yn^HWN55{u%? zQj3Z+^Yipm3iIN@i7GQMU9X_>mMApTQ{zE0d8s8}5A%T1y%0DjurTs4axk(mvM>rU ziZJpq7DPLo+iYL!N*kLvft}10xtlGB7ffu+^}3 zFw`)o2=+49vemHGu%$5tGiVAWUVvpbaFQJ6ZEXhzv&n!#LQ^=?+NG&QzEK1A;rMF@oa6T)^NX>(# z?bKq0%#vdClnY7js5uj1RI!2vC~<09DR`h756(28LIPemKn#Lr*m$r*5V`~4?gC}H z*Bl9&@;l9`(d${)qB+#CWDRzL`Y@-RGUfxQlPNm*hJF$Dog zH#9BcE&;%CqXP*)L{0ABB zLX2#TOi;+i2!l+FOyAgej6h|V0m$c!;3(1*xW%3WX$Rb5%`43J zbchlxE=f$vNsUiREKbeI%u6jc275h90Yh9bIX^cyKTi+pCrE&CBb6TDaE#&w1tBbu zi@{-ci^T^Nq?#aqf=bpRkP{((2UQFZ7B~PnY`|rCsvRg6i$T%D!3cspj9|#j!Nes3 E0MNC??EnA( literal 0 HcmV?d00001 diff --git a/src/Machine-Learning/LSTM-python/src/modular_version/__pycache__/environment.cpython-39.pyc b/src/Machine-Learning/LSTM-python/src/modular_version/__pycache__/environment.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..faf705f7a359f1eaf142ba710196e7409bd10a31 GIT binary patch literal 3552 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 literal 0 HcmV?d00001 diff --git a/src/Machine-Learning/LSTM-python/src/modular_version/__pycache__/resources.cpython-39.pyc b/src/Machine-Learning/LSTM-python/src/modular_version/__pycache__/resources.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1b3603d279b2f16f8ad54966e110248b6d7ca6f3 GIT binary patch literal 2388 zcmYe~<>g{vU|{f8J(|9jlY!weh=Yuo85kHG7#J9e;}{qiQW#Pga~Pr^G-DJan9mf& z1g4pzn87ql6bqPUjba1S>{09~OexGQ3{e~@EGeul3{jjZY$@z53{hMu+$o$XTrG@I z+$oH~44OPIK{op(gGd+#+0Vkjz~BsWgAoG*LkU9`V+vymQ!isJgv|_QGnO!9F{QAi zFsHEgGSxEGFw`*CFr~1~VGd@{WcPE^WW2?mlb@cMoR|~xl97RdVI|Woj?BE0)S|M) zoLg)KsYS^JrJBsQ_zE&Ai$SX5lkH0pwA-=i=l_eSZd0+*( z`6;D2iAC{csYS(^`FZ+9sm1xFMaikfdIgoYc+yi#;z16}%uCA$xwe=O6xNJ9j695d zOiYYSj7)!v_!$@&FroqECvY^lfumso<3fg7hIEEn#u^3}hFF7IrW(ctOf^hd%r#6| zEHzA7tSO8l3^hzyY&A?->@`eT95qZ?oGDCm*cUP~G878bfTEn)?_~-o#Mo~!Wv1L> z$xF;ly~UD~pO|usCpR@Wzo;_4B)=pv=N31VS6ZB!5(VR=6{V)$;x0+eEl4d&EGaEY z)#SRx<{l7Ql9?05o}OCb9uQi5i!HIBAT=+gNRWYnp-2cs2s1D+z|05%nI6RjF+CJy zIF#*Hl$u&3267tnEtd3x(&Aej=>?_npg_CDoL*20jzS0l3O`7&!c>54D3$^TD+ePB zBM7q~(JVi?IE!RJLCgeF1I26%3=E*W2oB;q3=9l43@MC~47E%p3^h#6j3ta&Oest@ z3`jg?6dsEWLk(lmrV{2XmIbUStP2@ynQNGfZd94nFuO3siqx`zWU|;6u-CApuq|X_ zWGM70;aI?#!d}8v!`#d`n<0f`E;A@mG6skBB+yg>2iZ%7BR6BV}Q0=JlpONwqWGdDF4l;j1AQ%m9@-ie2J2V8`uXXd5fVu7T?oYcHqJVB*-C7HRYt{~Un zVg-BR7AM3>Af+H@#b@S~6eY&z7sMAN7A5B7q~>H6=f*?S6yJiWNG-ylLX!Yl64JJQC$s_3q!0=EprJ-maT?4gc$1ZtR51i>t!xxApHT&S1F1vX0i~rWR)~$S%8Xa#v)@7#Zv@IT@c5Con#7f zmk!7cT!>^?1WJcR;vgwdbqDbQD8+%zLUI`*Idj;6tJYLIP;x8=1vLjF5@h1w;^5~H F0RYvAXzl<2 literal 0 HcmV?d00001 diff --git a/src/Machine-Learning/LSTM-python/src/output/LSTMDQN.log b/src/Machine-Learning/LSTM-python/src/output/LSTMDQN.log new file mode 100644 index 0000000..ffba986 --- /dev/null +++ b/src/Machine-Learning/LSTM-python/src/output/LSTMDQN.log @@ -0,0 +1,106 @@ +2025-03-06 06:49:25,296 - INFO - ===== Resource Statistics ===== +2025-03-06 06:49:25,297 - INFO - Physical CPU Cores: 28 +2025-03-06 06:49:25,297 - INFO - Logical CPU Cores: 56 +2025-03-06 06:49:25,297 - INFO - CPU Usage per Core: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]% +2025-03-06 06:49:25,297 - INFO - No GPUs detected. +2025-03-06 06:49:25,297 - INFO - ================================= +2025-03-06 06:49:25,298 - INFO - Configured TensorFlow to use CPU with optimized thread settings. +2025-03-06 06:49:25,298 - INFO - Loading data from: data/BAT.csv +2025-03-06 06:49:26,343 - INFO - Data columns after renaming: ['Date', 'Open', 'High', 'Low', 'Close', 'Volume'] +2025-03-06 06:49:26,364 - INFO - Data loaded and sorted successfully. +2025-03-06 06:49:26,364 - INFO - Calculating technical indicators... +2025-03-06 06:49:26,410 - INFO - Technical indicators calculated successfully. +2025-03-06 06:49:26,421 - INFO - Starting parallel feature engineering with 54 workers... +2025-03-06 06:49:38,011 - INFO - Parallel feature engineering completed. +2025-03-06 06:49:38,105 - INFO - Scaled training features shape: (14134, 15, 17) +2025-03-06 06:49:38,106 - INFO - Scaled validation features shape: (3028, 15, 17) +2025-03-06 06:49:38,106 - INFO - Scaled testing features shape: (3030, 15, 17) +2025-03-06 06:49:38,106 - INFO - Scaled training target shape: (14134,) +2025-03-06 06:49:38,106 - INFO - Scaled validation target shape: (3028,) +2025-03-06 06:49:38,106 - INFO - Scaled testing target shape: (3030,) +2025-03-06 06:49:38,106 - INFO - Starting LSTM hyperparameter optimization with Optuna using 54 parallel trials... +2025-03-06 06:53:59,556 - INFO - ===== Resource Statistics ===== +2025-03-06 06:53:59,557 - INFO - Physical CPU Cores: 28 +2025-03-06 06:53:59,557 - INFO - Logical CPU Cores: 56 +2025-03-06 06:53:59,557 - INFO - CPU Usage per Core: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]% +2025-03-06 06:53:59,557 - INFO - No GPUs detected. +2025-03-06 06:53:59,557 - INFO - ================================= +2025-03-06 06:53:59,558 - INFO - Configured TensorFlow to use CPU with optimized thread settings. +2025-03-06 06:53:59,558 - INFO - Loading data from: data/BAT.csv +2025-03-06 06:54:00,245 - INFO - Data columns after renaming: ['Date', 'Open', 'High', 'Low', 'Close', 'Volume'] +2025-03-06 06:54:00,262 - INFO - Data loaded and sorted successfully. +2025-03-06 06:54:00,262 - INFO - Calculating technical indicators... +2025-03-06 06:54:00,304 - INFO - Technical indicators calculated successfully. +2025-03-06 06:54:00,314 - INFO - Starting parallel feature engineering with 54 workers... +2025-03-06 06:54:11,569 - INFO - Parallel feature engineering completed. +2025-03-06 06:54:11,706 - INFO - Scaled training features shape: (14134, 15, 17) +2025-03-06 06:54:11,706 - INFO - Scaled validation features shape: (3028, 15, 17) +2025-03-06 06:54:11,706 - INFO - Scaled testing features shape: (3030, 15, 17) +2025-03-06 06:54:11,706 - INFO - Scaled training target shape: (14134,) +2025-03-06 06:54:11,706 - INFO - Scaled validation target shape: (3028,) +2025-03-06 06:54:11,706 - INFO - Scaled testing target shape: (3030,) +2025-03-06 06:54:11,706 - INFO - Starting LSTM hyperparameter optimization with Optuna using 54 parallel trials... +2025-03-06 08:22:49,294 - INFO - Best LSTM Hyperparameters: {'num_lstm_layers': 1, 'lstm_units': 128, 'dropout_rate': 0.29934814599446935, 'learning_rate': 0.008919175785207373, 'optimizer': 'Nadam', 'decay': 3.1609583590967994e-07} +2025-03-06 08:22:49,761 - INFO - Training best LSTM model with optimized hyperparameters... +2025-03-06 08:46:06,088 - INFO - Evaluating final LSTM model... +2025-03-06 08:46:07,865 - INFO - Test MSE: 0.0813 +2025-03-06 08:46:07,865 - INFO - Test RMSE: 0.2852 +2025-03-06 08:46:07,865 - INFO - Test MAE: 0.1850 +2025-03-06 08:46:07,866 - INFO - Test R2 Score: 0.9933 +2025-03-06 08:46:07,866 - INFO - Directional Accuracy: 0.4672 +2025-03-06 20:52:18,708 - INFO - ===== Resource Statistics ===== +2025-03-06 20:52:18,709 - INFO - Physical CPU Cores: 28 +2025-03-06 20:52:18,709 - INFO - Logical CPU Cores: 56 +2025-03-06 20:52:18,709 - INFO - CPU Usage per Core: [0.0, 0.0, 0.0, 0.0, 1.0, 4.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]% +2025-03-06 20:52:18,709 - INFO - No GPUs detected. +2025-03-06 20:52:18,710 - INFO - ================================= +2025-03-06 20:52:18,711 - INFO - Configured TensorFlow to use CPU with optimized thread settings. +2025-03-06 20:52:18,711 - INFO - Loading data from: data/BAT.csv +2025-03-06 20:52:19,952 - INFO - Data columns after renaming: ['Date', 'Open', 'High', 'Low', 'Close', 'Volume'] +2025-03-06 20:52:19,971 - INFO - Data loaded and sorted successfully. +2025-03-06 20:52:19,971 - INFO - Calculating technical indicators... +2025-03-06 20:52:20,022 - INFO - Technical indicators calculated successfully. +2025-03-06 20:52:20,034 - INFO - Starting parallel feature engineering with 54 workers... +2025-03-06 20:52:31,258 - INFO - Parallel feature engineering completed. +2025-03-06 20:53:22,073 - INFO - ===== Resource Statistics ===== +2025-03-06 20:53:22,074 - INFO - Physical CPU Cores: 28 +2025-03-06 20:53:22,074 - INFO - Logical CPU Cores: 56 +2025-03-06 20:53:22,074 - INFO - CPU Usage per Core: [0.0, 0.0, 0.0, 0.0, 0.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]% +2025-03-06 20:53:22,074 - INFO - No GPUs detected. +2025-03-06 20:53:22,074 - INFO - ================================= +2025-03-06 20:53:22,075 - INFO - Configured TensorFlow to use CPU with optimized thread settings. +2025-03-06 20:53:22,075 - INFO - Loading data from: data/BAT.csv +2025-03-06 20:53:23,075 - INFO - Data columns after renaming: ['Date', 'Open', 'High', 'Low', 'Close', 'Volume'] +2025-03-06 20:53:23,091 - INFO - Data loaded and sorted successfully. +2025-03-06 20:53:23,092 - INFO - Calculating technical indicators... +2025-03-06 20:53:23,124 - INFO - Technical indicators calculated successfully. +2025-03-06 20:53:23,132 - INFO - Starting parallel feature engineering with 54 workers... +2025-03-06 20:53:33,724 - INFO - Parallel feature engineering completed. +2025-03-06 20:53:33,858 - INFO - Scaled training features shape: (14134, 15, 17) +2025-03-06 20:53:33,858 - INFO - Scaled validation features shape: (3028, 15, 17) +2025-03-06 20:53:33,858 - INFO - Scaled testing features shape: (3030, 15, 17) +2025-03-06 20:53:33,858 - INFO - Scaled training target shape: (14134,) +2025-03-06 20:53:33,858 - INFO - Scaled validation target shape: (3028,) +2025-03-06 20:53:33,858 - INFO - Scaled testing target shape: (3030,) +2025-03-06 20:53:33,859 - INFO - Starting LSTM hyperparameter optimization with Optuna using 54 parallel trials... +2025-03-06 20:54:09,168 - INFO - ===== Resource Statistics ===== +2025-03-06 20:54:09,169 - INFO - Physical CPU Cores: 28 +2025-03-06 20:54:09,169 - INFO - Logical CPU Cores: 56 +2025-03-06 20:54:09,169 - INFO - CPU Usage per Core: [0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 10.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]% +2025-03-06 20:54:09,169 - INFO - No GPUs detected. +2025-03-06 20:54:09,169 - INFO - ================================= +2025-03-06 20:54:09,170 - INFO - Configured TensorFlow to use CPU with optimized thread settings. +2025-03-06 20:54:09,170 - INFO - Loading data from: data/BAT.csv +2025-03-06 20:54:10,397 - INFO - Data columns after renaming: ['Date', 'Open', 'High', 'Low', 'Close', 'Volume'] +2025-03-06 20:54:10,415 - INFO - Data loaded and sorted successfully. +2025-03-06 20:54:10,415 - INFO - Calculating technical indicators... +2025-03-06 20:54:10,459 - INFO - Technical indicators calculated successfully. +2025-03-06 20:54:10,471 - INFO - Starting parallel feature engineering with 54 workers... +2025-03-06 20:54:21,124 - INFO - Parallel feature engineering completed. +2025-03-06 20:54:21,265 - INFO - Scaled training features shape: (14134, 15, 17) +2025-03-06 20:54:21,265 - INFO - Scaled validation features shape: (3028, 15, 17) +2025-03-06 20:54:21,265 - INFO - Scaled testing features shape: (3030, 15, 17) +2025-03-06 20:54:21,265 - INFO - Scaled training target shape: (14134,) +2025-03-06 20:54:21,265 - INFO - Scaled validation target shape: (3028,) +2025-03-06 20:54:21,265 - INFO - Scaled testing target shape: (3030,) +2025-03-06 20:54:21,265 - INFO - Starting LSTM hyperparameter optimization with Optuna using 54 parallel trials... diff --git a/src/Machine-Learning/LSTM-python/src/requirements.txt b/src/Machine-Learning/LSTM-python/src/requirements.txt index f4be07e..5cc8dc1 100644 --- a/src/Machine-Learning/LSTM-python/src/requirements.txt +++ b/src/Machine-Learning/LSTM-python/src/requirements.txt @@ -1,92 +1,13 @@ -absl-py==2.1.0 -alembic==1.14.1 -astunparse==1.6.3 -certifi==2024.12.14 -charset-normalizer==3.4.1 -cloudpickle==3.1.1 -colorlog==6.9.0 -contourpy==1.3.1 +contourpy==1.3.0 cycler==0.12.1 -Farama-Notifications==0.0.4 -filelock==3.17.0 -flatbuffers==25.1.24 -fonttools==4.55.6 -fsspec==2024.12.0 -gast==0.6.0 -google-pasta==0.2.0 -GPUtil==1.4.0 -greenlet==3.1.1 -grpcio==1.70.0 -gym==0.26.2 -gym-notices==0.0.8 -gymnasium==1.0.0 -h5py==3.12.1 -idna==3.10 -Jinja2==3.1.5 -joblib==1.4.2 -keras==3.8.0 -kiwisolver==1.4.8 -libclang==18.1.1 -Mako==1.3.8 -Markdown==3.7 -markdown-it-py==3.0.0 -MarkupSafe==3.0.2 -matplotlib==3.10.0 -mdurl==0.1.2 -ml-dtypes==0.4.1 -mpmath==1.3.0 -namex==0.0.8 -networkx==3.4.2 -numpy==1.26.4 -nvidia-cublas-cu12==12.4.5.8 -nvidia-cuda-cupti-cu12==12.4.127 -nvidia-cuda-nvrtc-cu12==12.4.127 -nvidia-cuda-runtime-cu12==12.4.127 -nvidia-cudnn-cu12==9.1.0.70 -nvidia-cufft-cu12==11.2.1.3 -nvidia-curand-cu12==10.3.5.147 -nvidia-cusolver-cu12==11.6.1.9 -nvidia-cusparse-cu12==12.3.1.170 -nvidia-nccl-cu12==2.21.5 -nvidia-nvjitlink-cu12==12.4.127 -nvidia-nvtx-cu12==12.4.127 -opt_einsum==3.4.0 -optree==0.14.0 -optuna==4.2.0 -optuna-integration==4.2.1 +fonttools==4.56.0 +importlib_resources==6.5.2 +kiwisolver==1.4.7 +matplotlib==3.9.4 +numpy==2.0.2 packaging==24.2 -pandas==2.2.3 pillow==11.1.0 -protobuf==5.29.3 -psutil==6.1.1 -Pygments==2.19.1 pyparsing==3.2.1 python-dateutil==2.9.0.post0 -pytz==2024.2 -PyYAML==6.0.2 -requests==2.32.3 -rich==13.9.4 -scikit-learn==1.6.1 -scipy==1.15.1 -seaborn==0.13.2 -Shimmy==2.0.0 six==1.17.0 -SQLAlchemy==2.0.37 -stable_baselines3==2.4.1 -sympy==1.13.1 -tabulate==0.9.0 -tensorboard==2.18.0 -tensorboard-data-server==0.7.2 -tensorflow==2.18.0 -tensorflow-io-gcs-filesystem==0.37.1 -termcolor==2.5.0 -threadpoolctl==3.5.0 -torch==2.5.1 -tqdm==4.67.1 -triton==3.1.0 -typing_extensions==4.12.2 -tzdata==2025.1 -urllib3==2.3.0 -Werkzeug==3.1.3 -wrapt==1.17.2 -xgboost==2.1.3 +zipp==3.21.0