Pre-Trade Risk

The server-side checks every agent order must pass before it reaches the market.

View as Markdown

Beta, pre-release. The NinjaTrader MCP server and its trading skills are in beta and aren’t yet generally available. The beta runs on Demo only, which trades simulated money. Live access opens later. Server hostnames, the tool set, the skills, and the onboarding flow may change before launch.

Every order your agent submits runs the same server-side pre-trade checks as an order you place yourself in the trading platform. The MCP server doesn’t run a separate risk layer—it submits the agent’s order to the platform’s risk engine and relays the verdict. If a check fails, the order never reaches the market, and the agent receives the reason.

One account, one set of limits

Pre-trade checks evaluate your account as a whole, not the agent’s session. If you trade manually alongside a connected agent, both draw on the same margin, the same position limits, and the same loss limits: the agent doesn’t get a separate budget. The one agent-specific layer is the connection risk limits you can set when approving the connection, and the server measures even those against your entire account.

What gets checked

An order passes through two stages before it reaches the market.

Trading permission checks

Before submitting the order, the server confirms the account can trade the product at all:

  • An active subscription that permits trading
  • Product-type restrictions on the account
  • Required disclosures and agreements for the product—for example, the single-stock futures risk disclosure or a key information document
  • Temporary trading lockouts on the user or the account
  • Read-only accounts
  • The connection’s product allowlist, if you listed any products or contracts

If one of these fails, place_order returns a blocked status with a reason code and a plain-language message, and the server submits nothing.

Risk engine evaluation

Orders that pass go to the risk engine, the same engine that evaluates every order on the platform:

  • Margin: the engine checks the order’s projected initial margin requirement against the account’s available excess.
  • Position and quantity limits: maximum order quantity, maximum position per contract, and maximum total position.
  • Account and market restrictions: liquidation-only status, closed sessions, and price or quote validity.
  • Connection risk limits: the exposure and volume caps you set for this agent connection. The server skips them on a purely closing order, and the per-product and per-contract caps apply only to opening legs. The engine also rechecks the product allowlist here.

A failure here returns a rejected status with the reason—for example, MaxPosLimitReached—and a message describing the limit.

What the agent sees

place_order statusMeaning
okThe platform accepted the order, and it’s working.
blockedA trading permission check failed. The server submitted nothing.
rejectedThe risk engine or execution path declined the order at submission.
failedThe server couldn’t confirm the outcome. Either a downstream system, such as the exchange, rejected the order after acceptance and the response relays the reject reason, or the server stopped tracking the order after 15 seconds and returns the reason TrackingTimeout. On TrackingTimeout the order may still be working: check my_portfolio or order_details before you resubmit.

A blocked or rejected response names the check that failed, so the agent can explain the outcome and adjust: resize the order, pick another contract, or stop and ask you. A failed response names the reason the server has, which on a tracking timeout is only TrackingTimeout.

Pre-flight with estimate_order

estimate_order runs the same permission checks and the same risk engine in evaluate-only mode—a dry run that creates no order. The response reports whether the order is feasible, the current and projected margin, net liquidation value, remaining excess, and estimated fees. When the order isn’t feasible, the response names the reason. A reason from the risk engine matches the code a real order would return. When the engine raises no code but the projected excess is negative, estimate_order reports InsufficientExcess on its own, and a real order might still go through, for example, a closing order. Have your agent estimate before it places. The recommended workflow does exactly that.

The limits you control

  • Account risk settings: daily and weekly loss and profit limits, trailing max drawdown, and auto-liquidation thresholds. Read them with risk_settings and change them with update_risk_settings. They apply to the whole account, agent or not.
  • Connection risk limits: exposure and volume caps, and an optional product allowlist, that bind only this agent connection. You set them on the consent screen when you approve the connection. See Authentication & Access.
  • Auto-liquidation: the post-trade backstop when an account falls below health criteria. See Safety & Disclosures.