Day 29 — The Base Order: Side, Qty, and Type
Every trading system begins with a single abstraction: the order. Get this layer wrong and every component built on top of it inherits the flaw. This lesson builds it right, from scratch.
Table of Contents
1. The Dictionary Trap
Every new quant engineer writes this on day one. It works in a notebook, it passes a smoke test, and it gets merged:
# Looks fine. Ships to production. Causes account ruin.
order = {
"symbol": "AAPL",
"side": "buy",
"qty": 10.0,
"type": "market",
}
submit_order(order)
Then, at 09:31:04 EST on a high-volatility open, the async event loop processes two signals concurrently. A position-sizing coroutine reads
order["qty"]while a risk-gate coroutine is mid-write. You now have a torn read on a mutable dict. Your fill comes back for 7 shares on a 10-share order. Your P&L model is off by 3 shares forever, silently.That is the dictionary order trap. It is not a beginner mistake — it is an architectural one. Everything built on top of it inherits the flaw. We fix it at the foundation.
2. Three Failure Modes
These are not hypothetical edge cases. Each one has taken money out of real accounts.
Crash 01 — Floating-Point Qty Drift
# Simulating accumulated partial fills
qty_filled = 0.0
fills = [0.1] * 10 # ten 0.1-share fills
for f in fills:
qty_filled += f
print(qty_filled) # 0.9999999999999999
print(qty_filled == 1.0) # False
Your position reconciliation now shows -0.0000000000000001 shares. Multiplied across 500 positions and 6.5 trading hours, this is not rounding error — it is a systematic P&L leak that compounds into real dollar discrepancies at month-end.
Crash 02 — String Side Misrouting
SIDE_MAP = {"BUY": 1, "SELL": -1}
order["side"] = "Buy" # Capital B, lowercase uy — easy to type by hand
multiplier = SIDE_MAP[order["side"]] # KeyError at market open
StrEnum eliminates this entirely. Side.BUY == "buy" is True. You cannot construct an invalid side value at all — the error happens at the source, not at execution time.
Crash 03 — Mutable State in Async Context
# risk_gate coroutine
async def apply_risk_cap(order: dict, cap: float) -> None:
if order["qty"] > cap:
order["qty"] = cap # mutates shared reference
# sizing coroutine running concurrently
async def apply_kelly(order: dict, fraction: float) -> None:
order["qty"] = order["qty"] * fraction # reads mid-mutation
Python’s GIL does not protect you here. asyncio coroutines yield at await points, not at arbitrary dict mutations. Two coroutines operating on the same dict reference will tear each other’s writes. This bug never appears in your unit tests — only under load.
3. The AutoQuant-Alpha Architecture
We build BaseOrder around three constraints. Each one directly eliminates one of the crashes above.





