diff --git a/MT5-PY-AI-Tbot b/MT5-PY-AI-Tbot new file mode 100644 index 0000000..0f880a2 --- /dev/null +++ b/MT5-PY-AI-Tbot @@ -0,0 +1,373 @@ +--- C:\Users\anasw\Documents\GitHub\MT5-PY-AI-Tbot\Export_EURUSD_History.mq5 --- + +//+------------------------------------------------------------------+ +//| Export_EURUSD_History.mq5 | +//| Copyright 2025, https://github.com/Anaswar-ash | +//| author: Ash | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2025, https://github.com/Anaswar-ash" +#property link "https://github.com/Anaswar-ash" +#property version "1.00" +#property script_show_inputs + +//--- input parameters +input string InpFileName = "raw_price_data.csv"; // File name +input int InpDays = 1000; // Number of days + +//+------------------------------------------------------------------+ +//| Script program start function | +//+------------------------------------------------------------------+ +void OnStart() + { + MqlRates rates[]; + int copied; + + //--- get daily price data + copied = CopyRates("EURUSD", PERIOD_D1, 0, InpDays, rates); + if(copied > 0) + { + int file_handle = FileOpen(InpFileName, FILE_WRITE | FILE_CSV | FILE_ANSI, ','); + if(file_handle != INVALID_HANDLE) + { + //--- write header + FileWrite(file_handle, "Time", "Open", "High", "Low", "Close", "Volume"); + + //--- write data + for(int i = 0; i < copied; i++) + { + FileWrite(file_handle, + TimeToString(rates[i].time, TIME_DATE), + DoubleToString(rates[i].open, _Digits), + DoubleToString(rates[i].high, _Digits), + DoubleToString(rates[i].low, _Digits), + DoubleToString(rates[i].close, _Digits), + rates[i].tick_volume); + } + + FileClose(file_handle); + Print("Data successfully exported to ", InpFileName); + } + else + { + Print("Error opening file: ", GetLastError()); + } + } + else + { + Print("Error copying rates: ", GetLastError()); + } + } +//+------------------------------------------------------------------+ + + +--- C:\Users\anasw\Documents\GitHub\MT5-PY-AI-Tbot\Model_Development.py --- + +import pandas as pd + +# Load the data +raw_price_df = pd.read_csv("raw_price_data.csv") + +# Feature Engineering +raw_price_df["feature_price_change"] = raw_price_df["Close"].diff() + +# Target Engineering +raw_price_df["y_target_direction"] = (raw_price_df["Close"].shift(-1) > raw_price_df["Close"]).astype(int) + +# Drop rows with NaN values +raw_price_df.dropna(inplace=True) + +from sklearn.model_selection import TimeSeriesSplit, RandomizedSearchCV +from sklearn.neural_network import MLPClassifier + +# --- Hyperparameter Tuning --- +# Define the parameter search space +param_distributions = { + 'hidden_layer_sizes': [(50,), (100,), (50, 50)], + 'activation': ['tanh', 'relu'], + 'solver': ['adam', 'sgd'], + 'learning_rate': ['constant', 'adaptive'], +} + +# Create the neural network model +neural_network_model = MLPClassifier(max_iter=1000) + +# Create the time series split object +ts_split = TimeSeriesSplit(n_splits=5, gap=1) + +# Create the randomized search object +random_search = RandomizedSearchCV( + estimator=neural_network_model, + param_distributions=param_distributions, + n_iter=10, # Reduced for faster execution + cv=ts_split, + scoring='accuracy', + random_state=42, + n_jobs=-1 +) + +# Separate features and target +X = raw_price_df[['feature_price_change']] +y = raw_price_df['y_target_direction'] + +# Fit the randomized search to the data +random_search.fit(X, y) + +# Print the best parameters +import skl2onnx +import onnxruntime as rt +from skl2onnx.common.data_types import FloatTensorType + +# --- Final Model Training --- +# Initialize a new neural network model with the best parameters +final_model = MLPClassifier(**random_search.best_params_, max_iter=1000) + +# Train the model on the entire dataset +final_model.fit(X, y) + +# --- Export to ONNX --- +# Define the initial types for the ONNX conversion +initial_type = [('float_input', FloatTensorType([None, 1]))] + +# Convert the model to ONNX format +onnx_model = skl2onnx.convert_sklearn(final_model, initial_types=initial_type) + +# Save the ONNX model +with open("trading_neural_network_model.onnx", "wb") as f: + f.write(onnx_model.SerializeToString()) + +print("Model successfully exported to trading_neural_network_model.onnx") + + +--- C:\Users\anasw\Documents\GitHub\MT5-PY-AI-Tbot\Benchmark_Model_EA.mq5 --- + +//+------------------------------------------------------------------+ +//| Benchmark_Model_EA.mq5 | +//| Copyright 2025, https://github.com/Anaswar-ash | +//| author: Ash | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2025, https://github.com/Anaswar-ash" +#property link "https://github.com/Anaswar-ash" +#property version "1.00" + +#include + +//--- ONNX model parameters +int onnx_handle; +long onnx_input_shape[] = {1, 1}; +long onnx_output_shape[] = {1, 1}; + +//--- Expert Advisor parameters +input double InpLots = 0.1; +input int InpStopLoss = 50; +input int InpTakeProfit = 100; + +CTrade trade; + +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + onnx_handle = OnnxCreateFromFile("benchmark_logistic_model.onnx"); + if(onnx_handle == INVALID_HANDLE) + { + Print("Failed to create ONNX model from file: ", GetLastError()); + return(INIT_FAILED); + } + + if(!OnnxSetInputShape(onnx_handle, 0, onnx_input_shape)) + { + Print("OnnxSetInputShape failed with error: ", GetLastError()); + return(INIT_FAILED); + } + + if(!OnnxSetOutputShape(onnx_handle, 0, onnx_output_shape)) + { + Print("OnnxSetOutputShape failed with error: ", GetLastError()); + return(INIT_FAILED); + } + + return(INIT_SUCCEEDED); + } + +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { + if(onnx_handle != INVALID_HANDLE) + OnnxRelease(onnx_handle); + } + +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { + MqlRates rates[]; + if(CopyRates(_Symbol, PERIOD_D1, 0, 2, rates) < 2) + return; + + float input_data[1]; + input_data[0] = (float)(rates[1].close - rates[0].close); + + float output_data[1]; + + if(!OnnxRun(onnx_handle, input_data, output_data)) + { + Print("OnnxRun failed with error: ", GetLastError()); + return; + } + + if(output_data[0] == 1) + trade.Buy(InpLots, _Symbol, 0, 0, 0, "Buy order"); + else + trade.Sell(InpLots, _Symbol, 0, 0, 0, "Sell order"); + } +//+------------------------------------------------------------------+ + + +--- C:\Users\anasw\Documents\GitHub\MT5-PY-AI-Tbot\Neural_Network_Trader_EA.mq5 --- + +//+------------------------------------------------------------------+ +//| Neural_Network_Trader_EA.mq5 | +//| Copyright 2025, https://github.com/Anaswar-ash | +//| author: Ash | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2025, https://github.com/Anaswar-ash" +#property link "https://github.com/Anaswar-ash" +#property version "1.00" + +#include + +//--- ONNX model parameters +int onnx_handle; +long onnx_input_shape[] = {1, 1}; +long onnx_output_shape[] = {1, 2}; + +//--- Expert Advisor parameters +input double InpLots = 0.1; +input int InpStopLoss = 50; +input int InpTakeProfit = 100; + +CTrade trade; + +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + onnx_handle = OnnxCreateFromFile("trading_neural_network_model.onnx"); + if(onnx_handle == INVALID_HANDLE) + { + Print("Failed to create ONNX model from file: ", GetLastError()); + return(INIT_FAILED); + } + + if(!OnnxSetInputShape(onnx_handle, 0, onnx_input_shape)) + { + Print("OnnxSetInputShape failed with error: ", GetLastError()); + return(INIT_FAILED); + } + + if(!OnnxSetOutputShape(onnx_handle, 0, onnx_output_shape)) + { + Print("OnnxSetOutputShape failed with error: ", GetLastError()); + return(INIT_FAILED); + } + + return(INIT_SUCCEEDED); + } + +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { + if(onnx_handle != INVALID_HANDLE) + OnnxRelease(onnx_handle); + } + +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { + MqlRates rates[]; + if(CopyRates(_Symbol, PERIOD_D1, 0, 2, rates) < 2) + return; + + float input_data[1]; + input_data[0] = (float)(rates[1].close - rates[0].close); + + float output_data[2]; + + if(!OnnxRun(onnx_handle, input_data, output_data)) + { + Print("OnnxRun failed with error: ", GetLastError()); + return; + } + + if(output_data[0] > output_data[1]) + trade.Sell(InpLots, _Symbol, 0, 0, 0, "Sell order"); + else + trade.Buy(InpLots, _Symbol, 0, 0, 0, "Buy order"); + } +//+------------------------------------------------------------------+ + + +--- C:\Users\anasw\Documents\GitHub\MT5-PY-AI-Tbot\create_benchmark_model.py --- + +import pandas as pd +from sklearn.linear_model import LogisticRegression +import skl2onnx +from skl2onnx.common.data_types import FloatTensorType + +# Load the data +raw_price_df = pd.read_csv("raw_price_data.csv") + +# Feature Engineering +raw_price_df["feature_price_change"] = raw_price_df["Close"].diff() + +# Target Engineering +raw_price_df["y_target_direction"] = (raw_price_df["Close"].shift(-1) > raw_price_df["Close"]) + +# Drop rows with NaN values +raw_price_df.dropna(inplace=True) + +# Separate features and target +X = raw_price_df[['feature_price_change']] +y = raw_price_df['y_target_direction'] + +# Create and train the logistic regression model +log_reg_model = LogisticRegression() +log_reg_model.fit(X, y) + +# Convert the model to ONNX format +initial_type = [('float_input', FloatTensorType([None, 1]))] +onnx_model = skl2onnx.convert_sklearn(log_reg_model, initial_types=initial_type) + +# Save the ONNX model +with open("benchmark_logistic_model.onnx", "wb") as f: + f.write(onnx_model.SerializeToString()) + +print("Model successfully exported to benchmark_logistic_model.onnx") + + +--- C:\Users\anasw\Documents\GitHub\MT5-PY-AI-Tbot\raw_price_data.csv --- + +Time,Open,High,Low,Close,Volume +2023.01.01,1.1,1.2,1.0,1.15,100 +2023.01.02,1.15,1.25,1.1,1.2,200 +2023.01.03,1.2,1.3,1.15,1.25,300 +2023.01.04,1.25,1.35,1.2,1.3,400 +2023.01.05,1.3,1.4,1.25,1.35,500 + + +--- C:\Users\anasw\Documents\GitHub\MT5-PY-AI-Tbot\benchmark_logistic_model.onnx --- + +File Path: C:\Users\anasw\Documents\GitHub\MT5-PY-AI-Tbot\benchmark_logistic_model.onnx + +--- C:\Users\anasw\Documents\GitHub\MT5-PY-AI-Tbot\trading_neural_network_model.onnx --- + +File Path: C:\Users\anasw\Documents\GitHub\MT5-PY-AI-Tbot\trading_neural_network_model.onnx diff --git a/separate_codes/Benchmark_Model_EA.mq5 b/separate_codes/Benchmark_Model_EA.mq5 new file mode 100644 index 0000000..c6e2670 --- /dev/null +++ b/separate_codes/Benchmark_Model_EA.mq5 @@ -0,0 +1,85 @@ +//+------------------------------------------------------------------+ +//| Benchmark_Model_EA.mq5 | +//| Copyright 2025, https://github.com/Anaswar-ash | +//| author: Ash | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2025, https://github.com/Anaswar-ash" +#property link "https://github.com/Anaswar-ash" +#property version "1.00" + +#include + +//--- ONNX model parameters +int onnx_handle; +long onnx_input_shape[] = {1, 1}; +long onnx_output_shape[] = {1, 1}; + +//--- Expert Advisor parameters +input double InpLots = 0.1; +input int InpStopLoss = 50; +input int InpTakeProfit = 100; + +CTrade trade; + +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + onnx_handle = OnnxCreateFromFile("benchmark_logistic_model.onnx"); + if(onnx_handle == INVALID_HANDLE) + { + Print("Failed to create ONNX model from file: ", GetLastError()); + return(INIT_FAILED); + } + + if(!OnnxSetInputShape(onnx_handle, 0, onnx_input_shape)) + { + Print("OnnxSetInputShape failed with error: ", GetLastError()); + return(INIT_FAILED); + } + + if(!OnnxSetOutputShape(onnx_handle, 0, onnx_output_shape)) + { + Print("OnnxSetOutputShape failed with error: ", GetLastError()); + return(INIT_FAILED); + } + + return(INIT_SUCCEEDED); + } + +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { + if(onnx_handle != INVALID_HANDLE) + OnnxRelease(onnx_handle); + } + +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { + MqlRates rates[]; + if(CopyRates(_Symbol, PERIOD_D1, 0, 2, rates) < 2) + return; + + float input_data[1]; + input_data[0] = (float)(rates[1].close - rates[0].close); + + float output_data[1]; + + if(!OnnxRun(onnx_handle, input_data, output_data)) + { + Print("OnnxRun failed with error: ", GetLastError()); + return; + } + + if(output_data[0] == 1) + trade.Buy(InpLots, _Symbol, 0, 0, 0, "Buy order"); + else + trade.Sell(InpLots, _Symbol, 0, 0, 0, "Sell order"); + } +//+------------------------------------------------------------------+ diff --git a/separate_codes/Export_EURUSD_History.mq5 b/separate_codes/Export_EURUSD_History.mq5 new file mode 100644 index 0000000..c2c2f6b --- /dev/null +++ b/separate_codes/Export_EURUSD_History.mq5 @@ -0,0 +1,58 @@ +//+------------------------------------------------------------------+ +//| Export_EURUSD_History.mq5 | +//| Copyright 2025, https://github.com/Anaswar-ash | +//| author: Ash | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2025, https://github.com/Anaswar-ash" +#property link "https://github.com/Anaswar-ash" +#property version "1.00" +#property script_show_inputs + +//--- input parameters +input string InpFileName = "raw_price_data.csv"; // File name +input int InpDays = 1000; // Number of days + +//+------------------------------------------------------------------+ +//| Script program start function | +//+------------------------------------------------------------------+ +void OnStart() + { + MqlRates rates[]; + int copied; + + //--- get daily price data + copied = CopyRates("EURUSD", PERIOD_D1, 0, InpDays, rates); + if(copied > 0) + { + int file_handle = FileOpen(InpFileName, FILE_WRITE | FILE_CSV | FILE_ANSI, ','); + if(file_handle != INVALID_HANDLE) + { + //--- write header + FileWrite(file_handle, "Time", "Open", "High", "Low", "Close", "Volume"); + + //--- write data + for(int i = 0; i < copied; i++) + { + FileWrite(file_handle, + TimeToString(rates[i].time, TIME_DATE), + DoubleToString(rates[i].open, _Digits), + DoubleToString(rates[i].high, _Digits), + DoubleToString(rates[i].low, _Digits), + DoubleToString(rates[i].close, _Digits), + rates[i].tick_volume); + } + + FileClose(file_handle); + Print("Data successfully exported to ", InpFileName); + } + else + { + Print("Error opening file: ", GetLastError()); + } + } + else + { + Print("Error copying rates: ", GetLastError()); + } + } +//+------------------------------------------------------------------+ diff --git a/separate_codes/Model_Development.py b/separate_codes/Model_Development.py new file mode 100644 index 0000000..6fdedcc --- /dev/null +++ b/separate_codes/Model_Development.py @@ -0,0 +1,76 @@ +import pandas as pd + +# Load the data +raw_price_df = pd.read_csv("raw_price_data.csv") + +# Feature Engineering +raw_price_df["feature_price_change"] = raw_price_df["Close"].diff() + +# Target Engineering +raw_price_df["y_target_direction"] = (raw_price_df["Close"].shift(-1) > raw_price_df["Close"]).astype(int) + +# Drop rows with NaN values +raw_price_df.dropna(inplace=True) + +from sklearn.model_selection import TimeSeriesSplit, RandomizedSearchCV +from sklearn.neural_network import MLPClassifier + +# --- Hyperparameter Tuning --- +# Define the parameter search space +param_distributions = { + 'hidden_layer_sizes': [(50,), (100,), (50, 50)], + 'activation': ['tanh', 'relu'], + 'solver': ['adam', 'sgd'], + 'learning_rate': ['constant', 'adaptive'], +} + +# Create the neural network model +neural_network_model = MLPClassifier(max_iter=1000) + +# Create the time series split object +ts_split = TimeSeriesSplit(n_splits=2, gap=1) + +# Create the randomized search object +random_search = RandomizedSearchCV( + estimator=neural_network_model, + param_distributions=param_distributions, + n_iter=10, # Reduced for faster execution + cv=ts_split, + scoring='accuracy', + random_state=42, + n_jobs=-1 +) + +# Separate features and target +X = raw_price_df[['feature_price_change']] +y = raw_price_df['y_target_direction'] + +# Fit the randomized search to the data +random_search.fit(X, y) + +# Print the best parameters +import skl2onnx +import onnxruntime as rt +from skl2onnx.common.data_types import FloatTensorType + +# --- Final Model Training --- +# Initialize a new neural network model with the best parameters +final_model = MLPClassifier(**random_search.best_params_, max_iter=1000) + +# Train the model on the entire dataset +final_model.fit(X, y) + +# --- Export to ONNX --- +# Define the initial types for the ONNX conversion +initial_type = [('float_input', FloatTensorType([None, 1]))] + +# Convert the model to ONNX format +onnx_model = skl2onnx.convert_sklearn(final_model, initial_types=initial_type) + +# Save the ONNX model +with open("trading_neural_network_model.onnx", "wb") as f: + f.write(onnx_model.SerializeToString()) + +print("Model successfully exported to trading_neural_network_model.onnx") + + diff --git a/separate_codes/Neural_Network_Trader_EA.mq5 b/separate_codes/Neural_Network_Trader_EA.mq5 new file mode 100644 index 0000000..894b304 --- /dev/null +++ b/separate_codes/Neural_Network_Trader_EA.mq5 @@ -0,0 +1,85 @@ +//+------------------------------------------------------------------+ +//| Neural_Network_Trader_EA.mq5 | +//| Copyright 2025, https://github.com/Anaswar-ash | +//| author: Ash | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2025, https://github.com/Anaswar-ash" +#property link "https://github.com/Anaswar-ash" +#property version "1.00" + +#include + +//--- ONNX model parameters +int onnx_handle; +long onnx_input_shape[] = {1, 1}; +long onnx_output_shape[] = {1, 2}; + +//--- Expert Advisor parameters +input double InpLots = 0.1; +input int InpStopLoss = 50; +input int InpTakeProfit = 100; + +CTrade trade; + +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + onnx_handle = OnnxCreateFromFile("trading_neural_network_model.onnx"); + if(onnx_handle == INVALID_HANDLE) + { + Print("Failed to create ONNX model from file: ", GetLastError()); + return(INIT_FAILED); + } + + if(!OnnxSetInputShape(onnx_handle, 0, onnx_input_shape)) + { + Print("OnnxSetInputShape failed with error: ", GetLastError()); + return(INIT_FAILED); + } + + if(!OnnxSetOutputShape(onnx_handle, 0, onnx_output_shape)) + { + Print("OnnxSetOutputShape failed with error: ", GetLastError()); + return(INIT_FAILED); + } + + return(INIT_SUCCEEDED); + } + +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { + if(onnx_handle != INVALID_HANDLE) + OnnxRelease(onnx_handle); + } + +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { + MqlRates rates[]; + if(CopyRates(_Symbol, PERIOD_D1, 0, 2, rates) < 2) + return; + + float input_data[1]; + input_data[0] = (float)(rates[1].close - rates[0].close); + + float output_data[2]; + + if(!OnnxRun(onnx_handle, input_data, output_data)) + { + Print("OnnxRun failed with error: ", GetLastError()); + return; + } + + if(output_data[0] > output_data[1]) + trade.Sell(InpLots, _Symbol, 0, 0, 0, "Sell order"); + else + trade.Buy(InpLots, _Symbol, 0, 0, 0, "Buy order"); + } +//+------------------------------------------------------------------+ diff --git a/separate_codes/benchmark_logistic_model.onnx b/separate_codes/benchmark_logistic_model.onnx new file mode 100644 index 0000000..54db859 Binary files /dev/null and b/separate_codes/benchmark_logistic_model.onnx differ diff --git a/separate_codes/create_benchmark_model.py b/separate_codes/create_benchmark_model.py new file mode 100644 index 0000000..cd2546d --- /dev/null +++ b/separate_codes/create_benchmark_model.py @@ -0,0 +1,34 @@ +import pandas as pd +from sklearn.linear_model import LogisticRegression +import skl2onnx +from skl2onnx.common.data_types import FloatTensorType + +# Load the data +raw_price_df = pd.read_csv("raw_price_data.csv") + +# Feature Engineering +raw_price_df["feature_price_change"] = raw_price_df["Close"].diff() + +# Target Engineering +raw_price_df["y_target_direction"] = (raw_price_df["Close"].shift(-1) > raw_price_df["Close"]).astype(int) + +# Drop rows with NaN values +raw_price_df.dropna(inplace=True) + +# Separate features and target +X = raw_price_df[['feature_price_change']] +y = raw_price_df['y_target_direction'] + +# Create and train the logistic regression model +log_reg_model = LogisticRegression() +log_reg_model.fit(X, y) + +# Convert the model to ONNX format +initial_type = [('float_input', FloatTensorType([None, 1]))] +onnx_model = skl2onnx.convert_sklearn(log_reg_model, initial_types=initial_type) + +# Save the ONNX model +with open("benchmark_logistic_model.onnx", "wb") as f: + f.write(onnx_model.SerializeToString()) + +print("Model successfully exported to benchmark_logistic_model.onnx") \ No newline at end of file diff --git a/separate_codes/raw_price_data.csv b/separate_codes/raw_price_data.csv new file mode 100644 index 0000000..63fc511 --- /dev/null +++ b/separate_codes/raw_price_data.csv @@ -0,0 +1,6 @@ +Time,Open,High,Low,Close,Volume +2023.01.01,1.1,1.2,1.0,1.15,100 +2023.01.02,1.15,1.25,1.1,1.2,200 +2023.01.03,1.2,1.3,1.15,1.25,300 +2023.01.04,1.25,1.35,1.2,1.3,400 +2023.01.05,1.3,1.4,1.25,1.35,500 diff --git a/separate_codes/trading_neural_network_model.onnx b/separate_codes/trading_neural_network_model.onnx new file mode 100644 index 0000000..bd95285 Binary files /dev/null and b/separate_codes/trading_neural_network_model.onnx differ