Skip to main content

A Python-based MetaTrader strategy tester for the MetaTrader5 module

Project description

What is StrategyTester5?

The Full documentation is found here: strategytester5.com

StrategyTester5 (ST5) is a Python framework for building, testing, and optimizing algorithmic trading strategies using the MetaTrader 5 platform.

It extends the native MetaTrader 5 Python API by adding high-performance backtesting, simulation, and data handling capabilities that are not available out of the box.

mt5config

Why StrategyTester5?

The official MetaTrader5 Python API provides access to market data and trading operations — but it lacks a built-in way to efficiently backtest and simulate trading strategies.

StrategyTester5 fills this gap by providing:

  • ⚡ Fast historical data streaming (ticks & bars)
  • 🧠 MetaTrader5 trade simulation engine
  • 🔄 Multi-symbol backtesting support
  • 📊 Strategy testing workflows similar to MT5 Strategy Tester
  • 🧩 Seamless integration with the native MetaTrader5 API

Instead of building your own testing infrastructure from scratch, ST5 gives you a complete environment to develop and validate trading systems in Python.

Built for developers who want full control over their trading logic without leaving the MetaTrader 5 ecosystem.

How it Works

It works by mimicking a similar trading environment to that of the MetaTrader5 terminal, it then simulates that trading environment against actual ticks and bars history from the terminal.

🚀 Free vs Premium

Feature Free Premium
High-precision backtesting
Backtesting speed Fast ⚡ Ultra-fast
Multi-symbol & multi-timeframe strategies
Visual mode (MetaTrader5 simulation)
Strategy optimization
Advanced logging & debugging
Priority support

Get your premium copy today!

Quick Start | Build & Test your First Trading Robot

Every trading robot project needs atleast two files. The main Python file and a JSON configuration file.

essential files

These files can be named anything but it a good practice to use bot for the main trading robot and tester.json for the configuration file as it contains the so-called tester configurations.

Tester Configurations

{
    "tester": {
        "bot_name": "Simple Trading Robot",
        "symbols": ["USDJPY"],
        "timeframe": "H1",
        "start_date": "01.01.2026 00:00",
        "end_date": "27.03.2026 00:00",
        "modelling" : "1 minute OHLC",
        "deposit": 1000,
        "leverage": "1:100"
    }
}

These configurations resemble those needed to backtest a trading robot in MetaTrader5 GUI. mt5config

Nescessary Imports

Inside the main Python script (trading robot), you start by importing all necessary modules

import logging
import os
import sys

ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
sys.path.insert(0, ROOT)  # insert(0) so it wins over other paths

from strategytester5.tester import StrategyTester
import MetaTrader5 as mt5
from strategytester5.trade_classes.Trade import CTrade
import json

Importing JSON configurations (Optional)

Instead of importing tester configurations from a JSON file, you could have a dictionary with the right keys and values.

In this case, we have configurations from a JSON file in the same directory (folder) as the main script bot.py so, let's import those.

# Get path to the folder where this script lives
BASE_DIR = os.path.dirname(os.path.abspath(__file__))

try:
    with open(os.path.join(BASE_DIR, "tester.json"), 'r', encoding='utf-8') as file: # reading a JSON file
        # Deserialize the file data into a Python object
        tester_configs = json.load(file)
except Exception as e:
    raise RuntimeError(e)

Initializing MetaTrader5

Despite the strategy tester simulating the MetaTrader5 terminal, it still relies of the platform for crucial information from instruments (symbols) and a broker's account.

So, we have to initialize the MetaTrader5 terminal using it's native API as we'll need it later.

if not mt5.initialize():
    raise RuntimeError("Failed to initialize mt5.")

StrategyTester Initialization

tester = StrategyTester(tester_config=tester_configs["tester"], mt5_instance=mt5, logging_level=logging.DEBUG)

We also initialize the class CTrade (a submodule for easy and effective ways to manage trades)

# ---------------------- variables/optional ----------------------------

symbol = "USDJPY" # it should be one among the symbols in symbols list from tester.json (config file/dictionary)
timeframe = "PERIOD_H1"
magic_number = 10012026
slippage = 100
sl = 700
tp = 500

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

m_trade = CTrade(terminal=tester.simulated_mt5, magic_number=magic_number, filling_type_symbol=symbol, deviation_points=slippage, logger=tester.logger)

Trading Strategy

def pos_exists(magic: int, type: int) -> bool:
    
    """Check if position exists"""

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

    return False

symbol_info = tester.simulated_mt5.symbol_info(symbol=symbol)

def on_tick():
    
    """The main function that gets called upon the receival of new tick(s)"""

    tick_info = tester.simulated_mt5.symbol_info_tick(symbol=symbol)
    if tick_info is None:
        return

    ask = tick_info.ask
    bid = tick_info.bid
    
    pts = symbol_info.point

    if not pos_exists(magic=magic_number, type=mt5.POSITION_TYPE_BUY):  # If a position of such kind doesn't exist
        m_trade.buy(volume=0.01, symbol=symbol, price=ask, sl=ask - sl * pts, tp=ask + tp * pts, comment="Tester buy")  # we open a buy position

    if not pos_exists(magic=magic_number, type=mt5.POSITION_TYPE_SELL):  # If a position of such kind doesn't exist
        m_trade.sell(volume=0.01, symbol=symbol, price=bid, sl=bid + sl * pts, tp=bid - tp * pts, comment="Tester sell")  # we open a sell position

Running the Backtest

All it takes is one function call.

tester.run(on_tick_function=on_tick) # very important!

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

strategytester5-2.0.3.tar.gz (75.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

strategytester5-2.0.3-py3-none-any.whl (84.3 kB view details)

Uploaded Python 3

File details

Details for the file strategytester5-2.0.3.tar.gz.

File metadata

  • Download URL: strategytester5-2.0.3.tar.gz
  • Upload date:
  • Size: 75.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for strategytester5-2.0.3.tar.gz
Algorithm Hash digest
SHA256 5e53a92ac0cb64dde5fc42428aa0350950f00ceef5e3229abc1e7c81cae1c755
MD5 b18ea523826496240857e4c3704449de
BLAKE2b-256 c3caa69b842c43cc74c224d667e330f653e67cc30a8a3480f7c065d9dc5c10aa

See more details on using hashes here.

File details

Details for the file strategytester5-2.0.3-py3-none-any.whl.

File metadata

File hashes

Hashes for strategytester5-2.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 dca40c3b1ec6d7bb0e3206349149463c875c4a45a7eaa0b4c3f47d1b28bdefc2
MD5 2920e3f9c824eed2623b79261f386111
BLAKE2b-256 5b68df28a66694fc85a98246014afee8b1ba9b80e693302d3c7ccd48440e41c6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page