Skip to content
Course contents
From analysis to automation

The parts of an automated system

An automated trading system is not one program but several cooperating parts: a data feed, a strategy, a risk gate, an order manager, a broker connection, and a logger. This chapter draws the map the rest of the course fills in, and shows how the parts pass control around a single loop.

9 min readChapter 3 of 28
What you will learn
  • Name the components of an automated trading system and each one's responsibility
  • Trace the control loop from incoming data to a placed order to a recorded result
  • Explain why separating these concerns makes a system safer and testable

Think about what you do when you trade by hand, even if you have never named the steps. You watch a price. You decide, from some rule in your head, whether to act. You sanity-check the decision: is this size sensible, have I already lost too much today. If it passes, you place the order. And, if you are disciplined, you write it down. An automated system does exactly these things, with one difference. Each step becomes a separate part of a program, so it happens the same way every time and can be tested on its own. Learn the parts now as names, because the rest of the course builds them one by one.

The parts, and what each is for

An automated system has six parts, and each has one job.

The data feed brings prices in. For a backtest that is a file of history; for live trading it is a stream from the broker. It answers one question: what is the price now.

The strategy is the rule. It takes the incoming data and returns intended orders, such as "I want to buy 10 shares." It decides what to do, not how to do it. This is where your backtested idea lives.

The risk gate is the guard that stands between the strategy and the market. It can veto an order that breaks a rule: too large, past a position limit, after the day's loss cap is hit. It answers one question: is this order allowed.

The order manager takes approved orders, sends them to the broker, and remembers every one, so nothing is sent twice or lost track of.

The broker gateway is the connection to the outside world, the part that actually places the order. For this entire course it is the simulated broker. Only at the very end, and only with great care, is it ever a real one.

The logger is the witness. It records every price, decision, order, and fill, so you can see later exactly what the system did and why.

Notice the deliberate separation. The strategy decides, a separate gate approves, a separate manager sends. The strategy never touches the broker directly. That is not fussiness, it is safety, and the reason will become concrete in the risk chapters.

The loop that ties them together

A live system runs a loop. A price arrives, the strategy reacts, the risk gate rules, the order manager sends, the logger records, and it waits for the next price. Here is the whole shape as a runnable skeleton, with each part a stub that just prints what it does.

ExampleThe parts of a trading system and the loop that connects themch03/system_skeleton.py
# The skeleton of an automated trading system: the parts, and how control passes
# among them for each incoming price. Every part here is a stub that just prints
# what it does; later chapters build the real versions. The point is the SHAPE:
#   data feed -> strategy -> risk gate -> order manager -> broker
# with a logger recording every step. These names carry through the whole course.


class Logger:
    def record(self, event):
        print("LOG:", event)


class DataFeed:
    """Hands out prices one at a time. Later: a live stream from the broker."""
    def __init__(self, prices):
        self._prices = iter(prices)

    def next_price(self):
        return next(self._prices, None)


class Strategy:
    """Turns a price into intended orders. Toy rule: buy once, on the first dip."""
    def __init__(self):
        self.bought = False

    def on_price(self, symbol, price):
        if not self.bought and price < 1400:
            self.bought = True
            return [{"symbol": symbol, "side": "BUY", "quantity": 10}]
        return []


class RiskGate:
    """Approves or blocks an intended order. Toy rule: at most 50 shares."""
    def check(self, intent):
        return intent["quantity"] <= 50


class OrderManager:
    """Sends approved orders to the broker and remembers them."""
    def __init__(self, broker, logger):
        self.broker = broker
        self.logger = logger

    def send(self, intent):
        self.logger.record(f"sending {intent}")
        return self.broker.place_order(intent)


class Broker:
    """Stands in for the real broker. Later this is the paper broker, then, only
    with great care, a real one."""
    def place_order(self, intent):
        return {"status": "FILLED", **intent}


def run(prices):
    logger = Logger()
    feed = DataFeed(prices)
    strategy = Strategy()
    risk = RiskGate()
    orders = OrderManager(Broker(), logger)
    symbol = "RELIANCE"

    while True:
        price = feed.next_price()
        if price is None:
            break
        logger.record(f"price {symbol} {price}")
        for intent in strategy.on_price(symbol, price):
            if risk.check(intent):
                result = orders.send(intent)
                logger.record(f"filled {result}")
            else:
                logger.record(f"BLOCKED by risk gate: {intent}")


run([1405, 1398, 1402])
Output
LOG: price RELIANCE 1405
LOG: price RELIANCE 1398
LOG: sending {'symbol': 'RELIANCE', 'side': 'BUY', 'quantity': 10}
LOG: filled {'status': 'FILLED', 'symbol': 'RELIANCE', 'side': 'BUY', 'quantity': 10}
LOG: price RELIANCE 1402

Read the output as a story. A price arrives at 1,405, and the strategy is not interested yet. The next price, 1,398, dips below the strategy's threshold, so it returns an intent to buy 10 shares. The risk gate checks that size against its limit of 50 and approves it. The order manager sends it, the stub broker reports it filled, and the logger records each step. The third price arrives and the strategy, having already bought, does nothing. That is the entire heartbeat of an automated system. Everything else in this course makes one of these stub parts real: a genuine data stream, an actual strategy from your backtest, a risk gate with money limits, an order manager that survives a restart, and the simulated broker in the broker's place.

The parts of an automated trading system and the loop that connects them, from data feed to strategy to risk gate to order manager to broker, with a logger recording each step.
The parts of an automated trading system and the loop that connects them, from data feed to strategy to risk gate to order manager to broker, with a logger recording each step.

Why the parts stay separate

You might ask why not write it as one short script that reads a price and fires an order. Because a system that touches money has to be trustworthy, and trust comes from being able to test and reason about each part on its own.

When the risk gate is its own component, you can test that it blocks a too-large order without ever touching a broker. When the broker is just a component behind a common interface, you can run the entire system against the simulated broker, prove it behaves, and only then swap in a real connection with nothing else changed. When the strategy can reach the market only through the risk gate, no bug in the strategy can bypass your limits. Separation is what lets you sleep while a program trades.

What to carry forward

An automated trading system is six parts with one job each: a data feed brings prices in, a strategy turns them into intended orders, a risk gate approves or blocks, an order manager sends and remembers, a broker gateway places the order, and a logger records everything. They run in a loop, and keeping them separate is what makes the system testable and safe, especially the rule that the strategy touches the market only through the risk gate. The rest of the course builds these parts in turn. The next chapter sets up the workbench and the single most important safety habit: building and testing everything against a simulated broker, never a real one.