Quant Python: Architecting Autonomous Trading Systems

Quant Python: Architecting Autonomous Trading Systems

Day 32:Order Enums: Mapping Status Transitions at Execution Speed

Python Quant's avatar
Python Quant
Apr 09, 2026
∙ Paid

What You Will Learn Today

By the end of this lesson, you will understand why string comparisons on order status lead to silent P&L corruption, and you will have a working state machine that prevents it. This is the kind of code that separates engineers who have watched an order disappear from engineers who have not.

You will build three things:

  • OrderStatus — an enum that maps exactly to Alpaca’s wire format

  • Order — a frozen, immutable snapshot of every order state

  • OrderStateMachine — a guard that enforces valid transitions and prevents impossible state hops

Before you start: You need Python 3.11 or later, a free Alpaca Paper Trading account at alpaca.markets, and about 30 minutes. Run python --version now to confirm.


The “Dictionary of Strings” Trap

When someone first wires up a live broker API, the order update handler usually looks something like this. It seems reasonable. It works in backtests.

# This code will work in your backtest.
# It will fail silently in production.

def handle_order_update(payload: dict) -> None:
    if payload["status"] == "filled":
        record_fill(payload)
    elif payload["status"] == "canceled":
        cancel_position(payload)
    elif payload["status"] == "new":
        track_pending(payload)

Four ways this breaks in production

Each of these is a real failure mode. None of them will raise an exception. They all corrupt state silently.

1. Alpaca returns "partially_filled" as a distinct status. Your record_fill never runs. The order sits in limbo. You accumulate unhedged delta that grows with every price tick.

2. You cannot add a new status without breaking the chain. "pending_new", "accepted", "pending_cancel" — all valid Alpaca statuses, all unhandled. Not handled means silently skipped.

3. No transition guard. Nothing stops an order from jumping from NEW to FILLED without logging PARTIALLY_FILLED intermediate states. On a partial fill, your P&L calculation is wrong.

4. Thread safety is zero. If two WebSocket messages for the same order arrive out of order — a common occurrence under load — the mutable dict gets overwritten. The earlier message wins or loses depending on timing alone.


The Failure Mode

The technical crash is not an exception — that would be easy to catch. The failure mode is silent state corruption.

Picture a volatility spike during an earnings announcement. Your strategy fires 12 orders in 400 milliseconds. The Alpaca WebSocket pushes updates out of sequence, which is completely normal under load. Your string-comparison handler processes FILLED before PARTIALLY_FILLED for order #7. The position tracker marks the order complete at 80 shares instead of 100. The remaining 20 shares stay open, untracked, working against you.

By the time you notice, the position has moved 0.8% against you. On 100 orders per day that is not a rounding error — it is account ruin, compounding silently, with no log entry anywhere.

Root cause: The absence of a state machine. Without enforced transition rules, your order lifecycle is a free-for-all. An order can go from any state to any other state, in any order, and nothing complains.


The AutoQuant-Alpha Architecture

The solution has three layers. Each layer solves exactly one problem, and they are designed to compose cleanly.

Layer 1 — OrderStatus (StrEnum)

User's avatar

Continue reading this post for free, courtesy of Python Quant.

Or purchase a paid subscription.
© 2026 Python Quant · Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture