Conditional Orders
Stop-loss, take-profit, trailing-stop and OCO — submitted natively to Binance or watched in-house for internal pairs
What Conditional Orders Are
Conditional orders are orders that wait for a trigger before they hit the book. WPCrypto supports four kinds: stop-loss, take-profit, trailing-stop, and OCO (one-cancels-the-other). Each one can act either on a Binance-routed pair (native Binance order types) or on an internal MYEXCHANGE pair (watched by a cron-driven engine).
📈 Order Types Supported
- stop_loss: sell when price drops to or below the trigger (or buy when it rises above)
- take_profit: close a position once a favourable target price is hit
- trailing_stop: a stop that follows the price by a fixed % or absolute offset
- oco: pair a take-profit with a stop-loss; whichever fires first cancels the other
Two Execution Modes
Each conditional order picks one of two execution paths based on the exchange of the underlying pair:
| Exchange | How it triggers | Native order types used |
|---|---|---|
| BINANCE | The order is submitted to Binance as a native STOP_LOSS / TAKE_PROFIT / OCO so Binance watches the trigger. | STOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, TAKE_PROFIT_LIMIT, orderList/oco |
| MYEXCHANGE | A cron-driven watcher polls live prices every 30 seconds and fires the action order when the trigger is hit. | Plain MARKET or LIMIT order submitted to the internal matcher |
Trade Page Integration
The trade page renders a Conditional Order box right after the standard MARKET / LIMIT boxes. The box reads the symbol, base, quote and exchange directly from the trade settings so users do not pick the pair twice.
- Desktop: rendered as a full-width
.wpcrypto-boxunder the trade grid - Mobile drawer: appears as its own tab inside the trade drawer; the same form, sized for thumbs
- BUY / SELL buttons: separate submit buttons; the JS handler shares the same AJAX endpoint and validates fields client-side before the round trip
How Trailing Stops Work
For trailing stops on internal pairs the plugin watches the highest (or lowest) price seen since the order was placed and slides the trigger by the offset you set. As the market moves in the user's favour, the trigger moves with it; if the market reverses by more than the offset, the order fires. The user only sees the current effective trigger — the running high/low is tracked behind the scenes.
For Binance-routed trailing stops the plugin hands the trailing offset to Binance directly, so Binance watches the price server-side and the plugin only tracks the order id.
OCO (One-Cancels-Other)
OCO uses Binance's modern /api/v3/orderList/oco endpoint with an above-leg / below-leg model:
- Above leg: fires if price moves up (typically a TAKE_PROFIT_LIMIT)
- Below leg: fires if price moves down (typically a STOP_LOSS_LIMIT)
On the internal exchange the same row is paired with a sibling row via parent_order_id. When one leg triggers, the watcher cancels its sibling automatically.
Watcher Tick
The internal watcher runs every 30 seconds via a custom cron schedule (wpcrypto_risk_30s). Per tick it:
- Expires any pending row whose
expires_athas passed - Fetches all MYEXCHANGE pending rows and groups them by symbol
- Asks the live-market cache (Binance WebSocket) for the latest price per symbol, falling back to REST
- Evaluates each row's trigger; trailing stops update their watermark and effective trigger
- When a trigger fires, the row transitions to
triggered, the action order is dispatched, and the OCO sibling (if any) is cancelled - For BINANCE rows that use a native trailingDelta the watcher just polls Binance for status updates
What Gets Tracked per Order
For each conditional order the plugin records the trigger (direction, price, trailing offset + unit), the action that will fire (side, quantity, type, price), the exchange, the linked Binance order id when applicable, the OCO sibling, expiry, current status and any admin notes. This is shown in the user's conditional-order panel and the admin log — you never have to query anything by hand.
AJAX Endpoints
| Action | Purpose |
|---|---|
| wpcrypto_risk_create | Submit a new conditional order from the trade page |
| wpcrypto_risk_cancel | Cancel a conditional order (also cancels on Binance when applicable) |
| wpcrypto_risk_list | List the user's open conditional orders for the profile / trade page panel |
| wpcrypto_risk_check | Return the user's current risk policy state (cooldown, daily pnl, drawdown) |
Every endpoint requires a logged-in user and a valid nonce.
Operator Notes
⚠️ Things to Know
- Binance trailingDelta range: 10–2000 BIPS (0.1%–20%). Absolute trailing offsets fall back to a static stopPrice because Binance does not accept them.
- OCO trailing legs: use the
aboveTrailingDelta/belowTrailingDeltaparams on the OCO endpoint; the older single-leg trailingDelta is independent. - Internal pairs need a price: if a symbol does not exist on Binance the watcher cannot fetch a price for it, so its conditional orders never trigger (by design).
- Cron must run: deploy a real system cron or a server-side trigger calling
wp-cron.phpat least every 30 seconds — relying on browser-triggered cron will silently miss triggers when traffic is low.