Metadata-Version: 2.4
Name: strategytester5
Version: 1.6.2
Summary: A Python-based MetaTrader strategy tester for the MetaTrader5 module
Author-email: Omega Joctan Msigwa <omegajoctan@gmail.com>
License: MIT License
        
        Copyright (c) 2025 Omega Joctan
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
Project-URL: Homepage, https://github.com/MegaJoctan/StrategyTester5
Project-URL: Repository, https://github.com/MegaJoctan/StrategyTester5
Keywords: MetaTrader5,MetaTrader4,Strategytester,strategytesting,MT5,trading,forex,backtesting,algorithmic trading
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy
Requires-Dist: polars
Requires-Dist: matplotlib
Requires-Dist: seaborn
Requires-Dist: tqdm
Requires-Dist: numba
Requires-Dist: scipy
Provides-Extra: mt5
Requires-Dist: metatrader5; extra == "mt5"
Dynamic: license-file

### StrategyTester5

StrategyTester is a Python-based backtesting and strategy testing framework built specifically for the MetaTrader5 (MT5) Python API.


### Getting started

Ensure you have the MetaTrader 5 desktop application then proceeed to install the dependencies used in this project in your Python virtual environment

**On Windows:**
```bash
pip install strategytester5["mt5"]
```

**On Linux/MacOS:**

```bash
pip install strategytester5
# optional:
pip install "strategytester5[mt5]"
```
> Note: The second command with "[mt5]" installs the MetaTrader5 Python package which is primarily distributed for Windows; Doing so on Linux/macOS might throw critical pip installation errors. (Your core package can still work without the MT5 bindings if you have offline history, broker data for the tester-mode.) 

### Making your First MetaTrader5 Trading Robot in The Strategy Tester

**Step 1: Initialize the desired MetaTrader 5 terminal right after importing its module, alongside other useful Python modules for this project.**

```python
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, MetaTrader5 as mt5
from strategytester5.trade_classes.Trade import CTrade
import json


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

See examples the examples [https://github.com/MegaJoctan/StrategyTester5/tree/main/examples](https://github.com/MegaJoctan/StrategyTester5/tree/main/examples)

**Step 2: Load configurations from a JSON file. *In this case configs/tester.json file*.**

```python

# 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)
```

**Step 3: Initialize the Tester class, giving it configurations and an initialized MetaTrader 5 instance.**

```python
tester = StrategyTester(tester_config=tester_configs["tester"],
                        mt5_instance=mt5,
                        logging_level=logging.DEBUG,
                        broker_data_dir="ICMarketsSC-Demo") 
```

**Optionally, instantiate the CTrade class to make life much easier.**

```python
m_trade = CTrade(simulator=tester, magic_number=magic_number, filling_type_symbol=symbol, deviation_points=slippage)
```

**Step 4: Write some trading strategy**

```python
# ---------------------- inputs ----------------------------

symbol = "EURUSD"
timeframe = "PERIOD_H1"
magic_number = 10012026
slippage = 100
sl = 1000
tp = 100

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

symbol_info = tester.symbol_info(symbol=symbol) # symbol information

def pos_exists(magic: int, type: int) -> bool:

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

def on_tick():
    
    tick_info = tester.symbol_info_tick(symbol=symbol)
    
    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.1, 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.1, symbol=symbol, price=bid, sl=bid+sl*pts, tp=bid-tp*pts, comment="Tester sell") # we open a sell position
```

**Step 5: Call the main trading function into action on every tick, similarly to the [OnTick function in MQL5](https://www.mql5.com/en/docs/event_handlers/ontick)**

```python
tester.OnTick(ontick_func=on_tick) # very important!
```
**Step 6: Running your Systems**

On Windows you have two options:
**A: Running your robot(s) in a simulated environment using information stored in custom broker's directory and a specified history folder 'history_dir''**
```bash
python example_bot.py
```

**B: Running your robot(s) in a simulated environment but relying on the MetaTrader5-API for all information and history**
```bash
python example_bot.py --mt5
```
> Note: To run a script/robot in MetaTrader 5 mode, the platform must be installed and initialized before assigned to the StrategyTester class*

**More information about the project**

- [https://www.mql5.com/en/articles/18971](https://www.mql5.com/en/articles/18971)
- [https://www.mql5.com/en/articles/20455](https://www.mql5.com/en/articles/20455)
- [https://www.mql5.com/en/articles/20782](https://www.mql5.com/en/articles/20782)
- [https://www.mql5.com/en/articles/20917](https://www.mql5.com/en/articles/20917)
