Why a stop order does not trigger in a mobile app
A stop order did not trigger at the worst possible moment — the position remains open longer than the trader planned, and closes at a different price.
The reason is usually not the strategy, but the chain "app screen — communication channel — trading system": a conditional order is executed on the exchange side, but its placement is initiated by the phone, and any failure in this chain turns into a lost order.
Classic case — lost order when connection breaks. User tapped "buy", interface showed confirmation, but request did not reach trading core: when switching between networks, response is lost, and app draws success based on local state.
Second common story — order placement error in app, when price and volume are substituted from outdated order book snapshot, and stop goes out with a price that no longer exists on market.
Failed conditional order surfaces after app restart. If confirmed order ID is not saved on device, after cold start list of active stops is empty — trader places a new one, while old continues to live on system side.
Other side of same problem — duplicates: resending after timeout creates second order, and position closes with double volume.
For trading account, this results in an unclosed position, slippage, and manual investigations instead of work. Let's break down how this is closed at app level.
What correct operation of conditional orders provides
Correctness of a stop order is measured not by presence of a row in order list, but by share of executed conditional orders: condition triggered — order went to server and was confirmed.
By event log, this share is directly visible: count all triggers and subtract those where order remained local due to connection loss or state conflict.
Time from touching condition to sending — second metric. It depends on where condition is matched against quote stream: if waiting for server notification, delivery round trip is added, and order goes out with slippage.
Local matching with subsequent confirmation reduces trigger window severalfold and makes it predictable under channel overload.
Third slice — order failure classes. These include lost order when switching network and app minimizing, duplicates on resend, stuck stop orders after device sleep.
Local state log and idempotent order key enable resend without duplicates: server recognizes repeat and does not create second order.
Resilience of trading logic is tested by a set of scenarios, not one run: connection break at trigger moment, network switch, long sleep, session recovery.
We run builds on real devices and unstable networks via TestFlight — this way failure classes are caught before release, not on a volatility day.
Stop order placement modes: comparison of approaches
A conditional order differs from a regular one in that it does not enter order book immediately: it waits until price reaches threshold, and only then becomes market or limit. Hence main implementation question — where condition check lives and at what price it is calculated.
| Mode | Where logic lives | How condition is processed | Limitations |
|---|---|---|---|
| Stop on service side | Conditional order stored on server | Service monitors mark price and places order itself | Triggers when app closed; requires control that stop is not lost |
| Local logic in app | Threshold stored in app | Compares price stream with threshold and sends order | Only while app active and connection available |
| Hybrid | Condition on service, placement signed by app | Service triggers, app confirms execution | More reliable than local, but window before confirmation appears |
| Condition by mark price | Comparison point — mark price | Threshold checked against smoothed value from several sources | Fewer false triggers, but value updates less often |
Comparing threshold with last trade is dangerous: on thin order book one large order creates outlier, stop triggers, and price immediately returns — client gets execution without reason. Therefore condition is tied to mark price: fewer triggers, but each is justified.
Choice of mode is compromise between trigger reliability and reaction immediacy, and product itself sets it.
If stop protects position, logic is kept on service side, and state is duplicated in app; local logic is appropriate only as auxiliary and with honest warning about operating limits.
How we implement conditional orders: work stages
A conditional order is a deferred decision with trigger price, volume, and behavior on connection loss.
An error in any of these fields costs more than an error in interface, so we structure implementation stages of trading logic so that each relies on fixed result of previous one.
- Audit of order scenarios. We compile list: stop-loss and take-profit, stop-limit, tying to last trade or mark price, behavior on gap and partial execution. Output — matrix "scenario / trigger condition / expected behavior", agreed with your team.
- Schema design. We decide where order state lives — on client, on server, or in trading core — and how it is reconciled after reconnection. Separately, we close duplicate protection: resend on connection break must not create second order.
- Implementation. We write conditional order layer separately from interface so trigger logic can be changed without rebuilding screens. We handle price events in one stream with explicit queue — this removes races during sharp market movement.
- Test environment. We set up environment with quote stream and trading core responses, including failures: timeouts, rejected orders, state desync. Each matrix item is covered by automated test.
- Order testing on historical data. We replay real trading days with gaps and low liquidity: count where order triggered at expected price, where it slipped, where logic diverged from exchange.
- Handover and regulations. We hand over state schema, configuration description, incident investigation procedure, and metrics: share of rejected orders, delay from receiving price to sending, number of desyncs.
Configurations, calculation schemas, and handover regulations
After completion, client receives not an archive with source code, but a set by which trading logic can be maintained and developed by their own team. List of artifacts is fixed before start, so no "surprises" appear at delivery — what was promised is what is in hand.
- Documentation on trading logic: stop order lifecycle — placement, activation conditions, triggering, cancellation, handling connection breaks and retries.
- Order price calculation schema: where market data comes from, how price and volume are rounded to tick and minimum lot, how stop price and limit price relate.
- Specification of exchange with trading core: message formats, error codes, and how each is shown to user.
- Set of automated tests: scenarios of triggering, cancellation, and rejection of orders, checks of boundary price and volume values.
- Maintenance regulation: procedure for releasing changes in trading rules, mandatory checks before rollout, incident response times.
- Monitoring schemas: which stop order indicators are tracked and at which deviations duty officer receives signal.
- Engineering decision log: why activation and failure handling rules were chosen exactly this way.
The set is assembled during work, not reconstructed at the end, so handover takes one or two walkthroughs, not a month.
Case study: how we reduced number of failed orders
Situation before
Client — digital asset exchange — kept stop orders on app side: trigger price was checked in background on phone, and order went to server only if process was alive. App minimized, system unloaded it from memory — stop did not trigger.
During sharp market movements, share of failed stop orders reached 6.4%, and almost each turned into support request with manual investigation.
What we changed and what resulted
Logic was moved to server side: app only validates parameter correctness and sends stop order, while trigger, margin control, and allowable price deviation live in trading core. Each order is assigned immutable key — resend after connection break does not create duplicate.
On reconnection, client receives current snapshot of order state instead of recalculating it from local copy, so discrepancy "still on screen, already executed on exchange" is gone.
After refinement, share of failed stop orders — 0.7%, and these are mainly price exiting allowable deviation, where system honestly cancels order and shows reason. Support requests about stop orders became seven times fewer, order duplicates — zero.
In log, for each order it is visible when trigger fired, what trading core responded, and for what reason order did not pass.
Conditional limit or market order: what to choose
A stop order triggers by trigger, but then everything depends on order type: conditional limit order and market order differ in what exactly is guaranteed after level touch. In first case, price is fixed; in second, fact of execution. Before triggering, both sit in order book the same way.
A conditional limit order after trigger becomes a regular limit order. Client is protected from drawdown on execution: trade will occur at specified price or better, but not worse.
Flip side — no execution guarantee: on sharp movement price moves away from level, order remains unexecuted, and position continues to hang unclosed.
A market order closes position at any available price within order book depth. Here execution is guaranteed, not price: the thinner order book, the more noticeable drawdown on execution.
On liquid instrument, deviation from trigger level is measured in fractions of price tick; on thin, in several levels, especially if volume is comparable to best quotes.
Separate risk of thin market — partial execution and gaps between levels: large order eats near levels and picks up volume deeper. Therefore in mobile app expected drawdown is calculated and shown before confirmation, not after trade.
Choice of trigger type comes down to priority: price protection or protection from non-execution. For protective stop on liquid instrument, market order is usually sufficient — exit is more important than a few price ticks.
For entry on thin market, limit with buffer from trigger is wiser so execution does not fail on first impulse.
Technical doubts: questions and answers on orders
Below are four doubts most often raised during task review. We answer specifically: how stop order behaves when app is closed, what happens on connection break, and how to test logic without risking positions.
Will a stop order trigger if app is closed?
Yes. After confirmation, conditional order lives on trading core side, and phone only transmits parameters: activation price, volume, expiry. Triggering and placement into order book are performed by server, so turned-off screen or lost network do not cancel condition. Trigger notification is consequence, not mechanism.
What happens on connection break at placement moment?
Request goes out with retry key: if response did not arrive, app sends it again, and core recognizes duplicate instead of second order. After connection recovery, list is reconciled with order log, not with phone memory. This way "phantom" stop orders do not appear on screen and real ones are not lost.
How to test logic without risking positions?
We run scenarios on test environment with same core: sharp price break, partial execution, cancellation at activation boundary, re-placement. Separately, we check minimum volume and price tick — frequent cause of rejection already at confirmation. Live account is not involved in these runs.
Will orders be lost after app update?
We do not consider local cache source of truth. When storage schema changes, migration is built in, and on first launch of updated version client reconciles list with server by identifier — missing conditional orders return to interface. Separate scenario — rollback to previous version: it must not break already placed stop orders.
Let's discuss the task: prepare inputs on trading logic
To come back with estimate for refinement and work plan, we need inputs on trading logic — not general description, but how stop order should behave exactly in your product. Below is minimum that removes most questions before first call.
- Types and combinations of orders: only stop-loss or stop-limit, whether take-profit and combination are needed, where execution of one order removes paired one.
- Trigger: by last price, by mark price, or by index; what we consider source and how we act on discrepancy between sources.
- Account modes: spot, margin trading, futures market; how stop combines with risk limits, leverage, and forced position closing.
- Volumes and removal rules: available and blocked volume for order, partial execution, trailing stop following position, limit of simultaneously active orders.
- Behavior on failures: connection break with exchange, service restart, resend — where order state is stored and how we exclude duplicates.
- Events and notifications: what goes to transaction history and log, what we show client on screen and in notifications.
- Data for testing: access to exchange test environment, accounts in different modes, and list of problem cases from support.
If some answers are in exchange documentation — a link to the needed section is enough. Describe the task, attach current mockups and logs of disputed triggers — we will discuss the task and come back with refinement estimate, stage composition, and work plan.







