P
PipsGrowth
Automation

MT5 Optimization CLI Automation: Run Backtests from Command Line

Complete guide to automating MT5 Strategy Tester optimization from the command line. Learn config ini files, batch scripts, parallel testing, and CI/CD integration for EA optimization.

PG
Pips Growth Team
2026-07-10
12 min

MT5 Optimization CLI Automation: Run Backtests from Command Line

Manually running MT5 Strategy Tester for each EA, symbol, and parameter set is slow and tedious. What if you could launch 50 optimizations overnight, parse the results, and pick the best strategy — all from a single script?

MetaTrader 5 supports command-line execution via config files. This guide shows you exactly how to automate backtesting and optimization using .ini files, batch scripts, Python, and AI-assisted IDE workflows.

Prerequisites

Before you start, make sure you have:

  • MetaTrader 5 terminal installed and logged into a demo or live account
  • At least one compiled EA (.ex5 file) in your MQL5\Experts folder
  • MetaEditor installed (comes with MT5) — needed for CLI compilation
  • Windows (MT5 CLI automation is Windows-only)
  • Python 3.10+ with MetaTrader5, pandas packages (for results parsing)
  • Basic familiarity with MQL5 and the Strategy Tester (see our MT5 EA Backtesting Tutorial)

Finding Your MT5 Paths

You'll need these paths for automation. The terminal data folder varies per installation:

:: Find your MT5 installation path
where terminal64.exe

:: Or check the default location
dir "C:\Program Files\MetaTrader 5\terminal64.exe"

:: Find your data directory (where EAs and Files live)
:: It's usually: C:\Users\<you>\AppData\Roaming\MetaQuotes\Terminal\<ID>\
:: The <ID> is a long hash string

dir /b "%APPDATA%\MetaQuotes\Terminal\"

The MQL5\Experts subfolder is where your compiled EAs live. The MQL5\Files subfolder is where ONNX models and data files go.

How MT5 CLI Backtesting Works

The MT5 terminal executable (terminal64.exe) accepts a /config: parameter pointing to an .ini file with all test settings:

"C:\Program Files\MetaTrader 5\terminal64.exe" /config:C:\MT5\backtest_config.ini

When launched this way, MT5:

  1. Starts in headless mode (no GUI interaction needed)
  2. Loads the EA and parameters from the config
  3. Runs the backtest or optimization
  4. Saves the report to disk
  5. Shuts down automatically (if ShutdownTerminal=1)

The Config File (.ini) — Complete Reference

Create a text file with the following sections:

[Tester]
;--- EA to test (path relative to MQL5\Experts folder)
Expert=MyEAs\TrendFollower

;--- EA parameters file (located in MQL5\Profiles\Tester)
ExpertParameters=trend_follower.set

;--- Symbol and timeframe
Symbol=EURUSD
Period=H1

;--- Account settings
Login=123456
Deposit=10000
Currency=USD
Leverage=1:100

;--- Tick generation model
; 0 = Every tick (slowest, most accurate)
; 1 = 1 minute OHLC (fast, good for most EAs)
; 2 = Open price only (fastest, for bar-close strategies)
; 3 = Math calculations (for indicators only)
; 4 = Every tick based on real ticks (most realistic)
Model=4

;--- Execution mode
; 0 = Instant execution
; -1 = Random delay
; >0 = Custom delay in milliseconds (max 600000)
ExecutionMode=0

;--- Optimization mode
; 0 = Disabled (single backtest)
; 1 = Slow complete algorithm (tests every combination)
; 2 = Fast genetic based algorithm (recommended for large parameter spaces)
; 3 = All symbols selected in Market Watch
Optimization=2

;--- Optimization criterion (what to maximize)
; 0 = Maximum balance
; 1 = Balance × profitability
; 2 = Balance × expected payoff
; 3 = (100% - Drawdown) × Balance
; 4 = Balance × recovery factor
; 5 = Balance × Sharpe Ratio
; 6 = Custom criterion from OnTester()
; 7 = Complex criterion (built-in)
OptimizationCriterion=5

;--- Date range
FromDate=2023.01.01
ToDate=2025.01.01

;--- Forward testing
; 0 = Off
; 1 = 1/2 of testing period
; 2 = 1/3 of testing period
; 3 = 1/4 of testing period
; 4 = Custom date (use ForwardDate)
ForwardMode=2

;--- Report output
Report=my_ea_optimization
ReplaceReport=1

;--- Auto-shutdown after completion
ShutdownTerminal=1

;--- Agent settings
UseLocal=1
UseRemote=0
UseCloud=0

;--- Visual mode (0 = off, 1 = on)
Visual=0

;--- Port for parallel testing agents
Port=2000

Compiling EAs from Command Line

Before you can backtest an EA, it must be compiled from .mq5 to .ex5. You can automate this too:

"C:\Program Files\MetaTrader 5\MetaEditor64.exe" /compile:"C:\Users\you\AppData\Roaming\MetaQuotes\Terminal\ID\MQL5\Experts\MyEAs\TrendFollower.mq5"

Compile with Log Output

"C:\Program Files\MetaTrader 5\MetaEditor64.exe" /compile:"C:\path\to\MyEA.mq5" /log

The log file (.log) is created next to the source file and contains compilation errors and warnings.

Batch Compile All EAs in a Folder

@echo off
set METAEDITOR="C:\Program Files\MetaTrader 5\MetaEditor64.exe"
set EA_DIR=C:\Users\you\AppData\Roaming\MetaQuotes\Terminal\ID\MQL5\Experts\MyEAs

for %%f in (%EA_DIR%\*.mq5) do (
    echo Compiling %%~nxf ...
    %METAEDITOR% /compile:"%%f" /log
)
echo All EAs compiled.

Python Wrapper for Compilation

import subprocess
import os

def compile_ea(mq5_path, metaeditor_path=r"C:\Program Files\MetaTrader 5\MetaEditor64.exe"):
    """Compile a .mq5 file to .ex5 using MetaEditor CLI."""
    result = subprocess.run(
        [metaeditor_path, f"/compile:{mq5_path}", "/log"],
        capture_output=True, timeout=60
    )
    
    # Check log for errors
    log_path = mq5_path.replace('.mq5', '.log')
    if os.path.exists(log_path):
        with open(log_path, 'r') as f:
            log_content = f.read()
            if 'error' in log_content.lower():
                print(f"Compilation errors in {mq5_path}:")
                print(log_content)
                return False
    
    ex5_path = mq5_path.replace('.mq5', '.ex5')
    return os.path.exists(ex5_path)

# Usage
success = compile_ea(r"C:\Users\you\AppData\Roaming\MetaQuotes\Terminal\ID\MQL5\Experts\MyEAs\TrendFollower.mq5")
print(f"Compilation {'succeeded' if success else 'failed'}")

EA Parameter (.set) Files

When running optimization, MT5 needs to know which EA inputs to optimize and their ranges. This is defined in .set files stored in MQL5\Profiles\Tester\.

Creating .set Files Manually

A .set file is a simple text file:

;--- TrendFollower.set
;--- Parameter | Start | Step | Stop
FastMA=10||10||50||Y
SlowMA=50||10||200||Y
StopLossPips=50||10||200||Y
TakeProfitPips=100||10||400||Y
RiskPercent=1.0||0.5||5.0||Y

Format: ParameterName=Start||Step||Stop||Optimize(Y/N)

  • Start — initial value for the optimization range
  • Step — increment between test values
  • Stop — end value for the optimization range
  • OptimizeY to include in optimization, N to keep fixed

Generating .set Files from Strategy Tester

  1. Open MT5 → View → Strategy Tester
  2. Select your EA
  3. Go to the Inputs tab
  4. Set the start/step/stop values for each parameter
  5. Right-click → Save → saves a .set file to MQL5\Profiles\Tester\

Generating .set Files with Python

def create_set_file(params, output_path):
    """Create an MT5 .set file for optimization.
    
    Args:
        params: dict of {name: (start, step, stop, optimize)}
        output_path: where to save the .set file
    """
    lines = []
    for name, (start, step, stop, optimize) in params.items():
        opt_flag = 'Y' if optimize else 'N'
        lines.append(f"{name}={start}||{step}||{stop}||{opt_flag}")
    
    with open(output_path, 'w') as f:
        f.write('\n'.join(lines))
    print(f"Set file created: {output_path}")

# Usage
params = {
    'FastMA': (10, 5, 50, True),
    'SlowMA': (50, 10, 200, True),
    'StopLossPips': (30, 10, 150, True),
    'TakeProfitPips': (60, 20, 300, True),
    'RiskPercent': (0.5, 0.5, 3.0, True),
    'MagicNumber': (123456, 0, 123456, False),  # Fixed, not optimized
}
create_set_file(params, r'C:\Users\you\AppData\Roaming\MetaQuotes\Terminal\ID\MQL5\Profiles\Tester\TrendFollower.set')

Batch File Automation

Single EA, Multiple Symbols

@echo off
set MT5="C:\Program Files\MetaTrader 5\terminal64.exe"
set CONFIG=D:\MT5\Configs\optimize_eurusd.ini

set SYMBOLS=EURUSD GBPUSD USDJPY AUDUSD USDCHF

for %%S in (%SYMBOLS%) do (
    echo Optimizing %%S ...
    powershell -Command "(Get-Content %CONFIG%) -replace 'Symbol=.*', 'Symbol=%%S' | Set-Content D:\MT5\Configs\temp_%%S.ini"
    %MT5% /config:D:\MT5\Configs\temp_%%S.ini
)
echo All optimizations complete.

Multiple EAs, Multiple Symbols, Multiple Timeframes

@echo off
set MT5="C:\Program Files\MetaTrader 5\terminal64.exe"
set CONFIG_DIR=D:\MT5\Configs
set REPORT_DIR=D:\MT5\Reports

set EAS=TrendFollower GridMaster ScalperPro
set SYMBOLS=EURUSD GBPUSD USDJPY
set TIMEFRAMES=M5 H1 H4

for %%E in (%EAS%) do (
    for %%S in (%SYMBOLS%) do (
        for %%T in (%TIMEFRAMES%) do (
            echo Testing %%E on %%S %%T ...
            powershell -Command "(Get-Content %CONFIG_DIR%\base.ini) -replace 'Expert=.*', 'Expert=MyEAs\%%E' -replace 'Symbol=.*', 'Symbol=%%S' -replace 'Period=.*', 'Period=%%T' -replace 'Report=.*', 'Report=%REPORT_DIR%\%%E_%%S_%%T' | Set-Content %CONFIG_DIR%\run_%%E_%%S_%%T.ini"
            %MT5% /config:%CONFIG_DIR%\run_%%E_%%S_%%T.ini
        )
    )
)
echo All tests complete. Reports saved to %REPORT_DIR%

Parallel Optimization with Multiple Ports

MT5 allows running multiple instances simultaneously by assigning different ports:

@echo off
set MT5="C:\Program Files\MetaTrader 5\terminal64.exe"

:: Launch 4 parallel optimizations
start "" %MT5% /config:D:\MT5\config_eurusd.ini /port:2000
start "" %MT5% /config:D:\MT5\config_gbpusd.ini /port:2001
start "" %MT5% /config:D:\MT5\config_usdjpy.ini /port:2002
start "" %MT5% /config:D:\MT5\config_audusd.ini /port:2003

echo 4 parallel optimizations launched.

Python Wrapper for Results Parsing

After optimization completes, parse the XML report with Python:

import xml.etree.ElementTree as ET
import pandas as pd
import glob
import os

def parse_optimization_report(xml_path):
    """Parse MT5 optimization XML report into a DataFrame."""
    tree = ET.parse(xml_path)
    root = tree.getroot()
    
    results = []
    for item in root.findall('.//Item'):
        result = {
            'pass': item.get('Pass'),
            'profit': float(item.findtext('Profit', 0)),
            'profit_factor': float(item.findtext('ProfitFactor', 0)),
            'drawdown': float(item.findtext('EquityDrawdown', 0)),
            'sharpe': float(item.findtext('SharpeRatio', 0)),
            'trades': int(item.findtext('TotalTrades', 0)),
            'win_rate': float(item.findtext('WinRate', 0)),
        }
        # Extract input parameters
        for param in item.findall('.//Input'):
            result[param.get('Name')] = float(param.text)
        results.append(result)
    
    return pd.DataFrame(results)

def find_best_params(report_dir):
    """Find best optimization result across all reports."""
    all_results = []
    for xml_file in glob.glob(os.path.join(report_dir, '*.xml')):
        df = parse_optimization_report(xml_file)
        df['source_file'] = os.path.basename(xml_file)
        all_results.append(df)
    
    combined = pd.concat(all_results, ignore_index=True)
    
    # Filter: profitable, >50 trades, drawdown < 20%
    filtered = combined[
        (combined['profit'] > 0) &
        (combined['trades'] > 50) &
        (combined['drawdown'] < 20)
    ]
    
    # Sort by Sharpe ratio
    best = filtered.sort_values('sharpe', ascending=False).head(10)
    return best

# Usage
best_params = find_best_params(r'D:\MT5\Reports')
print(best_params[['source_file', 'profit', 'sharpe', 'drawdown', 'trades']])
best_params.to_csv('best_optimization_results.csv', index=False)

Full Automation Pipeline

Here's a complete Python script that creates configs, runs optimizations, and parses results:

import subprocess
import os
import time
import xml.etree.ElementTree as ET
import pandas as pd

class MT5Optimizer:
    def __init__(self, terminal_path, experts_dir, report_dir):
        self.terminal = terminal_path
        self.experts_dir = experts_dir
        self.report_dir = report_dir
        os.makedirs(report_dir, exist_ok=True)
    
    def create_config(self, ea_name, symbol, timeframe, 
                      start_date, end_date, deposit=10000,
                      optimization=2, criterion=5, port=2000):
        """Generate MT5 optimization config file."""
        config_path = os.path.join(self.report_dir, f'config_{ea_name}_{symbol}_{timeframe}.ini')
        report_name = f'report_{ea_name}_{symbol}_{timeframe}'
        
        config = f"""[Tester]
Expert=MyEAs\\{ea_name}
Symbol={symbol}
Period={timeframe}
Deposit={deposit}
Currency=USD
Leverage=1:100
Model=4
Optimization={optimization}
OptimizationCriterion={criterion}
FromDate={start_date}
ToDate={end_date}
ForwardMode=2
Report={report_name}
ReplaceReport=1
ShutdownTerminal=1
UseLocal=1
UseRemote=0
UseCloud=0
Visual=0
Port={port}
"""
        with open(config_path, 'w') as f:
            f.write(config)
        return config_path, report_name
    
    def run_optimization(self, config_path, timeout=3600):
        """Run MT5 optimization and wait for completion."""
        cmd = f'"{self.terminal}" /config:{config_path}'
        process = subprocess.Popen(cmd, shell=True)
        process.wait(timeout=timeout)
        return process.returncode
    
    def batch_optimize(self, ea_name, symbols, timeframes, 
                       start_date, end_date):
        """Run optimization across multiple symbols and timeframes."""
        all_results = []
        port = 2000
        
        for symbol in symbols:
            for tf in timeframes:
                print(f"Optimizing {ea_name} on {symbol} {tf}...")
                
                config_path, report_name = self.create_config(
                    ea_name, symbol, tf, start_date, end_date, port=port
                )
                
                try:
                    self.run_optimization(config_path)
                except subprocess.TimeoutExpired:
                    print(f"  Timeout for {symbol} {tf}, skipping...")
                    continue
                
                # Parse results
                xml_path = os.path.join(self.report_dir, f'{report_name}.xml')
                if os.path.exists(xml_path):
                    df = self.parse_xml(xml_path)
                    df['symbol'] = symbol
                    df['timeframe'] = tf
                    all_results.append(df)
                    print(f"  Found {len(df)} optimization passes")
                
                port += 1
        
        if all_results:
            return pd.concat(all_results, ignore_index=True)
        return pd.DataFrame()
    
    @staticmethod
    def parse_xml(xml_path):
        """Parse optimization XML report."""
        tree = ET.parse(xml_path)
        root = tree.getroot()
        results = []
        
        for item in root.findall('.//Item'):
            row = {
                'profit': float(item.findtext('Profit', 0)),
                'profit_factor': float(item.findtext('ProfitFactor', 0)),
                'drawdown': float(item.findtext('EquityDrawdown', 0)),
                'sharpe': float(item.findtext('SharpeRatio', 0)),
                'trades': int(item.findtext('TotalTrades', 0)),
            }
            for param in item.findall('.//Input'):
                row[param.get('Name')] = float(param.text)
            results.append(row)
        
        return pd.DataFrame(results)

# Usage
optimizer = MT5Optimizer(
    terminal_path=r'C:\Program Files\MetaTrader 5\terminal64.exe',
    experts_dir=r'C:\Users\you\AppData\Roaming\MetaQuotes\Terminal\ID\MQL5\Experts',
    report_dir=r'D:\MT5\Reports'
)

results = optimizer.batch_optimize(
    ea_name='TrendFollower',
    symbols=['EURUSD', 'GBPUSD', 'USDJPY'],
    timeframes=['H1', 'H4'],
    start_date='2023.01.01',
    end_date='2025.01.01'
)

# Find best parameters
best = results.sort_values('sharpe', ascending=False).head(10)
print(best[['symbol', 'timeframe', 'profit', 'sharpe', 'drawdown', 'trades']])
best.to_csv('best_params.csv', index=False)

Optimization Criteria Explained

Criterion When to Use
0 — Max Balance Simple strategies, quick screening
1 — Balance × Profitability Balanced approach, penalizes large losses
2 — Balance × Expected Payoff Focus on consistent per-trade profit
3 — (100% - DD) × Balance Risk-averse, penalizes drawdown heavily
4 — Balance × Recovery Factor Good overall metric, balances profit and drawdown
5 — Balance × Sharpe Ratio Recommended — risk-adjusted returns
6 — Custom (OnTester) Advanced: define your own fitness function
7 — Complex Criterion MT5's built-in multi-factor score

Custom Optimization Criterion in MQL5

Use criterion 6 to define your own fitness function:

double OnTester()
{
    // Get standard stats
    double profit = TesterStatistics(STAT_PROFIT);
    double max_dd = TesterStatistics(STAT_EQUITY_DD);
    double trades = TesterStatistics(STAT_TRADES);
    double profit_factor = TesterStatistics(STAT_PROFIT_FACTOR);
    double sharpe = TesterStatistics(STAT_SHARPE_RATIO);
    
    // Custom fitness: penalize few trades and high drawdown
    if(trades < 30) return -1000;  // Minimum trade count
    if(max_dd > 20) return -1000;  // Max drawdown 20%
    
    // Reward high Sharpe with decent profit
    double fitness = sharpe * MathSqrt(MathAbs(profit));
    
    // Bonus for high profit factor
    if(profit_factor > 1.5) fitness *= 1.2;
    
    return fitness;
}

IDE Integration: Optimize EAs from Your Code Editor

You don't need to switch between MT5 and a text editor manually. Modern IDEs can handle the entire workflow: edit MQL5 → compile → backtest → parse results → iterate.

VS Code Setup

  1. Install the MQL5 extension for syntax highlighting:

    • Open VS Code → Extensions → search "MQL5" → install
  2. Create build tasks (.vscode/tasks.json):

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Compile EA",
      "type": "shell",
      "command": "C:\\Program Files\\MetaTrader 5\\MetaEditor64.exe",
      "args": ["/compile:${file}", "/log"],
      "group": "build",
      "problemMatcher": []
    },
    {
      "label": "Run Backtest",
      "type": "shell",
      "command": "C:\\Program Files\\MetaTrader 5\\terminal64.exe",
      "args": ["/config:D:\\MT5\\backtest.ini"],
      "group": "build",
      "dependsOn": "Compile EA",
      "problemMatcher": []
    },
    {
      "label": "Parse Results",
      "type": "shell",
      "command": "python",
      "args": ["D:\\MT5\\parse_results.py"],
      "group": "build",
      "dependsOn": "Run Backtest",
      "problemMatcher": []
    }
  ]
}

Press Ctrl+Shift+B to compile → backtest → parse results in sequence.

  1. Launch configuration for debugging Python parsers (.vscode/launch.json):
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Parse MT5 Results",
      "type": "python",
      "request": "launch",
      "program": "D:\\MT5\\parse_results.py",
      "console": "integratedTerminal"
    }
  ]
}

Windsurf / Cursor / AI IDE Setup

AI-powered IDEs like Windsurf and Cursor can handle the full EA optimization workflow. The AI can:

  1. Write MQL5 code — describe your strategy in plain English
  2. Compile via MetaEditor CLI — the IDE runs metaeditor64.exe /compile
  3. Generate .ini configs — AI creates config files based on your parameters
  4. Run backtests — AI calls terminal64.exe /config:backtest.ini
  5. Parse XML results — AI reads the optimization report and analyzes performance
  6. Suggest improvements — AI recommends parameter adjustments based on results

Example AI prompt for Windsurf/Cursor:

"Compile my TrendFollower EA, create an optimization config for EURUSD H1 from 2023-2025 with genetic optimization on FastMA (10-50), SlowMA (50-200), and StopLoss (30-150). Run the optimization, parse the XML results, and show me the top 5 parameter sets by Sharpe ratio."

The AI will execute the full pipeline:

metaeditor64.exe /compile:TrendFollower.mq5 /log
→ Check compilation log for errors
→ Generate optimize.ini with parameters
→ terminal64.exe /config:optimize.ini
→ Parse optimization_report.xml
→ Display top 5 results in a table

Claude Desktop with MCP Server

For fully autonomous EA development, use the MT5 MCP Server with Claude Desktop:

// ~/.claude/settings.json
{
  "mcpServers": {
    "mt5": {
      "command": "python",
      "args": ["C:\\path\to\mt5-mcp-server\\server.py"]
    }
  }
}

This gives Claude 16 tools: write_ea, compile_mql5, run_backtest, get_backtest_results, and more. See our AI Forex Trading guide for full setup.

Recommended IDE Workflow

┌──────────────────────────────────────────────────────┐
│  IDE (VS Code / Windsurf / Cursor)                   │
│                                                      │
│  1. Edit .mq5 source code                            │
│  2. Ctrl+Shift+B → Compile via MetaEditor CLI        │
│  3. Check .log for compilation errors                │
│  4. Run terminal64.exe /config:optimize.ini          │
│  5. Parse XML report with Python script              │
│  6. Analyze results, adjust parameters               │
│  7. Repeat                                           │
└──────────────────────────────────────────────────────┘

MQL5 Cloud Network for Faster Optimization

If local optimization is too slow, use the MQL5 Cloud Network to distribute across hundreds of agents:

[Tester]
;--- Enable cloud agents
UseCloud=1
UseLocal=1
UseRemote=0

Cloud optimization costs MQL5 cloud credits but can be 10-100x faster for large parameter spaces. You can purchase credits in your MQL5 account.

Tips for Effective CLI Optimization

  1. Use genetic algorithm (Optimization=2) — it's 10-100x faster than complete enumeration for large parameter spaces
  2. Set ShutdownTerminal=1 — ensures clean exit for batch processing
  3. Use different ports for parallel runs — prevents agent conflicts
  4. Always use forward testing — catches overfitting early
  5. Parse XML reports — automation only works if you can read results programmatically
  6. Filter results rigorously — minimum 50 trades, max drawdown < 20%, positive Sharpe
  7. Save all configs — reproducibility is key in optimization
  8. Compile before testing — always run metaeditor64.exe /compile before backtesting
  9. Check the .log file — compilation errors will silently produce no .ex5 file
  10. Use MQL5 Cloud for large sweepsUseCloud=1 for parameter spaces > 10,000 combinations

FAQ

Can I run MT5 backtesting on Linux or Mac?

No. The terminal64.exe CLI is Windows-only. You can run it in a Windows VM on Linux/Mac, or use a Windows VPS. The Python MetaTrader5 package also requires Windows.

How long does an optimization take?

It depends on the parameter space, date range, and tick model. A genetic optimization (Optimization=2) on EURUSD H1 over 2 years with 5 parameters typically takes 10-30 minutes locally. Complete enumeration (Optimization=1) can take hours or days.

What's the difference between .htm and .xml reports?

.htm reports are for single backtests — they contain charts, trade lists, and statistics in human-readable format. .xml reports are for optimizations — they contain all passes with input parameters and results in machine-readable format. Always use .xml for automation.

Do I need a live account for backtesting?

No. MT5 can backtest without logging in. However, you need historical data downloaded for the symbol you're testing. Open a demo account and browse the symbol chart to download data.

Can I optimize multiple EAs in parallel?

Yes. Launch multiple terminal64.exe instances with different /config: files and different Port= values. Each instance runs independently. See our Batch File Automation guide for scripts.

How do I know if my optimization results are overfit?

Use forward testing (ForwardMode=1 or 2). If the EA performs well on the in-sample period but poorly on the forward (out-of-sample) period, it's overfit. Also check: minimum 50 trades, reasonable parameter values (not at extremes), and consistent performance across different symbols.

Related Guides

Affiliate Disclosure: This page contains affiliate links. We may earn a commission when you click on certain links or sign up with brokers featured on this site, at no additional cost to you. Our reviews and recommendations are based on thorough research and remain unbiased.Learn more

Risk Warning: Trading forex and CFDs involves significant risk of loss. Past performance is not indicative of future results. CFDs are complex instruments and come with a high risk of losing money rapidly due to leverage. Ensure you understand the risks before trading. This content is for educational purposes only and does not constitute financial advice.

Written by

Pips Growth Team

Trading Education & Research Team

The Pips Growth Team is a group of experienced traders, financial analysts, and trading educators dedicated to providing accurate, actionable forex education. Our team combines decades of hands-on market experience with deep technical knowledge to create comprehensive guides, honest broker reviews, and proven trading strategies. Every article is thoroughly researched, fact-checked, and reviewed by multiple team members to ensure the highest quality and accuracy.

15+ Years Experience81+ Articles Published
Forex & CFD TradingTechnical AnalysisRisk ManagementBroker Reviews & Evaluation
View Full Profile
Share

Get Trading Tips

MT5 Optimization CLI Automation: Run Backtests from Command Line | PipsGrowth