Module 5 — Algorithmic trading · Lesson 23 of 23 · 8 min

Execution, monitoring and risk of an algorithm

From test to live account: paper trading, architecture, execution with MetaTrader 5, the essential safety systems, monitoring drift and what to do when things go wrong.

A positive backtest is not a green light. Between the test and the live account there are obstacles the test doesn't see: variable spreads, slippage, rejected orders, bugs, connection outages, broker rule changes. This lesson guides you through a gradual and prudent transition, with the safety systems that must exist before running an algorithm with money.

  1. A solid backtest with realistic costs and validation (previous modules).
  2. Paper trading (real-time data, simulated orders or on a demo account) for at least a few weeks and a minimum number of trades.
  3. Live with minimum size (risk 0.1-0.25%) for 1-3 months, to verify execution, slippage and real behaviour.
  4. Gradual increase only if results stay consistent with the test and the safety limits work.

What changes between test and live

AspectIn the backtestLive
Entry priceOpen of the next candleAvailable price with slippage and delay
SpreadFixed or averageVariable: widens on news and at night
Order rejectionNeverPossible (requote, market closed, margin)
OutagesNoneConnection, broker servers, updates
HoursClean dataClock changes, holidays, unusual closures
BehaviourFixed rulesTemptation to intervene by hand

The architecture of an execution system

A simple but robust system has these blocks:

  1. Data ingestion: reads closed candles (from the broker or a reliable source).
  2. Signal engine: the same code used in the backtest, applied in real time to the candle that has just closed.
  3. Risk manager (risk guard): a module that can block any order (daily limits, maximum positions, abnormal spread, hours).
  4. Executor: sends orders to the broker with stop loss and take profit already set.
  5. Log: records every decision, order and response.
  6. Monitoring and alerts: notifies errors and threshold breaches.
  7. Kill switch: a simple way to shut everything down (even by hand).

The key principle: the risk guard must be independent of the signal engine and have the last word.

A risk guard example

An outline in pure Python (no broker dependencies), to be thoroughly tested:

from datetime import datetime, timezone

class RiskGuard:
    def __init__(self, max_daily_loss_r=2.0, max_trades_per_day=3, max_spread_pips=2.5,
                 max_open_positions=1, allowed_hours=(7, 10)):
        self.max_daily_loss_r = max_daily_loss_r
        self.max_trades_per_day = max_trades_per_day
        self.max_spread_pips = max_spread_pips
        self.max_open_positions = max_open_positions
        self.allowed_hours = allowed_hours
        self.reset_day()

    def reset_day(self):
        self.day = datetime.now(timezone.utc).date()
        self.daily_r = 0.0
        self.trades_today = 0
        self.killed = False

    def register_result(self, r):
        self.daily_r += r
        if self.daily_r <= -self.max_daily_loss_r:
            self.killed = True          # daily loss limit reached

    def can_trade(self, spread_pips, open_positions, now=None):
        now = now or datetime.now(timezone.utc)
        if now.date() != self.day:
            self.reset_day()
        if self.killed:
            return False, "kill switch: daily loss reached"
        if self.trades_today >= self.max_trades_per_day:
            return False, "maximum daily trades"
        if open_positions >= self.max_open_positions:
            return False, "maximum open positions"
        if spread_pips > self.max_spread_pips:
            return False, "abnormal spread"
        if not (self.allowed_hours[0] <= now.hour < self.allowed_hours[1]):
            return False, "outside the time window"
        return True, "ok"

Every order goes through can_trade: if it returns False, nothing is sent and the reason is written to the log.

An order-sending example with MetaTrader 5 (outline only, on demo)

MetaTrader 5 has an official Python library (the MetaTrader5 package, on Windows). An outline of sending an order with stop and take profit:

import MetaTrader5 as mt5

def open_long(symbol, lots, sl, tp, magic=20260101):
    if not mt5.initialize():
        raise RuntimeError("MT5 not initialised")
    tick = mt5.symbol_info_tick(symbol)
    request = {
        "action": mt5.TRADE_ACTION_DEAL,
        "symbol": symbol,
        "volume": lots,
        "type": mt5.ORDER_TYPE_BUY,
        "price": tick.ask,
        "sl": sl,
        "tp": tp,
        "deviation": 10,                 # maximum tolerated slippage (in points)
        "magic": magic,                  # identifies your algorithm's orders
        "comment": "algo-demo",
        "type_time": mt5.ORDER_TIME_GTC,
        "type_filling": mt5.ORDER_FILLING_IOC,
    }
    result = mt5.order_send(request)
    ok = result is not None and result.retcode == mt5.TRADE_RETCODE_DONE
    return ok, result

Key points: stop and take profit sent with the order, a magic number to recognise your positions, a slippage limit (deviation), the retcode check and never an order without going through the risk guard. The details (filling modes, symbols, decimals) depend on the broker: read the official documentation and try on demo.

The essential safety systems

  • A stop loss on every position, sent to the broker together with the order (not managed "by the program").
  • A daily and weekly loss limit that shuts the algorithm down.
  • A maximum number of positions and a maximum size (a "hard" value in the code: if the calculation produces an enormous volume through a bug, it's cut).
  • Spread filter and time filter.
  • An easy-to-use manual kill switch (for example a "STOP" file the program checks every loop).
  • Check of open positions at startup: avoids opening duplicates after a restart.
  • Complete log of every decision and order, with UTC date and time.
  • No "martingale" or automatic size increases after losses.

Monitoring: how to notice something is wrong

Regularly compare live statistics with the backtest's:

  • Win rate, average R of wins and losses, expectancy.
  • Average slippage and effective spread paid.
  • Number of expected vs. occurred signals.
  • Real drawdown vs. the Monte Carlo distribution.

If after a significant sample (say 50-100 trades) live statistics are much worse than the expected interval, stop the algorithm and investigate: the market may have changed, the test was optimistic or there's an execution error. Rule: before risking more, verify that live confirms the test.

What can go wrong (and how to prepare)

ScenarioDefence
A bug opening multiple positionsMaximum positions and size limits; check at startup
Connection loss with open positionsStop and TP already at the broker; alert
Abnormal spread or newsSpread and news filter
The broker changes leverage, symbols or hoursPeriodic check of conditions
The server restartsPosition reconciliation; restart script
Losing streak longer than expectedDaily/weekly limits; Monte Carlo for realistic expectations
The market changes regimeDrift monitoring; shutdown if statistics collapse

To run the algorithm without interruption many use a virtual private server (VPS), but this adds costs and error surface: assess whether it's really needed.

Course conclusion

You've travelled a whole path: market structure, liquidity, areas, timing, trading model, management, plan, statistical validation, critical evaluation of evidence and automation. The real skill isn't knowing the terms: it's being able to measure whether an idea has an edge, manage risk when it doesn't and stay honest with your own data. Go slowly, with capital you can afford to lose, always keep a journal of your results and remember that the best protection is prudence.

Come back whenever you like to the community to share your tests, to the tools to calculate risk and size and to the market analysis to train reading context.

In short

  • From backtest to live: paper trading, live at minimum size, gradual growth.
  • Execution requires an independent risk guard, stop and TP at the broker, logs and a kill switch.
  • Try every piece of code on demo and make it impossible to open positions outside the rules.
  • Monitor live statistics against the test and stop if they diverge significantly.
  • Plan for failure scenarios and put prudence first.

Practical exercise

  1. Write the rules of your risk guard (daily loss, number of trades, maximum spread, hours).
  2. Test the RiskGuard class with hand-built cases (maximum loss reached, high spread, out of hours).
  3. Prepare a paper-trading plan of at least a month with algorithm stop thresholds if statistics diverge from the test.

Test what you've learned

1. Why must stop and TP be sent with the order?

2. What is the risk guard's role?

3. What do you do if live statistics are much worse than expected?

4. Why start with minimum size live?

Have a question or want to share your exercise?

Post in the community, or join the free signals room on Telegram.

Educational content, not financial advice. Trading involves risk. ICT is a term referring to the materials of Michael Huddleston: this course is independent and not affiliated.