feat: Add MT5 trading bot project files
This commit includes the initial project files for the MT5 trading bot. It includes: - MQL5 scripts for exporting data and for the trading EAs. - Python scripts for model development and for creating a benchmark model. - ONNX models for the trading EAs. - A file with all the code concatenated. - A directory with the separate code files.
This commit is contained in:
@@ -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 <Trade/Trade.mqh>
|
||||
|
||||
//--- 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");
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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 <Trade/Trade.mqh>
|
||||
|
||||
//--- 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");
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -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")
|
||||
@@ -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
|
||||
|
Binary file not shown.
Reference in New Issue
Block a user