Component · L4

Risk Gate

github.com/juanmmm21/risk-management-engine

Pre-trade risk gate enforcing position sizing, stop-loss and max drawdown limits.

Lines
849
Files
22
Test files
6
Commits
14
Started
29 Jun 2026
Last commit
6 Jul 2026
  • Python 100%

● Where it sits

Layer 4 of Quant — risk & audit.

Pre-trade safety shield that intercepts orders before sending them to the market and verifies strict mathematical rules: position size, mandatory stop-loss, and maximum daily loss (max drawdown). Ninth module of the quant-core-infra ecosystem.

Repository: github.com/juanmmm21/risk-management-engine

What it is and what problem it solves

A trading bot can generate signals that are technically valid but dangerous in terms of capital: orders that are too large, entries without a stop-loss, or trades during a critical daily drawdown.

This module acts as a deterministic filter between strategy logic and order-routing-gateway. No order reaches the exchange without passing through the risk engine.


Role in quant-core-infra

alpha-signal-generator ──► event-driven-backtester ──► ProposedOrder
                                                              │
                                                              ▼
                                                   risk-management-engine
                                                              │
                                         approved ────────────┼──────── rejected
                                                              ▼
                                                   order-routing-gateway
                                                              │
                                                   trade-audit-logger

It sits before routing and after order generation.


Purpose

Demonstrates:

  • Pre-trade rule engine extensible via RiskRule
  • Position sizing validation with Decimal
  • Mandatory stop-loss on new entries
  • Blocking on maximum daily drawdown
  • JSONL pipelines for proposed orders and portfolio snapshots

Implemented rules

Position sizing (position_sizing)

CheckRejection condition
Notional per orderquantity × price > equity × max_order_notional_pct
Position notional(pos + qty) × price > equity × max_position_notional_pct
Available capitalnotional > cash on buys

Stop-loss (stop_loss)

CheckRejection condition
Mandatory stopNew long entry without stop_loss_price
Valid stopstop_loss >= reference_price on longs
Minimum distance(price - stop) / price < min_stop_loss_distance_pct

Drawdown (drawdown)

drawdown_pct = (peak_equity_today - equity) / peak_equity_today

If drawdown_pct >= max_daily_drawdown_pct → blocks new buys. Sells (risk reduction) are still allowed.


How it works

  1. Portfolio snapshot: cash, equity, open position, daily PnL, and the day's peak.
  2. Proposed order: quantity, reference price, and optional stop-loss.
  3. Evaluation: each rule returns a RiskViolation or an empty list.
  4. Verdict: approved with no violations; rejected with at least one.

Architecture

ProposedOrder + PortfolioSnapshot
              │
              ▼
    RiskManagementEngine
              │
    ┌─────────┼─────────┐
    ▼         ▼         ▼
Drawdown  Position   StopLoss
 Rule      Sizing      Rule
              │
              ▼
       RiskCheckResult

Components

ModuleResponsibility
rules/position_sizing.pyNotional and capital limits
rules/stop_loss.pyStop validation on entries
rules/drawdown.pyDaily drawdown blocking
engine.pyRule orchestration
ingest.pyJSON/JSONL parsing
pipeline.pyEnd-to-end run

Configuration: RiskLimitsConfig

ParameterDefaultDescription
max_position_notional_pct0.25Max 25% of equity in position
max_order_notional_pct0.10Max 10% of equity per order
max_daily_drawdown_pct0.05Max daily drawdown 5%
require_stop_loss_on_entrytrueMandatory stop on long entries
min_stop_loss_distance_pct0.005Minimum stop distance (0.5%)

Requirements

  • Python 3.11+

Installation

cd risk-management-engine
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

CLI usage

risk-management-engine check \
  --orders samples/proposed_orders.jsonl \
  --portfolio samples/portfolio.json \
  --symbol BTCUSDT \
  --max-order-notional-pct 0.10 \
  --output risk_results.json

Expected output (excerpt)

{
  "client_order_id": "ord-no-stop",
  "verdict": "rejected",
  "violations": [
    {
      "rule_id": "stop_loss",
      "violation_type": "missing_stop_loss",
      "message": "stop_loss_price is required for new long entries"
    }
  ]
}

Input formats

Proposed order (JSONL)

{
  "client_order_id": "ord-1",
  "symbol": "BTCUSDT",
  "side": "buy",
  "quantity": "0.01",
  "reference_price": "1000",
  "stop_loss_price": "990",
  "submitted_at": "2024-01-01T12:00:00.000Z"
}

Portfolio snapshot (JSON)

{
  "symbol": "BTCUSDT",
  "cash": "9500",
  "equity": "10000",
  "position_quantity": "0",
  "average_entry_price": "0",
  "daily_realized_pnl": "0",
  "peak_equity_today": "10000",
  "snapshot_time": "2024-01-01T12:00:00.000Z"
}

Programmatic usage

from datetime import UTC, datetime
from decimal import Decimal

from risk_management_engine import (
    PortfolioSnapshot,
    ProposedOrder,
    RiskLimitsConfig,
    RiskManagementEngine,
    run_risk_check_pipeline,
)

results = run_risk_check_pipeline(
    orders_path="orders.jsonl",
    portfolio_path="portfolio.json",
    symbol="BTCUSDT",
    config=RiskLimitsConfig(max_daily_drawdown_pct=Decimal("0.03")),
)

engine = RiskManagementEngine(RiskLimitsConfig())
check = engine.check_order(order, portfolio)

Development

pytest -q
ruff check src tests
mypy src

Troubleshooting

SymptomLikely causeSolution
All orders rejected for drawdownequity far below peak_equity_todayUpdate the snapshot or adjust max_daily_drawdown_pct
flat position must have zero average_entry_priceZero position with a non-zero average priceSet average_entry_price: "0" when position_quantity is 0
order symbol must match portfolioMismatched symbolsAlign --symbol and the symbol fields in both files

Roadmap

  • Multi-symbol exposure and correlation rules
  • Trailing stop and take-profit as additional validations
  • Inline integration with order-routing-gateway as middleware
  • Persisting violations in trade-audit-logger

License

MIT

esc
↑↓ navigate↵ open