MetaTrader5 Buy and Sell Signals: A Beginner’s #Python Algorithmic Trading Tutorial #finance

import datetime
import pytz
import pandas as pd
import MetaTrader5 as mt5
import numpy as np
import matplotlib.pyplot as plt

#Initialise and login to MetaTrader5
mt5.initialize()
# mt5.login(login="*****", password="****", server="**")
mt5.login(login="****", password="!***", server="MetaQuotes-Demo")

#Define time frames
time_frames = {
    'M15': mt5.TIMEFRAME_M15,
    'M30': mt5.TIMEFRAME_M30,
    'D1': mt5.TIMEFRAME_D1,
    'W1': mt5.TIMEFRAME_W1,
    'MN1': mt5.TIMEFRAME_MN1
}

# Define assets to fetch data

assets = ['EURUSD', 'USDCHF', 'GBPUSD', 'USDCAD','BTCUSD']

# Buying 1 EUR 1.07516 USD

#Fetch data 

def fetch_data(time_frame, year=2024, month=1, day=1, asset="EURUSD"):
    if not mt5.initialize():
        print("Initization failed, error code=", mt5.last_error())
        return None
    timezone=pytz.timezone("America/New_York")
    start_time = datetime.datetime(year, month, day, tzinfo=timezone)
    end_time = datetime.datetime.now(timezone) + datetime.timedelta(days=1)

    print(f"Fetching data for {asset} from {start_time} to {end_time} with timeframe {time_frame}")

    rates = mt5.copy_rates_range(asset, time_frame, start_time, end_time)

    if rates is None:
        print(f"No Data for {asset} in the specified range")
    
    return pd.DataFrame(rates)

def import_data(asset_index, time_frame_key):
    asset = assets[asset_index]
    data = fetch_data(time_frames[time_frame_key], 2024, 6, 1, asset=asset)

    if data is None or data.empty:
        print(f"No Data returned for {asset} on {time_frame_key} timeframe.")
        return None
    data_values =  data.iloc[:, 1:5].values.round(decimals=5)
    #4 decimal pipe 5 demical pipette
    #1.0964
    #1.0964f5
    return data_values

#fetch data for a specific asset and time frame
my_data = import_data(0, 'D1')

if my_data is not None:
    print("Fetched Data:\n", my_data)
else:
    print("No Data Fetched")

#create buy or sell signal columns
def add_columns(data, times):
    for _ in range(times):
        new_column = np.zeros((len(data), 1), dtype=float)
        data = np.append(data, new_column, axis=1)
    return data

#Generate Signals
def generate_signals(data):
    data = add_columns(data, 2) # add 2 columns as buy and sell signal
    for i in range(2, len(data)-1):
        try:
            if data[1,3] > data[i - 2, 3]:
                data[i + 1, 4] = 1
            elif data[i, 3] < data[i - 2, 3]:
                data[i + 1, 5] = -1
        except IndexError:
            pass
    return data

# OHLC Open, High, Low, Close

def ohlc_plot_candles(data, window): #500 last 500 records
    sample= data[-window:]
    for i in range(len(sample)):
        plt.vlines(x = i, ymin = sample[i, 2], ymax = sample[i, 1],color = 'black', linewidth = 1)
        if sample[i, 3] > sample[i, 0]:
            plt.vlines(x = i, ymin = sample[i, 0], ymax = sample[i, 3],color = 'green', linewidth = 3)
        if sample[i, 3] < sample[i, 0]:
            plt.vlines(x = i, ymin = sample[i, 3], ymax = sample[i, 0],color = 'red', linewidth = 3)
        else:
            plt.vlines(x = i, ymin = sample[i, 3], ymax = sample[i, 0] + 0.00003, color = 'black', linewidth = 1.00)
    plt.grid()
            
def plot_signal_chart(data, position, buy_column, sell_column, window=500):
    data = generate_signals(data)
    sample = data[-window:]
    fig, ax = plt.subplots(figsize=(12, 6))  # Adjust figure size for better proportion
    ohlc_plot_candles(sample, window)
    for i in range(len(sample)):
        if sample[i, buy_column] == 1:
            ax.annotate('Buy', xy=(i, sample[i, position]), xytext=(i, sample[i, position] + 0.0001),
                        arrowprops=dict(facecolor='green', shrink=0.05, width=1, headwidth=2, headlength=1),
                        horizontalalignment='center', verticalalignment='bottom')
        elif sample[i, sell_column] == -1:
            ax.annotate('Sell', xy=(i, sample[i, position]), xytext=(i, sample[i, position] - 0.0001),
                        arrowprops=dict(facecolor='red', shrink=0.05, width=1, headwidth=2, headlength=1),
                        horizontalalignment='center', verticalalignment='top')
    plt.show()

if my_data is not None:
    plot_signal_chart(my_data, 3, 4, 5, window=500)