Learn / Exchange APIs

Monitoring a trading integration

Figures on this page are as of 2026-09. Fees, limits and margin tiers change — check the venue's own docs before acting on a number.

The failures that cost money in a trading integration do not throw exceptions. A stream that silently stopped updating, a permission that expired three months after you set it up, a position that drifted from what your code believes — none of these produce an error.

So monitoring built around “alert on exceptions” misses the entire category that matters.

The four silent failures

1. State divergence. Your code’s view of positions differs from the exchange’s. Caused by a missed stream update, a partial fill you did not process, or a manual trade. Nothing reports it, and every subsequent decision is made on wrong numbers.

2. A stale stream. The socket is open, no data is arriving. A quiet market and a dead connection look identical from the application’s side — see WebSocket reconnection patterns.

3. Silently expired permission. On Binance, a key without an IP whitelist has spot trading switched off 90 days after activation. Reads keep working. Only orders fail, with -2015, three months after anyone touched the setup. See the IP whitelist article.

4. An unprotected position. The entry filled, the stop did not — a partial sequence failure that leaves you exposed with nothing behind it. Everything looks normal until it does not.

What to check, and how often

Continuously

Data freshness. Time since the last message on each subscription. If it exceeds what is plausible for that stream, treat the connection as dead. This single check catches failure 2, which nothing else will.

Position reconciliation. Compare your view against a REST query on an interval and after every reconnect. Any mismatch is an alert, not a log line.

Every position has its stop. For each open position, verify a protective order exists at the expected level. This catches failure 4, and it is the check most worth having.

At startup

Assert key permissions. On Binance, GET /sapi/v1/account/apiRestrictions returns ipRestrict, enableReading, enableWithdrawals and the rest. Assert what you expect and refuse to start if it differs — see Binance API key permissions.

Log the environment. Which base URL, testnet or live. One line that answers “which environment is this process actually in” without inference.

Log the clock delta against the venue’s server time. Drift causes authentication failures that look like signing bugs — clock sync and timestamp errors.

Daily

Key age. Binance’s 90-day expiry is predictable, so alert at 75 days rather than discovering it. Bybit UTA keys expire too, surfacing as 10003 on spot or 33004 on derivatives.

Rate limit headroom. Binance reports weight usage in response headers. If you are routinely near the ceiling, you have no capacity left for reconciliation when you need it most.

Realised versus planned R. Not infrastructure, but it degrades silently and it is where execution problems show up first.

What to alert on

The hard part of alerting is not what to include — it is what to leave out, since an alert stream you ignore is worse than none.

Alert:

  • Position mismatch between your state and the exchange
  • An open position with no protective order
  • Stream stale beyond threshold
  • Permission assertion failed
  • Ambiguous outcome on an order call — rare, consequential, easy to miss
  • Rate limit escalation: HTTP 418 on Binance is an IP ban, not throttling
  • Repeated authentication failures

Do not alert:

  • Individual transient errors. They are normal
  • 429 rate limits handled by backoff
  • Reconnects that reconciled cleanly
  • Individual losing trades. That is not an infrastructure signal

The ambiguous-order alert deserves emphasis. It happens rarely, which means it will be a line in a log that nobody reads, and it is precisely the case where reconciliation before acting is mandatory.

Heartbeat, or the absence of it

A process that dies silently generates no alerts, because alerting is something the process does.

The fix is inverted: have the process emit a heartbeat and alert on its absence. Otherwise a crashed integration looks exactly like a quiet one, and the difference is a position with nobody watching it.

For AI-assisted setups

Two extra things worth capturing:

Tool call volume. A model can fan out into far more requests than a hand-written client, and rate limits arrive faster than expected — see rate limits in an MCP trading setup.

The tool list. MCP servers can change their exposed tools, and notifications/tools/list_changed exists because this is normal. A server you reviewed as read-only can gain an order tool in an update. Recording the tool list at startup turns that into something you can diff.

The principle

Monitor for the absence of expected things, not just the presence of errors.

Expected: data arriving, positions matching, stops existing, the process alive, permissions intact. Each of those failing produces silence, and silence is what you have to instrument for.

FAQ

What should I monitor in a trading bot?

Data freshness on every stream, position reconciliation against the exchange, the existence of a protective order for every open position, and a heartbeat you alert on the absence of. These cover the silent failures; exception logging already covers the loud ones.

How do I detect that my position state is wrong?

Query the exchange on an interval and after every stream reconnect, and compare against your own view. There is no other reliable detector, because a divergence caused by a missed update produces no error and every subsequent update applies cleanly to the wrong base.

Why did my trading integration stop working after three months?

On Binance, most likely the 90-day expiry of spot trading permission on keys without an IP whitelist. Reads continue working so the failure is order-specific, typically -2015. Alerting on key age at 75 days turns this into a scheduled task rather than an outage.

What should I not alert on?

Individual transient errors, handled rate limits, and clean reconnects. They are normal operation, and alerting on them produces a stream you stop reading — which then hides the alerts that matter.