Zum Hauptinhalt springen
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
Windows Tipps & SecurityGrafikkarte vor Überhitzung schützen: So geht’s(25.09.2026 um 08:00 Uhr)
••••••••••
Windows Tipps & SecurityGrafikkarte vor Überhitzung schützen: So geht’s(25.09.2026 um 08:00 Uhr)
••••••••••
Intelligence View
⚡ tsecurity.de Intelligence

AIOMQL-The Complete Guide to Building Algorithmic Trading Bots with Python & MetaTrader 5

What is aiomql? aiomql is a Python framework for building algorithmic trading bots on top of MetaTrader 5. Rather than writing raw MT5 API calls and managing connection boilerplate, aiomql gives you: An async-first MetaTrader 5…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!




What is aiomql?



aiomql is a Python framework for building algorithmic trading bots on top of

MetaTrader 5. Rather than writing raw MT5 API calls and managing connection boilerplate, aiomql gives you:





  • An async-first MetaTrader 5 interface — every MT5 function wrapped with
    asyncio.to_thread and automatic reconnection on transient errors.


  • High-level abstractions — Strategy, Bot, Trader, Order, Symbol, Sessions, RAM,
    and more — so you can focus on trading logic.


  • A full synchronous API — every async class has a sync counterpart for scripts,
    notebooks, and quick prototyping.


  • Built-in technical analysis — pandas-ta integration with optional TA-Lib support.


  • Trade recording — persist results to CSV, JSON, or SQLite automatically.


  • Position tracking — monitor open positions with trailing stops, extending
    take-profits, hedging, and stacking.


  • Multi-process execution — run independent bots in parallel with a single call.



aiomql is designed for traders who want to build, test, and deploy algorithmic strategies in Python without reinventing the wheel.







Installation & Requirements





Prerequisites
























Requirement Details
Python ≥ 3.13
OS Windows (MetaTrader 5 terminal requirement)
Account A MetaTrader 5 trading account (demo or live)




Install via pip





pip install aiomql







Optional Extras





# TA-Lib technical indicators
pip install aiomql[talib]

# Optional accelerators (Cython, Numba, tqdm)
pip install aiomql[optional]

# Everything
pip install aiomql[all]









Configuration



aiomql uses a singleton Config class that can load settings from a JSON file or be configured programmatically. This single configuration object is shared across all components.





Option 1: JSON Configuration File



Create an aiomql.json file in your project root:




{
"login": 12345678,
"password": "your_password",
"server": "YourBroker-Demo",
"trade_record_mode": "csv"
}






The Config class automatically searches for aiomql.json in your project directory tree, starting from the current working directory and walking up to the root.






Option 2: Programmatic Configuration






from aiomql import Config

config = Config(
login=12345678,
password="your_password",
server="YourBroker-Demo",
trade_record_mode="csv"
)









Key Configuration Options











































Setting Type Description
login int MetaTrader account number
password str Account password
server str Broker server name
path str Path to the MT5 terminal executable
trade_record_mode str Trade logging format: "csv", "json", or "sql"
root str Project root directory


Because Config is a singleton, any component in your application that creates a Config() instance receives the same shared configuration.






State & Store



The Config class also provides access to two persistent storage mechanisms:





  • config.state — A State object for persistent key-value storage (backed by SQLite).


  • config.store — A Store object for in-memory shared state accessible across components. These are useful for sharing data between strategies, trackers, and other components at runtime.









Connecting to MetaTrader 5



The MetaTrader class wraps every MT5 API function with async execution and automatic retry logic. It supports both async context manager usage and direct calls.






Basic Connection






import asyncio
from aiomql import MetaTrader

async def main():
async with MetaTrader() as mt5:
# Get account information
account = await mt5.account_info()
print(f"Balance: {account.balance}")
print(f"Equity: {account.equity}")

# Get terminal info
terminal = await mt5.terminal_info()
print(f"Terminal: {terminal.name}")

# Get available symbols
symbols = await mt5.symbols_get()
print(f"{len(symbols)} symbols available")


asyncio.run(main())









How It Works



Under the hood, MetaTrader runs every MT5 call through asyncio.to_thread, which means your event loop stays responsive even during blocking I/O. If a connection

error occurs, the _handler method automatically retries initialization and login up to 3 times.




# The MetaTrader class is also a singleton — every instance shares the same state
mt5_a = MetaTrader()
mt5_b = MetaTrader()
assert mt5_a is mt5_b # True









Key Methods








































































Method Description
initialize() Connect to the MT5 terminal
login() Log in with credentials
shutdown() Close the connection
account_info() Get account details
terminal_info() Get terminal details
symbols_get() List available symbols
symbol_info() Get info for a specific symbol
copy_rates_from() Fetch OHLC bar data
copy_rates_from_pos() Fetch recent bars by count
copy_ticks_from() Fetch tick data
order_check() Check if an order can be executed
order_send() Send a trade order
positions_get() Get open positions
history_deals_get() Get historical deals
history_orders_get() Get historical orders








Working with Symbols



The Symbol class is a high-level wrapper around a financial instrument. It pulls properties from MT5 (spread, lot sizes, contract size, etc.) and provides methods to fetch market data.






Initializing a Symbol






from aiomql import Symbol

async def main():
symbol = Symbol(name="EURUSD")
await symbol.initialize()

# Now you can access all symbol properties
print(f"Spread: {symbol.spread}")
print(f"Point: {symbol.point}")
print(f"Min volume: {symbol.volume_min}")
print(f"Max volume: {symbol.volume_max}")
print(f"Volume step: {symbol.volume_step}")
print(f"Contract size: {symbol.trade_contract_size}")









Getting Price Data






# Get the current tick
tick = await symbol.info_tick()
print(f"Bid: {tick.bid}, Ask: {tick.ask}")

# Get the last 500 H1 candles
from aiomql import TimeFrame

candles = await symbol.copy_rates_from_pos(
timeframe=TimeFrame.H1, count=500
)









Volume Utilities



The Symbol class includes helpers for working with lot sizes:




# Check if a volume is valid
is_valid, adjusted = symbol.check_volume(volume=0.15)

# Round volume to the nearest step
rounded = symbol.round_off_volume(volume=0.153, round_down=True)









Currency Conversion






# Convert between currencies using live rates
amount_in_usd = await symbol.convert_currency(
amount=100.0,
from_currency="EUR",
to_currency="USD"
)









ForexSymbol — Specialized for Forex



The ForexSymbol class extends Symbol with forex-specific calculations:




from aiomql import ForexSymbol

eurusd = ForexSymbol(name="EURUSD")
await eurusd.initialize()

# Pip value (point * 10)
print(f"Pip: {eurusd.pip}") # 0.0001 for most pairs

# Compute volume based on risk amount and stop loss distance
volume = await eurusd.compute_volume_sl(
amount=100.0, # risk $100
price=1.1000, # entry price
sl=1.0950, # stop loss
round_down=True
)

# Compute volume based on risk amount and points
volume = await eurusd.compute_volume_points(
amount=100.0,
points=500,
round_down=True
)

# Compute points needed for a given profit at a given volume
points = eurusd.compute_points(amount=50.0, volume=0.1)












Market Data: Candles & Ticks






Candles



The Candles class wraps pandas DataFrame with trading-specific functionality.

When you fetch rates from a Symbol, you receive a Candles object:




from aiomql import TimeFrame

candles = await symbol.copy_rates_from_pos(
timeframe=TimeFrame.H1, count=500
)

# It's a DataFrame under the hood
print(candles.data.head())

# Access individual candles by index
last_candle = candles[-1]
print(f"Open: {last_candle.open}, Close: {last_candle.close}")

# Candle properties
print(f"Body: {last_candle.body}")
print(f"Range: {last_candle.range}")
print(f"Is Bullish: {last_candle.is_bullish()}")
print(f"Is Bearish: {last_candle.is_bearish()}")
print(f"Is Doji: {last_candle.is_doji()}")

# DataFrame columns are accessible directly
print(candles.open) # Series of open prices
print(candles.close) # Series of close prices
print(candles.high) # Series of high prices
print(candles.low) # Series of low prices









Renaming Columns






# Rename DataFrame columns (useful after adding indicators)
candles.rename(
EMA_34="fast_ema",
EMA_55="slow_ema",
inplace=True
)









Ticks



The Tick class represents a single price tick, and Ticks is a collection:




# Get recent ticks
ticks = await symbol.copy_ticks_from(
date_from=datetime.now() - timedelta(minutes=5),
count=1000
)

# Access tick data
for tick in ticks:
print(f"Time: {tick.time}, Bid: {tick.bid}, Ask: {tick.ask}")

# The Ticks object also supports technical analysis
ticks.ta.sma(length=20, append=True)












Technical Analysis



aiomql integrates pandas-ta (classic) out of the box, available through the .ta accessor on Candles and Ticks objects. Every pandas-ta indicator is available

directly.





Using pandas-ta Indicators





candles = await symbol.copy_rates_from_pos(
timeframe=TimeFrame.H1, count=500
)

# Moving averages
candles.ta.sma(length=20, append=True)
candles.ta.ema(length=50, append=True)

# RSI
candles.ta.rsi(length=14, append=True)

# MACD
candles.ta.macd(fast=12, slow=26, signal=9, append=True)

# Bollinger Bands
candles.ta.bbands(length=20, std=2, append=True)

# ATR
candles.ta.atr(length=14, append=True)

# Stochastic
candles.ta.stoch(k=14, d=3, append=True)

# Access the results as DataFrame columns
print(candles.data.columns.tolist())







The ta_lib Helper



The Candles object also includes a ta_lib helper with convenience functions:




# Check if series A is above series B
above = candles.ta_lib.above(candles.fast_ema, candles.slow_ema)

# Check if series A is below series B
below = candles.ta_lib.below(candles.fast_ema, candles.slow_ema)









Optional: TA-Lib Integration



If you install aiomql[talib], you get access to the full C-based TA-Lib library for high-performance indicator computation.









Placing Orders



The Order class handles all trade order operations. It's a subclass of

TradeRequest and provides methods for checking, sending, and managing orders.





Creating and Sending a Market Order





from aiomql import Order, OrderType, TradeAction

# Create a buy order
order = Order(
symbol="EURUSD",
type=OrderType.BUY,
volume=0.1,
price=1.1000,
sl=1.0950,
tp=1.1100
)

# Check if the order can be executed
check_result = await order.check()
print(f"Margin required: {check_result.margin}")

# Send the order
result = await order.send()
print(f"Order ticket: {result.order}")
print(f"Return code: {result.retcode}")







Modifying an Order





order.modify(
sl=1.0960,
tp=1.1120
)







Margin and Profit Calculations





# Calculate required margin
margin = await order.calc_margin()
print(f"Margin needed: {margin}")

# Calculate expected profit (at take-profit level)
profit = await order.calc_profit()
print(f"Expected profit: {profit}")

# Calculate expected loss (at stop-loss level)
loss = await order.calc_loss()
print(f"Expected loss: {loss}")







Pending Order Management





# Get total pending orders
total = await Order.orders_total()

# Get all pending orders
pending = await Order.get_pending_orders()

# Get a specific pending order by ticket
order = await Order.get_pending_order(ticket=123456)

# Cancel a pending order
await Order.cancel_order(order=123456, symbol="EURUSD")







Connection Retry Logic



The send_order method automatically retries on connection errors (retcode 10031)

with exponential backoff, up to 3 retries.







The Trader Abstraction



While Order handles the low-level mechanics, the Trader class provides a

higher-level interface for placing trades with proper risk management and trade

recording.





Why Use Trader?



Trader ties together the Order, Symbol, and RAM (risk manager) classes

into a cohesive workflow:





  1. Calculate position size based on your risk parameters


  2. Set stop-loss and take-profit levels


  3. Check the order before sending


  4. Send the order and handle errors


  5. Record the trade to your chosen storage format





Creating Orders with Stops





from aiomql import Trader, ForexSymbol, RAM, OrderType

symbol = ForexSymbol(name="EURUSD")
await symbol.initialize()

ram = RAM(risk=2, risk_to_reward=3) # 2% risk, 1:3 R:R
trader = Trader(symbol=symbol, ram=ram)

# Create order with stop-loss and take-profit using absolute prices
await trader.create_order_with_stops(
order_type=OrderType.BUY,
sl=1.0950,
tp=1.1150
)

# Create order with just a stop-loss (TP calculated from R:R ratio)
await trader.create_order_with_sl(
order_type=OrderType.BUY,
sl=1.0950
)

# Create order using points distance
await trader.create_order_with_points(
order_type=OrderType.BUY,
points=500
)

# Create a simple order with no stops
await trader.create_order_no_stops(
order_type=OrderType.BUY,
volume=0.01
)







Checking and Sending





# Check if the order passes broker validation
can_trade = await trader.check_order()

if can_trade:
result = await trader.send_order()







Recording Trades



After sending, trades are automatically recorded via the record_trade method:




await trader.record_trade(
result=result,
parameters={"strategy": "EMA Crossover"},
name="EMAXOver",
expected_profit=25.50
)









Pre-Built Traders



aiomql ships with two ready-to-use Trader subclasses in the contrib package:






SimpleTrader



Places trades with a specified stop-loss. Volume is calculated based on the RAM

risk amount and the distance to the stop-loss.




from aiomql import SimpleTrader, ForexSymbol, OrderType

symbol = ForexSymbol(name="EURUSD")
trader = SimpleTrader(symbol=symbol)

await trader.place_trade(
order_type=OrderType.BUY,
sl=1.0950,
parameters={"name": "MyStrategy"}
)









ScalpTrader



Places trades using minimum volume and no stop-loss/take-profit levels.

Ideal for scalping strategies where positions are managed manually.




from aiomql import ScalpTrader, ForexSymbol, OrderType

symbol = ForexSymbol(name="EURUSD")
trader = ScalpTrader(symbol=symbol)

await trader.place_trade(
order_type=OrderType.BUY,
parameters={"name": "ScalpBot"}
)












Risk & Money Management (RAM)



The RAM (Risk Assessment & Money) class is at the heart of aiomql's risk

management. It calculates position sizes, enforces trade limits, and manages

your exposure.





Configuration





from aiomql import RAM

ram = RAM(
risk=2, # Risk 2% of free margin per trade
risk_to_reward=3, # 1:3 risk-to-reward ratio
min_amount=5, # Minimum $5 risk per trade
max_amount=500, # Maximum $500 risk per trade
loss_limit=3, # Max 3 losing positions at once
open_limit=5, # Max 5 total open positions
fixed_amount=None # Set to override percentage-based calculation
)







Calculating Risk Amount





# Get the amount to risk per trade (based on free margin)
amount = await ram.get_amount()
print(f"Amount to risk: ${amount:.2f}")

# If fixed_amount is set, it always returns that
ram.modify_ram(fixed_amount=100.0)
amount = await ram.get_amount() # Always $100







Enforcing Position Limits





# Check if we can open a new position
can_open = await ram.check_open_positions()
if not can_open:
print("Too many open positions!")

# Check if we've hit the loss limit
can_trade = await ram.check_losing_positions()
if not can_trade:
print("Too many losing positions!")







How the Amount is Calculated



The calculation flow is:




  1. If fixed_amount is set → return fixed_amount

  2. Otherwise → margin_free × (risk / 100)

  3. If min_amount and max_amount are set → clamp the result







Building a Strategy



The Strategy class is the cornerstone of aiomql. You subclass it, define your

parameters, and implement the trade() method. The framework handles everything

else — initialization, the execution loop, session management, and error handling.





Anatomy of a Strategy





from aiomql import Strategy, ForexSymbol, TimeFrame, Tracker, OrderType, Sessions, ScalpTrader


class MyStrategy(Strategy):
# Type annotations for strategy-specific parameters
ttf: TimeFrame
fast_period: int
slow_period: int
tracker: Tracker

# Default parameter values — these become instance attributes
parameters = {
"ttf": TimeFrame.H1,
"fast_period": 20,
"slow_period": 50,
}

def __init__(self, *, symbol: ForexSymbol, params: dict = None,
sessions: Sessions = None, name: str = "MyStrategy"):
super().__init__(symbol=symbol, params=params, sessions=sessions, name=name)
self.tracker = Tracker(snooze=self.ttf.seconds)
self.trader = ScalpTrader(symbol=self.symbol)

async def trade(self):
"""This method is called repeatedly by the execution loop."""
# 1. Fetch market data
candles = await self.symbol.copy_rates_from_pos(
timeframe=self.ttf, count=200
)

# 2. Apply indicators
candles.ta.sma(length=self.fast_period, append=True)
candles.ta.sma(length=self.slow_period, append=True)
candles.rename(
**{f"SMA_{self.fast_period}": "fast",
f"SMA_{self.slow_period}": "slow"},
inplace=True
)

# 3. Check for signals
if candles.ta_lib.above(candles.fast, candles.slow).iloc[-1]:
self.tracker.update(order_type=OrderType.BUY, snooze=3600)
elif candles.ta_lib.below(candles.fast, candles.slow).iloc[-1]:
self.tracker.update(order_type=OrderType.SELL, snooze=3600)
else:
self.tracker.update(order_type=None, snooze=self.ttf.seconds)

# 4. Execute or sleep
if self.tracker.order_type is not None:
await self.trader.place_trade(
order_type=self.tracker.order_type,
parameters=self.parameters
)
await self.delay(secs=self.tracker.snooze)
else:
await self.sleep(secs=self.tracker.snooze)







Key Concepts





Parameters Dictionary



The parameters class attribute defines default values for your strategy. When you

instantiate the strategy, you can override any parameter via the params argument:




strategy = MyStrategy(
symbol=ForexSymbol(name="EURUSD"),
params={"fast_period": 10, "slow_period": 30}
)






Parameters are also accessible as attributes thanks to __getattr__:




print(strategy.fast_period)  # 10









The Tracker



The Tracker (from aiomql.contrib.utils) is a lightweight state holder for

strategies. It stores the current order_type, a snooze duration, and any extra

state you want to track:




from aiomql import Tracker

tracker = Tracker(snooze=300) # default snooze of 5 minutes

# Update tracker state
tracker.update(
order_type=OrderType.BUY,
snooze=3600,
trend="bullish",
last_price=1.1050
)

# Access state
print(tracker.order_type) # OrderType.BUY
print(tracker.trend) # "bullish"









Sleep vs Delay





  • self.sleep(secs=...) — Computes the exact time until the next bar opens,
    ensuring your strategy wakes up right at the start of a new candle. This is
    critical for cooperative multitasking.


  • self.delay(secs=...) — A simple asyncio.sleep for the given duration.






Initialization



Override initialize() to run one-time setup. By default, it initializes the

symbol:




async def initialize(self):
"""Called once before the strategy starts trading."""
result = await self.symbol.initialize()
# Load historical data, train models, etc.
return result









Stopping a Strategy



Raise StopTrading from within trade() to gracefully stop the strategy:




from aiomql.core.exceptions import StopTrading

async def trade(self):
if some_condition:
raise StopTrading("Reached daily profit target")












Trading Sessions



Sessions let you restrict when a strategy can trade. This is essential for forex

markets where different sessions (London, New York, Tokyo) have different

characteristics.





Defining Sessions





from datetime import time
from aiomql import Session, Sessions

# Define individual sessions (times are in UTC)
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)
)

tokyo = Session(
name="Tokyo",
start=time(0, 0),
end=time(9, 0)
)







Session Actions



Sessions can automatically execute actions at their start and end:




# Close all positions when the London session ends
london = Session(
name="London",
start=time(8, 0),
end=time(16, 0),
on_end="close_all"
)

# Close only losing positions at session end
new_york = Session(
name="New York",
start=time(13, 0),
end=time(21, 0),
on_end="close_loss"
)

# Close only winning positions
tokyo = Session(
name="Tokyo",
start=time(0, 0),
end=time(9, 0),
on_end="close_win"
)

# Custom actions
async def my_start_action(session):
print(f"{session.name} started!")

async def my_end_action(session):
print(f"{session.name} ended!")

custom = Session(
name="Custom",
start=time(10, 0),
end=time(18, 0),
on_start="custom_start",
on_end="custom_end",
custom_start=my_start_action,
custom_end=my_end_action
)









Combining Sessions



Group sessions together with the Sessions class. When a strategy uses

Sessions, the framework automatically:




  1. Checks if the current time falls within any session

  2. Waits (sleeps) if outside all sessions

  3. Handles transitions between sessions (closing the previous, opening the next)



sessions = Sessions(sessions=[london, new_york])

strategy = MyStrategy(
symbol=ForexSymbol(name="EURUSD"),
sessions=sessions
)







Session Utilities





# Check if currently in session
print(london.in_session())

# Get session duration
duration = london.duration()
print(f"Duration: {duration.hours}h {duration.minutes}m")

# Seconds until session starts
secs = london.until()
print(f"Session starts in {secs} seconds")









The Bot Orchestrator



The Bot class is the top-level orchestrator that brings everything together.

It manages the MT5 terminal connection, initializes strategies, and coordinates

their execution.





Basic Usage





from aiomql import Bot, ForexSymbol
from my_strategies import EMAXOver, RSIStrategy

def main():
# Create symbols
symbols = [ForexSymbol(name=s) for s in ["EURUSD", "GBPUSD", "USDJPY"]]

# Create strategies
strategies = [EMAXOver(symbol=sym) for sym in symbols]

# Create bot and add strategies
bot = Bot()
bot.add_strategies(strategies)

# Run (blocks until shutdown)
bot.execute()


if __name__ == "__main__":
main()







Adding Coroutines



You can add background coroutines that run alongside your strategies:




async def log_account_status():
"""Periodically log account balances."""
from aiomql import Account
account = Account()
while True:
await account.refresh()
print(f"Balance: {account.balance}, Equity: {account.equity}")
await asyncio.sleep(60)


bot = Bot()
bot.add_strategies(strategies)

# Runs in the same event loop
bot.add_coroutine(coroutine=log_account_status)

# Runs on a separate thread (for CPU-intensive or blocking tasks)
bot.add_coroutine(
coroutine=some_blocking_task,
on_separate_thread=True
)









Adding Functions



For synchronous functions that should run in a thread pool:




import time

def heartbeat(interval=30):
while True:
print("Bot is alive...")
time.sleep(interval)


bot.add_function(function=heartbeat, interval=30)









Async Entry Point



If you're already inside an async context, use start() instead of execute():




async def main():
bot = Bot()
bot.add_strategies(strategies)
await bot.start()

asyncio.run(main())









What Happens Inside



When you call bot.execute():





  1. Terminal Start — connects to the MT5 terminal and logs in


  2. Strategy Initialization — each strategy's initialize() is called;
    strategies that fail are silently skipped


  3. Executor Start — the Executor runs all strategies, coroutines, and
    functions concurrently using asyncio tasks and thread pools









Position Tracking



aiomql provides a sophisticated position tracking system through the contrib.trackers

package. This allows you to monitor open positions and apply automated management rules.





OpenPosition



The OpenPosition class wraps a trade position with tracking, hedging, and stacking

capabilities:




from aiomql import OpenPosition, PositionTracker

# Create an OpenPosition from a trade result
pos = OpenPosition(
ticket=123456,
symbol="EURUSD",
# ... other position details
)

# Modify stop-loss and take-profit
await pos.modify_stops(sl=1.0960, tp=1.1120)

# Close the position
success, result = await pos.close_position()

# Add custom trackers to the position
pos.add_tracker(tracker=my_tracker, name="trailing_stop")









Position Tracking Functions



aiomql includes pre-built tracking functions:





  • exit_at_profit — Close a position when profit reaches a target price


  • extend_take_profit — Dynamically extend the take-profit as price moves favorably






OpenPositionsTracker



The OpenPositionsTracker manages all open positions and runs their trackers

automatically:




from aiomql import Bot, OpenPositionsTracker

bot = Bot()
bot.add_strategies(strategies)

# Track all open positions on a separate thread
bot.add_coroutine(
coroutine=OpenPositionsTracker(autocommit=True).track,
on_separate_thread=True
)

bot.execute()






This automatically:




  • Discovers all open positions

  • Runs any registered trackers on each position

  • Handles position closure and cleanup

  • Manages hedges, stacks, and pending orders









Trade Result Recording



Every trade can be automatically recorded for analysis. The Result class supports

three storage formats:





CSV





# In your Config or aiomql.json
config = Config(trade_record_mode="csv")

# Trades are saved to: <root>/trade_records/<strategy_name>.csv







JSON





config = Config(trade_record_mode="json")

# Trades are saved to: <root>/trade_records/<strategy_name>.json







SQLite





config = Config(trade_record_mode="sql")

# Trades are saved to a SQLite database in your project root







What Gets Recorded?



Each trade record includes:





  • Order result — ticket, deal, volume, price, retcode


  • Strategy parameters — all parameters from the strategy's parameters dict


  • Trade request — the actual request sent to the broker


  • Extras — timestamp, expected profit, strategy name





Manual Recording





from aiomql import Result
from aiomql.core.models import OrderSendResult

result = Result(
result=order_send_result,
parameters={"strategy": "EMA", "timeframe": "H1"},
name="EMAXOver",
expected_profit=25.0
)

await result.save(trade_record_mode="csv")









Trade History



The History class lets you retrieve completed deals and orders from your account

history:




from datetime import datetime, timedelta
from aiomql import History

# Get the last 7 days of history
history = History(
date_from=datetime.now() - timedelta(days=7),
date_to=datetime.now()
)

# Fetch deals and orders
await history.initialize()

# Access deals
print(f"Total deals: {history.total_deals}")
for deal in history.deals:
print(f" {deal.symbol}: {deal.profit}")

# Access orders
print(f"Total orders: {history.total_orders}")

# Filter by ticket
deals = history.filter_deals_by_ticket(ticket=123456)

# Filter by position ID
deals = history.filter_deals_by_position(position=789012)

# Filter by symbol group (e.g., only USD pairs)
history = History(
date_from=datetime.now() - timedelta(days=30),
date_to=datetime.now(),
group="*USD*"
)












Contributed Extensions



The contrib package contains community extensions that build on the core framework.






Strategies






Chaos



A demo strategy that randomly buys or sells. Useful for testing your infrastructure:




from aiomql import Chaos, ForexSymbol

strategy = Chaos(symbol=ForexSymbol(name="EURUSD"))









Symbols






ForexSymbol



Specialized Symbol subclass with pip calculations and volume computation based on

stop-loss distance. See the Symbols section above for details.





Traders





SimpleTrader



Trades with a stop-loss, calculating volume from risk.

See above.





ScalpTrader



Trades with minimum volume and no stops.

See above.





Trackers





Tracker (Strategy Tracker)



A lightweight state holder for tracking strategy signals and snooze timers.

See the Strategy section.





PositionTracker



Wraps a tracking function to execute on an open position.





OpenPositionsTracker



Automatically discovers and manages all open positions.

See the Position Tracking section.







Multi-Process Execution



For running completely independent bots in parallel, use Bot.process_pool():




from aiomql import Bot, ForexSymbol
from strategies import ForexStrategy, CryptoStrategy


def run_forex():
bot = Bot()
symbols = [ForexSymbol(name=s) for s in ["EURUSD", "GBPUSD"]]
strategies = [ForexStrategy(symbol=s) for s in symbols]
bot.add_strategies(strategies)
bot.execute()


def run_crypto():
bot = Bot()
symbols = [ForexSymbol(name=s) for s in ["BTCUSD", "ETHUSD"]]
strategies = [CryptoStrategy(symbol=s) for s in symbols]
bot.add_strategies(strategies)
bot.execute()


# Run both bots in separate processes
Bot.process_pool(
processes={
run_forex: {},
run_crypto: {}
},
num_workers=2
)






Each process gets its own event loop, MT5 connection, and strategy set. This is

useful when you want complete isolation between different trading systems.









Synchronous API



Every async class in aiomql has a synchronous counterpart. This makes the library

usable in Jupyter notebooks, simple scripts, or anywhere you don't want to deal with

asyncio.






Synchronous MetaTrader






from aiomql.core.sync import MetaTrader as SyncMetaTrader

mt5 = SyncMetaTrader()
mt5.initialize_sync()
mt5.login_sync(login=12345678, password="your_password", server="YourBroker-Demo")

account = mt5._account_info()
print(f"Balance: {account.balance}")

mt5.shutdown()









Synchronous Strategy Initialization






# The Bot class handles sync initialization internally
bot = Bot()
bot.execute() # Uses sync initialization under the hood









Synchronous RAM






ram = RAM(risk=2)
amount = ram.get_amount_sync()
can_trade = ram.check_open_positions_sync()












Full Example: EMA Crossover Bot



Here's a complete, production-ready example that puts everything together:






Project Structure






my_trading_bot/
├── aiomql.json
├── strategies/
│ ├── __init__.py
│ └── ema_crossover.py
└── bot.py









aiomql.json






{
"login": 12345678,
"password": "your_password",
"server": "YourBroker-Demo",
"trade_record_mode": "csv"
}









strategies/ema_crossover.py






from aiomql import (
Strategy, ForexSymbol, TimeFrame, Tracker,
OrderType, Sessions, ScalpTrader
)


class EMAXOver(Strategy):
"""EMA Crossover strategy.

Buys when the fast EMA crosses above the slow EMA.
Sells when the fast EMA crosses below the slow EMA.
"""

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, # 3 hours cooldown after a trade
}

def __init__(self, *, symbol: ForexSymbol, params: dict = 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 = ScalpTrader(symbol=self.symbol)

async def find_entry(self):
# Fetch candle data
candles = await self.symbol.copy_rates_from_pos(
timeframe=self.ttf, count=self.tcc
)

# Calculate EMAs
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,
)

# Check for crossover signals
fast_above_slow = candles.ta_lib.above(
candles.fast_ema, candles.slow_ema
)
fast_below_slow = candles.ta_lib.below(
candles.fast_ema, candles.slow_ema
)

if fast_above_slow.iloc[-1]:
self.tracker.update(
order_type=OrderType.BUY,
snooze=self.timeout
)
elif fast_below_slow.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:
# No signal — sleep until next bar
await self.sleep(secs=self.tracker.snooze)
else:
# Signal found — place trade and cooldown
await self.trader.place_trade(
order_type=self.tracker.order_type,
parameters=self.parameters,
)
await self.delay(secs=self.tracker.snooze)









bot.py






import logging
from aiomql import Bot, ForexSymbol, OpenPositionsTracker
from strategies.ema_crossover import EMAXOver

logging.basicConfig(level=logging.INFO)


def main():
# Define symbols to trade
symbols = [
ForexSymbol(name=s)
for s in ["EURUSD", "GBPUSD", "USDJPY"]
]

# Create a strategy instance for each symbol
strategies = [EMAXOver(symbol=sym) for sym in symbols]

# Create the bot
bot = Bot()
bot.add_strategies(strategies)

# Track open positions on a separate thread
bot.add_coroutine(
coroutine=OpenPositionsTracker(autocommit=True).track,
on_separate_thread=True
)

# Start trading
bot.execute()


if __name__ == "__main__":
main()












Architecture Overview






┌─────────────────────────────────────────────────────┐
│ Bot (Orchestrator) │
│ ┌──────────────────────────────────────────────┐ │
│ │ Executor │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────────────┐│ │
│ │ │Strategy 1│ │Strategy 2│ │ Coroutines/ ││ │
│ │ │(EURUSD) │ │(GBPUSD) │ │ Functions ││ │
│ │ └────┬────┘ └────┬────┘ └────────┬────────┘│ │
│ └───────┼───────────┼───────────────┼──────────┘ │
│ │ │ │ │
│ ┌───────▼───────────▼───────────────▼──────────┐ │
│ │ Shared Services │ │
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐│ │
│ │ │ Config │ │MetaTrader│ │ RAM │ │ Result ││ │
│ │ │(single)│ │(single) │ │ │ │ ││ │
│ │ └────────┘ └────────┘ └────────┘ └────────┘│ │
│ └──────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────┐
│ MetaTrader 5 │
│ Terminal │
│ (asyncio.to_thread)│
└─────────────────────┘









Design Principles





  1. Singletons — Config and MetaTrader in some cases are singletons, ensuring consistent
    state across all components.


  2. Async-first — Every MT5 call is wrapped with asyncio.to_thread, keeping
    the event loop responsive.


  3. Composition — Components are designed to be composed. A Strategy uses a
    Symbol, Trader, RAM, and Sessions.


  4. Separation of concerns — Market data (Symbol, Candles, Ticks), trade
    execution (Order, Trader), risk management (RAM), and orchestration (Bot,
    Executor) are all separate modules.









Summary


































































































Feature Module Description
MT5 Connection MetaTrader Async MT5 interface with retry
Configuration Config Singleton JSON/programmatic config
Market Data
Symbol, Candles, Ticks
Symbols, OHLC bars, tick data
Technical Analysis ta_libs pandas-ta + optional TA-Lib
Orders Order Check, send, margin/profit calc
Trade Execution
Trader, SimpleTrader, ScalpTrader
High-level trade placement
Risk Management RAM Position sizing, trade limits
Strategy Strategy Base class for trading logic
Sessions
Session, Sessions
Time-window trading restrictions
Orchestration
Bot, Executor
Multi-strategy concurrent execution
Position Tracking
OpenPositionsTracker, OpenPosition
Trailing stops, hedging, stacking
Trade Recording Result CSV, JSON, SQLite persistence
History History Deal and order history queries
Forex Helpers ForexSymbol Pip calc, volume from SL
Positions Positions Open position management
Multi-Process Bot.process_pool() Run bots in parallel processes
Sync API
core.sync, lib.sync
Synchronous mirrors


aiomql takes care of the infrastructure, the connection handling, the execution

loops, and the bookkeeping — so you can focus on what matters: your trading

strategy
.






For the full API reference, see the documentation.



aiomql is MIT-licensed and maintained by Ichinga Samuel.









Support This Project



If you found this tutorial helpful, consider supporting the development of aiomql:



1. Sofort-Triage & Abwehrmaßnahmen

SOC Incident Playbook: Remote Code Execution (RCE) Defense
Syntax validiert (0 Fehler)
title: Detect Exploitation - AIOMQL-The Complete Guide to Building Algorithmic Trading Bots with Python & MetaTrader 5
id: 129e71a2-1b80-487c-a7eb-7fd9803c967b
status: experimental
description: Automatisch generierte SIEM-Erkennungsregel basierend auf CTI Intelligence
references:
  - https://tsecurity.de/
author: iShareStuff CTI Automated Detection Engine
date: 2026-09-25
logsource:
  category: network_connection
  product: any
detection:
  selection:
      CommandLine|contains:
        - 'exploit'
  condition: selection
falsepositives:
  - Legitime administrative Zugriffe oder Penetrationstests
level: high
tags:
  - attack.initial_access
Syntax validiert (0 Fehler)
rule CTI_Threat_Indicator {
    meta:
        author = "iShareStuff CTI Automated Detection Engine"
        date = "2026-09-25"
        description = "YARA Signature for "
    strings:
        $str = "AIOMQL-The Complete Guide to B" ascii wide
    condition:
        any of them
}
Syntax validiert (0 Fehler)
index=security sourcetype IN ("cisco:asa", "pan:traffic", "zeek_conn", "suricata", "WinEventLog:Security")
("AIOMQL-The Complete Guide to Building Al")
| stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip, dest_ip, dest_host, signature
| eval first_seen=strftime(first_seen, "%Y-%m-%d %H:%M:%S"), last_seen=strftime(last_seen, "%Y-%m-%d %H:%M:%S")
| sort - count
Syntax validiert (0 Fehler)
message: "*AIOMQL-The Complete Guide to Building Al*"
Syntax validiert (0 Fehler)
CommonSecurityLog
| where Message has "AIOMQL-The Complete Guide to Building Al"
| summarize EventCount = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by SourceIP, DestinationIP, DestinationPort, Activity
| extend DetectionRule = "iShareStuff-CTI-Compiled"
| sort by EventCount desc

2. Cyber Threat Intelligence & Forensik

CTI Threat Relationship Graph2 Knoten / 1 Relationen
CVE / Incident Software MITRE ATT&CK CWE Weakness IoC
🎯
MITRE ATT&CK Matrix Navigator 14 Taktiken
Reconnaissance
-
Resource Development
-
Initial Access
Execution
Persistence
-
Privilege Escalation
Defense Evasion
Credential Access
-
Discovery
-
Lateral Movement
-
Collection
-
Command and Control
Exfiltration
-
Impact
tsecurity.de Cognitive Threat RAG
Fokus-Vektor:

Kognitive Analyse für identifizierte Bedrohung: Erhöhte Bedrohungslage im Bereich AIOMQL-The Complete Guide to Building Al.... Basierend auf 368k Vektor-Korrelationen werden sofortige Isolationsmaßnahmen für betroffene Endpunkte empfohlen.

🛡️ Angriffsfläche & Exposure

Netzwerk/Remote-Zugriff ohne Vorauthentifizierung möglich.

⚡ Empfohlene Sofortmaßnahmen
  • 1. Perimeter-Inspektion: Relevante Portfreigaben und exponierte Endpunkte unverzüglich scannen.
  • 2. Patch-Applikation: Hersteller-Hotfix einspielen oder betroffene Daemons in isolierte DMZ-Segmente überführen.
  • 3. Telemetrie & EDR-Alerts: Prozessaufrufe und Child-Processes auf anomale Shell-Spawns überwachen.
🔗 Semantisch verwandte Zero-Days MariaDB 11.7 VEC
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten AIOMQL-The Complete Guide to Building Algorithmic Trading Bots with Python & MetaTrader 5

Thematisch verwandte Begriffe: AIOMQLThe, Complete, Guide, Building · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-85291 | InvoicePlane is a self-hosted open source application for managing invoi…
Advisory →
tsecurity.de Icon
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag