Files
Ichinga Samuel 54b171bb5c v4.1.2
2026-02-28 22:22:30 +01:00

344 lines
10 KiB
Markdown

# aiomql
![aiomql](docs/images/cover.png)
**Asynchronous MetaTrader 5 Library & Algorithmic Trading Framework**
![PyPI Version](https://img.shields.io/pypi/v/aiomql)
![Python](https://img.shields.io/pypi/pyversions/aiomql)
![License](https://img.shields.io/github/license/ichinga-samuel/aiomql?style=plastic)
![GitHub Issues](https://img.shields.io/github/issues/ichinga-samuel/aiomql?style=plastic)
---
## 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_thread` and 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
```bash
pip install aiomql
```
**Optional extras:**
```bash
# 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:
```json
{
"login": 12345678,
"password": "your_password",
"server": "YourBroker-Demo"
}
```
All settings can also be set programmatically via the singleton `Config` class:
```python
from aiomql import Config
config = Config(login=12345678, password="your_password", server="YourBroker-Demo")
```
### Using the MetaTrader Interface
```python
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.
```python
# 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
```python
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 of `bot.execute()` if you're already inside an async context.
### 3. Trading Sessions
Restrict when a strategy trades by passing `Sessions`:
```python
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:
```python
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](docs/toc.md) for detailed documentation of every module.
---
## Testing
```bash
# 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](https://github.com/Ichinga-Samuel/aiomql/issues) first
to discuss what you would like to change.
---
## License
[MIT](LICENSE)
---
## Support
If you find this project useful, consider supporting its development:
- [❤️ Sponsor on GitHub](https://github.com/sponsors/Ichinga-Samuel)
- [☕ Buy Me a Coffee](https://buymeacoffee.com/ichingasamuel)