Dynamically calculate lot size for your algorithmic trading bot

As an Amazon Associate I earn from qualifying purchases.

4 Min Read

In the last post, we looked at how you can dynamically load strategies into your trader. Today, I will show you how to dynamically calculate the lot size your algorithmic trading bot. The position size of a trade will depend on a percentage of risk, you are willing to take on your account balance. E.g. if your risk percentage is 1% and you have a $5000 account then the maximum amount of money you can lose in one trade is $50.

Calculate the value of one pip

To start, you will need to install a new library called forex-python. You can install this using the command below or by going here. Forex Python is a Free Foreign exchange rates and currency conversion which we will be using to calculate the value of a pip.

pip install forex-python

After this has been installed, go to your constants.py file and import this new library as follows:

import talib as ta
from forex_python.converter import CurrencyRates

Next, let’s add a method to our constants.py file to calculate the pip value. We need to calculate the size of one pip for a given instrument. You can call this new method get_pip_value and it should take arguments of symbol and account_currency:

def get_pip_value(symbol, account_currency):

Now we need to split up our symbol into 2 currencies. I.e if we passed “EURUSD” as a symbol then we need to split it up as “EUR” and “USD”:

def get_pip_value(symbol, account_currency):
	symbol_1 = symbol[0:3]
	symbol_2 = symbol[3:6]

Finally, using the CurrencyRates module lets calculate the value of one pip and convert it to our local currency. More information on how the convert method works can be found here:

def get_pip_value(symbol, account_currency):
	symbol_1 = symbol[0:3]
	symbol_2 = symbol[3:6]
	c = CurrencyRates()
	return c.convert(symbol_2, account_currency, c.convert(symbol_1, symbol_2, 1))

Dynamically calculate the lot size for your algorithmic trading bot

Let’s have a look at your trader.py file again. You will be adding a new method called calc_position_size which takes the following arguments: symbol, strategy.

def calc_position_size(symbol, strategy):

To calculate a percentage of your balance you are willing to risk you need to actually know the current balance of your account. Retrieve this by using the acount_info method from the MT5 API. More information on this can be found here. Call this method and assign it to a variable named account. Also, add a print statement to say that you are calculating the position size for a given symbol.

def calc_position_size(symbol, strategy):
    print("Calculating position size for: ", symbol)
    account = mt5.account_info()

With this done, create a new variable named balance and get the balance from account:

    balance = float(account.balance)

Now, we need to calculate the pip value of the symbol. This is done by calling the method created earlier in constants.py. Remember, you will need to pass in the symbol and account currency for this method. Assign this to a new variable called pip_value:

    pip_value = constants.getPipValue(symbol, strategy['account_currency'])

Don’t worry about referencing account_currency in your strategy. You will be adding this entry to your strategy json file later. You will now need to calculate the lot size based of your account balance. To calculate the lot size use the following equation:

Lot size = (balance * risk) / pip value * stop loss

Your python code should look like the following:

lot_size = (float(balance) * (float(strategy["risk"])/100)) / (pip_value * strategy["stopLoss"])

Finally, round the value to 2 decimal places (as MT5 only accepts lot sizes rounded to 2 decimal places) and return:

    lot_size = round(lot_size, 2)
    return lot_size

Let’s go back to the check_trades methods created earlier. In that method, find where you are opening a position (open_position…) and above this method call add the following line:

                lot_size = calc_position_size(pair, strategy)

In your open_position call, replace the current lot size with the one from the variable created above:

                open_position(pair, "BUY", lot_size, float (strategy['takeProfit']), float(strategy['stopLoss']))

Adding new properties to the strategy json file

You will remember that we references 2 new properties from the strategy in this post called account_currency and risk. These properties do not exist in our strategy yet. Let’s fix that!

Go to your strategy.json file and add the account_currency property to the top of the file. In my case, I will add USD as my account currency:

{
   "account_currency" : "USD",
	 "strategy_name": "myStrategy",

After strategy_name define your risk as a percentage value. E.g. 2 = 2%:

{
  "account_currency" : "USD",
	"strategy_name": "myStrategy",
	"pairs": [
		"EURUSD",
		"USDCAD",
		"GBPUSD"
    ],
    "risk" : 2,

Testing the code

Now let’s test our code. For this test I will simply run the trader and wait for a trade to open. The lot size should be dynamically calculated based on my account balance and risk.

C:\Users\conor\Documents\blog files>python trader.py strategy
Trading bot started with strategy: strategy
Connected: Connecting to MT5 Client
Running trader at 2021-01-29 08:30:00.939338
Connected: Connecting to MT5 Client
Running trader at 2021-01-29 08:45:00.242999
Connected: Connecting to MT5 Client
Running trader at 2021-01-29 09:00:00.561294
Connected: Connecting to MT5 Client
Running trader at 2021-01-29 09:15:00.412300
Connected: Connecting to MT5 Client
Running trader at 2021-01-29 09:30:00.343254
Connected: Connecting to MT5 Client
Running trader at 2021-01-29 09:45:00.835452
Connected: Connecting to MT5 Client
Calculating position size for:  EURUSD
Order successfully placed!

As you can see above, the trader ran and opened a position on EURUSD with a calculated lot size of 5.53.

If you are interested in learning more about algo trading and trading systems, I highly recommend reading this book. I have taken some of my own trading ideas and strategies from this book. It also provided me a great insight into effective back testing. Check it out here.

That’s all for now! Check back on Monday to see how you can send trading alerts to your phone via slack! 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.

4 thoughts on “Dynamically calculate lot size for your algorithmic trading bot”

  1. Avatar

    Hi, first i want to tell you that your tutorial is awesome, Congrats !

    I have a problem, maybe I did something wrong but the lot size doesn’t seems to be accurate. I compare my result with this site : https://www.myfxbook.com/fr/forex-calculators/position-size

    for instance :
    I have a account with 100 000 EUR, with a risk of 1% and a 5 pips SL. I trade on AUDUSD.
    The program give me a lot size equal to 31.33 , on the other hand the site give me a lot size equal to 24.24. Do you have the same problem ?

    On an other subject, do you think you will implement the backtest of the trading robot in your tutorial ?

    Anyway, thanks again for this incredible tutorial !
    regards,
    Thibault

    1. Conor O'Hanlon

      Thanks! Is “account_currency” in strategy.json set to “EUR”? Also, yes this should be coming out within the next few weeks 🙂

      1. Avatar

        I don’t use the json part, because I want to create a strategy using price action so i really need to code all my strat,
        but anyway my two function looks like that (almost the same as yours) :

        def get_pip_value(symbol : str, account_currency : str) -> CurrencyRates:
        symbol_1 = symbol[0:3]
        symbol_2 = symbol[3:6]
        c = CurrencyRates()
        return c.convert(symbol_2, account_currency, c.convert(symbol_1, symbol_2, 1))

        def calc_position_size(symbol : str, account_currency : str, risk : float, sl : int) -> float:
        account = mt5.account_info()
        balance = float(account.balance)
        pip_value = get_pip_value(symbol, account_currency)
        lot_size = (balance * (risk / 100)) / (pip_value * sl)
        lot_size = round(lot_size, 2)
        return lot_size

        for instance, if I took the same example from my first comment:
        When i call calc_position_size, I set symbol to “AUDUSD”, account_currency to “EUR”, risk to 1 and sl to 50.

        1. Avatar

          I think i have understand why i had this problem. It was because c.converter is not very precise (and not negligible at all).

          In my function I have the last_row_lot_all_pair argument which is the information of the last 1 minute candle of the needed pair, so we have a lot of precision with this. I post my function below if you want to see, but now i have the exact same result than myfxbook.

          def calc_position_size(symbol : str, account_currency : str, risk : float, sl : int, last_row_lot_all_pair: dict) -> float:
          ACCOUNT = mt5.account_info()
          BALANCE = ACCOUNT.balance
          CURRENCY_2 = symbol[3:6]
          SYMBOL_TO_CONVERT = account_currency + CURRENCY_2
          close_candle_symbol_to_convert = float(last_row_lot_all_pair[SYMBOL_TO_CONVERT][“close”])
          if CURRENCY_2 == “JPY” :
          JPY_CONVERTER_PIPS = 100
          close_candle_symbol_to_convert = close_candle_symbol_to_convert/JPY_CONVERTER_PIPS
          SL_PIPS = sl/10
          PERCENTAGE_CONVERTER = 0.01
          RISK_PERCENTAGE = risk*PERCENTAGE_CONVERTER
          PIP_VALUE = ((BALANCE*RISK_PERCENTAGE)/SL_PIPS)
          STANDARD_LOT = 1
          PRICE_STANDART_LOT = 10
          MINI_LOT = 0.1
          PRICE_MINI_LOT = 1
          MICRO_LOT = 0.01
          PRICE_MICRO_LOT = 0.1
          if PIP_VALUE < PRICE_MINI_LOT :
          lot_size = (PIP_VALUE/(PRICE_MICRO_LOT/close_candle_symbol_to_convert))*MICRO_LOT
          elif PIP_VALUE < PRICE_STANDART_LOT :
          lot_size = (PIP_VALUE/(PRICE_MINI_LOT/close_candle_symbol_to_convert))*MINI_LOT
          else :
          lot_size = (PIP_VALUE/(PRICE_STANDART_LOT/close_candle_symbol_to_convert))*STANDARD_LOT
          lot_size = round(lot_size,2)
          return lot_size

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