Skip to content

Quick Start | Build & Test your First Trading Robot

All you need is to add three (3) Lines of code to your existing Python project.

01: Import the VirtualMetaTrader5 class

from strategytester5.MetaTrader5.api import VirtualMetaTrader5

02: Assign the parent (MetaTrader5) initialized instance to the VirtulMetaTrader5 object

if not mt5.initialize():
    raise RuntimeError(f"Failed to initialize mt5. Error = {mt5.last_error()}")

virtual_mt5 = VirtualMetaTrader5(parent_mt5=mt5)

Optional : Choosing the right MT5 instance

Since the VirtualMetaTrader5 object has similar methods and constants to MetaTrader5 API.

To keep all the code in a single file, introduce if statements to check for passed arguments from the script.

Rule of Thumb

For instance, if a user has passed --backtesting when calling the main script the script should use a simulated MetaTrader5 rather than the actual one.

script_argument = sys.argv[1:]
if "--backtesting" in script_argument:
    mt5 = VirtualMetaTrader5(parent_mt5=parent_mt5) # Assign parent MetaTrader5 to the virtual MetaTrader5 class object
else:
    mt5 = parent_mt5

Always use the virtual MetaTrader5 object for backtesting and visualization purposes and stick to the original one for live trading. That's all

03: Backtesting your Python Trading Strategies

To Backtest your trading systems call the function run_backtesting.

if "--backtesting" in script_argument:

    stats = run_backtesting(
        main_function=main,
        tester_config=tester_config,
        virtual_mt5=mt5,
        logging_level=logging.DEBUG
    )

else:
    # run the script on the market (realtime)
    while True:
        main()

Tester Configurations

The so-called tester_config is supposed to be a dictionary with a set of key, and value pairs that resemble MetaTrader5's strategy tester section.

mt5config

example tester config(s)
tester_config = {
        "bot_name": "RSI Strategy Bot",
        "symbols": ["EURUSD"],
        "timeframe": "H1",
        "start_date": "01.01.2026",
        "end_date": "01.06.2026",
        "modelling" : "open price only",
        "deposit": 1000,
        "leverage": "1:100"
}
Learn More.

Rule of Thumb

Storing tester configuration in a JSON file is the best way forward. It helps adjust the values without changing the original code :)

A complete Trading robot Example.

simple trading bot\bot.py
import logging
from strategytester5.MetaTrader5.api import VirtualMetaTrader5
from strategytester5.tester import run_backtesting
from strategytester5.trade_classes.Trade import CTrade
import MetaTrader5 as parent_mt5
import sys

if not parent_mt5.initialize():
    raise RuntimeError(f"Failed to initialize mt5. Error = {parent_mt5.last_error()}")

script_argument = sys.argv[1:]
if "--backtesting" in script_argument:
    mt5 = VirtualMetaTrader5(parent_mt5=parent_mt5) # Assign parent MetaTrader5 to the virtual MetaTrader5 class object
else:
    mt5 = parent_mt5

# ---------------------- inputs/global variables ----------------------------

symbol = "EURUSD"
timeframe = mt5.TIMEFRAME_H1 # This should be an integer so you should convert timeframe in string into integer
MAGIC_NUMBER = 1001

# ---------------------------------------------------------

m_trade = CTrade(terminal=mt5, symbol=symbol, magic_number=MAGIC_NUMBER, deviation_points=100)

def pos_exists(magic: int, pos_type: int) -> bool:
    """Checks if position exists"""

    positions_found = mt5.positions_get()
    if positions_found:
        for position in positions_found:
            if position.type == pos_type and position.magic == magic:
                return True

    return False


def main(stop_loss: float=500,
         take_profit: float=700
         ):

    symbol_info = mt5.symbol_info(symbol) # Symbols information
    if symbol_info is None:
        return

    pts = symbol_info.point

    lot_size = symbol_info.volume_min # use the minimum volume (lot size)

    ticks = mt5.symbol_info_tick(symbol)

    if ticks is None:
        return

    ask = ticks.ask
    bid = ticks.bid

    # print(f"ask: {ask}, bid: {bid}, pts: {pts}")

    if not pos_exists(magic=MAGIC_NUMBER, pos_type=mt5.POSITION_TYPE_BUY): # if a buy position doesn't exist
        m_trade.buy(volume=lot_size,
                    price=ask,
                    sl=ask-stop_loss * pts,
                    tp=ask+take_profit * pts,
                    comment="Simple bot Buy Trade"
                    ) # open a new buy position (trade)

    if not pos_exists(magic=MAGIC_NUMBER, pos_type=mt5.POSITION_TYPE_SELL): # if a sell position doesn't exist
        m_trade.sell(volume=lot_size,
                     price=bid,
                     sl=bid + stop_loss * pts,
                     tp=bid - take_profit * pts,
                     comment="Simple bot Sell Trade"
                     ) # open a new sell position (trade)

tester_config = {
        "bot_name": "RSI Strategy Bot",
        "symbols": ["EURUSD"],
        "timeframe": timeframe,
        "start_date": "01.01.2026",
        "end_date": "01.06.2026",
        "modelling" : "1 minute ohlc",
        "deposit": 1000,
        "leverage": "1:100"
}

if "--backtesting" in script_argument:

    stats = run_backtesting(
        main_function=main,
        tester_config=tester_config,
        virtual_mt5=mt5,
        logging_level=logging.DEBUG
    )

else:
    # run the script on the market (realtime)
    while True:
        main()

And that’s it: Calling a script with — backtesting will start backtesting (simulation) in the web browser.

python bot.py --backtesting
Results:

Results

To backtest your strategies in MetaTrader5’s StrategyTester App, add visual_mode to tester configurations.

tester_config = {
        "bot_name": "RSI Strategy Bot",
        "symbols": ["EURUSD"],
        "timeframe": timeframe,
        "start_date": "01.01.2026",
        "end_date": "01.06.2026",
        "modelling" : "1 minute ohlc",
        "deposit": 1000,
        "leverage": "1:100",
        "visual_mode": True
}

This time, when you run the script using the same command, backtesting will take place inside the MetaTrader5 App (terminal)🤯

st5-visualization

More examples and Python files used in this article are found here: GitHub repo.