The most valuable agent in an automated trading stack may be the one designed to say no. A risk agent should observe account, portfolio, market, execution, and system conditions independently from the strategy that wants to trade. Its purpose is not to find better entries. Its purpose is to prevent a valid-looking strategy signal from creating unacceptable account exposure.
A robust MT5 risk agent uses broker-reported account and position state as the source of truth. It converts that state into a small, explicit set of risk modes such as NORMAL, REDUCED, ENTRIES_BLOCKED, and EMERGENCY_FLATTEN. Each state maps to deterministic actions that strategies and execution modules cannot override.
Machine learning can help detect unusual combinations of conditions, but core limits must remain explicit. Maximum daily loss, maximum open risk, allowed symbols, trading hours, position limits, and emergency stop behavior should never depend on a model’s confidence score. Anomaly detection is a supplement to hard limits, not a replacement.
This article is an educational software-architecture guide for MQL5 developers and systematic traders. It is not financial or investment advice. Automated trading and AI systems can fail, broker execution conditions can change, and all risk controls should be tested in controlled environments before any live use.
The Core Principle
The design rule is:
Run the risk process independently from the signal process.
A strategy wants to find a reason to trade. A risk system must be designed to find reasons not to trade. Combining both roles inside the same module creates a conflict: a strategy can be tempted to reinterpret risk constraints so that its preferred order is still allowed.
A safer architecture is:
STRATEGY SIGNALS → RISK AGENT → DETERMINISTIC RISK POLICY → MT5 ORDER AUTHORITY
In parallel:
MT5 ACCOUNT + POSITIONS + MARKET CONDITIONS + EXECUTION HEALTH + SYSTEM HEALTH → INDEPENDENT RISK AGENT
The strategy can recommend a candidate. The independent risk agent determines the current risk state. The deterministic risk policy determines whether a candidate can be authorized. MT5 executes only a validated command.
Why Independence Matters
Risk control is weakest when it depends on the same state, assumptions, or process that generated the trade. A signal process may have stale account information, fail to recognize correlated exposure, ignore a growing drawdown, or keep trying to enter after repeated order errors.
An independent risk agent reduces this problem by:
- Reading current broker-reported account state directly.
- Aggregating exposure across all strategies, symbols, charts, and pending orders.
- Monitoring execution health independently from signal quality.
- Applying limits even when a strategy has a high-confidence recommendation.
- Maintaining a durable state that survives strategy restarts.
- Issuing a no-entry or emergency command without needing strategy agreement.
The risk agent does not need to predict whether the next trade will win. It needs to determine whether the account can safely accept any additional exposure.
Risk Agent Architecture
A practical architecture separates observation, classification, deterministic policy, and enforcement:
BROKER STATE + PORTFOLIO STATE + MARKET STATE + SYSTEM STATE → RISK SNAPSHOT → HARD-LIMIT CHECKS + OPTIONAL ANOMALY DETECTION → RISK STATE → ENFORCEMENT POLICY → MT5
| Layer | Responsibility | Must Not Do |
|---|---|---|
| State collector | Read broker-reported account, position, order, quote, and terminal information. | Invent exposure, infer fills from intent, or trust cached strategy memory over platform facts. |
| Risk snapshot | Normalize account, portfolio, market, execution, and system metrics at a known timestamp. | Mix old and new values without freshness metadata. |
| Hard-limit evaluator | Apply deterministic daily loss, risk, margin, symbol, session, and exposure constraints. | Let a model confidence score override a hard limit. |
| Anomaly detector | Flag unusual combinations of conditions for conservative escalation. | Replace explicit limits or directly authorize an order. |
| Risk-state machine | Set a durable state such as normal, reduced, blocked, or emergency flatten. | Instantly re-enable trading after a transient metric improvement when latching is required. |
| Enforcement adapter | Block entries, cap risk, cancel pending orders, or flatten positions according to policy. | Allow a strategy to bypass the current risk state. |
| Audit and monitoring | Persist snapshots, state changes, reasons, commands, and broker results. | Rely on an in-memory flag or incomplete terminal history. |
Use Broker-Reported State as the Source of Truth
For live risk control, broker-reported positions, orders, deals, account equity, margin, and symbol properties are the source of truth. A strategy’s internal record may be delayed, incomplete, or wrong after a restart, partial fill, rejected order, manual intervention, or connection interruption.
The risk agent should query or reconcile:
- Account balance, equity, margin, free margin, and margin level.
- Open positions, including symbol, direction, volume, entry price, stop-loss, take-profit, and magic number where applicable.
- Pending orders that could become exposure.
- Recent deals, realized profit and loss, commissions, swaps, and close reasons.
- Current bid, ask, spread, symbol trade mode, and trading session state.
- Contract size, tick value, volume step, stop levels, and margin rules for active symbols.
- Terminal connection state, trading permissions, and recent order results.
Use strategy records as supplemental context, not as the final account ledger. If the strategy believes a position is closed but the broker reports it open, the broker state wins.
The Risk Snapshot
The risk snapshot is the normalized record used to evaluate account and system health. It should have a unique ID, UTC timestamp, freshness information, and clear source fields.
Useful Risk Inputs
A risk snapshot can include the following categories.
Account and Drawdown
- Current balance and equity.
- Session-start equity and day-start equity.
- Realized daily profit and loss.
- Floating profit and loss.
- Daily drawdown in money, percentage, and R where applicable.
- Peak equity and drawdown from peak.
- Consecutive losses and recent strategy losses.
Margin and Capacity
- Used margin and free margin.
- Margin level.
- Projected margin after each pending or proposed position.
- Margin buffer relative to configured thresholds.
- Broker margin-call and stop-out awareness for the current account type.
Portfolio Exposure
- Total open risk if all active stops are reached.
- Per-symbol open risk.
- Per-strategy open risk.
- Risk committed by pending orders.
- Directional exposure by currency, asset class, correlation group, or market theme.
- Number of open positions and pending orders.
- Net and gross exposure according to your portfolio policy.
Market Conditions
- Current spread and spread percentile relative to a historical baseline.
- Realized volatility and volatility percentile.
- Price gaps, abnormal tick behavior, or unavailable quote data.
- Session status, rollover period, market open or close condition, and trading-hours restrictions.
- Scheduled event or news-state restrictions, if your policy uses them.
Execution and System Health
- Recent order rejection rate.
- Recent requote, invalid-stop, off-quote, or insufficient-margin events.
- Observed entry and exit slippage.
- Connection state and time since last valid quote.
- Time synchronization health.
- EA heartbeat, process heartbeat, and data-feed freshness.
- Recent reconciliation failures or unknown order states.
The specific metrics should fit the strategy and broker environment. The principle is that risk decisions should reflect the whole account and operating condition, not only one planned trade.
Keep the Output Small and Explicit
The risk agent should emit a small number of clear states. A compact state machine is easier to test, monitor, and enforce than a long list of ambiguous warnings.
A practical state set is:
| Risk State | Meaning | Deterministic Action |
|---|---|---|
| NORMAL | Account, portfolio, market, execution, and system metrics are within policy limits. | Allow eligible strategies to request trades through the normal risk gate. |
| REDUCED | Conditions are not yet a hard stop, but risk is elevated or execution quality is degraded. | Apply a configured risk cap, reduce maximum total exposure, block selected symbols, or require stricter setup filters. |
| ENTRIES_BLOCKED | New exposure is not permitted because a hard limit, uncertainty, event state, or operational issue is active. | Block all new entries and pending-order activation; allow only defined protective management of existing positions. |
| EMERGENCY_FLATTEN | An emergency condition requires attempts to reduce or close exposure according to a pre-defined protocol. | Block new entries, cancel eligible pending orders, and attempt to flatten or reduce positions with complete audit logging. |
Do not create a state named “probably okay” or “use judgment.” The enforcement action must be explicit and codeable.
Hard Limits Come Before AI
Hard limits are deterministic rules that apply regardless of model output, market narrative, or strategy confidence. They are the foundation of the risk agent.
Examples of hard limits include:
- Maximum daily loss.
- Maximum drawdown from day-start or peak equity.
- Maximum total open risk.
- Maximum risk per symbol or strategy.
- Maximum correlated currency or asset-class exposure.
- Maximum number of open positions and pending orders.
- Maximum spread and maximum spread percentile.
- Minimum free-margin buffer and minimum margin level.
- Allowed symbols, sessions, and trading hours.
- Maximum consecutive losses.
- Maximum order rejection or execution-error rate.
- Maximum age of market data or account-state snapshot.
- Global kill switch and manual-disable state.
These rules should live in deterministic configuration and code. A machine-learning model should not decide whether a maximum daily loss is “still acceptable.”
Anomaly Detection Is a Supplement
Machine learning can help detect unusual combinations of conditions that are hard to capture with one simple threshold. For example, a model might flag an unusual pattern of widened spreads, high volatility, increased slippage, rising order rejections, and concentrated exposure.
That can be useful as an additional signal for escalation. But anomaly detection should not replace hard limits.
A safer hierarchy is:
- Hard limit breach: immediately set the deterministic risk state required by policy.
- No hard breach but anomaly detected: move to a conservative reduced or blocked state according to predefined thresholds.
- No hard breach and no anomaly: remain in normal state if all data is reliable.
- Unknown data or failed risk process: block new entries by default.
The anomaly detector may recommend caution. It must not authorize additional exposure.
Example Anomaly Signals
A risk anomaly model can observe a vector of system and market features. It should produce a bounded risk-related output, not a trade direction.
Potential features include:
- Current spread divided by rolling median spread.
- Current realized volatility percentile.
- Recent negative slippage percentile.
- Order rejection rate over a rolling window.
- Recent terminal disconnections or data gaps.
- Total open risk and risk concentration.
- Daily drawdown and change in drawdown speed.
- Number of correlated positions.
- Time until scheduled high-impact event.
- Difference between expected and actual fill quality.
Example output:
{ "schema_version": "risk_anomaly_result_v1", "snapshot_id": "risk_snap_2026-08-24_001", "agent_id": "risk_anomaly_detector", "agent_version": "1.2.0", "anomaly_score": 0.87, "status": "ELEVATED_CONDITIONS", "evidence_tags": [ "spread_percentile_99", "slippage_above_baseline", "usd_exposure_concentrated" ], "created_at_utc": "2026-08-24T23:50:00Z" }
The deterministic policy may map a score above a defined threshold to REDUCED or ENTRIES_BLOCKED. The model score should not directly set lot size or send a flatten command unless a deterministic policy explicitly maps it to that action.
Calculate Portfolio Risk, Not Just Ticket Risk
Risk sizing on one order is necessary but not sufficient. Several individually acceptable trades can combine into excessive account exposure, especially when they are correlated.
Portfolio risk should account for:
- Open positions with active stop-losses.
- Positions without a stop-loss, which require a separate conservative policy.
- Pending orders that can trigger together.
- Partial fills and partially closed positions.
- Long and short exposure by currency and symbol.
- Correlation groups or common market themes.
- Multiple EAs, manual positions, and external trading tools using the same account.
- Scheduled event risk that can cause multiple positions to move together.
For example, buying EURUSD and GBPUSD while selling USDJPY may create multiple positions dependent on broad USD weakness. Each ticket can fit an individual risk limit while the combined portfolio becomes a concentrated USD position.
Exposure Aggregation
Define how the risk agent aggregates exposure. The method should be simple enough to test and explain.
Possible aggregation layers include:
- Per-trade planned risk in account currency or R.
- Per-symbol total planned risk.
- Per-strategy total planned risk.
- Per-currency directional exposure for forex symbols.
- Per-asset-class exposure for indices, metals, commodities, or cryptocurrencies.
- Correlation-group exposure based on a documented mapping.
- Gross exposure and net exposure.
- Maximum combined loss under a simplified stress scenario.
Do not let a strategy decide its own correlation group at order time. Store mappings in versioned configuration and review them periodically.
Stop Distance and Contract Specifications Still Matter
An independent risk agent does not replace basic position-sizing mechanics. Final volume must still be calculated from stop-loss distance, account risk, tick or pip value, contract size, and broker volume rules.
The general relationship remains:
Position size = permitted account risk ÷ (stop-loss distance × value per point, pip, or tick).
For each proposed order, the risk process should verify:
- The stop-loss is directionally valid.
- The stop-loss is beyond the broker’s minimum stop distance and freeze level.
- The stop-loss represents logical invalidation according to strategy rules.
- The volume is calculated using current symbol specifications.
- The volume respects minimum, maximum, and step restrictions.
- Spread, commission, expected slippage, and financing are considered where relevant.
- The incremental risk keeps total open risk below the current risk-state cap.
- Margin remains above the required safety buffer after the proposed trade.
The beginner guide to stop-loss and take-profit placement covers the basic mechanics. Advanced automation extends that discipline across a portfolio and enforces it without negotiation.
Risk State Must Be Latched
Severe stop states should be latched. A latch means that once the system enters a severe state, a brief improvement in one metric does not instantly re-enable trading.
For example, a daily drawdown may exceed the maximum threshold and trigger ENTRIES_BLOCKED. If equity then improves slightly because an open trade moves favorably, the system should not automatically return to normal and start opening new positions. The daily risk event has already occurred and requires a defined reset process.
Latching prevents rapid state oscillation and reduces the chance that a transient recovery turns into repeated re-entry during unstable conditions.
Example Latch Rules
| Trigger | Latched State | Release Condition |
|---|---|---|
| Maximum daily loss reached | ENTRIES_BLOCKED | Next configured trading day, plus explicit account-state validation. |
| Emergency flatten triggered | EMERGENCY_FLATTEN then ENTRIES_BLOCKED | Manual review or explicit reset procedure after reconciliation. |
| Repeated execution failures | ENTRIES_BLOCKED | Connection, broker state, and execution health pass a documented recovery checklist. |
| Critical stale-data or time-sync failure | ENTRIES_BLOCKED | Fresh data, time synchronization, and snapshot integrity verified for a configured stable period. |
| Extreme spread or volatility anomaly | REDUCED or ENTRIES_BLOCKED | Metric remains normal for a defined cooldown interval and no other hard limit is active. |
Release conditions should be explicit. “Metrics look normal now” is not a sufficient rule without defined checks, time windows, and authority.
Build a Risk State Machine
A state machine makes risk behavior explicit. The system should know which transitions are allowed and which conditions cause them.
A simple state model:
NORMAL ├── elevated soft condition ──> REDUCED ├── hard risk limit or uncertainty ──> ENTRIES_BLOCKED └── emergency condition ──> EMERGENCY_FLATTEN REDUCED ├── sustained recovery and cooldown ──> NORMAL ├── hard risk limit or uncertainty ──> ENTRIES_BLOCKED └── emergency condition ──> EMERGENCY_FLATTEN ENTRIES_BLOCKED ├── documented reset and validation ──> NORMAL or REDUCED └── emergency condition ──> EMERGENCY_FLATTEN EMERGENCY_FLATTEN └── reconciliation and manual or documented reset ──> ENTRIES_BLOCKED
Keep the transition logic deterministic. Record the metric, threshold, timestamp, policy version, and reason code that caused every state change.
Emergency Flatten Is Not Magic
An emergency flatten command is an attempt to reduce or close exposure according to policy. It cannot guarantee exact execution price, complete fills, or immediate closure during a disconnected, gapping, or illiquid market.
Design emergency behavior with realistic expectations:
- Block all new entries immediately.
- Cancel eligible pending orders to prevent additional exposure.
- Attempt to close positions according to a defined priority policy.
- Reconcile every order, deal, and remaining position after each action.
- Handle partial fills, rejections, requotes, and connection failures explicitly.
- Continue logging until account state is known or manual escalation is required.
- Latch the system in blocked state after flatten attempts.
Do not assume a single close request closes all exposure. Market conditions and broker rules may prevent immediate or complete execution.
Define Flatten Priority
If several positions are open, define in advance how the system prioritizes reduction. There is no universal answer, but an undefined priority creates inconsistent behavior.
Possible policies include:
- Close all positions immediately in a fixed deterministic order.
- Cancel all pending orders first, then close positions by largest planned risk.
- Close positions with the greatest correlation concentration first.
- Close positions with the greatest margin consumption first.
- Close positions associated with a failed strategy or symbol first.
- Reduce all positions proportionally where broker and strategy rules permit.
Whatever policy you choose, test it under partial fills, delayed responses, and rapidly moving prices. The risk agent should log every attempted action and actual remaining exposure.
Risk Agent Pseudocode
function EvaluateRiskState(snapshot, config): if !SnapshotIsReliable(snapshot): return SetState(ENTRIES_BLOCKED, "UNRELIABLE_BROKER_STATE") if KillSwitchActive(config): return SetState(ENTRIES_BLOCKED, "KILL_SWITCH_ACTIVE") if EmergencyCondition(snapshot, config): return SetState(EMERGENCY_FLATTEN, "EMERGENCY_CONDITION") if HardLimitBreached(snapshot, config): return SetState(ENTRIES_BLOCKED, HardLimitReason(snapshot, config)) anomaly = OptionalAnomalyDetector.Evaluate(snapshot) if anomaly.IsInvalid(): return SetState(ENTRIES_BLOCKED, "RISK_ANOMALY_SERVICE_UNRELIABLE") if anomaly.ExceedsBlockThreshold(config): return SetState(ENTRIES_BLOCKED, "ANOMALY_BLOCK") if SoftLimitBreached(snapshot, config) || anomaly.ExceedsReduceThreshold(config): return SetState(REDUCED, "ELEVATED_RISK") return SetState(NORMAL, "ALL_RISK_CHECKS_PASS")
The risk state is then consumed by the policy engine. Strategies should not be able to change it, downgrade it, or ignore it.
Order Authorization With Risk State
When a strategy submits a trade candidate, the order authorization process should use the current latched risk state.
function AuthorizeTrade(candidate, snapshot, risk_state, config):
if risk_state == EMERGENCY_FLATTEN:
return Deny("EMERGENCY_STATE")
if risk_state == ENTRIES_BLOCKED:
return Deny("NEW_ENTRIES_BLOCKED")
if !CandidateIsValid(candidate):
return Deny("INVALID_CANDIDATE")
allowed_risk = RiskCapForState(risk_state, config)
volume = CalculateVolume(candidate.stop_distance, allowed_risk, snapshot)
if !PortfolioAllowsIncrementalRisk(candidate, volume, snapshot, config):
return Deny("PORTFOLIO_EXPOSURE_LIMIT")
if !ExecutionConditionsAllow(candidate, snapshot, config):
return Deny("EXECUTION_CONDITION_BLOCK")
return Approve(BuildTradeIntent(candidate, volume)) In a reduced state, the policy may use a smaller predetermined risk cap or narrower symbol allowlist. It should not use an undefined judgment call or a model confidence multiplier.
Monitor Execution Health
Execution failures can be risk events. A system that receives repeated rejected orders, unusual slippage, invalid-stop errors, stale quotes, or reconciliation failures may not be operating in the conditions assumed by its strategy.
Track:
- Order request count and order rejection rate.
- Requote, off-quote, invalid-price, invalid-stop, and insufficient-margin responses.
- Requested versus actual fill price.
- Negative slippage distribution by symbol and session.
- Partial-fill and fill-delay behavior where relevant.
- Unknown execution states after timeouts or connection loss.
- Repeated broker trade-mode or symbol-session restrictions.
Define thresholds that move the risk state to reduced or blocked. A signal may remain valid, but the environment may no longer support reliable execution.
Spread and Volatility Monitoring
Absolute spread thresholds are useful, but spread percentile can add context. A 15-point spread may be normal for one symbol and extreme for another. It may also be normal during a certain session and abnormal during the strategy’s usual session.
A risk agent can compare current spread with:
- A fixed per-symbol maximum.
- A session-specific baseline.
- A rolling median or percentile distribution.
- A combined spread and volatility condition.
- A scheduled-event or rollover restriction.
Do not let a spread filter simply wait for a lower number if the strategy signal will be stale by then. If conditions are not acceptable now, reject the candidate and wait for a new valid setup.
System Health Is Risk Health
A trading system cannot safely make new decisions if it does not know its own state. Monitor connectivity, time, data freshness, and software health as risk inputs.
Critical system-health checks include:
- Terminal connection to broker.
- Quote freshness and time since last tick.
- Broker server time and local UTC synchronization.
- EA timer or heartbeat status.
- Availability of current account, positions, and order data.
- Availability of required risk configuration and version compatibility.
- Audit-log persistence health.
- Availability of required event or session state, if used.
- Successful reconciliation after recent order actions.
If account state, time synchronization, or data freshness is uncertain, block new entries. A system that cannot verify the current account does not have enough information to safely increase exposure.
Test the Kill Switch Under Failure
A kill switch that works only in normal conditions is not enough. Test it when the system is stressed.
Test scenarios should include:
- Broker or terminal disconnection.
- Stale or missing quotes.
- Partial fills.
- Rapidly moving prices and widening spreads.
- Rejected close requests.
- Requotes, invalid prices, and invalid stops.
- Pending orders that could trigger during a stop state.
- EA restart during an active flatten sequence.
- Manual position changes outside the EA.
- Multiple strategies attempting to submit new orders simultaneously.
- Risk process restart while the strategy process remains active.
- Audit-log or state-store persistence failure.
For each test, verify that new entries are blocked, existing exposure is accurately reconciled, attempted protective actions are logged, and the latched state does not disappear after restart.
Durable State and Restart Recovery
Risk state must survive restarts. If an EA or terminal restart clears an in-memory daily-loss block, the account may begin trading again when it should remain stopped.
Persist:
- Current risk state and latch status.
- State-transition timestamp and reason code.
- Policy version and configuration hash.
- Day-start equity reference and daily drawdown metrics.
- Processed emergency actions and their reconciliation status.
- Current kill-switch status and authorized reset method.
- Last reliable broker-state snapshot and freshness status.
On startup, the risk agent should load durable state, query current broker facts, reconcile positions and pending orders, verify time and connection health, and then decide whether any state can be released. It should never default to normal simply because the process restarted.
Manual Override and Reset Authority
Some severe states should require an explicit manual reset after review. This prevents a transient data recovery or automated restart from re-enabling a system that experienced an emergency condition.
Define:
- Who can reset a latched state.
- What evidence is required before reset.
- Whether reset must occur outside market hours or after a cooldown period.
- Whether positions must be flat before reset.
- Which health checks must pass after reset.
- How the reset is authenticated, timestamped, and logged.
A manual reset should be an audit event, not a hidden configuration edit.
Risk-Agent Audit Log
Every risk-state decision should be auditable. A later review should show what the system knew, what threshold was crossed, what policy version was active, and what enforcement actions occurred.
Log:
- Risk snapshot ID, UTC timestamp, broker server time, and freshness status.
- Account balance, equity, margin, free margin, and margin level.
- Open positions, pending orders, and aggregated exposure metrics.
- Daily drawdown, total open risk, correlated exposure, and remaining risk budgets.
- Spread, volatility, event state, and execution-health metrics.
- Hard-limit evaluation results and exact threshold comparisons.
- Anomaly result, version, evidence tags, and threshold mapping if used.
- Previous risk state, new risk state, transition reason, and latch status.
- Enforcement command: block, reduce, cancel, flatten, or no action.
- Every MT5 request, retcode, fill, rejection, partial fill, and reconciliation result.
- Manual reset or configuration change events.
Log normal cycles as well as failures. Without normal data, you cannot compare the conditions that preceded a transition.
MQL5 Component Layout
Keep risk logic separate from signal logic and execution policy. A modular structure makes it easier to test, monitor, and maintain independent authority.
/IndependentRiskAgentMT5 /Core RiskSnapshot.mqh BrokerStateCollector.mqh ExposureAggregator.mqh HardLimitEvaluator.mqh AnomalyAdapter.mqh RiskStateMachine.mqh LatchManager.mqh EnforcementPolicy.mqh EmergencyFlatten.mqh AuditLogger.mqh DurableStateStore.mqh KillSwitch.mqh /Infrastructure TimeUtils.mqh SymbolUtils.mqh TradeReconciliation.mqh Serialization.mqh /Config RiskPolicyConfig.mqh CorrelationMap.mqh IndependentRiskAgent.mq5
The risk agent can run as a dedicated EA, service-like chart component, or tightly controlled account-level module. The key requirement is that its authority and data path remain independent from individual signal generators.
Conceptual MQL5 Risk Loop
OnTimer():
snapshot = BrokerStateCollector.BuildRiskSnapshot()
if !snapshot.IsReliable():
state = RiskStateMachine.SetBlocked("UNRELIABLE_BROKER_STATE")
EnforcementPolicy.Apply(state, snapshot)
Audit.Log(snapshot, state)
return
hard_result = HardLimitEvaluator.Evaluate(snapshot)
anomaly_result = AnomalyAdapter.Evaluate(snapshot)
state = RiskStateMachine.Resolve(
current_state,
hard_result,
anomaly_result,
snapshot
)
DurableStateStore.Save(state)
EnforcementPolicy.Apply(state, snapshot)
Audit.LogRiskCycle(snapshot, hard_result, anomaly_result, state) The risk loop should run on a predictable schedule appropriate to the system. It may also be triggered by trade transactions, state changes, connection events, or other defined events. It should not depend on a strategy producing a signal before it checks account health.
Enforcement Pseudocode
function ApplyRiskState(state, snapshot): if state == NORMAL: SetNewEntryRiskCap(NormalRiskCap()) return if state == REDUCED: SetNewEntryRiskCap(ReducedRiskCap()) BlockRestrictedSymbolsAndStrategies() return if state == ENTRIES_BLOCKED: BlockAllNewEntries() CancelEligiblePendingOrders() AllowOnlyDefinedProtectiveManagement() return if state == EMERGENCY_FLATTEN: BlockAllNewEntries() CancelEligiblePendingOrders() EmergencyFlatten.ExecuteAndReconcile(snapshot) LatchBlockedStateAfterFlattenAttempt() return
The enforcement action should be idempotent. Reapplying a blocked state should not create duplicate cancellation or close requests without first reconciling actual broker state.
Common Risk-Agent Mistakes
Letting the Strategy Control Its Own Risk State
A strategy that benefits from entry has a conflict of interest. Separate risk evaluation and enforcement from strategy logic.
Using Cached Strategy Positions as Truth
Cached state can be wrong after partial fills, manual trades, restarts, or failed requests. Use broker-reported positions and account data as the source of truth.
Relying on an AI Score Instead of Hard Limits
Anomaly detection can flag unusual conditions, but daily loss, open risk, margin, and allowed-symbol limits must remain explicit deterministic rules.
Not Latching Severe States
A transient recovery can trigger repeated re-entry if severe stop states clear automatically. Use latch and documented reset rules.
Ignoring Pending Orders
Pending orders can become exposure during volatile conditions. Include them in total-risk and emergency-control logic.
Assuming Emergency Flatten Guarantees Closure
Close requests can be rejected, delayed, or partially filled. Reconcile every action and maintain the blocked state until account state is known.
Testing Only During Calm Markets
Risk controls must be tested under disconnections, partial fills, rejected requests, wide spreads, rapid movement, and restart conditions.
Using Free Margin as Permission for More Trades
Free margin is a buffer, not a risk budget. Use stop-loss-based risk, total exposure caps, and correlation limits before allowing additional positions.
Implementation Checklist
Use this checklist when building an independent MT5 risk agent:
- Run the risk process independently from every signal and strategy process.
- Use broker-reported positions, orders, equity, margin, and quote data as the source of truth.
- Build timestamped risk snapshots covering account, portfolio, market, execution, and system health.
- Use a small explicit state set: normal, reduced, entries blocked, and emergency flatten.
- Map every risk state to deterministic actions that strategies cannot override.
- Keep maximum daily loss, open risk, allowed symbols, session rules, and emergency behavior as hard limits.
- Use anomaly detection only as a conservative supplement to explicit limits.
- Calculate total portfolio exposure, including pending orders, correlation, and multiple strategies.
- Respect stop distance, tick value, contract specifications, volume steps, and broker stop rules in final sizing.
- Latch severe states and require documented recovery or manual reset procedures.
- Block new entries whenever broker state, time synchronization, quote freshness, or reconciliation is uncertain.
- Define emergency flatten priorities and reconcile partial fills, rejections, and remaining exposure.
- Test the kill switch under disconnection, rapid price movement, partial fills, manual intervention, and restart conditions.
- Persist risk state, transitions, latches, and daily references so restarts cannot silently re-enable trading.
- Audit every snapshot, threshold check, anomaly result, state change, enforcement action, and broker response.
Final Thoughts
An independent risk agent is valuable because it is designed to reject trades when strategy logic alone would prefer to continue. It turns risk management from a collection of optional warnings into a separate authority that monitors the entire account, portfolio, market, and operating environment.
Use broker-reported state, hard deterministic limits, explicit risk modes, durable latches, and carefully tested enforcement. Let machine learning flag unusual combinations of conditions, but never let it replace daily loss limits, exposure caps, stop-distance sizing, or an emergency kill switch. A strategy can recommend. An independent risk agent must be able to say no.
Risk disclaimer: Automated trading, artificial intelligence, risk-management agents, Expert Advisors, foreign exchange, CFDs, commodities, indices, stocks, cryptocurrencies, and other leveraged products involve substantial risk and may not be suitable for all investors. This article is for educational and software-architecture purposes only and does not constitute financial, investment, legal, tax, cybersecurity, or regulatory advice. Risk controls, stop-losses, and emergency procedures cannot guarantee exact execution or prevent all losses in fast, illiquid, disconnected, or gapping markets. Past performance, backtests, forward tests, and demo results do not guarantee future results. Test all systems carefully, verify broker-specific behavior, and use robust independent risk controls before considering live deployment.


