Asynchronous MetaTrader5 library and Algorithmic Trading Framework
Project description
aiomql
Asynchronous MetaTrader 5 Library & Algorithmic Trading Framework
Overview
aiomql is a Python framework for building algorithmic trading bots on top of MetaTrader 5. It wraps every MT5 API call in an async-friendly interface and provides high-level abstractions for strategies, risk management, trade execution, session management, and position tracking — so you can focus on your trading logic instead of boilerplate.
Key Features
- Async-first MT5 interface — every MT5 function wrapped with
asyncio.to_threadand automatic reconnection - Full synchronous API — every async class has a sync counterpart for scripts and notebooks
- Bot orchestrator — run multiple strategies on multiple instruments concurrently via thread-pool executors
- Strategy base class — define
trade(), set parameters, and let the framework handle the execution loop - Session management — restrict trading to specific time windows (London, New York, Tokyo, etc.)
- Risk & money management — built-in
RAM(Risk Assessment & Money) manager - Trade recording — persist results to CSV, JSON, or SQLite
- Position tracking — monitor open positions with trailing stops, extending take-profits, and custom tracking functions
- Technical analysis — built-in pandas-ta integration plus optional TA-Lib support
- Multi-process execution — run independent bots in parallel with
Bot.process_pool() - JSON configuration — centralise credentials and settings in
aiomql.json - Contributed extensions — pre-built traders (
SimpleTrader,ScalpTrader), strategies (Chaos), and specialised symbols (ForexSymbol)
Requirements
- Python ≥ 3.13
- Windows (MetaTrader 5 terminal requirement)
- A MetaTrader 5 trading account
Installation
pip install aiomql
Optional extras:
# TA-Lib technical indicators
pip install aiomql[talib]
# Optional (Cython, Numba, tqdm)
pip install aiomql[optional]
# Both
pip install aiomql[all]
Quick Start
Configuration
Create an aiomql.json file in your project root:
{
"login": 12345678,
"password": "your_password",
"server": "YourBroker-Demo"
}
All settings can also be set programmatically via the singleton Config class:
from aiomql import Config
config = Config(login=12345678, password="your_password", server="YourBroker-Demo")
Using the MetaTrader Interface
import asyncio
from aiomql import MetaTrader
async def main():
async with MetaTrader() as mt5:
# Account information
account = await mt5.account_info()
print(account)
# Available symbols
symbols = await mt5.symbols_get()
print(f"{len(symbols)} symbols available")
asyncio.run(main())
Building a Trading Bot
1. Define a Strategy
Subclass Strategy and implement the trade() method. Parameters declared in the
parameters dict become instance attributes and can be overridden at construction time.
# strategies/ema_crossover.py
from aiomql import Strategy, ForexSymbol, TimeFrame, Tracker, OrderType, Sessions, Trader, ScalpTrader
class EMAXOver(Strategy):
ttf: TimeFrame
tcc: int
fast_ema: int
slow_ema: int
tracker: Tracker
interval: TimeFrame
timeout: int
parameters = {
"ttf": TimeFrame.H1,
"tcc": 3000,
"fast_ema": 34,
"slow_ema": 55,
"interval": TimeFrame.M15,
"timeout": 3 * 60 * 60,
}
def __init__(self, *, symbol: ForexSymbol, params: dict | None = None,
trader: Trader = None, sessions: Sessions = None,
name: str = "EMAXOver"):
super().__init__(symbol=symbol, params=params, sessions=sessions, name=name)
self.tracker = Tracker(snooze=self.interval.seconds)
self.trader = trader or ScalpTrader(symbol=self.symbol)
async def find_entry(self):
candles = await self.symbol.copy_rates_from_pos(
timeframe=self.ttf, count=self.tcc
)
candles.ta.ema(length=self.fast_ema, append=True)
candles.ta.ema(length=self.slow_ema, append=True)
candles.rename(
**{f"EMA_{self.fast_ema}": "fast_ema",
f"EMA_{self.slow_ema}": "slow_ema"},
inplace=True,
)
fas = candles.ta_lib.above(candles.fast_ema, candles.slow_ema)
fbs = candles.ta_lib.below(candles.fast_ema, candles.slow_ema)
if fas.iloc[-1]:
self.tracker.update(order_type=OrderType.BUY, snooze=self.timeout)
elif fbs.iloc[-1]:
self.tracker.update(order_type=OrderType.SELL, snooze=self.timeout)
else:
self.tracker.update(order_type=None, snooze=self.interval.seconds)
async def trade(self):
await self.find_entry()
if self.tracker.order_type is None:
await self.sleep(secs=self.tracker.snooze)
else:
await self.trader.place_trade(
order_type=self.tracker.order_type, parameters=self.parameters
)
await self.delay(secs=self.tracker.snooze)
2. Wire It Up with a Bot
import logging
from aiomql import Bot, ForexSymbol, OpenPositionsTracker
from strategies.ema_crossover import EMAXOver
logging.basicConfig(level=logging.INFO)
def main():
symbols = [ForexSymbol(name=s) for s in ["EURUSD", "GBPUSD", "USDJPY"]]
strategies = [EMAXOver(symbol=sym) for sym in symbols]
bot = Bot()
bot.add_strategies(strategies)
# Optionally track open positions on a separate thread
bot.add_coroutine(
coroutine=OpenPositionsTracker(autocommit=True).track,
on_separate_thread=True,
)
bot.execute() # synchronous entry point (blocks until shutdown)
if __name__ == "__main__":
main()
Tip: Use
await bot.start()instead ofbot.execute()if you're already inside an async context.
3. Trading Sessions
Restrict when a strategy trades by passing Sessions:
from datetime import time
from aiomql import Session, Sessions, ForexSymbol, Chaos
london = Session(name="London", start=time(8, 0), end=time(16, 0))
new_york = Session(name="New York", start=time(13, 0), end=time(21, 0))
sessions = Sessions(sessions=[london, new_york])
strategy = Chaos(symbol=ForexSymbol(name="USDJPY"), sessions=sessions)
4. Multi-Process Execution
Run completely independent bots in separate processes:
from aiomql import Bot
def run_forex():
bot = Bot()
# ... add forex strategies ...
bot.execute()
def run_crypto():
bot = Bot()
# ... add crypto strategies ...
bot.execute()
Bot.process_pool(processes={run_forex: {}, run_crypto: {}}, num_workers=2)
Project Structure
src/aiomql/
├── core/ # Low-level infrastructure
│ ├── _core.py # MT5 function definitions & async wrappers
│ ├── meta_trader.py # MetaTrader singleton (init, login, symbol/order calls)
│ ├── config.py # Singleton Config (JSON + programmatic settings)
│ ├── constants.py # Enums (TimeFrame, OrderType, TradeAction, …)
│ ├── models.py # Data models (SymbolInfo, AccountInfo, TradeRequest, …)
│ ├── base.py # _Base metaclass (attribute helpers, MT5 access)
│ ├── db.py # SQLite trade-results database
│ ├── store.py # In-memory shared state store
│ ├── state.py # State management
│ ├── task_queue.py # Async task queue for scheduled work
│ ├── errors.py # Error definitions
│ ├── exceptions.py # Custom exceptions (OrderError, LoginError, …)
│ └── sync/ # Synchronous MetaTrader wrapper
│
├── lib/ # High-level trading components
│ ├── bot.py # Bot orchestrator (strategy runner, process pool)
│ ├── executor.py # Thread/task executor for strategies
│ ├── strategy.py # Strategy base class (trade loop, sessions)
│ ├── symbol.py # Symbol (market data, ticks, rates)
│ ├── order.py # Order (check, send, margin, profit)
│ ├── trader.py # Trader (place_trade, SL/TP management)
│ ├── account.py # Account singleton
│ ├── candle.py # Candles collection (DataFrame + TA)
│ ├── ticks.py # Tick & Ticks (tick data collections)
│ ├── positions.py # Position querying & management
│ ├── history.py # Trade & order history
│ ├── ram.py # RAM (Risk Assessment & Money) manager
│ ├── sessions.py # Session & Sessions (time-window trading)
│ ├── terminal.py # Terminal info wrapper
│ ├── result.py # Trade result recording (CSV/JSON)
│ ├── result_db.py # Trade result recording (SQLite)
│ ├── trade_records.py# Trade records management
│ └── sync/ # Synchronous mirrors of lib modules
│
├── contrib/ # Community extensions
│ ├── strategies/ # Chaos (random buy/sell demo)
│ ├── symbols/ # ForexSymbol (pip & volume calculations)
│ ├── trackers/ # Position & open-positions trackers
│ ├── traders/ # SimpleTrader, ScalpTrader
│ └── utils/ # StrategyTracker (Tracker)
│
├── ta_libs/ # Technical analysis (pandas-ta classic)
└── utils/ # Decorators, price helpers, process pool
API Documentation
See the full API Reference for detailed documentation of every module.
Testing
# Install dev dependencies
pip install -e ".[dev]"
# Run the test suite
pytest tests
Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
License
Support
If you find this project useful, consider supporting its development:
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aiomql-4.1.2.tar.gz.
File metadata
- Download URL: aiomql-4.1.2.tar.gz
- Upload date:
- Size: 256.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fc234304c2cf8a467c39db999c191daec2897ff4b62186c8898a7a87f3b3440e
|
|
| MD5 |
fbcefd0a290583014e5d212b9ed6e218
|
|
| BLAKE2b-256 |
4ea0eb12b8050d6c708f5902447e1dd0dc22537951688c2ae13f5bbf10952a15
|
File details
Details for the file aiomql-4.1.2-py3-none-any.whl.
File metadata
- Download URL: aiomql-4.1.2-py3-none-any.whl
- Upload date:
- Size: 402.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ae72c58a122bdeb42f4c6601035df2d2c21b5041d84b502130a9f1b7df713d77
|
|
| MD5 |
aeb5444a85b334a253634a37e8759cf0
|
|
| BLAKE2b-256 |
c6b9a4c07c242349fb21a38eb04aecd7a4c35883cdc4b6ecbf1897c5d8758fa7
|