Skip to content

Risk Management Agent

Trade validation, position sizing, and portfolio limit enforcement


December 2025 Status

ACTIVE - Enforcing risk rules on all trades

Rule Status Value
Max Position Size ✅ Enforced $1,000
Max Portfolio % ✅ Enforced 20% concentration
Min Cash Reserve ✅ Enforced 50%
Min Risk/Reward ✅ Enforced 2.5:1
Sentiment Blocking ✅ Active 4hr block on bearish alerts

Overview

The Risk Management Agent validates trades, calculates position sizes, and enforces portfolio limits.

trading_agents/risk_management_agent.py

Responsibilities: - Calculate position size based on risk parameters - Validate trades against portfolio limits - Enforce cash reserve requirements - Approve or reject trade requests - Handle sentiment alerts for position blocking


Risk Rules

Rule Default Description
Max Position Size $1,000 Maximum value per position
Max Portfolio % 20% Maximum position as % of portfolio
Min Cash Reserve 50% Minimum cash reserve requirement
Min Risk/Reward 2.5:1 Minimum risk/reward ratio
Stop Loss Required All positions must have stops

Event Architecture

Events Published

Event Description Data
risk.trade_approved Trade passed all risk checks symbol, quantity, position_value
risk.trade_rejected Trade violated risk rules symbol, reason, checks_failed
risk.size_calculated Position size determined symbol, quantity, buying_power
risk.review_position Review triggered by sentiment symbol, recommendation

Events Subscribed

Event Handler Description
strategy.entry_signal handle_strategy_entry_signal Validate entry requests
risk.calculate_size handle_risk_calculate_size Calculate position size
risk.check_limits handle_risk_check_limits Report current limits
sentiment.alert handle_sentiment_alert Block bearish symbols

Risk Checks Performed

Trade Approval Flow

graph TD
    A[Entry Signal] --> B{Symbol Blocked?}
    B -->|Yes| C[REJECT: Bearish Sentiment]
    B -->|No| D{R/R Ratio OK?}
    D -->|No| E[REJECT: R/R Too Low]
    D -->|Yes| F{Position Size OK?}
    F -->|No| G[REJECT: Size Exceeded]
    F -->|Yes| H{Portfolio % OK?}
    H -->|No| I[REJECT: Concentration]
    H -->|Yes| J{Cash Reserve OK?}
    J -->|No| K[REJECT: Insufficient Cash]
    J -->|Yes| L{Buying Power OK?}
    L -->|No| M[REJECT: No Buying Power]
    L -->|Yes| N[APPROVE TRADE]

Check Details

Check Validation Failure Message
Symbol Blocked Not in bearish sentiment list symbol_blocked_sentiment
Risk/Reward ratio >= 2.5:1 risk_reward_too_low
Position Size value <= $1,000 position_size_exceeded
Portfolio Concentration position/portfolio <= 20% portfolio_concentration_exceeded
Cash Reserve remaining cash >= 50% cash_reserve_insufficient
Buying Power position <= buying power buying_power_insufficient

Sentiment Integration

Bearish Sentiment Blocking

When sentiment.alert with HIGH severity BEARISH is received:

  1. Symbol added to blocked_symbols set
  2. Block expires after 4 hours (configurable)
  3. New entry signals for blocked symbols are rejected
  4. risk.review_position published for open positions

Bullish Sentiment Handling

  • Symbol removed from blocked list
  • Position size multiplier applied (up to 1.25x)

Configuration

# Risk Management Agent defaults
self.sentiment_block_duration_hours = 4
self.sentiment_veto_threshold = -0.6
self.sentiment_boost_threshold = 0.5
self.sentiment_boost_multiplier = 1.25

Position Size Calculation

Algorithm

# Base calculation
adjusted_max_position = max_position_size * position_size_multiplier
position_value = min(adjusted_max_position, buying_power)
quantity = int(position_value / entry_price)

Factors Affecting Size

Factor Impact
max_position_size Hard cap at $1,000
position_size_multiplier 1.0-1.25x based on sentiment
buying_power Available cash limits position
entry_price Determines share quantity

Usage Examples

Initialize Agent

from trading_agents.risk_management_agent import RiskManagementAgent

agent = RiskManagementAgent(
    max_position_size=1000.0,    # $1,000 max
    max_portfolio_pct=0.20,      # 20% max concentration
    min_cash_reserve_pct=0.50,   # 50% cash reserve
    min_risk_reward=2.5,         # 2.5:1 minimum R/R
    paper=True                   # Paper trading mode
)

agent.start()

Check Risk Limits

# Request current limits
agent.publish_event(
    event="risk.check_limits",
    data={}
)

# Response:
# {
#     "max_position_size": 1000,
#     "max_portfolio_pct": 0.20,
#     "min_cash_reserve_pct": 0.50,
#     "buying_power": 66248.57,
#     "portfolio_value": 101305.76,
#     "cash": 66248.57,
#     "cash_reserve_pct": 0.654
# }

Calculate Position Size

agent.publish_event(
    event="risk.calculate_size",
    data={
        "symbol": "AAPL",
        "entry_price": 175.50
    }
)

# Response:
# {
#     "symbol": "AAPL",
#     "entry_price": 175.50,
#     "quantity": 5,
#     "position_value": 877.50,
#     "buying_power": 66248.57
# }

Circuit Breaker Protection

The agent uses circuit breakers for Alpaca API calls:

# Paper trading breaker
self.circuit_breaker = create_alpaca_paper_breaker()

# Protected API call
account = self.circuit_breaker.call(
    self.trading_client.get_account
)

Breaker States

State Behavior
Closed Normal operation
Open Fail fast, skip API calls
Half-Open Test single request

Logging Examples

Successful Approval

INFO Trade approved: AAPL | 5 shares @ $175.50 ($877.50)

Rejection

WARNING Trade rejected: AAPL | Reasons: cash_reserve_insufficient

Sentiment Block

WARNING RISK BLOCK: AAPL blocked for 4hr due to HIGH bearish sentiment (-0.72)

Configuration Reference

Parameter Type Default Description
max_position_size float 1000.0 Max position value in dollars
max_portfolio_pct float 0.20 Max position as % of portfolio
min_cash_reserve_pct float 0.50 Min cash reserve %
min_risk_reward float 2.5 Min risk/reward ratio
paper bool True Use paper trading account
redis_host str "localhost" Redis host for message bus
redis_port int 6379 Redis port

See Also


Last Updated: January 10, 2026 Platform: Alpaca API | Redis Pub/Sub | Sentiment Integration