### Install StrategyTester5 from local clone Source: https://github.com/megajoctan/strategytester5/blob/main/docs/installation.md Install the StrategyTester5 package in editable mode after cloning the repository from GitHub. ```bash pip install -e strategytester5 ``` -------------------------------- ### Install StrategyTester5 with pip Source: https://github.com/megajoctan/strategytester5/blob/main/docs/installation.md Use this command to install the StrategyTester5 package from the Python Package Index. ```bash pip install strategytester5 ``` -------------------------------- ### Install or Update StrategyTester5 with pip Source: https://github.com/megajoctan/strategytester5/blob/main/docs/installation.md Use this command to install the latest version of StrategyTester5 or update an existing installation. ```bash pip install -U strategytester5 ``` -------------------------------- ### Initialize StrategyTester and Helpers Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/rsi_strategy.md Sets up the StrategyTester object with the configuration and MetaTrader5 instance, and extracts the simulated MT5 object and logger for convenience. ```python tester = StrategyTester(tester_config=tester_config, mt5_instance=mt5, logging_level=logging.DEBUG) sim_mt5 = tester.simulated_mt5 # extract the simulated metatrader5 from the StrategyTester object and assign it to a simple variable logger = tester.logger # extract a logger ``` -------------------------------- ### Complete StrategyTester5 Script with SMA Indicator (Python) Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/working_with_indicators.md This full script initializes `MetaTrader5` and `StrategyTester5`, configures the bot, defines the `on_tick` function to calculate SMA, and runs the backtest. It requires `logging`, `MetaTrader5`, `pandas`, and `ta` libraries. ```python import logging from strategytester5.tester import StrategyTester import MetaTrader5 as mt5 import pandas as pd from ta.trend import sma_indicator if not mt5.initialize(): raise RuntimeError("Failed to initialize mt5.") tester_config = { "bot_name": "Working With Indicators", "symbols": ["USDJPY"], "timeframe": "H1", "start_date": "01.01.2026 00:00", "end_date": "27.03.2026 00:00", "modelling" : "Open price only", "deposit": 1000, "leverage": "1:100" } tester = StrategyTester(tester_config=tester_config, mt5_instance=mt5, logging_level=logging.DEBUG) sim_mt5 = tester.simulated_mt5 # extract the simulated metatrader5 from the StrategyTester object and assign it to a simple variable logger = tester.logger # ---------------------- inputs ---------------------------- symbol = tester_config["symbols"][0] # it should be one among the symbols in symbols list from tester.json (config file/dictionary) timeframe = sim_mt5.TIMEFRAME_H1 # This should be an integer so you should convert timeframe in string into integer # --------------------------------------------------------- def on_tick(): indicator_window = 20 rates = sim_mt5.copy_rates_from_pos(symbol=symbol, timeframe=timeframe, start_pos=0, count=indicator_window) if rates is None or len(rates) < indicator_window: # if no information was found, or less than expected rates were returned return # prevent further calculations rates_df = pd.DataFrame(data=rates) # print(rates_df.head(-10)) sma_indicator_values = sma_indicator(rates_df["close"], window=indicator_window) logger.info(f"Current sma({indicator_window}) : {sma_indicator_values.iloc[-1]}") # print the last calculated value in the array tester.run(on_tick_function=on_tick) # very important! ``` -------------------------------- ### Initializing StrategyTester and CTrade Source: https://github.com/megajoctan/strategytester5/blob/main/docs/quickstart.md Initializes the StrategyTester with configurations and the MetaTrader5 instance. Also initializes the CTrade class for managing trades. ```python tester = StrategyTester(tester_config=tester_configs["tester"], mt5_instance=mt5, logging_level=logging.DEBUG) # ---------------------- 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) ``` -------------------------------- ### Define Trading Parameters and Initialize CTrade Source: https://github.com/megajoctan/strategytester5/blob/main/README.md Sets up essential trading parameters like symbol, timeframe, magic number, slippage, stop loss, and take profit, then initializes the CTrade object for executing trades within the simulated environment. ```python 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) ``` -------------------------------- ### Initialize MetaTrader5 Terminal Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/index.md Before using StrategyTester5, initialize the MetaTrader5 terminal using its native API. This provides essential platform and broker details to the simulated environment. ```python from metatrader5.api import MetaTrader5 # Initialize MetaTrader5 terminal mt5 = MetaTrader5() mt5.initialize() ``` -------------------------------- ### Initialize StrategyTester and Simulated MT5 Instance Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/working_with_indicators.md Initialize the StrategyTester object and extract the simulated MetaTrader5 instance for use in your strategy. This provides a convenient way to access MT5 functionalities. ```python tester = StrategyTester(tester_config=tester_config, mt5_instance=mt5, logging_level=logging.DEBUG) sim_mt5 = tester.simulated_mt5 # extract the simulated metatrader5 from the StrategyTester object and assign it to a simple variable logger = tester.logger # obtain the logger ``` -------------------------------- ### Importing JSON Configurations Source: https://github.com/megajoctan/strategytester5/blob/main/docs/quickstart.md Loads tester configurations from a 'tester.json' file located in the same directory as the script. Handles potential file reading errors. ```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) ``` -------------------------------- ### StrategyTester5 Initialization Configuration Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/index.md The StrategyTester class requires a dictionary for tester configurations. It's recommended to load these configurations from a JSON file for easier management. ```python from strategytester5 import StrategyTester import logging # Example tester configuration dictionary # It's recommended to load this from a JSON file tester_config = { "bot_name": "MyTradingBot", "symbols": ["EURUSD", "GBPUSD"], "timeframe": "1h", "start_date": "2023-01-01", "end_date": "2023-12-31", "modelling": "1 minute OHLC", "deposit": 10000, "leverage": 100, "visual_mode": False } # Initialize StrategyTester # mt5_instance should be an initialized MetaTrader5 object tester = StrategyTester(tester_config=tester_config, mt5_instance=mt5, logging_level=logging.DEBUG) ``` -------------------------------- ### Configure Strategy Tester Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/rsi_strategy.md Defines the parameters for the backtesting simulation, including bot name, symbols, timeframe, date range, modeling mode, deposit, and leverage. ```python tester_config = { "bot_name": "RSI Strategy Bot", "symbols": ["EURUSD"], "timeframe": "H1", "start_date": "01.01.2026 00:00", "end_date": "27.03.2026 00:00", "modelling" : "Open price only", "deposit": 1000, "leverage": "1:100" } ``` -------------------------------- ### Initialize Trade Execution Helper Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/rsi_strategy.md Creates an instance of the CTrade helper class for managing trade operations, specifying the simulated MT5 terminal, magic number, symbol, deviation, and logger. ```python symbol = tester_config["symbols"][0] # should be one among the symbols in symbols list from tester.json (config file/dictionary) timeframe = sim_mt5.TIMEFRAME_H1 # This should be an integer so you should convert timeframe in string into integer # --------------------------------------------------------- MAGIC_NUMBER = 1001 m_trade = CTrade(terminal=sim_mt5, magic_number=MAGIC_NUMBER, filling_type_symbol=symbol, deviation_points=100, logger=tester.logger) ``` -------------------------------- ### Initializing MetaTrader5 Terminal Source: https://github.com/megajoctan/strategytester5/blob/main/docs/quickstart.md Initializes the MetaTrader5 terminal using its native API. This is required for accessing instrument and broker account information. ```python if not mt5.initialize(): raise RuntimeError("Failed to initialize mt5.") ``` -------------------------------- ### Running the Backtest Source: https://github.com/megajoctan/strategytester5/blob/main/docs/quickstart.md Initiates the backtesting process by calling the run method with the defined on_tick function. ```python tester.run(on_tick_function=on_tick) # very important! ``` -------------------------------- ### Import Necessary Modules Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/rsi_strategy.md Imports essential libraries for strategy testing, trade execution, MetaTrader5 interaction, data manipulation, and technical indicators. ```python import logging from strategytester5.tester import StrategyTester from strategytester5.trade_classes.Trade import CTrade import MetaTrader5 as mt5 import pandas as pd from ta.momentum import rsi ``` -------------------------------- ### Tester Configurations Source: https://github.com/megajoctan/strategytester5/blob/main/docs/quickstart.md Defines the backtesting parameters for a trading robot, similar to MetaTrader5 GUI configurations. ```json { "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" } } ``` -------------------------------- ### Copy Rates from Simulator Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/working_with_indicators.md Copy historical rate data from the simulated MetaTrader5 instance for a specified symbol and timeframe. This data is essential for calculating indicators. ```python def on_tick(): indicator_window = 20 rates = sim_mt5.copy_rates_from_pos(symbol=symbol, timeframe=timeframe, start_pos=0, count=indicator_window) if rates is None or len(rates) < indicator_window: # if no information was found, or less than expected rates were returned return # prevent further calculations ``` -------------------------------- ### Run Backtest with RSI Strategy Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/rsi_strategy.md Initiates a backtest using the specified on_tick function. Ensure the on_tick function is defined elsewhere in your strategy. ```python tester.run(on_tick_function=on_tick) ``` -------------------------------- ### Clone StrategyTester5 from GitHub Source: https://github.com/megajoctan/strategytester5/blob/main/docs/installation.md Clone the StrategyTester5 repository directly from GitHub using the provided Git URL. ```bash git clone git@github.com:MegaJoctan/StrategyTester5.git strategytester5 ``` -------------------------------- ### Time-Aware Logging with Simulated MetaTrader5 Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/logging_debugging.md Log messages with awareness of the simulated trading time by using the current_time() method from the simulated MetaTrader5 object. This is useful for debugging historical data. ```python def on_tick(): #... #... indicator_value = 100 logger.info(f"time_sec: {sim_mt5.current_time()} Current indicator value : {indicator_value}") ``` -------------------------------- ### Console Output of SMA Calculation (Bash) Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/working_with_indicators.md This output demonstrates the logged SMA values and strategy tester progress during a backtest, showing how the `logger.info` call in the `on_tick` function appears in the console. ```bash StrategyTester Progress: 0%| | 0/1441 [00:00 Current sma(20) : 156.8057 2026-01-02 01:00:00 | INFO | Simple Trading Robot | [bot.py:45 - on_tick() ] => Current sma(20) : 156.81225 2026-01-02 02:00:00 | INFO | Simple Trading Robot | [bot.py:45 - on_tick() ] => Current sma(20) : 156.8277 2026-01-02 03:00:00 | INFO | Simple Trading Robot | [bot.py:45 - on_tick() ] => Current sma(20) : 156.83785 2026-01-02 04:00:00 | INFO | Simple Trading Robot | [bot.py:45 - on_tick() ] => Current sma(20) : 156.83785 2026-01-05 00:00:00 | INFO | Simple Trading Robot | [bot.py:45 - on_tick() ] => Current sma(20) : 156.833 2026-01-05 01:00:00 | INFO | Simple Trading Robot | [bot.py:45 - on_tick() ] => Current sma(20) : 156.7946 2026-01-05 02:00:00 | INFO | Simple Trading Robot | [bot.py:45 - on_tick() ] => Current sma(20) : 156.754 2026-01-05 03:00:00 | INFO | Simple Trading Robot | [bot.py:45 - on_tick() ] => Current sma(20) : 156.7232 2026-01-05 04:00:00 | INFO | Simple Trading Robot | [bot.py:45 - on_tick() ] => Current sma(20) : 156.69075 StrategyTester Progress: 2%|▏ | 33/1441 [00:00<00:04, 326.34bar/s]2026-01-05 05:00:00 | INFO | Simple Trading Robot | [bot.py:45 - on_tick() ] => Current sma(20) : 156.6599 ``` -------------------------------- ### Import Pandas for Data Handling Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/working_with_indicators.md Import the pandas library for data manipulation and analysis. ```python import pandas as pd ``` -------------------------------- ### Import SMA Indicator from TA Framework Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/working_with_indicators.md Import the Simple Moving Average (SMA) indicator from the 'trend' submodule of the ta library. ```python from ta.trend import sma_indicator ``` -------------------------------- ### Calculate SMA in `on_tick` function (Python) Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/working_with_indicators.md This snippet shows how to fetch historical rates, validate the data, calculate a Simple Moving Average (SMA) using `pandas` and `ta.trend`, and log the latest indicator value within the `on_tick` function of a `StrategyTester5` bot. ```python def on_tick(): indicator_window = 20 rates = sim_mt5.copy_rates_from_pos(symbol=symbol, timeframe=timeframe, start_pos=0, count=indicator_window) if rates is None or len(rates) < indicator_window: # if no information was found, or less than expected rates were returned return # prevent further calculations rates_df = pd.DataFrame(data=rates) sma_indicator_values = sma_indicator(rates_df["close"], window=indicator_window) logger.info(f"Current sma({indicator_window}) : {sma_indicator_values.iloc[-1]}") # print the last calculated value in the array ``` -------------------------------- ### Implement a Basic Trading Strategy with on_tick Source: https://github.com/megajoctan/strategytester5/blob/main/README.md Defines a trading strategy that checks for existing positions and opens new buy or sell positions if none exist, triggered by new ticks. This snippet includes a helper function to check position existence. ```python 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.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 - sl * pts, comment="Tester sell") # we open a sell position ``` -------------------------------- ### Python run Method Signature Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/index.md This is the signature for the run method. It accepts a function to be executed on each tick and returns TesterStats. ```python def run(self, on_tick_function: Any) -> stats.TesterStats: ``` -------------------------------- ### Check for Sufficient Rate Data Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/working_with_indicators.md Verify that enough historical rate data has been returned before proceeding with indicator calculations. This prevents errors caused by insufficient data, especially during the early stages of a backtest. ```python if rates is None or len(rates) < indicator_window: # if no information was found, or less than expected rates were returned return # prevent further calculations ``` -------------------------------- ### Extract Logger from StrategyTester Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/index.md Instead of using the built-in print function, use the logger extracted from the StrategyTester. This logger provides detailed logs aware of the simulated time. ```python # Extract the logger logger = tester.logger # Use the logger for output logger.info("This is an informational message.") logger.debug("This is a debug message.") ``` -------------------------------- ### Extracting Logger from StrategyTester Instance Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/logging_debugging.md Instantiate StrategyTester and then extract the logger object for custom logging within your scripts. This allows for flexible log management. ```python tester = StrategyTester(tester_config=tester_config, mt5_instance=mt5, logging_level=logging.DEBUG) sim_mt5 = tester.simulated_mt5 # extract the simulated metatrader5 from the StrategyTester object and assign it to a simple variable logger = tester.logger # extract the logger ``` -------------------------------- ### Necessary Imports for Trading Robot Source: https://github.com/megajoctan/strategytester5/blob/main/docs/quickstart.md Imports essential modules for the trading robot script, including StrategyTester and MetaTrader5 API. ```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 import MetaTrader5 as mt5 from strategytester5.trade_classes.Trade import CTrade import json ``` -------------------------------- ### Extract Simulated MetaTrader5 Instance Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/index.md After instantiating StrategyTester, extract the simulated MetaTrader5 object. Replace all native API calls with this simulated instance in your existing logic. ```python # Extract the simulated MetaTrader5 instance sim_mt5 = tester.simulated_mt5 ``` -------------------------------- ### RSI Strategy Logic Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/rsi_strategy.md Implements the RSI trading logic: opens long trades on oversold signals and short trades on overbought signals, while managing existing opposite positions. ```python def on_tick(): indicator_window = 14 rates = sim_mt5.copy_rates_from_pos(symbol=symbol, timeframe=timeframe, start_pos=0, count=indicator_window) if rates is None or len(rates) < indicator_window: # if no information was found, or less than expected rates were returned return # prevent further calculations rates_df = pd.DataFrame(data=rates) rsi_value = rsi(close=rates_df["close"], window=indicator_window).iloc[-1] # rsi strategy rsi_oversold = 30.0 rsi_overbought = 70.0 symbol_info = sim_mt5.symbol_info(symbol=symbol) lot_size = symbol_info.volume_min if rsi_value < rsi_oversold: # long signal if not pos_exists(magic=MAGIC_NUMBER, pos_type=sim_mt5.POSITION_TYPE_BUY): m_trade.buy(volume=lot_size, symbol=symbol, price=symbol_info.ask) close_pos_by_type(magic=MAGIC_NUMBER, pos_type=sim_mt5.POSITION_TYPE_SELL) if rsi_value > rsi_overbought: # short signal if not pos_exists(magic=MAGIC_NUMBER, pos_type=sim_mt5.POSITION_TYPE_SELL): m_trade.sell(volume=lot_size, symbol=symbol, price=symbol_info.bid) close_pos_by_type(magic=MAGIC_NUMBER, pos_type=sim_mt5.POSITION_TYPE_BUY) ``` -------------------------------- ### Trading Strategy: On Tick Function Source: https://github.com/megajoctan/strategytester5/blob/main/docs/quickstart.md The main trading logic executed on each new tick. It checks for existing positions and opens buy or sell orders if none are found. ```python 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 ``` -------------------------------- ### Close Position by Type Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/rsi_strategy.md Closes any open positions that match the provided magic number and position type. ```python def close_pos_by_type(magic: int, pos_type: int): """Close positions by type""" positions_found = sim_mt5.positions_get() for position in positions_found: if position.type == pos_type and position.magic == magic: m_trade.position_close(position.ticket) ``` -------------------------------- ### Trading Strategy: Position Existence Check Source: https://github.com/megajoctan/strategytester5/blob/main/docs/quickstart.md Defines a function to check if a trading position with a specific magic number and type already exists. ```python 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 ``` -------------------------------- ### Logging Indicator Value with External Logger Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/logging_debugging.md Use the extracted logger object to log information, such as indicator values, during the on_tick event. Logs are stored in a 'Logs' subfolder. ```python def on_tick(): #... #... indicator_value = 100 logger.info(f"Current indicator value : {indicator_value}") ``` -------------------------------- ### Check for Existing Position Source: https://github.com/megajoctan/strategytester5/blob/main/docs/documentation/rsi_strategy.md A helper function to determine if a position of a specific type and magic number already exists. ```python def pos_exists(magic: int, pos_type: int) -> bool: """Check if position exists""" positions_found = sim_mt5.positions_get() for position in positions_found: if position.type == pos_type and position.magic == magic: return True return False ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.