How to Set Up MetaTrader 5 on Mac with Local MQL5 Compilation
Most MQL5 tutorials assume you're on Windows. If you're on a Mac, you're expected to spin up a VM, run Parallels, or push to GitHub Actions every time you want to compile. None of that is necessary. MetaTrader 5 on macOS bundles its own Wine runtime, which means you already have everything you need to compile .mq5 files locally, straight from your terminal or VS Code.
This is the setup I use daily for algo trading development. It took a few hours of trial and error to get right, so here's every step, every gotcha, and every command.
What You'll Get
By the end of this guide:
- MetaTrader 5 running natively on macOS (via the bundled Wine layer)
- Local
.mq5compilation from terminal, no Windows VM needed - VS Code integration with syntax highlighting, build tasks, and error matching
- A compile script that handles path conversion and include resolution automatically
Step 1: Install MetaTrader 5
Download the official macOS package from MetaQuotes:
curl -L -o ~/Downloads/MetaTrader5.pkg.zip \
"https://download.mql5.com/cdn/web/metaquotes.software.corp/mt5/MetaTrader5.pkg.zip"Unzip and run the installer:
cd ~/Downloads
unzip MetaTrader5.pkg.zip
open MetaTrader5.pkgFollow the installer prompts. It installs to /Applications/MetaTrader 5.app.
What's actually happening: MetaTrader 5 for Mac is not a native Cocoa app. It's the Windows version bundled with Wine 10.0 inside the .app package. The Wine binary lives at /Applications/MetaTrader 5.app/Contents/SharedSupport/wine/bin/wine64 and the Windows filesystem (C: drive) lives in your home directory at ~/Library/Application Support/net.metaquotes.wine.metatrader5/.
Once installed, open MetaTrader 5 from your Applications folder and log into a broker account. This creates the full Wine prefix and directory structure we need.
Step 2: Verify the Wine Setup
MetaTrader bundles Wine 10.0. Confirm it exists:
ls -la "/Applications/MetaTrader 5.app/Contents/SharedSupport/wine/bin/wine64"Check that the Wine prefix was created:
ls ~/Library/Application\ Support/net.metaquotes.wine.metatrader5/drive_c/Program\ Files/MetaTrader\ 5/You should see metaeditor64.exe, terminal64.exe, and the MQL5/ directory with the standard library:
ls ~/Library/Application\ Support/net.metaquotes.wine.metatrader5/drive_c/Program\ Files/MetaTrader\ 5/MQL5/Include/Trade/Expected output:
AccountInfo.mqh OrderInfo.mqh Trade.mqh
DealInfo.mqh PositionInfo.mqh TerminalInfo.mqh
HistoryOrderInfo.mqh SymbolInfo.mqh
If you see those files, your setup is good. If not, open MetaTrader 5 from Applications at least once and try again.
Step 3: Create the Local Compile Script
This is the core of the setup. Create a script that converts macOS paths to Wine paths and calls MetaEditor's compiler.
In your MQL5 project, create scripts/compile-local.sh:
mkdir -p scripts#!/bin/bash
# Local MQ5 Compiler using system MetaTrader 5 Wine + MetaEditor
# Usage: ./scripts/compile-local.sh src/experts/MyEA.mq5
# ./scripts/compile-local.sh --all
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
WINE="/Applications/MetaTrader 5.app/Contents/SharedSupport/wine/bin/wine64"
WINEPREFIX="$HOME/Library/Application Support/net.metaquotes.wine.metatrader5"
METAEDITOR="C:\\Program Files\\MetaTrader 5\\metaeditor64.exe"
INCLUDE_DIR="$PROJECT_DIR/src"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
if [[ ! -f "$WINE" ]]; then
echo -e "${RED}Wine not found at: $WINE${NC}"
echo "Install MetaTrader 5 first."
exit 1
fi
compile_file() {
local mq5_file="$1"
local abs_path="$PROJECT_DIR/$mq5_file"
if [[ ! -f "$abs_path" ]]; then
echo -e "${RED}File not found: $mq5_file${NC}"
return 1
fi
# Convert macOS path to Wine path
local wine_path
wine_path=$(WINEPREFIX="$WINEPREFIX" "$WINE" winepath -w "$abs_path" 2>/dev/null)
echo -e "${YELLOW}Compiling: $mq5_file${NC}"
# Run MetaEditor compile
WINEPREFIX="$WINEPREFIX" "$WINE" "$METAEDITOR" \
/compile:"$wine_path" \
/include:"$(WINEPREFIX="$WINEPREFIX" "$WINE" winepath -w "$INCLUDE_DIR" 2>/dev/null)" \
/log 2>/dev/null
# Check if .ex5 was produced
local ex5_file="${abs_path%.mq5}.ex5"
if [[ -f "$ex5_file" ]]; then
echo -e "${GREEN} OK: $(basename "$ex5_file")${NC}"
return 0
else
echo -e "${RED} FAIL: no .ex5 produced${NC}"
local log_file="${abs_path%.mq5}.log"
if [[ -f "$log_file" ]]; then
echo -e "${YELLOW} Log:${NC}"
cat "$log_file"
fi
return 1
fi
}
if [[ $# -eq 0 ]]; then
echo -e "${RED}Usage: $0 <file.mq5> [file2.mq5 ...]${NC}"
echo " $0 --all"
exit 1
fi
FAILED=0
if [[ "$1" == "--all" ]]; then
echo -e "${YELLOW}Compiling all .mq5 files...${NC}"
while IFS= read -r -d '' f; do
rel="${f#$PROJECT_DIR/}"
compile_file "$rel" || FAILED=$((FAILED + 1))
done < <(find "$PROJECT_DIR/src" -name "*.mq5" -print0)
else
for f in "$@"; do
compile_file "$f" || FAILED=$((FAILED + 1))
done
fi
if [[ $FAILED -gt 0 ]]; then
echo -e "${RED}$FAILED file(s) failed to compile.${NC}"
exit 1
else
echo -e "${GREEN}All files compiled successfully.${NC}"
fiMake it executable:
chmod +x scripts/compile-local.shNow test it:
./scripts/compile-local.sh src/experts/HelloWorld.mq5You should see:
Compiling: src/experts/HelloWorld.mq5
OK: HelloWorld.ex5
All files compiled successfully.
Step 4: The Include Path Gotcha
This is the single biggest headache you'll hit. MetaEditor's /include: flag does not point to the Include directory directly. It points to the MQL5 root, and MetaEditor internally appends Include/ when resolving #include <...> directives.
If your project structure looks like this:
my-project/
src/
include/ <-- your custom includes + standard library copies
Trade/
Trade.mqh
MyCustomLib/
Utils.mqh
experts/
MyEA.mq5 <-- #include <Trade/Trade.mqh>
Then the include path must be src/, not src/include/. If you set it to src/include/, MetaEditor will look for src/include/Include/Trade/Trade.mqh (double nesting) and fail with error 106.
# Wrong - causes "file not found" for standard includes
INCLUDE_DIR="$PROJECT_DIR/src/include"
# Correct - MetaEditor adds Include/ internally
INCLUDE_DIR="$PROJECT_DIR/src"This cost me an afternoon. The error message is cryptic because MetaEditor outputs wide-character (UTF-16) log files that render as spaced-out text on macOS. Look for error 106: file '...' not found buried in the garbled output.
Step 5: Standard Library Includes
Your EAs probably use standard MQL5 includes like #include <Trade/Trade.mqh> and #include <Trade/PositionInfo.mqh>. These ship with MetaTrader but not with your project.
You have two options:
Option A: Copy the standard library into your project (recommended)
# Create the include directory matching MQL5 structure
mkdir -p src/include/Trade
# Copy from the MT5 Wine prefix
cp ~/Library/Application\ Support/net.metaquotes.wine.metatrader5/drive_c/Program\ Files/MetaTrader\ 5/MQL5/Include/Trade/*.mqh \
src/include/Trade/This makes your project self-contained and compilable without MetaTrader installed (e.g., in CI).
Option B: Point the include path to the MT5 installation
Change the script's include dir to the MT5 standard MQL5 directory:
INCLUDE_DIR="$HOME/Library/Application Support/net.metaquotes.wine.metatrader5/drive_c/Program Files/MetaTrader 5/MQL5"This uses the live MT5 includes but means your custom includes need to live under that directory too, which gets messy.
Step 6: VS Code Integration
Syntax Highlighting
Install the MQL Tools extension from the VS Code marketplace. It provides syntax highlighting and some IntelliSense for .mq5 and .mqh files.
Add file associations to .vscode/settings.json:
{
"files.associations": {
"*.mq5": "mql5",
"*.mqh": "mql5"
},
"editor.tabSize": 3,
"editor.detectIndentation": false
}MQL5 uses 3-space indentation by convention. Set detectIndentation to false so VS Code doesn't override this.
Build Task
Create .vscode/tasks.json to compile the currently open file with Cmd+Shift+B:
{
"version": "2.0.0",
"tasks": [
{
"label": "Compile MQ5 File",
"type": "shell",
"command": "${workspaceFolder}/scripts/compile-local.sh",
"args": ["${relativeFile}"],
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared",
"clear": true
},
"problemMatcher": {
"owner": "mql5",
"fileLocation": ["relative", "${workspaceFolder}"],
"pattern": {
"regexp": "^(.+)\\((\\d+),(\\d+)\\)\\s*:\\s*(warning|error)\\s+(.+)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
}
},
{
"label": "Compile All MQ5",
"type": "shell",
"command": "${workspaceFolder}/scripts/compile-local.sh",
"args": ["--all"],
"group": "build"
}
]
}The problemMatcher parses MetaEditor's error format (file(line,col) : error message) and shows errors inline in VS Code.
MQL Tools Extension Configuration
If you want the MQL Tools extension's built-in compile command (right-click > Compile), add these settings:
{
"mql_tools.Metaeditor.Metaeditor5Dir": "/Users/YOUR_USERNAME/Library/Application Support/net.metaquotes.wine.metatrader5/drive_c/Program Files/MetaTrader 5",
"mql_tools.Metaeditor.WinePrefixME5": "/Users/YOUR_USERNAME/Library/Application Support/net.metaquotes.wine.metatrader5",
"mql_tools.Metaeditor.Include5Dir": "/Users/YOUR_USERNAME/path-to-your-project/src"
}MQL Tools activation quirk: The extension only activates when the VS Code workspace folder is named exactly MQL4 or MQL5. If your project folder has a different name, create a symlink: ln -s ~/Dev/my-mql5-project ~/Dev/MQL5 and open VS Code from the symlink path. The build task approach works regardless of folder name, so you can skip this if you prefer Cmd+Shift+B.
Step 7: Compile and Deploy
With everything wired up, your workflow is:
- Write code in VS Code with syntax highlighting
- Compile with Cmd+Shift+B (or
./scripts/compile-local.sh src/experts/MyEA.mq5) - Check errors inline in VS Code via the problem matcher
- Copy the .ex5 to your MetaTrader data directory for testing:
cp src/experts/MyEA.ex5 \
~/Library/Application\ Support/net.metaquotes.wine.metatrader5/drive_c/Program\ Files/MetaTrader\ 5/MQL5/Experts/Then refresh the Expert Advisors panel in MetaTrader 5 and attach it to a chart.
For batch compilation of your entire project:
./scripts/compile-local.sh --allProject Structure
Here's the project layout that works well for this setup:
my-mql5-project/
src/
include/ # Standard library + custom includes
Trade/
Object.mqh
MyCustomLib/
experts/ # Expert Advisors (.mq5)
indicators/ # Custom indicators
scripts/ # MQL5 scripts (one-shot)
scripts/
compile-local.sh # The compile script
.vscode/
settings.json
tasks.json
.gitignore # Exclude *.ex5, *.ex4, *.log
Add to your .gitignore:
*.ex5
*.ex4
*.log
Troubleshooting
"Wine not found" error: MetaTrader 5 isn't installed, or it's in a non-standard location. Check /Applications/MetaTrader 5.app/Contents/SharedSupport/wine/bin/wine64.
"error 106: file not found" for standard includes: Your include path is wrong. Remember: point to the MQL5 root (src/), not the Include directory (src/include/).
Garbled log output: MetaEditor writes UTF-16 encoded logs. The compile script shows them as-is, which looks like spaced-out characters. The actual error messages are readable if you look past the formatting.
MQL Tools "command not found": The extension isn't activated because your workspace folder isn't named MQL5. Use the symlink workaround or stick with the build task.
Compilation succeeds but no .ex5 appears: Check if your .gitignore or VS Code files.exclude is hiding .ex5 files. They're generated in the same directory as the source .mq5 file.
What's Next
This setup gives you a proper local development loop for MQL5 on macOS. No VMs, no GitHub Actions round-trips, no waiting. Write, compile, test, iterate.
I'm using this exact workflow to build algorithmic trading systems for gold, starting with EMA zone retest strategies and working towards AI-driven signal generation that incorporates price action, sentiment, and market structure. More on that soon.