ARCH Production Architecture
Designing a production-grade, scalable trading system architecture
Learning Objectives
- •Design production-ready trading system architecture
- •Understand microservices vs monolith for trading
- •Plan for failover, redundancy, and disaster recovery
Explain Like I'm 5
Production architecture is the blueprint for how all the pieces fit together: data ingestion, feature engineering, model inference, order management, risk control, monitoring. A good architecture separates concerns, handles failures gracefully, and can be maintained and upgraded without downtime.
Think of It This Way
System architecture is like city planning. You need roads (data pipelines), buildings (services), traffic lights (risk controls), hospitals (error recovery), and police (monitoring). Poor city planning creates gridlock and chaos. Good planning creates a city that functions smoothly even during rush hour.
1V7 Production Architecture
2Scaling Considerations
Hands-On Code
Modular Architecture Components
from abc import ABC, abstractmethod
class DataProvider(ABC):
"""Abstract data provider — swap MT5 for any other source."""
@abstractmethod
def get_bars(self, symbol, timeframe, bars): pass
@abstractmethod
def is_connected(self) -> bool: pass
class SignalGenerator(ABC):
"""Abstract signal generator — L1 model."""
@abstractmethod
def predict(self, features) -> float: pass
class RiskManager(ABC):
"""Abstract risk manager — S40 and friends."""
@abstractmethod
def check_risk(self, signal) -> bool: pass
@abstractmethod
def get_position_size(self, signal) -> float: pass
class OrderExecutor(ABC):
"""Abstract order executor — swap between live and paper."""
@abstractmethod
def execute(self, order) -> dict: pass
class TradingEngine:
"""Composable trading engine."""
def __init__(self, data: DataProvider, signals: SignalGenerator,
risk: RiskManager, executor: OrderExecutor):
self.data = data
self.signals = signals
self.risk = risk
self.executor = executor
def run_cycle(self, symbols):
"""One trading cycle."""
for symbol in symbols:
bars = self.data.get_bars(symbol, 'M15', 200)
features = compute_features(bars) # 38 features
score = self.signals.predict(features)
if score < 0.50:
continue
signal = {'symbol': symbol, 'score': score}
if not self.risk.check_risk(signal):
continue
size = self.risk.get_position_size(signal)
order = build_order(signal, size)
self.executor.execute(order)Abstract interfaces let you swap components: use MT5 for live, CSV for backtest, mock for testing. Same engine code, different implementations. This is the power of proper abstraction.
Knowledge Check
Q1.Your engine and dashboard are in the same process. The dashboard crashes. What happens to trading?
Assignment
Refactor a simple trading system to use abstract interfaces for data, signals, risk, and execution. Implement at least two concrete implementations (live + backtest) for one of these interfaces.