How risk rules work
This guide explains where risk rules run, what they count, what happens when one trips, and why you can always close a position.
1. Rules run next to the terminal
Every trading account has a risk policy. When the account’s deployment runs in risk mode, the policy is sent to your server and enforced there by nile-risk, a separate process inside the terminal’s container. Every order passes through it before it reaches MetaTrader 5.
- The control plane also checks each order when it accepts it, so most refusals show up at once. The check on the server is the one that counts.
- If the control plane is unreachable, the server keeps enforcing the last policy it applied. Losing the control plane never closes positions or stops terminals. It only means no new orders can be accepted.
- nile-risk keeps a journal on the server that survives restarts. After a restart it refuses new orders until it has read its journal and rebuilt its figures from the broker’s history.
Risk mode is set when a deployment is created and cannot be changed. The New deployment form does not offer it yet: it is set with risk_mode: true on POST /api/v1/deployments, together with allow_trading: true. The server’s agent policy must allow it (trading.risk: true, venue mt5, and the commands trade.risk.policy and trade.risk.clear).
Without risk mode, your rules are stored but not enforced on a server. The account’s Risk tab says “Your rules are stored, not checked on this account”, and only the guards from the limits are checked.
2. What a rule counts
A rule is one to four criteria joined by AND. Each criterion measures something for a subject:
- the whole account, or one route, depending on what the rule is assigned to;
- one strategy (the strategy tag on orders);
- one symbol;
- one strategy on one symbol.
Measures cover profit and loss (amount or percentage), activity (trades, orders, open positions, net volume, orders in flight) and order-time checks (order volume, price age, spread). An order on a route is checked against the route’s rules first, then the account-wide rules. It must pass all of them.
Every account also keeps mandatory guards converted from its limits: order volume, open positions, orders in flight, price age, orders per minute and the automatic stop after repeated refusals. Guards cannot be deleted. There is no “unlimited”.
Manual trades and other Expert Advisors in the terminal count towards account and symbol totals, never towards a route or strategy. To write rules, see Writing a rule.
Next to these rules, an account can have time rules for trading hours, market close and news windows (section 5).
3. Periods and latches
Counted measures use a period: minute (orders only), day, week or month. Periods follow the broker’s server time, never your server’s clock. A day runs 00:00 to 24:00, a week from Monday 00:00, a month from the 1st.
When a rule with a period trips, it latches: it keeps refusing new exposure until the end of its longest period, even if the figure drops back. A loss limit for the day stays tripped until the broker’s midnight. A rule with only order-time or state criteria never latches; it refuses that one order.
A user with trading:configure can ask the server to clear a latch early through the API. The dashboard cannot clear a latch yet. The request is sent until the server answers, also while it is unreachable, and it is audit-logged. Clearing closes nothing, and the server refuses a clear for a latch that is no longer current. See Writing a rule for the calls.
4. When a rule trips
Each rule has an action:
| ACTION | WHAT HAPPENS |
|---|---|
| block_new_exposure (default) | New opening orders in the rule’s scope are refused with the rule’s name (risk_rule_tripped). Closing a position is still allowed. |
| block_and_close | Would also close positions of one chosen target (the account, a route, a strategy or a symbol). Not available yet: the agent refuses to deliver a policy with such a rule (close_action_unsupported), and the server keeps its previous policy. The dashboard says “Closing positions is not available yet.” |
Other refusal codes you may see: risk_policy_pending (a saved revision is not yet applied on the server), risk_engine_unavailable, risk_evidence_stale and risk_evaluation_error. A rule that cannot be evaluated refuses; it never counts as “not tripped”.
A tripped limit or expression rule is not yet raised as a monitoring alert; its refusals show on the order and in the account’s events. Time rules can raise alerts (section 5), and alerts can be sent to Telegram, Slack, email or a webhook. See Alert notifications.
5. Trading hours, market close and news
Time rules limit when new positions may open. Set them on the account’s Risk tab, under Hours and news. Each rule applies to the whole account or chosen routes, and optionally to some symbols. There are three kinds:
| KIND | WHAT IT DOES |
|---|---|
| Trading hours | New orders only inside your weekly windows, for example Monday to Friday 09:00 to 18:00. The clock is the broker’s server time or a time zone you pick, daylight saving included. Outside the windows, orders are refused with risk_outside_trading_hours. |
| Market close | Blocks new orders some minutes before each daily close, or only before the weekly close, until the market opens again (risk_market_closing). Close times come from the broker’s trading sessions for each symbol. |
| News | Blocks new orders from some minutes before to some minutes after economic news (risk_news_window). News comes from the economic calendar built into MetaTrader 5. Choose high impact, or high and moderate, the currencies (by default those of the order’s symbol), or pick exact events such as a central bank rate decision. |
Each rule can also act before its block starts:
- Close open positions before the block, 1 to 240 minutes ahead (10 by default). For example, close everything 15 minutes before the Friday close, or 10 minutes before major news.
- Cancel pending orders while it blocks, on by default.
- Raise an alert when the rule leaves positions open at its deadline (TIME_PLAN_MISSED) or cannot decide (TIME_RULES_UNAVAILABLE).
Time rules never latch: the block ends when its window ends. They never refuse a close or a cancel you send. They need risk mode, because only nile-risk on the server enforces them. An account can have up to 20 time rules.
When a rule cannot decide, it refuses new orders in its scope instead of guessing: risk_news_unavailable when no complete calendar read is less than 30 minutes old, and risk_sessions_unavailable when a symbol’s trading sessions are unknown.
6. You can always close
Reducing risk must never be blocked. A close of an existing position, for at most its volume, goes through when:
- a rule has tripped or latched, or a time rule blocks;
- trading is turned off for the account or a route;
- the organization’s emergency halt is on (see Stopping safely);
- nile-risk is not running.
While nile-risk is down, the agent closes through a separate close-only channel. The Expert Advisor inside the terminal accepts nothing from it except closing an open position on the bound account, so it can never open or flip a position. Opening orders are refused with risk_engine_unavailable until nile-risk is back, which normally takes seconds.
7. Check what is enforced
Each saved change is a new policy revision. Through the API, GET /api/v1/trading/accounts/{account_id}/risk-policy shows whether the current revision is applied on the server, still pending, rejected with the server’s reason, or control_plane_only. Until a revision is applied, new opening orders on the account are refused; closes are not held.
The dashboard cannot yet show which revision the server has applied. Expect a saved rule to start refusing orders soon after you save it. See the Trading API reference.