Day 22: The Security Base Class
Engineering a type-safe, memory-efficient abstraction for every tradeable asset in the engine.
Contents
1. The “Fat Dataclass” Trap
Junior engineers — and most tutorial code you will find online — model a security like this:
# DON'T DO THIS
security = {
"symbol": "AAPL",
"price": 182.5000000000002, # float arithmetic gift
"fractionable": True,
"option_strike": None, # None for equities — why is this field here?
"crypto_network": None, # likewise
"tradable": True,
}
Sometimes it graduates to a dataclass with 30 fields and 12 Optional[...] annotations. Same problem. You add CryptoPerp support six weeks later, forget to implement margin_requirement(), and the gap between “it compiled” and “it blew up in production” is exactly one leveraged trade.
This is not a hypothetical. Real money disappears this way. The abstraction boundary you build today is the wall between a systematic edge and account ruin.
2. The Failure Mode: Three Silent Killers
None of these failures shout at you. They accumulate quietly — in your P&L, in your memory, in your first 3 AM incident.
Killer 1 — Float Price Drift
>>> tick = 0.01
>>> price = 182.50
>>> price % tick
7.105427357601002e-15 # should be 0.0
Your tick-violation check passes because 7e-15 is not zero but is also not caught as an error. The broker rejects the order. You never see the failure — it lands in an async callback you forgot to handle. The order is silently dropped.
Killer 2 — Memory Bloat at Universe Scale
Without __slots__, every Python instance carries a __dict__. For 10,000 securities in a universe scan:
This is before you attach market data. At 50,000 symbols — the full US equity universe — the difference is 13 MB of dead weight the GC must clean up on every tick cycle.
Killer 3 — Structural Incompleteness
No abstract base class enforcement means CryptoPerp.margin_requirement() is silently missing until your risk engine calls it. Python’s duck typing will not save you here — the attribute access will succeed, the method will not exist, and you will get an AttributeError in the middle of a volatility spike. The abstract contract is the last line of defense.
3. The AutoQuant-Alpha Architecture
We build three tightly coupled components. Each layer has exactly one responsibility and no knowledge of the layers above it.
PriceConstraints (frozen dataclass, Decimal arithmetic)
└─ Security (ABC, __slots__, @abstractmethod enforcement)
├─ Equity (NYSE / NASDAQ / OTC)
├─ Crypto (Spot, Alpaca BASE/QUOTE format)
└─ Future (homework — CME Globex)
└─ SecurityRegistry (thread-safe singleton + Alpaca hydration)
The invariants enforced at construction time are non-negotiable:
Symbol is normalized — uppercase, non-empty, valid charset per asset class.
Prices are
Decimal, neverfloat. The type system is the first validator.Tick size is stored as
Decimalfor exact modular arithmetic.Status is a typed
Enum— not a string you can typo at 2 AM.




