Quant Trading Systems: Architecture & Infrastructure › Risk Management Systems

Michael BrenndoerferJanuary 21, 20263 min read
Quantitative FinanceAll chapters
Part 15 of 15Trading Systems and Production Deployment
Chapter 77Quant Trading Systems: Architecture & Infrastructure › Risk Management Systems
Reading section 5 of 14 · Risk Management Systems · 3 minSection 5 of 14 · 3 min

Book contents

Section 5 of 14 · 3 min read

Quant Trading Systems: Architecture & Infrastructure › Risk Management SystemsOne section · Sections in this chapter5 / 14 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Real-time risk management is the guardian of your capital. As we covered extensively in Part V, risk comes in many forms: market risk, credit risk, liquidity risk. A production trading system must monitor and control all relevant risk dimensions continuously. The cost of inadequate risk management can be catastrophic, as numerous trading blow-ups have demonstrated.

Risk management in a trading system operates at multiple levels. Pre-trade checks validate individual orders before they're submitted. Real-time monitoring tracks aggregate portfolio risk continuously. Circuit breakers halt trading when anomalies are detected. Each layer provides defense against different types of failures.

Pre-Trade Risk Checks

Before any order is sent, the system should verify it doesn't violate risk limits. These checks serve as the last line of defense before capital is committed. They must be fast enough not to delay time-sensitive orders, yet thorough enough to catch dangerous trades.

In[17]:
Code
@dataclass
class Order:
    """Represents a trading order."""

    symbol: str
    side: str  # 'BUY' or 'SELL'
    quantity: float
    order_type: str  # 'MARKET', 'LIMIT', etc.
    limit_price: Optional[float] = None


class RiskLimits:
    """Configuration for risk limits."""

    max_position_size: float = 100000  # Max notional per position
    max_order_size: float = 50000  # Max notional per order
    max_portfolio_exposure: float = 500000  # Total long + short notional
    max_concentration: float = 0.2  # Max weight in single position
    max_daily_loss: float = 10000  # Stop trading if exceeded
    max_drawdown: float = 0.05  # 5% drawdown limit


class PreTradeRiskChecker:
    """Validates orders against risk limits before submission."""

    def __init__(self, limits: RiskLimits):
        self.limits = limits

    def check_order(
        self,
        order: Order,
        current_position: float,
        portfolio_value: float,
        current_price: float,
        total_exposure: float,
        daily_pnl: float,
    ) -> tuple[bool, str]:
        """
        Check if order passes all pre-trade risk checks.
        Returns (approved, reason).
        """
        order_notional = order.quantity * current_price

        # Check order size limit
        if order_notional > self.limits.max_order_size:
            return (
                False,
                f"Order size {order_notional:.0f} exceeds limit {self.limits.max_order_size:.0f}",
            )

        # Check resulting position size
        if order.side == "BUY":
            new_position = current_position + order.quantity
        else:
            new_position = current_position - order.quantity

        new_position_notional = abs(new_position * current_price)
        if new_position_notional > self.limits.max_position_size:
            return (
                False,
                f"Resulting position {new_position_notional:.0f} exceeds limit",
            )

        # Check concentration limit
        concentration = new_position_notional / portfolio_value
        if concentration > self.limits.max_concentration:
            return (
                False,
                f"Position concentration {concentration:.1%} exceeds {self.limits.max_concentration:.1%}",
            )

        # Check portfolio exposure
        new_exposure = total_exposure + order_notional
        if new_exposure > self.limits.max_portfolio_exposure:
            return (
                False,
                f"Portfolio exposure {new_exposure:.0f} would exceed limit",
            )

        # Check daily loss limit
        if daily_pnl < -self.limits.max_daily_loss:
            return False, "Daily loss limit breached, trading suspended"

        return True, "Order approved"
In[18]:
Code
# Demonstrate pre-trade risk checks
limits = RiskLimits()
risk_checker = PreTradeRiskChecker(limits)

# Test various orders
test_orders = [
    (Order("AAPL", "BUY", 100, "MARKET"), 0, 185.0, "Normal order"),
    (Order("AAPL", "BUY", 1000, "MARKET"), 0, 185.0, "Large order"),
    (
        Order("AAPL", "BUY", 100, "MARKET"),
        500,
        185.0,
        "Would exceed position limit",
    ),
]

portfolio_value = 500000
total_exposure = 200000
daily_pnl = -2000

risk_results = []
for order, current_pos, price, description in test_orders:
    approved, reason = risk_checker.check_order(
        order, current_pos, portfolio_value, price, total_exposure, daily_pnl
    )
    status = "✓ APPROVED" if approved else "✗ REJECTED"
    risk_results.append(f"{description:30s} | {status:12s} | {reason}")
Out[19]:
Console
Pre-Trade Risk Check Results:
----------------------------------------------------------------------
Normal order                   | ✓ APPROVED   | Order approved
Large order                    | ✗ REJECTED   | Order size 185000 exceeds limit 50000
Would exceed position limit    | ✗ REJECTED   | Resulting position 111000 exceeds limit

The risk checker rejects the large order and the position-limit breaching order while approving the normal trade, preventing the system from taking excessive risk. Notice that each check is independent: an order might pass the size check but fail the concentration check, or pass all position checks but be rejected because the daily loss limit has already been breached.