← Back to Learn
III AdvancedWeek 29 • Lesson 81Duration: 35 min

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

Current V7 architecture (monolith): The V7 Trading Engine contains: - L1 Signal -> L2 Gate -> L3 Exit (the 3-layer ML pipeline) - Risk Management (S40, DD scaling) - MT5 Connector (broker interface) - Feature Engineering (38 features per bar) This is perfectly adequate for a single trader/account. But for scaling to multiple accounts or adding the dashboard, a more modular architecture helps.

2Scaling Considerations

When to evolve the architecture: Multiple accounts: Run separate engine instances per account, each with its own config and risk state. Could share data pipeline. Adding dashboard: Separate the API/dashboard from the engine. Communicate via REST API or WebSocket. Adding alerting: Separate alerting service that subscribes to engine events. Failover: Run a standby instance that can take over if the primary fails. Key principles: - Separation of concerns: each component does one thing well - Loose coupling: components communicate through well-defined interfaces - Data persistence: all state stored durably (not just in memory) - Idempotency: operations can be safely retried - Graceful degradation: if one component fails, others continue For V7, the practical next steps: 1. API layer (FastAPI) wrapping the engine 2. Dashboard (React) consuming the API 3. PostgreSQL for trade/state persistence 4. Redis for real-time data caching 5. Alerting service (Telegram/email) for critical events

Hands-On Code

Modular Architecture Components

python
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.