Open a trade using the MT5 API with Python

As an Amazon Associate I earn from qualifying purchases.

4 Min Read

When I decided to build my own automated trading platform, one of the first key pieces of functionality was to open a trade programmatically. Now that you have seen how to open a connection to the MT5 platform and pull data (if you haven’t seen this blog post I highly suggest reading it before continuing) it’s time to do something a little more exciting. In today’s post I will show you how to open a trade using the MT5 API with Python.

Validating the instrument exists

Let’s start by looking at the connection code from the previous post:

import MetaTrader5 as mt5
from datetime import datetime

account = int(YOUR ID HERE)

mt5.initialize()
authorized=mt5.login(account)

if authorized:
    print("Connected: Connecting to MT5 Client")
else:
    print("Failed to connect at account #{}, error code: {}"
          .format(account, mt5.last_error()))

Let’s clean this up by making a method called connect that takes an account number:

import MetaTrader5 as mt5
from datetime import datetime


def connect(account):
    account = int(account)
    mt5.initialize()
    authorized=mt5.login(account)

    if authorized:
        print("Connected: Connecting to MT5 Client")
    else:
        print("Failed to connect at account #{}, error code: {}"
              .format(account, mt5.last_error()))

Next, you will want to create another method and name it open_position with the following signature :

def openPosition(pair, order_type, size, tp_distance=None, stop_distance=None):

Before opening a trade, it is advisable to add some safety checks in. This is to make sure the instrument you want to execute orders on exists and is available to trade with the broker:

def open_position(pair, order_type, size, tp_distance=None, stop_distance=None):
    symbol_info = mt5.symbol_info(pair)
    if symbol_info is None:
        print(pair, "not found")
        return

    if not symbol_info.visible:
        print(pair, "is not visible, trying to switch on")
        if not mt5.symbol_select(pair, True):
            print("symbol_select({}}) failed, exit",pair)
            return
    print(pair, "found!")

To make sure this code is working, let’s try to connect and open a position on an instrument that does not exist:

>>> connect(39672374)
Connected: Connecting to MT5 Client
>>> open_position("Fake_Pair", "BUY", 1)
Fake_Pair not found

When we called the open_position method with the argument “Fake_Pair” it failed to find the pair as expected.

Now try a valid pair such as “EURUSD”:

>>> connect(39672374)
Connected: Connecting to MT5 Client
>>> open_position("EURUSD", "BUY", 1.0)
EURUSD found!

You can see above that the pair was found and is ready to trade.

Executing the order

Now we are ready to open a trade using the MT5 API with Python. The first thing you will need to do is get the ‘point’ of the instrument you are trading. The point is defined as the smallest price increment change that can happen on an instrument.

point = symbol_info.point
volume_step = symbol_info.volume_step

Next, create an if statement to check whether your order is a BUY or SELL. This is important because stop losses and take profits are calculated differently based on if you are buying or selling.

The stop loss and take profit in the method signature are the distance in pips from the original price. For MT5, you need to provide a stop loss and take profit price (if you are using a stop loss and take profit – they can also be left blank). To calculate this, you must take the current price and add or subtract the stop loss/take profit multiplied by the point. An example of this is show below:

if(order_type == "BUY"):
	order = mt5.ORDER_TYPE_BUY
	price = mt5.symbol_info_tick(pair).ask
	if(stop_distance):
		sl = price - (stop_distance * point)
	if(tp_distance):
		tp = price + (tp_distance * point)
if(order_type == "SELL"):
	order = mt5.ORDER_TYPE_SELL
	price = mt5.symbol_info_tick(pair).bid
	if(stop_distance):
		sl = price + (stop_distance * point)
	if(tp_distance):
		tp = price - (tp_distance * point)

Now, it is time to call the API that actually submits the order. To do this we will use the order_send() method from the MT5 API. But first, lets build up our request. A full list of available methods for the MT5 API can be found here.

The request is a dictionary with the following keys:

    • action
    • symbol
    • volume
    • type
    • price
    • magic
    • comment
    • type_time
    • type_filling

In case you are wondering what the mysterious parameter ‘magic’ means – it is essentially just a client ID (this can be set to any number). In our case, the request is coded as follows:

request = {
	    "action": mt5.TRADE_ACTION_DEAL,
	    "symbol": pair,
	    "volume": float(size),
	    "type": order,
	    "price": price,
      "sl": sl,
      "tp": tp,
	    "magic": 234000,
	    "comment": "My first trade",
	    "type_time": mt5.ORDER_TIME_GTC,
	    "type_filling": mt5.ORDER_FILLING_IOC,
}

To send the request use the order_send() method:

	result = mt5.order_send(request)

Finally, you will want to check if your order is successful or not. You can do this by going to the MT5 desktop application and checking your account or alternatively, by adding the following code under order_send:

if result.retcode != mt5.TRADE_RETCODE_DONE:
		print("Failed to send order :(")
	else:
		print ("Order successfully placed!")

Testing our code

If you have followed along during this tutorial you should have something similar to the code shown below:

import MetaTrader5 as mt5
from datetime import datetime

def connect(account):
    account = int(account)
    mt5.initialize()
    authorized=mt5.login(account)

    if authorized:
        print("Connected: Connecting to MT5 Client")
    else:
        print("Failed to connect at account #{}, error code: {}"
              .format(account, mt5.last_error()))

def open_position(pair, order_type, size, tp_distance=None, stop_distance=None):
    symbol_info = mt5.symbol_info(pair)
    if symbol_info is None:
        print(pair, "not found")
        return

    if not symbol_info.visible:
        print(pair, "is not visible, trying to switch on")
        if not mt5.symbol_select(pair, True):
            print("symbol_select({}}) failed, exit",pair)
            return
    print(pair, "found!")

    point = symbol_info.point
    
    if(order_type == "BUY"):
        order = mt5.ORDER_TYPE_BUY
        price = mt5.symbol_info_tick(pair).ask
        if(stop_distance):
            sl = price - (stop_distance * point)
        if(tp_distance):
            tp = price + (tp_distance * point)
            
    if(order_type == "SELL"):
        order = mt5.ORDER_TYPE_SELL
        price = mt5.symbol_info_tick(pair).bid
        if(stop_distance):
            sl = price + (stop_distance * point)
        if(tp_distance):
            tp = price - (tp_distance * point)

    request = {
        "action": mt5.TRADE_ACTION_DEAL,
        "symbol": pair,
        "volume": float(size),
        "type": order,
        "price": price,
        "sl": sl,
        "tp": tp,
        "magic": 234000,
        "comment": "",
        "type_time": mt5.ORDER_TIME_GTC,
        "type_filling": mt5.ORDER_FILLING_IOC,
    }

    result = mt5.order_send(request)

    if result.retcode != mt5.TRADE_RETCODE_DONE:
        print("Failed to send order :(")
    else:
        print ("Order successfully placed!")

To test the above code works, you need to call both methods. In the example below, I open a trade for EURUSD using 1 standard lot, a take profit distance of 300 and a stop loss distance of 100:

>>> connect(39672374)
Connected: Connecting to MT5 Client
>>> open_position("EURUSD", "BUY", 1, 300, 100)
EURUSD found!
Order successfully placed!

If you go back to the MT5 desktop application, a new trade should be open on your account:

You can see here that the entry price is 1.21717, the stop loss is 100 pips less than the entry price (1.21617) and the take profit is 300 more (1.22017).

That’s all for this post! As always, if you have any questions or comments please feel free to post them below. Additionally, if you run into any issues please let me know.

19 thoughts on “Open a trade using the MT5 API with Python”

  1. Avatar

    Great series so far, thanks! I have one suggestion, if I may:
    If it fails to send the order, we could print the reason why, with
    print (result.comment)

    1. Conor O'Hanlon

      Great suggestion. Later in the series I will revisit the code and add more error handling etc. Thanks for the support.

  2. Avatar

    Going great! I have a question. I always imagined I would use threads in my bot so that it could trade in multiple stocks if I gave it a list of sorts. But I see mt5 does not use a class so it seems I wouldn’t be able to have a class instance for each stock. I suppose I could have it take turns. But otherwise can more than one scripts can be run in mt5 without interference?

  3. Avatar

    Hello conor

    I really appreciate this course and your effort building it.

    Unfortunatly i am stuck and cant get rid of this error…

    >>> open_position(“EURUSD”, “BUY”, 1, 300, 100)
    EURUSD found!
    Failed to send order 🙁

    Could you point me in the right direction?

    Thank you

    1. Conor O'Hanlon

      Hmm. Can you print the `result.retcode` from the response? I would also check if you have enabled algotrading on MT5

      1. Avatar

        I added the code accordingly:
        if result.retcode != mt5.TRADE_RETCODE_DONE:
        print(result.retcode)
        print(“Failed to send order :(“)
        else:
        print (“Order successfully placed!”)

        Now I get this output:

        >>> open_position(“EURUSD”, “BUY”, 1, 300, 100)
        EURUSD found!
        10027
        Failed to send order 🙁

        Thank you for the help

          1. Avatar

            I received 10027 with the button in the red state and this one with the green state:
            EURUSD found!
            10030
            Failed to send order 🙁

          2. Avatar

            Thank you for you help!

            type_filling”: mt5.ORDER_FILLING_IOC instead of type_filling”: mt5.ORDER_FILLING_FOK solved it!

  4. Avatar

    Hi Connor, this is a great course so far. I seem to be getting stuck when defining the point;
    “point = symbol_info.point”
    returns with; “NameError: name ‘symbol_info’ is not defined”
    Any idea why this wouldn’t be defined? I am new to python so it’s possible I missed crucial step.

  5. Avatar

    I did everything mentioned and got a successful trade but idk where to look for the open trades in the MT5 Desktop app

Leave a Comment

Your email address will not be published. Required fields are marked *

Subscribe to my newsletter to keep up to date with my latest posts

Holler Box