Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 184760765e | |||
| a59a7352c8 | |||
| 528422aa24 |
Regular → Executable
+1
-3
@@ -1,3 +1 @@
|
||||
.vscode
|
||||
.venv
|
||||
__pycache__/
|
||||
.vscode
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
# Use an official Python runtime as a parent image
|
||||
FROM python:3.10
|
||||
|
||||
# Set the working directory to C:\app
|
||||
WORKDIR C:\app
|
||||
|
||||
# Install necessary system packages
|
||||
# Note: Windows containers don't use apt-get, so we skip this step on Windows
|
||||
|
||||
# Copy the current directory contents into the container at C:\app
|
||||
COPY . .
|
||||
|
||||
# Install TA-Lib
|
||||
# COPY app/Tab-Lib-deps/ta-lib-0.4.0-src.tar.gz .
|
||||
# RUN New-Item -ItemType Directory -Path C:\ta-lib
|
||||
# RUN tar -zxvf .\ta-lib-0.4.0-src.tar.gz -C C:\ta-lib --strip-components=1
|
||||
# RUN Remove-Item .\ta-lib-0.4.0-src.tar.gz -Force
|
||||
|
||||
# Install any needed packages specified in requirements.txt
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Make port 5000 available to the world outside this container
|
||||
EXPOSE 5000
|
||||
|
||||
# Define environment variable
|
||||
ENV NAME trading-bot
|
||||
|
||||
# Run app.py when the container launches
|
||||
CMD ["flask", "run", "--host=0.0.0.0"]
|
||||
Executable
+59
@@ -0,0 +1,59 @@
|
||||
#import <ZmqMql4Connector.mqh>
|
||||
|
||||
// Define the ZeroMQ server endpoint
|
||||
#define ZMQ_SERVER_ENDPOINT "tcp://*:5900"
|
||||
// Replace 'metatrader-port' with the port number you want to use for communication
|
||||
|
||||
// Define the ZeroMQ socket and context
|
||||
CZmqMql4Server g_server;
|
||||
CZmqContext g_context;
|
||||
|
||||
// Define a function to handle incoming messages
|
||||
void OnMessageReceived(string message)
|
||||
{
|
||||
// Process the received message and perform necessary actions
|
||||
// ...
|
||||
|
||||
// Send a response message (if needed)
|
||||
string responseMessage = "Response from MetaTrader";
|
||||
g_server.Send(responseMessage);
|
||||
}
|
||||
|
||||
// The start function that is called when the EA/script is initialized
|
||||
int OnInit()
|
||||
{
|
||||
// Initialize the ZeroMQ server
|
||||
if (!g_server.Initialize(ZMQ_SERVER_ENDPOINT, g_context, OnMessageReceived))
|
||||
{
|
||||
Print("Failed to initialize ZeroMQ server");
|
||||
return INIT_FAILED;
|
||||
}
|
||||
|
||||
// Start the ZeroMQ server
|
||||
if (!g_server.Start())
|
||||
{
|
||||
Print("Failed to start ZeroMQ server");
|
||||
return INIT_FAILED;
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
return INIT_SUCCEEDED;
|
||||
}
|
||||
|
||||
// The main function that is called on each tick
|
||||
void OnTick()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
// The deinitialization function that is called when the EA/script is stopped
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
// Stop the ZeroMQ server
|
||||
g_server.Stop();
|
||||
|
||||
// Deinitialize the ZeroMQ server and context
|
||||
g_server.Deinitialize();
|
||||
g_context.Terminalize();
|
||||
}
|
||||
Executable
+105
@@ -0,0 +1,105 @@
|
||||
// ZmqMql4Connector.mqh
|
||||
|
||||
// Define the ZMQ message callback function type
|
||||
typedef void OnZmqMessageReceived(string message);
|
||||
|
||||
class CZmqMql4Server
|
||||
{
|
||||
private:
|
||||
string m_endpoint; // ZeroMQ server endpoint
|
||||
int m_socket; // ZeroMQ socket
|
||||
int m_context; // ZeroMQ context
|
||||
OnZmqMessageReceived @m_callback; // Message callback function
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
CZmqMql4Server()
|
||||
{
|
||||
m_socket = -1;
|
||||
m_context = -1;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
~CZmqMql4Server()
|
||||
{
|
||||
Deinitialize();
|
||||
}
|
||||
|
||||
// Initialize the ZeroMQ server
|
||||
bool Initialize(string endpoint, OnZmqMessageReceived @callback)
|
||||
{
|
||||
m_endpoint = endpoint;
|
||||
m_callback = @callback;
|
||||
|
||||
m_context = zmq_init(1);
|
||||
if (m_context == -1)
|
||||
return false;
|
||||
|
||||
m_socket = zmq_socket(m_context, ZMQ_REP);
|
||||
if (m_socket == -1)
|
||||
return false;
|
||||
|
||||
int bindResult = zmq_bind(m_socket, m_endpoint);
|
||||
if (bindResult == -1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Start the ZeroMQ server
|
||||
bool Start()
|
||||
{
|
||||
if (m_socket == -1 || m_context == -1)
|
||||
return false;
|
||||
|
||||
while (true)
|
||||
{
|
||||
string message = Receive();
|
||||
if (message != "")
|
||||
m_callback(message);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Stop the ZeroMQ server
|
||||
void Stop()
|
||||
{
|
||||
if (m_socket != -1)
|
||||
zmq_close(m_socket);
|
||||
m_socket = -1;
|
||||
}
|
||||
|
||||
// Send a message from the server
|
||||
void Send(string message)
|
||||
{
|
||||
if (m_socket != -1)
|
||||
zmq_send(m_socket, message, StringLen(message), 0);
|
||||
}
|
||||
|
||||
// Receive a message in the server
|
||||
string Receive()
|
||||
{
|
||||
if (m_socket != -1)
|
||||
{
|
||||
string message;
|
||||
int receivedBytes = zmq_recv(m_socket, message, 4096, 0);
|
||||
if (receivedBytes > 0)
|
||||
return message;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
// Deinitialize the ZeroMQ server
|
||||
void Deinitialize()
|
||||
{
|
||||
if (m_socket != -1)
|
||||
zmq_close(m_socket);
|
||||
if (m_context != -1)
|
||||
zmq_term(m_context);
|
||||
|
||||
m_socket = -1;
|
||||
m_context = -1;
|
||||
}
|
||||
};
|
||||
Regular → Executable
Executable
+289
@@ -0,0 +1,289 @@
|
||||
from keras.optimizers import Adam
|
||||
from keras.layers import Dense, Dropout
|
||||
from keras.models import Sequential
|
||||
import matplotlib.pyplot as plt
|
||||
import talib
|
||||
from sklearn.preprocessing import MinMaxScaler
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import time
|
||||
import os
|
||||
import zmq
|
||||
|
||||
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
|
||||
|
||||
|
||||
def start_mt5_bot():
|
||||
# Define the symbols and timeframes
|
||||
symbol = 'EURUSD'
|
||||
timeframe = 'H1' # H1 timeframe (1 hour)
|
||||
|
||||
# Set up initial variables
|
||||
lot_size = 0.01
|
||||
stop_loss = 100
|
||||
take_profit = 150
|
||||
|
||||
# Define TensorFlow neural network model
|
||||
def create_neural_network_model(input_shape):
|
||||
model = Sequential()
|
||||
model.add(Dense(64, activation='relu', input_shape=input_shape))
|
||||
model.add(Dropout(0.2))
|
||||
model.add(Dense(64, activation='relu'))
|
||||
model.add(Dropout(0.2))
|
||||
model.add(Dense(1, activation='sigmoid'))
|
||||
return model
|
||||
|
||||
# Define input shape for the neural network
|
||||
# Adjust the input shape based on your features and data
|
||||
input_shape = (10,)
|
||||
|
||||
# Create the neural network model
|
||||
neural_network_model = create_neural_network_model(input_shape)
|
||||
|
||||
# Compile the model
|
||||
neural_network_model.compile(optimizer=Adam(
|
||||
learning_rate=0.001), loss='binary_crossentropy')
|
||||
|
||||
def get_historical_data(socket):
|
||||
# Request historical data from MetaTrader app
|
||||
socket.send_string(
|
||||
f"GET_HISTORICAL_DATA {symbol} {timeframe} 01/01/2022 31/12/2022")
|
||||
|
||||
# Receive historical data from MetaTrader app
|
||||
response = socket.recv_string()
|
||||
data = pd.read_json(response)
|
||||
df = data[['open', 'high', 'low', 'close', 'tick_volume']]
|
||||
return df
|
||||
|
||||
def calculate_indicators_and_detect_patterns(df):
|
||||
# Calculate RSI
|
||||
rsi_period = 14
|
||||
df['rsi'] = talib.RSI(df['close'], rsi_period)
|
||||
|
||||
# Calculate MACD
|
||||
macd_fast_period = 12
|
||||
macd_slow_period = 26
|
||||
macd_signal_period = 9
|
||||
_, _, df['macd'] = talib.MACD(df['close'], fastperiod=macd_fast_period,
|
||||
slowperiod=macd_slow_period, signalperiod=macd_signal_period)
|
||||
|
||||
# Detect divergence based on RSI and MACD
|
||||
df['rsi_divergence'] = np.where(
|
||||
df['rsi'].diff().shift(-1) * df['macd'].diff().shift(-1) < 0, True, False)
|
||||
df['macd_divergence'] = np.where(
|
||||
df['macd'].diff().shift(-1) * df['rsi'].diff().shift(-1) < 0, True, False)
|
||||
|
||||
# Detect support and resistance levels
|
||||
window = 10
|
||||
df['support'] = df['low'].rolling(window).min()
|
||||
df['resistance'] = df['high'].rolling(window).max()
|
||||
|
||||
# Determine trend direction
|
||||
df['trend_200'] = df['close'].rolling(window=200).mean()
|
||||
df['trend_50'] = df['close'].rolling(window=50).mean()
|
||||
|
||||
# Detect double tops and bottoms
|
||||
df['pattern'] = 'None'
|
||||
df['top_pattern'] = np.where((df['high'].shift(1) < df['high']) & (df['high'].shift(-1) < df['high']) &
|
||||
(df['high'].shift(2) > df['high']) & (
|
||||
df['high'].shift(-2) > df['high']),
|
||||
'Double Top', 'None')
|
||||
df.loc[df['top_pattern'] != 'None', 'pattern'] = df['top_pattern']
|
||||
df['bottom_pattern'] = np.where((df['low'].shift(1) > df['low']) & (df['low'].shift(-1) > df['low']) &
|
||||
(df['low'].shift(2) < df['low']) & (
|
||||
df['low'].shift(-2) < df['low']),
|
||||
'Double Bottom', 'None')
|
||||
df.loc[df['bottom_pattern'] != 'None',
|
||||
'pattern'] = df['bottom_pattern']
|
||||
|
||||
return df
|
||||
|
||||
def generate_signals(df):
|
||||
# Determine trade signals based on divergences, patterns, and trend direction
|
||||
df['signal'] = 'None'
|
||||
df['divergence_signal'] = np.where((df['rsi_divergence'] == True) & (df['pattern'] != 'None'), 'Both',
|
||||
np.where(df['rsi_divergence'] == True, 'RSI', 'Pattern'))
|
||||
df['strongest_divergence_signal'] = df[[
|
||||
'divergence_signal', 'macd_divergence']].max(axis=1)
|
||||
df['support_resistance_signal'] = np.where(df['close'] > df['resistance'], 'Resistance',
|
||||
np.where(df['close'] < df['support'], 'Support', 'None'))
|
||||
df['trend_signal'] = np.where(df['close'] > df['trend_200'], 'Uptrend',
|
||||
np.where(df['close'] < df['trend_200'], 'Downtrend', 'None'))
|
||||
for i in range(1, len(df)):
|
||||
prev_divergence_signal = df['divergence_signal'].iloc[i - 1]
|
||||
curr_divergence_signal = df['divergence_signal'].iloc[i]
|
||||
strongest_divergence_signal = df['strongest_divergence_signal'].iloc[i]
|
||||
support_resistance_signal = df['support_resistance_signal'].iloc[i]
|
||||
trend_signal = df['trend_signal'].iloc[i]
|
||||
|
||||
if strongest_divergence_signal != 'None':
|
||||
df['signal'].iloc[i] = strongest_divergence_signal
|
||||
elif prev_divergence_signal == curr_divergence_signal and curr_divergence_signal != 'None':
|
||||
df['signal'].iloc[i] = curr_divergence_signal
|
||||
else:
|
||||
df['signal'].iloc[i] = support_resistance_signal
|
||||
|
||||
if trend_signal != 'None' and df['signal'].iloc[i] != 'None':
|
||||
df['signal'].iloc[i] = trend_signal
|
||||
|
||||
return df
|
||||
|
||||
def execute_trade(signal, df, socket):
|
||||
# Implement risk management and trade execution logic based on the signals generated
|
||||
# Update TensorFlow neural network model with trade outcome
|
||||
|
||||
# Calculate risk and position size based on lot size, stop loss, and take profit
|
||||
risk = lot_size * stop_loss
|
||||
strongest_divergence_signal = df['strongest_divergence_signal'].iloc[-1]
|
||||
if strongest_divergence_signal == 'RSI':
|
||||
risk *= 1.2 # Increase risk by 20% if RSI divergence is the strongest
|
||||
elif strongest_divergence_signal == 'Pattern':
|
||||
risk *= 1.5 # Increase risk by 50% if pattern divergence is the strongest
|
||||
|
||||
position_size = risk / (take_profit - stop_loss)
|
||||
|
||||
try:
|
||||
if signal == 'Buy':
|
||||
# Place a buy trade
|
||||
socket.send_string(
|
||||
f"PLACE_TRADE {symbol} BUY {lot_size} {stop_loss} {take_profit}")
|
||||
response = socket.recv_string()
|
||||
outcome = 'Win' if response == 'TRADE_EXECUTED' else 'Loss'
|
||||
|
||||
elif signal == 'Sell':
|
||||
# Place a sell trade
|
||||
socket.send_string(
|
||||
f"PLACE_TRADE {symbol} SELL {lot_size} {stop_loss} {take_profit}")
|
||||
response = socket.recv_string()
|
||||
outcome = 'Win' if response == 'TRADE_EXECUTED' else 'Loss'
|
||||
|
||||
# Example trade outcome information
|
||||
trade_outcome = {
|
||||
'pattern': df['pattern'].iloc[-1],
|
||||
'divergence_strength': strongest_divergence_signal,
|
||||
'time': df.index[-1],
|
||||
'trend_direction': df['trend_signal'].iloc[-1],
|
||||
'indicator_used': strongest_divergence_signal,
|
||||
'outcome': outcome
|
||||
}
|
||||
|
||||
# Update TensorFlow neural network model with trade outcome
|
||||
update_neural_network_model(trade_outcome)
|
||||
|
||||
# Example print statements for debugging
|
||||
print(
|
||||
f"Executed {signal} trade with position size: {position_size}")
|
||||
print(f"Trade outcome: {trade_outcome}")
|
||||
|
||||
# Additional logic for trade management, monitoring, etc.
|
||||
except Exception as e:
|
||||
print(f"Error executing trade: {str(e)}")
|
||||
|
||||
def update_neural_network_model(trade_outcome):
|
||||
# Implement code to update the neural network model based on trade outcome
|
||||
pattern = trade_outcome['pattern']
|
||||
divergence_strength = trade_outcome['divergence_strength']
|
||||
time = trade_outcome['time']
|
||||
trend_direction = trade_outcome['trend_direction']
|
||||
indicator_used = trade_outcome['indicator_used']
|
||||
outcome = trade_outcome['outcome']
|
||||
|
||||
# Example update code: Append trade outcome information to a dataset for future training
|
||||
trade_data = pd.DataFrame({
|
||||
'pattern': [pattern],
|
||||
'divergence_strength': [divergence_strength],
|
||||
'time': [time],
|
||||
'trend_direction': [trend_direction],
|
||||
'indicator_used': [indicator_used],
|
||||
'outcome': [outcome]
|
||||
})
|
||||
# Append the trade data to the dataset for future training
|
||||
dataset = pd.read_csv('trade_dataset.csv') # Load existing dataset
|
||||
updated_dataset = pd.concat([dataset, trade_data], ignore_index=True)
|
||||
# Save updated dataset
|
||||
updated_dataset.to_csv('trade_dataset.csv', index=False)
|
||||
|
||||
# Example retraining code: Retrain the neural network model with the updated dataset
|
||||
# Preprocess data as per your requirements
|
||||
X_train, y_train = preprocess_data(updated_dataset)
|
||||
# Example retraining step
|
||||
neural_network_model.fit(X_train, y_train, epochs=10, batch_size=32)
|
||||
|
||||
# Save the updated model weights
|
||||
neural_network_model.save_weights('weights/model_weights.h5')
|
||||
|
||||
def preprocess_data(dataset):
|
||||
# Define the numerical features (if any)
|
||||
numerical_features = [] # Update with the actual numerical feature column names
|
||||
|
||||
# Define the input features
|
||||
input_features = dataset[[
|
||||
'pattern', 'divergence_strength', 'trend_direction', 'indicator_used']]
|
||||
|
||||
# Convert categorical features to one-hot encoding
|
||||
input_features = pd.get_dummies(input_features)
|
||||
|
||||
# Normalize numerical features (if any)
|
||||
if numerical_features:
|
||||
scaler = MinMaxScaler()
|
||||
input_features[numerical_features] = scaler.fit_transform(
|
||||
input_features[numerical_features])
|
||||
|
||||
# Extract target labels from the dataset
|
||||
target_labels = dataset['outcome']
|
||||
|
||||
# Convert target labels to numerical representation (0s and 1s)
|
||||
target_labels = target_labels.map({'Loss': 0, 'Win': 1})
|
||||
|
||||
# Return the preprocessed input features and target labels
|
||||
return input_features, target_labels
|
||||
|
||||
def visualize_data(df):
|
||||
plt.figure(figsize=(10, 6))
|
||||
plt.plot(df.index, df['close'], label='Close')
|
||||
# Add visualizations for other indicators, levels, and patterns
|
||||
plt.scatter(df[df['pattern'] == 'Double Top'].index, df[df['pattern'] == 'Double Top']['high'],
|
||||
color='red', marker='v', label='Double Top')
|
||||
plt.scatter(df[df['pattern'] == 'Double Bottom'].index, df[df['pattern'] == 'Double Bottom']['low'],
|
||||
color='green', marker='^', label='Double Bottom')
|
||||
plt.legend()
|
||||
plt.show()
|
||||
|
||||
# Connect to MetaTrader app using ZeroMQ
|
||||
context = zmq.Context()
|
||||
socket = context.socket(zmq.REQ)
|
||||
socket.connect("tcp://metatrader_service:5900")
|
||||
# Replace 'metatrader-container-ip' and 'metatrader-port' with the IP address and port of the MetaTrader container
|
||||
|
||||
while True:
|
||||
try:
|
||||
# Get historical data
|
||||
df = get_historical_data(socket)
|
||||
|
||||
# Calculate indicators and detect patterns
|
||||
df = calculate_indicators_and_detect_patterns(df)
|
||||
|
||||
# Generate trade signals
|
||||
df = generate_signals(df)
|
||||
|
||||
# Execute trades
|
||||
for i in range(1, len(df)):
|
||||
signal = df['signal'].iloc[i]
|
||||
if signal != 'None':
|
||||
execute_trade(signal, df, socket)
|
||||
|
||||
# Visualize data
|
||||
visualize_data(df)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error running trading bot: {str(e)}")
|
||||
|
||||
# Wait for the next iteration
|
||||
time.sleep(60) # Adjust the time interval as needed
|
||||
|
||||
# Disconnect from ZeroMQ socket
|
||||
socket.close()
|
||||
|
||||
|
||||
# Start the MetaTrader bot
|
||||
start_mt5_bot()
|
||||
Regular → Executable
+3
-5
@@ -1,9 +1,7 @@
|
||||
# requirements.txt
|
||||
pandas
|
||||
numpy
|
||||
scikit-learn
|
||||
pandas
|
||||
TA-Lib
|
||||
matplotlib
|
||||
MetaTrader5
|
||||
scikit-learn
|
||||
tensorflow
|
||||
flask
|
||||
pyzmq
|
||||
Regular → Executable
Executable
+30
@@ -0,0 +1,30 @@
|
||||
import socketio
|
||||
import time
|
||||
|
||||
# Connect to the trading bot container
|
||||
sio = socketio.Client()
|
||||
# Replace with the appropriate URL and port of your trading bot container
|
||||
sio.connect('tcp://trading_bot:3000')
|
||||
|
||||
# Handle events from the trading bot container
|
||||
|
||||
|
||||
@sio.event
|
||||
def connect():
|
||||
print('Connected to trading bot container')
|
||||
|
||||
|
||||
@sio.event
|
||||
def disconnect():
|
||||
print('Disconnected from trading bot container')
|
||||
|
||||
|
||||
@sio.event
|
||||
def send_trade_signal(signal):
|
||||
print(f'Received trade signal: {signal}')
|
||||
# Process the trade signal and execute trades through MetaTrader 5
|
||||
|
||||
|
||||
# Main loop to keep the script running
|
||||
while True:
|
||||
time.sleep(1)
|
||||
Regular → Executable
+50
-13
@@ -1,17 +1,54 @@
|
||||
version: '3'
|
||||
version: "3"
|
||||
services:
|
||||
trading-bot:
|
||||
metatrader_service:
|
||||
image: ejtrader/metatrader:5
|
||||
container_name: metatrader
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- DISPLAY=$DISPLAY
|
||||
privileged: true
|
||||
volumes:
|
||||
- ejtraderMT:/data
|
||||
ports:
|
||||
- "5900:5900"
|
||||
- "15555:15555"
|
||||
- "15556:15556"
|
||||
- "15557:15557"
|
||||
- "15558:15558"
|
||||
networks:
|
||||
- trading_network
|
||||
|
||||
trading_bot:
|
||||
container_name: trading_bot
|
||||
restart: unless-stopped
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "5000:5000"
|
||||
dockerfile: docker/DockerFile
|
||||
volumes:
|
||||
- ./src:/app/src
|
||||
- ./static:/app/static
|
||||
- ./templates:/app/templates
|
||||
- ./model_weights.h5:/app/model_weights.h5
|
||||
environment:
|
||||
- FLASK_APP=main.py
|
||||
- FLASK_RUN_HOST=0.0.0.0
|
||||
- PYTHONUNBUFFERED=1
|
||||
- ./app:/app
|
||||
ports:
|
||||
- 3000:3000
|
||||
depends_on:
|
||||
- metatrader_service
|
||||
networks:
|
||||
- trading_network
|
||||
|
||||
mt5_bridge:
|
||||
container_name: mt5_bridge
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/DockerFile.mt5_bridge
|
||||
volumes:
|
||||
- ./bridge:/bridge
|
||||
depends_on:
|
||||
- metatrader_service
|
||||
- trading_bot
|
||||
networks:
|
||||
- trading_network
|
||||
|
||||
networks:
|
||||
trading_network:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
ejtraderMT: {}
|
||||
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
# Use an official Python runtime as the base image
|
||||
FROM python:3.10
|
||||
|
||||
# Set the working directory in the container
|
||||
WORKDIR /app
|
||||
|
||||
# Copy the requirements file to the working directory
|
||||
COPY app/requirements.txt .
|
||||
|
||||
# Copy the Tab-Lib dependencies to the working directory
|
||||
COPY app/Tab-Lib-deps/ta-lib-0.4.0-src.tar.gz .
|
||||
|
||||
# Extract and install Tab-Lib
|
||||
RUN tar -xzf ta-lib-0.4.0-src.tar.gz && \
|
||||
rm ta-lib-0.4.0-src.tar.gz && \
|
||||
cd ta-lib && \
|
||||
./configure --prefix=/usr && \
|
||||
make && \
|
||||
make install && \
|
||||
cd ..
|
||||
|
||||
# Install the Python dependencies
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
RUN pip install ejtraderMT -U
|
||||
|
||||
# Copy the application code to the container
|
||||
COPY app/ .
|
||||
|
||||
# Run the bot script using xvfb-run
|
||||
CMD [ "python", "bot.py" ]
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
FROM python:3.10
|
||||
|
||||
# Set the working directory in the container
|
||||
WORKDIR /app
|
||||
|
||||
# Copy the bridge script to the container
|
||||
COPY bridge/mt5_bridge.py .
|
||||
|
||||
# Install any dependencies required by the bridge script
|
||||
RUN pip install python-socketio python-engineio requests
|
||||
|
||||
CMD ["python", "mt5_bridge.py"]
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
FROM ejtrader/metatrader:5
|
||||
|
||||
# Add your custom configuration and scripts here, if needed
|
||||
|
||||
# Start MetaTrader 5
|
||||
CMD ["/root/.wine/drive_c/Program Files/MetaTrader 5/terminal64.exe"]
|
||||
@@ -1,157 +0,0 @@
|
||||
"""
|
||||
Main script for running the trading bot with a web interface.
|
||||
|
||||
This script initializes the MetaTrader 5 connection, runs the trading bot, and integrates with a web interface for user credentials.
|
||||
|
||||
Author: Mike Kiwalabye
|
||||
"""
|
||||
|
||||
import time
|
||||
from flask import Flask, render_template, request, redirect, json, Response
|
||||
from src.connectors import mt5_connector
|
||||
from src.models import neural_network_model
|
||||
from src.strategies.trading_strategy import get_historical_data, calculate_indicators_and_detect_patterns, generate_trade_signals, execute_trade
|
||||
from src.utils.visualization import plot_trade_signals
|
||||
import threading
|
||||
import pandas as pd
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
# Define input shape for the neural network
|
||||
input_shape = (11,) # Adjust the input shape based on your features and data
|
||||
|
||||
# Create the neural network model
|
||||
neural_network_model = neural_network_model.create_neural_network_model(input_shape)
|
||||
|
||||
# Global state to track whether MT5 is initialized
|
||||
mt5_initialized = False
|
||||
latest_trade_signals = []
|
||||
|
||||
|
||||
# Web Interface Routes
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
"""Render the main page with the login form."""
|
||||
return render_template('index.html')
|
||||
|
||||
@app.route('/login', methods=['POST'])
|
||||
def login():
|
||||
"""
|
||||
Handle the login form submission.
|
||||
|
||||
If the credentials are valid, start the trading bot with the provided credentials.
|
||||
|
||||
Returns:
|
||||
- str: HTML response.
|
||||
"""
|
||||
global mt5_initialized
|
||||
if request.method == 'POST':
|
||||
credentials = {
|
||||
'username': request.form['username'],
|
||||
'password': request.form['password'],
|
||||
'server': request.form['server'],
|
||||
'path': request.form['path']
|
||||
}
|
||||
if mt5_connector.connect_to_mt5(credentials):
|
||||
# Set MT5 initialization state to True
|
||||
mt5_initialized = True
|
||||
# Redirect to the main dashboard or another page
|
||||
return redirect('/dashboard')
|
||||
else:
|
||||
return render_template('index.html', error='Invalid credentials. Please try again.')
|
||||
|
||||
@app.route('/dashboard')
|
||||
def dashboard():
|
||||
# Replace these with the actual MetaTrader data retrieval logic
|
||||
mt5_data = mt5_connector.get_account_info() # Replace with the actual method to get account info
|
||||
user_data = {'username': mt5_data.name, 'account_balance': mt5_data.balance, 'currency': mt5_data.currency}
|
||||
username = user_data.get('username', 'N/A')
|
||||
account_balance = user_data.get('account_balance', 'N/A')
|
||||
account_currency = user_data.get('currency', 'N/A')
|
||||
|
||||
return render_template('dashboard.html', username=username, account_balance=account_balance, account_currency=account_currency)
|
||||
|
||||
# Flask app routes
|
||||
|
||||
@app.route('/start_ml_bot', methods=['POST'])
|
||||
def start_ml_bot():
|
||||
"""
|
||||
Handle the request to start the ML bot.
|
||||
"""
|
||||
# Start the ML bot
|
||||
threading.Thread(target=run_trading_bot_web_interface).start()
|
||||
|
||||
# Return an empty response
|
||||
return Response(status=200)
|
||||
|
||||
|
||||
@app.route("/stop_ml_bot", methods=['GET'])
|
||||
def stop_ml_bot():
|
||||
mt5_connector.stop_mt5_ml_bot()
|
||||
redirect('/dashboard')
|
||||
|
||||
def map_signal_priority(signal_priority):
|
||||
# Define a mapping for string values to integers
|
||||
signal_mapping = {
|
||||
'Both': 1,
|
||||
'Pattern': 2,
|
||||
'RSI': 3
|
||||
# Add more mappings as needed
|
||||
}
|
||||
|
||||
# Use the mapping, default to 0 if not found
|
||||
return signal_mapping.get(signal_priority, 0)
|
||||
# Main Trading Bot Logic
|
||||
|
||||
def run_trading_bot_web_interface():
|
||||
"""
|
||||
Run the trading bot using MetaTrader 5 credentials from the web interface.
|
||||
"""
|
||||
global latest_trade_signals
|
||||
historical_data_df = pd.DataFrame()
|
||||
|
||||
while True:
|
||||
try:
|
||||
symbol = 'EURUSD'
|
||||
lot_size = 0.01
|
||||
stop_loss = 100
|
||||
take_profit = 200
|
||||
|
||||
# Get the latest historical data
|
||||
historical_data_df = get_historical_data(symbol, historical_data_df)
|
||||
|
||||
# Calculate indicators and detect patterns for the latest data
|
||||
df = calculate_indicators_and_detect_patterns(historical_data_df)
|
||||
|
||||
# Generate trade signals for the latest data
|
||||
df = generate_trade_signals(df)
|
||||
df.to_csv('your_file.csv', sep='\t', index=False)
|
||||
|
||||
# Inside the run_trading_bot_web_interface function
|
||||
latest_trade_signals = df.replace({pd.NA: 'null'}).to_json(orient='records')
|
||||
|
||||
|
||||
# Execute trades
|
||||
for i in range(len(df)):
|
||||
|
||||
signal_priority = df['signal'].iloc[i] # Replace with your actual value
|
||||
mapped_priority = map_signal_priority(signal_priority)
|
||||
|
||||
if mapped_priority != 0:
|
||||
execute_trade(mapped_priority, df, symbol, lot_size, stop_loss, take_profit)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error running trading bot: {str(e)}")
|
||||
|
||||
# Wait for the next iteration
|
||||
time.sleep(60) # Adjust the time interval as needed
|
||||
|
||||
@app.route('/get_latest_trade_signals', methods=['GET'])
|
||||
def get_latest_trade_signals():
|
||||
global latest_trade_signals
|
||||
return json.dumps(latest_trade_signals)
|
||||
|
||||
# Start the Flask app
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True)
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
# Start the X server
|
||||
Xvfb :0 -screen 0 1024x768x16 &
|
||||
|
||||
# Set the X display
|
||||
export DISPLAY=:0
|
||||
|
||||
# Install necessary dependencies using winetricks
|
||||
winetricks -q corefonts
|
||||
|
||||
# Add a small delay for X server initialization
|
||||
sleep 2
|
||||
|
||||
# Run MetaTrader 5
|
||||
exec su - trader -c 'wine "/home/trader/.wine/drive_c/Program Files/MetaTrader 5/terminal64.exe"'
|
||||
|
||||
# Clean up X server resources
|
||||
killall Xvfb
|
||||
rm -rf /tmp/.X11-unix
|
||||
@@ -1,78 +0,0 @@
|
||||
# mt5_connector.py
|
||||
|
||||
"""
|
||||
Module for connecting to MetaTrader 5 (MT5) using the MetaTrader5 Python package.
|
||||
|
||||
This module provides functions for initializing and connecting to MT5, along with error handling.
|
||||
|
||||
Author: Mike Kiwalabye
|
||||
"""
|
||||
|
||||
import MetaTrader5 as mt5
|
||||
|
||||
|
||||
def start_mt5(username: str, password: str, server: str, path: str) -> bool:
|
||||
"""
|
||||
Initialize and start a connection to MetaTrader 5.
|
||||
|
||||
Parameters:
|
||||
- username (str): The MT5 account username.
|
||||
- password (str): The MT5 account password.
|
||||
- server (str): The MT5 trading server.
|
||||
- path (str): The file path to the MetaTrader 5 executable.
|
||||
|
||||
Returns:
|
||||
- bool: True if successfully initialized, False otherwise.
|
||||
"""
|
||||
# Ensure that all variables are the correct type
|
||||
uname = int(username) # Username must be an int
|
||||
pword = str(password) # Password must be a string
|
||||
trading_server = str(server) # Server must be a string
|
||||
filepath = str(path) # Filepath must be a string
|
||||
|
||||
# Connect to MetaTrader 5
|
||||
if mt5.initialize(login=uname, password=pword, server=trading_server, path=filepath):
|
||||
# Login to MT5
|
||||
if mt5.login(login=uname, password=pword, server=trading_server):
|
||||
return True
|
||||
else:
|
||||
print("Login Fail")
|
||||
quit()
|
||||
return PermissionError
|
||||
else:
|
||||
print("MT5 Initialization Failed")
|
||||
quit()
|
||||
return ConnectionAbortedError
|
||||
|
||||
def connect_to_mt5(credentials: dict):
|
||||
"""
|
||||
Connect to MetaTrader 5.
|
||||
|
||||
Parameters:
|
||||
- credentials (dict): Dictionary containing 'username', 'password', 'server', and 'path'.
|
||||
"""
|
||||
# Start the MetaTrader 5 instance
|
||||
if start_mt5(credentials['username'], credentials['password'], credentials['server'], credentials['path']):
|
||||
print("Connected to MetaTrader 5")
|
||||
return True
|
||||
else:
|
||||
print("Failed to connect to MetaTrader 5")
|
||||
return False
|
||||
|
||||
def get_account_info():
|
||||
"""
|
||||
Get account information from MetaTrader 5.
|
||||
|
||||
Returns:
|
||||
- dict: Dictionary containing account information (e.g., username, account balance).
|
||||
"""
|
||||
|
||||
# Fetch account information
|
||||
account_info = mt5.account_info()
|
||||
|
||||
return account_info
|
||||
|
||||
def stop_mt5_ml_bot():
|
||||
|
||||
mt5.shutdown()
|
||||
return "Disconnected from MetaTrader 5"
|
||||
@@ -1,147 +0,0 @@
|
||||
# neural_network_model.py
|
||||
"""
|
||||
Module for defining and managing the TensorFlow Neural Network model.
|
||||
|
||||
This module provides functions to create, compile, and update a simple feedforward neural network
|
||||
model for use in a trading bot.
|
||||
|
||||
Author: Mike Kiwalabye
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
from keras.models import Sequential, load_model
|
||||
from keras.layers import Dense, Dropout
|
||||
from keras.optimizers import Adam
|
||||
from keras.losses import BinaryCrossentropy
|
||||
from sklearn.preprocessing import MinMaxScaler
|
||||
import numpy as np
|
||||
|
||||
|
||||
def create_neural_network_model(input_shape: tuple) -> Sequential:
|
||||
"""
|
||||
Create a simple feedforward neural network model.
|
||||
|
||||
Parameters:
|
||||
- input_shape (tuple): The shape of the input data.
|
||||
|
||||
Returns:
|
||||
- Sequential: The Keras Sequential model representing the neural network.
|
||||
"""
|
||||
model = Sequential()
|
||||
model.add(Dense(64, activation='relu', input_shape=input_shape))
|
||||
model.add(Dropout(0.2))
|
||||
model.add(Dense(64, activation='relu'))
|
||||
model.add(Dropout(0.2))
|
||||
model.add(Dense(1, activation='sigmoid'))
|
||||
return model
|
||||
|
||||
|
||||
def compile_neural_network_model(model: Sequential, learning_rate: float = 0.001) -> None:
|
||||
"""
|
||||
Compile the neural network model.
|
||||
|
||||
Parameters:
|
||||
- model (Sequential): The Keras Sequential model representing the neural network.
|
||||
- learning_rate (float): The learning rate for the Adam optimizer.
|
||||
"""
|
||||
model.compile(optimizer=Adam(learning_rate=learning_rate), loss='binary_crossentropy', metrics=['accuracy'])
|
||||
|
||||
|
||||
def preprocess_data(dataset: pd.DataFrame) -> tuple:
|
||||
"""
|
||||
Preprocess the dataset for training the neural network model.
|
||||
|
||||
Parameters:
|
||||
- dataset (pd.DataFrame): The dataset containing trade outcome information.
|
||||
|
||||
Returns:
|
||||
- tuple: A tuple containing preprocessed input features and target labels.
|
||||
"""
|
||||
# Define the numerical features (if any)
|
||||
numerical_features = [] # Update with the actual numerical feature column names
|
||||
|
||||
# Define the input features
|
||||
input_features = dataset[[
|
||||
'pattern', 'divergence_strength', 'trend_direction', 'indicator_used']]
|
||||
|
||||
# Convert categorical features to one-hot encoding
|
||||
input_features = pd.get_dummies(input_features)
|
||||
|
||||
# Normalize numerical features (if any)
|
||||
if numerical_features:
|
||||
scaler = MinMaxScaler()
|
||||
input_features[numerical_features] = scaler.fit_transform(
|
||||
input_features[numerical_features])
|
||||
|
||||
# Extract target labels from the dataset
|
||||
target_labels = dataset['outcome']
|
||||
|
||||
# Convert target labels to numerical representation (0s and 1s)
|
||||
target_labels = target_labels.map({'Loss': 0, 'Win': 1})
|
||||
|
||||
# Return the preprocessed input features and target labels
|
||||
return input_features, target_labels
|
||||
|
||||
|
||||
def update_neural_network_model(trade_outcome: dict, dataset_path: str) -> None:
|
||||
"""
|
||||
Update the neural network model based on trade outcome.
|
||||
|
||||
Parameters:
|
||||
- trade_outcome (dict): Trade outcome information.
|
||||
- dataset_path (str): The path to the dataset file for updating and saving.
|
||||
"""
|
||||
# Load existing model or create a new one if it doesn't exist
|
||||
try:
|
||||
model = load_model('model_weights.h5')
|
||||
except (OSError, ValueError):
|
||||
# If loading fails, create a new model
|
||||
input_shape = (5,) # Replace with the actual input shape
|
||||
model = create_neural_network_model(input_shape)
|
||||
compile_neural_network_model(model, learning_rate=0.001)
|
||||
|
||||
pattern = trade_outcome['pattern']
|
||||
divergence_strength = trade_outcome['divergence_strength']
|
||||
time = trade_outcome['time']
|
||||
trend_direction = trade_outcome['trend_direction']
|
||||
indicator_used = trade_outcome['indicator_used']
|
||||
outcome = trade_outcome['outcome']
|
||||
|
||||
# Example update code: Append trade outcome information to a dataset for future training
|
||||
trade_data = pd.DataFrame({
|
||||
'pattern': [pattern],
|
||||
'divergence_strength': [divergence_strength],
|
||||
'time': [time],
|
||||
'trend_direction': [trend_direction],
|
||||
'indicator_used': [indicator_used],
|
||||
'outcome': [outcome]
|
||||
})
|
||||
|
||||
try:
|
||||
# Load existing dataset if it exists
|
||||
dataset = pd.read_csv(dataset_path)
|
||||
except (FileNotFoundError, pd.errors.EmptyDataError):
|
||||
# Create an empty dataset if the file doesn't exist or is empty
|
||||
dataset = pd.DataFrame()
|
||||
|
||||
# Concatenate the trade data to the dataset for future training
|
||||
updated_dataset = pd.concat([dataset, trade_data], ignore_index=True)
|
||||
|
||||
# Save updated dataset
|
||||
updated_dataset.to_csv(dataset_path, index=False)
|
||||
|
||||
# Example retraining code: Retrain the neural network model with the updated dataset
|
||||
# Preprocess data as per your requirements
|
||||
X_train, y_train = preprocess_data(updated_dataset) # Implement the preprocess_data function
|
||||
|
||||
# Convert labels to NumPy array and ensure the correct data type
|
||||
y_train = np.array(y_train).astype(float) # Convert to float
|
||||
|
||||
# Ensure labels have the correct shape
|
||||
y_train = y_train.reshape(-1)
|
||||
|
||||
# Example retraining step
|
||||
model.fit(X_train, y_train, epochs=10, batch_size=32)
|
||||
|
||||
# Save the updated model weights
|
||||
model.save_weights('model_weights.h5')
|
||||
@@ -1,254 +0,0 @@
|
||||
# trading_strategy.py
|
||||
"""
|
||||
Module for defining the trading strategy used by the trading bot.
|
||||
|
||||
This module provides functions for generating trade signals based on various indicators,
|
||||
divergences, patterns, and trend directions.
|
||||
|
||||
Author: Mike Kiwalabye
|
||||
"""
|
||||
|
||||
import MetaTrader5 as mt5
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from sklearn.preprocessing import MinMaxScaler
|
||||
from talib import abstract
|
||||
from src.models import neural_network_model
|
||||
|
||||
def get_historical_data(symbol: str, existing_data: pd.DataFrame = None) -> pd.DataFrame:
|
||||
"""
|
||||
Retrieve historical data for a given symbol and timeframe from MetaTrader 5.
|
||||
|
||||
Parameters:
|
||||
- symbol (str): The financial instrument symbol (e.g., 'EURUSD').
|
||||
- existing_data (pd.DataFrame): Existing historical data DataFrame.
|
||||
|
||||
Returns:
|
||||
- pd.DataFrame: DataFrame containing historical data with columns: ['time', 'open', 'high', 'low', 'close', 'tick_volume', 'spread', 'real_volume'].
|
||||
"""
|
||||
print(len(existing_data))
|
||||
if len(existing_data) == 0:
|
||||
# If no existing data, fetch the last 2500 bars
|
||||
rates = mt5.copy_rates_from_pos(symbol, mt5.TIMEFRAME_M1, 0, 2500)
|
||||
df = pd.DataFrame(rates)
|
||||
else:
|
||||
# If existing data is provided, fetch only the latest bar
|
||||
rates = mt5.copy_rates_from_pos(symbol, mt5.TIMEFRAME_M1, 0, 1)
|
||||
new_data = pd.DataFrame(rates)
|
||||
|
||||
# Concatenate the new data to the existing data
|
||||
df = pd.concat([existing_data, new_data])
|
||||
|
||||
# Convert data to DataFrame
|
||||
df['time'] = pd.to_datetime(df['time'], unit='s')
|
||||
df.set_index('time', inplace=True)
|
||||
|
||||
return df
|
||||
|
||||
def calculate_patterns(df: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Calculate common trade patterns such as double tops & bottoms, pennants, wedges, and bull and bear flags.
|
||||
|
||||
Parameters:
|
||||
- df (pd.DataFrame): The DataFrame containing price and indicator information.
|
||||
|
||||
Returns:
|
||||
- pd.DataFrame: The DataFrame with added columns for detected patterns.
|
||||
"""
|
||||
# Detect Double Tops & Bottoms
|
||||
df['double_top'] = np.where((df['high'].shift(1) > df['high']) & (df['high'].shift(1) > df['high'].shift(2)), 'Double Top', 'None')
|
||||
df['double_bottom'] = np.where((df['low'].shift(1) < df['low']) & (df['low'].shift(1) < df['low'].shift(2)), 'Double Bottom', 'None')
|
||||
|
||||
# Detect Bull and Bear Flags
|
||||
df['bull_flag'] = np.where((df['close'] > abstract.BBANDS(df['close'], timeperiod=5, nbdevup=2.0, nbdevdn=2.0)[0]) & (df['close'].shift(1) < abstract.BBANDS(df['close'].shift(1), timeperiod=5, nbdevup=2.0, nbdevdn=2.0)[0]), 'Bull Flag', 'None')
|
||||
df['bear_flag'] = np.where((df['close'] < abstract.BBANDS(df['close'], timeperiod=5, nbdevup=2.0, nbdevdn=2.0)[2]) & (df['close'].shift(1) > abstract.BBANDS(df['close'].shift(1), timeperiod=5, nbdevup=2.0, nbdevdn=2.0)[2]), 'Bear Flag', 'None')
|
||||
|
||||
# Assign patterns based on conditions
|
||||
df['pattern'] = 'None'
|
||||
conditions = [
|
||||
(df['double_top'] != 'None'),
|
||||
(df['double_bottom'] != 'None'),
|
||||
(df['bull_flag'] != 'None'),
|
||||
(df['bear_flag'] != 'None')
|
||||
]
|
||||
|
||||
choices = ['Double Top', 'Double Bottom', 'Bull Flag', 'Bear Flag']
|
||||
df['pattern'] = np.select(conditions, choices, default='None')
|
||||
|
||||
return df
|
||||
|
||||
def calculate_indicators_and_detect_patterns(df: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Generate trade signals based on divergences, patterns, and trend direction.
|
||||
|
||||
Parameters:
|
||||
- df (pd.DataFrame): The DataFrame containing indicators, patterns, and trend information.
|
||||
|
||||
Returns:
|
||||
- pd.DataFrame: The DataFrame with added columns for trade signals.
|
||||
"""
|
||||
# Calculate indicators and detect patterns
|
||||
# Add your indicator calculation and pattern detection logic here
|
||||
|
||||
# Example: Calculate RSI
|
||||
df['rsi'] = abstract.RSI(df['close'], timeperiod=14)
|
||||
# print(df['close'].values)
|
||||
|
||||
# Example: Detect RSI divergence
|
||||
df['rsi_divergence'] = (df['rsi'] > 70) & (df['close'] < df['close'].shift())
|
||||
|
||||
# Example: Detect TREND signal
|
||||
df['trend_signal'] = 'None'
|
||||
df['short_ma'] = df['close'].rolling(window=50).mean()
|
||||
df['long_ma'] = df['close'].rolling(window=200).mean()
|
||||
|
||||
df.loc[df['short_ma'] > df['long_ma'], 'trend_signal'] = 'Uptrend'
|
||||
df.loc[df['short_ma'] < df['long_ma'], 'trend_signal'] = 'Downtrend'
|
||||
# Add your MACD divergence detection logic here
|
||||
|
||||
# Example: Detect patterns
|
||||
df['pattern'] = 'None'
|
||||
# Add your pattern detection logic here
|
||||
df = calculate_patterns(df)
|
||||
|
||||
return df
|
||||
|
||||
def generate_trade_signals(df: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Generate trade signals based on divergences, patterns, and trend direction.
|
||||
|
||||
Parameters:
|
||||
- df (pd.DataFrame): The DataFrame containing indicators, patterns, and trend information.
|
||||
|
||||
Returns:
|
||||
- pd.DataFrame: The DataFrame with added columns for trade signals.
|
||||
"""
|
||||
# Determine trade signals based on divergences, patterns, and trend direction
|
||||
df['signal'] = 'None'
|
||||
df['divergence_signal'] = np.where((df['rsi_divergence'] == True) & (df['pattern'] != 'None'), 'Both',
|
||||
np.where(df['rsi_divergence'] == True, 'RSI', 'Pattern'))
|
||||
df['strongest_divergence_signal'] = df[['divergence_signal']].max(axis=1)
|
||||
|
||||
# Additional conditions for trade signals
|
||||
conditions = [
|
||||
(df['strongest_divergence_signal'] != 'None'),
|
||||
# Placeholder for 'resistance' calculation - replace this with your actual logic
|
||||
(df['close'] > df['close'].rolling(window=10).max()),
|
||||
(df['close'] < df['close'].rolling(window=10).min()),
|
||||
# Use the calculated 'trend_signal' column for trend condition
|
||||
(df['trend_signal'] == 'Uptrend'),
|
||||
(df['trend_signal'] == 'Downtrend'),
|
||||
# Additional condition to check if the pattern is valid
|
||||
(df['pattern'] != 'None'),
|
||||
]
|
||||
|
||||
choices = ['Divergence', 'Resistance', 'Support', 'Uptrend', 'Downtrend', 'Pattern']
|
||||
|
||||
# Ensure that the lengths of conditions and choices are the same
|
||||
if len(conditions) == len(choices):
|
||||
df['support_resistance_signal'] = np.select(conditions, choices, default='None')
|
||||
else:
|
||||
# Handle the case where lengths do not match (print an error message for debugging)
|
||||
print("Error: Lengths of conditions and choices do not match.")
|
||||
df['support_resistance_signal'] = 'None'
|
||||
|
||||
# Iterate over the data points
|
||||
for i in range(1, len(df)):
|
||||
strongest_divergence_signal = df['strongest_divergence_signal'].iloc[i]
|
||||
support_resistance_signal = df['support_resistance_signal'].iloc[i]
|
||||
trend_signal = df['trend_signal'].iloc[i]
|
||||
|
||||
if strongest_divergence_signal != 'None':
|
||||
df.loc[df.index[i], 'signal'] = strongest_divergence_signal
|
||||
elif support_resistance_signal != 'None':
|
||||
df.loc[df.index[i], 'signal'] = support_resistance_signal
|
||||
elif trend_signal != 'None':
|
||||
df.loc[df.index[i], 'signal'] = trend_signal
|
||||
|
||||
return df
|
||||
|
||||
def execute_trade(signal_priority, df, symbol, lot_size, stop_loss, take_profit):
|
||||
"""
|
||||
Execute a trade based on the provided signal and trading parameters.
|
||||
|
||||
Parameters:
|
||||
- signal_priority (int): The priority assigned to the trade signal.
|
||||
- df (pd.DataFrame): The DataFrame containing trade-related information.
|
||||
- symbol (str): The financial instrument symbol (e.g., 'EURUSD').
|
||||
- lot_size (float): The size of the trading position.
|
||||
- stop_loss (float): The stop-loss level.
|
||||
- take_profit (float): The take-profit level.
|
||||
"""
|
||||
for index, row in df.iterrows():
|
||||
|
||||
# Additional conditions for Buy trade
|
||||
if (
|
||||
(signal_priority == 3 and row['rsi_divergence'] and row['rsi_value'] < 30 and row['trend_signal'] == 'Downtrend') or
|
||||
(signal_priority == 2 and row['pattern'] == 'Double Bottom' and row['trend_signal'] == 'Downtrend') or
|
||||
(signal_priority == 1 and 40 <= row['rsi_value'] <= 60 and row['pattern'] == 'Bull Flag' and row['trend_signal'] == 'Uptrend') or
|
||||
(signal_priority == 0 and row['rsi_value'] < 30 and row['rsi_divergence'] and row['pattern'] == 'Bull')
|
||||
):
|
||||
# Place a buy trade
|
||||
request = {
|
||||
'action': mt5.TRADE_ACTION_DEAL,
|
||||
'symbol': symbol,
|
||||
'volume': lot_size,
|
||||
'type': mt5.ORDER_TYPE_BUY,
|
||||
'price': mt5.symbol_info_tick(symbol).ask,
|
||||
'sl': mt5.symbol_info_tick(symbol).ask - stop_loss * mt5.symbol_info(symbol).point,
|
||||
'tp': mt5.symbol_info_tick(symbol).ask + take_profit * mt5.symbol_info(symbol).point,
|
||||
'deviation': 0,
|
||||
'magic': 123456,
|
||||
'comment': "Buy trade",
|
||||
'type_time': mt5.ORDER_TIME_GTC,
|
||||
'type_filling': mt5.ORDER_FILLING_IOC,
|
||||
}
|
||||
elif (
|
||||
(signal_priority == 3 and row['rsi_divergence'] and row['rsi_value'] > 70 and row['trend_signal'] == 'Uptrend') or
|
||||
(signal_priority == 2 and row['pattern'] == 'Double Top' and row['trend_signal'] == 'Uptrend') or
|
||||
(signal_priority == 1 and 40 <= row['rsi_value'] <= 60 and row['pattern'] == 'Bear Flag' and row['trend_signal'] == 'Downtrend') or
|
||||
(signal_priority == 0 and row['rsi_value'] > 70 and row['rsi_divergence'] and row['pattern'] == 'Bear')
|
||||
):
|
||||
# Place a sell trade
|
||||
request = {
|
||||
'action': mt5.TRADE_ACTION_DEAL,
|
||||
'symbol': symbol,
|
||||
'volume': lot_size,
|
||||
'type': mt5.ORDER_TYPE_SELL,
|
||||
'price': mt5.symbol_info_tick(symbol).bid,
|
||||
'sl': mt5.symbol_info_tick(symbol).bid + stop_loss * mt5.symbol_info(symbol).point,
|
||||
'tp': mt5.symbol_info_tick(symbol).bid - take_profit * mt5.symbol_info(symbol).point,
|
||||
'deviation': 0,
|
||||
'magic': 123456,
|
||||
'comment': "Sell trade",
|
||||
'type_time': mt5.ORDER_TIME_GTC,
|
||||
'type_filling': mt5.ORDER_FILLING_IOC,
|
||||
}
|
||||
|
||||
try:
|
||||
if signal_priority != 0:
|
||||
|
||||
result = mt5.order_send(request)
|
||||
print(result)
|
||||
outcome = 'Win' if result.retcode == mt5.TRADE_RETCODE_DONE else 'Loss'
|
||||
|
||||
# Example trade outcome information
|
||||
trade_outcome = {
|
||||
'pattern': row['pattern'],
|
||||
'divergence_strength': row['strongest_divergence_signal'],
|
||||
'time': pd.Timestamp.now(),
|
||||
'trend_direction': row['trend_signal'],
|
||||
'indicator_used': row['strongest_divergence_signal'],
|
||||
'outcome': outcome
|
||||
}
|
||||
# Update TensorFlow neural network model with trade outcome
|
||||
neural_network_model.update_neural_network_model(trade_outcome, 'tradedata.csv')
|
||||
|
||||
# Example print statements for debugging
|
||||
print(
|
||||
f"Executed trade with signal priority: {signal_priority}, position size: {lot_size}")
|
||||
print(f"Trade outcome: {trade_outcome}")
|
||||
|
||||
# Additional logic for trade management, monitoring, etc.
|
||||
except Exception as e:
|
||||
print(f"Error executing trade: {str(e)}")
|
||||
@@ -1,68 +0,0 @@
|
||||
# data_processing.py
|
||||
"""
|
||||
Module for processing and preprocessing data for the trading bot.
|
||||
|
||||
This module provides functions for loading, cleaning, and preprocessing historical price data.
|
||||
|
||||
Author: Mike Kiwalabye
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
from sklearn.preprocessing import MinMaxScaler
|
||||
|
||||
def load_data(file_path: str) -> pd.DataFrame:
|
||||
"""
|
||||
Load historical price data from a CSV file.
|
||||
|
||||
Parameters:
|
||||
- file_path (str): The path to the CSV file containing historical price data.
|
||||
|
||||
Returns:
|
||||
- pd.DataFrame: The DataFrame containing historical price data.
|
||||
"""
|
||||
# Load data from CSV file
|
||||
df = pd.read_csv(file_path)
|
||||
|
||||
# Ensure the 'time' column is in datetime format
|
||||
df['time'] = pd.to_datetime(df['time'])
|
||||
|
||||
return df
|
||||
|
||||
def clean_data(df: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Clean the historical price data by handling missing values and removing duplicates.
|
||||
|
||||
Parameters:
|
||||
- df (pd.DataFrame): The DataFrame containing historical price data.
|
||||
|
||||
Returns:
|
||||
- pd.DataFrame: The cleaned DataFrame.
|
||||
"""
|
||||
# Handle missing values (if any)
|
||||
df.dropna(inplace=True)
|
||||
|
||||
# Remove duplicate rows (if any)
|
||||
df.drop_duplicates(inplace=True)
|
||||
|
||||
return df
|
||||
|
||||
def preprocess_data(df: pd.DataFrame, numerical_features: list = []) -> pd.DataFrame:
|
||||
"""
|
||||
Preprocess the historical price data by normalizing numerical features and encoding categorical features.
|
||||
|
||||
Parameters:
|
||||
- df (pd.DataFrame): The DataFrame containing historical price data.
|
||||
- numerical_features (list): A list of column names corresponding to numerical features.
|
||||
|
||||
Returns:
|
||||
- pd.DataFrame: The preprocessed DataFrame.
|
||||
"""
|
||||
# Convert categorical features to one-hot encoding
|
||||
df = pd.get_dummies(df)
|
||||
|
||||
# Normalize numerical features (if any)
|
||||
if numerical_features:
|
||||
scaler = MinMaxScaler()
|
||||
df[numerical_features] = scaler.fit_transform(df[numerical_features])
|
||||
|
||||
return df
|
||||
@@ -1,73 +0,0 @@
|
||||
# visualization.py
|
||||
"""
|
||||
Module for visualizing data for the trading bot.
|
||||
|
||||
This module provides functions for visualizing historical price data and trade signals.
|
||||
|
||||
Author: Mike Kiwalabye
|
||||
"""
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import pandas as pd
|
||||
|
||||
def plot_price_data(df: pd.DataFrame, title: str = 'Price Chart') -> None:
|
||||
"""
|
||||
Plot the historical price data.
|
||||
|
||||
Parameters:
|
||||
- df (pd.DataFrame): The DataFrame containing historical price data.
|
||||
- title (str): The title of the plot.
|
||||
|
||||
Returns:
|
||||
- None
|
||||
"""
|
||||
try:
|
||||
plt.figure(figsize=(10, 6))
|
||||
plt.plot(df.index, df['close'], label='Close')
|
||||
|
||||
# Add visualizations for other indicators, levels, and patterns
|
||||
# (Add more visualizations as needed)
|
||||
|
||||
plt.title(title)
|
||||
plt.xlabel('Time')
|
||||
plt.ylabel('Price')
|
||||
plt.legend()
|
||||
|
||||
# Use plt.show(block=True) to make the plot blocking
|
||||
plt.show(block=True)
|
||||
except Exception as e:
|
||||
print(f"Error plotting trade signals: {str(e)}")
|
||||
|
||||
# ...
|
||||
|
||||
def plot_trade_signals(df: pd.DataFrame, title: str = 'Trade Signals') -> None:
|
||||
"""
|
||||
Plot trade signals on the historical price chart.
|
||||
|
||||
Parameters:
|
||||
- df (pd.DataFrame): The DataFrame containing historical price data with trade signals.
|
||||
- title (str): The title of the plot.
|
||||
|
||||
Returns:
|
||||
- None
|
||||
"""
|
||||
try:
|
||||
plt.figure(figsize=(10, 6))
|
||||
plt.plot(df.index, df['close'], label='Close')
|
||||
|
||||
# Plot trade signals
|
||||
buy_signals = df[df['signal'] == 'Buy']
|
||||
sell_signals = df[df['signal'] == 'Sell']
|
||||
|
||||
plt.scatter(buy_signals.index, buy_signals['close'], color='green', marker='^', label='Buy Signal')
|
||||
plt.scatter(sell_signals.index, sell_signals['close'], color='red', marker='v', label='Sell Signal')
|
||||
|
||||
plt.title(title)
|
||||
plt.xlabel('Time')
|
||||
plt.ylabel('Price')
|
||||
plt.legend()
|
||||
|
||||
# Use plt.show(block=True) to make the plot blocking
|
||||
plt.show(block=True)
|
||||
except Exception as e:
|
||||
print(f"Error plotting trade signals: {str(e)}")
|
||||
@@ -1,110 +0,0 @@
|
||||
<!-- dashboard.html -->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Trading Dashboard</title>
|
||||
|
||||
<!-- Include Chart.js from a CDN -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Trading Dashboard</h1>
|
||||
|
||||
<div>
|
||||
<p><strong>Username:</strong> {{ username }}</p>
|
||||
<p><strong>Account Balance:</strong> {{ account_balance }} <small>{{ account_currency }}</small></p>
|
||||
</div>
|
||||
|
||||
<!-- Add a canvas element for the chart -->
|
||||
<canvas id="tradeChart" width="800" height="400"></canvas>
|
||||
|
||||
<form action="/stop_ml_bot" method="get">
|
||||
<button type="submit">Stop ML Bot</button>
|
||||
</form>
|
||||
|
||||
<!-- Use a button without a form to start the ML Bot -->
|
||||
<button onclick="startBot()">Start ML Bot</button>
|
||||
|
||||
<script>
|
||||
// Function to update the chart with new trade signals
|
||||
function updateChart(tradeSignals) {
|
||||
// Parse the JSON-formatted string to an object
|
||||
const parsedTradeSignals = JSON.parse(tradeSignals);
|
||||
|
||||
// Extract relevant data for the chart (modify as needed)
|
||||
const timestamps = parsedTradeSignals.map(signal => signal.time);
|
||||
const prices = parsedTradeSignals.map(signal => signal.close);
|
||||
|
||||
// Get the canvas element
|
||||
const ctx = document.getElementById('tradeChart');
|
||||
|
||||
// Destroy existing chart if it exists
|
||||
if (ctx.chart) {
|
||||
ctx.chart.destroy();
|
||||
}
|
||||
|
||||
// Initialize the chart
|
||||
const myChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: timestamps,
|
||||
datasets: [{
|
||||
label: 'Close Price',
|
||||
data: prices,
|
||||
borderColor: 'rgba(75, 192, 192, 1)',
|
||||
borderWidth: 1,
|
||||
fill: false
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
x: {
|
||||
type: 'time',
|
||||
time: {
|
||||
unit: 'minute' // Adjust as needed
|
||||
}
|
||||
},
|
||||
y: {
|
||||
beginAtZero: false
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Function to periodically update the chart
|
||||
function periodicallyUpdateChart() {
|
||||
// Fetch the latest trade signals from the server
|
||||
fetch('/get_latest_trade_signals')
|
||||
.then(response => response.json())
|
||||
.then(tradeSignals => {
|
||||
// Update the chart with the new trade signals
|
||||
updateChart(tradeSignals);
|
||||
|
||||
// Schedule the next update
|
||||
setTimeout(periodicallyUpdateChart, 5000); // Update every 5 seconds
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error fetching trade signals:', error);
|
||||
// Retry the update after an interval
|
||||
setTimeout(periodicallyUpdateChart, 5000); // Retry after 5 seconds
|
||||
});
|
||||
}
|
||||
|
||||
// Start the initial chart update
|
||||
periodicallyUpdateChart();
|
||||
|
||||
function startBot() {
|
||||
// Send an asynchronous request to start the bot
|
||||
fetch('/start_ml_bot', { method: 'POST' });
|
||||
|
||||
// Optionally, you can add logic here to update the UI or provide feedback to the user
|
||||
console.log('Bot started!');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,28 +0,0 @@
|
||||
<!-- templates/index.html -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>MT5 Connector</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>MetaTrader 5 Connector</h1>
|
||||
<form action="/login" method="post">
|
||||
<label for="username">Username:</label>
|
||||
<input type="text" id="username" name="username" required><br>
|
||||
|
||||
<label for="password">Password:</label>
|
||||
<input type="password" id="password" name="password" required><br>
|
||||
|
||||
<label for="server">Server:</label>
|
||||
<input type="text" id="server" name="server" required><br>
|
||||
|
||||
<label for="path">MT5 Path:</label>
|
||||
<input type="text" id="path" name="path" required><br>
|
||||
|
||||
<input type="submit" value="Connect">
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user