Profit Lock
What it does
Watches your combined long and short PnL on a pair and, when a trigger fires, cancels open orders, reduces both sides to flat, and freezes the realized PnL at that moment. Optionally rolls into a new cycle with reseeded grids.
Why this exists
A long grid and a short grid running independently in hedge mode can each be doing well in isolation while the pair as a whole has built up a fragile structure. Two situations are the most common:
- The long has appreciated nicely on an uptrend and you want to bank the gain before it gives back.
- The short has grown much larger than the long during a sustained pump, and the short side now carries unbounded loss risk.
Profit Lock handles both with one mechanism: pick a trigger condition, and when that condition fires the bot exits both sides cleanly and records the realized PnL as a frozen result. From there you can leave it flat, manually re-enter, or let Auto-Cycle reseed and start over.
For all config fields, see Config Reference. Strategy Config can create or update locks through
defaults.profitLocks. When defaults.profitLocks.enabled is true, every enabled symbol uses those global settings and becomes read-only in the modal. Put a profitLock override inside an existing pairs entry for symbol-specific changes or opt-outs.Trigger kinds
Profit Lock supports two trigger kinds. Pick the one that matches what you actually want to lock in.
USD target
The classic mode. You choose a USD target; when combined PnL reaches or exceeds that target, the lock fires.
| Fires when | Combined long + short PnL ≥ your target |
| Use when | You have a specific dollar amount you want to bank, e.g. "$50 on this pair and I'm done." |
| Cell display | currentPnl / target while watching, FROZEN finalPnl / target once triggered |
Short ≥ Long
The risk-management mode. The lock fires when your short position becomes at least as large as your long. There is no USD target to set.
| Fires when | Your short notional is greater than or equal to your long notional |
| Use when | You ran a long-biased grid through a pump, your short side has grown to match or exceed your long, and you want to exit before short risk runs further |
| Cell display | currentPnl / "short ≥ long" while watching, FROZEN finalPnl / "short ≥ long" once triggered |
The asymmetry is intentional. Short-side risk on a perp is unbounded as price climbs; long-side risk has a floor at zero. There is no symmetric "long ≥ short" trigger.
You can switch a watching lock from one kind to the other at any time from the modal, including changing the USD target value.
How it works
Once a Profit Lock is enabled on a pair, the bot watches your positions on every position update or order fill. It tracks combined PnL across both sides, and for the short ≥ long kind it also tracks long and short notional in USD.
When the trigger condition becomes true, the lock fires once and runs a fixed sequence:
- Cancel all open grid orders on both sides for the pair.
- Reduce the side with the larger notional first, then the other side, with reduce-only market orders.
- Stop the grid bot for the pair.
- Freeze the realized PnL at the moment the reduces confirm. That frozen number is what shows up in the cell from then on.
If a reduce order fails (rare, usually a Bybit ack rejection or a partial fill), the lock stays in the triggered state with no frozen value, and you can re-run the trigger actions from the modal.
Auto-Cycle
Auto-Cycle is opt-in and works for both trigger kinds. After the lock triggers and reduces both sides, Auto-Cycle:
- Bumps the cycle count.
- Reseeds the long and short sides with market orders sized by your seed values.
- Rotates the lock back to watching for the next cycle.
- Stops once the cycle count reaches your max.
For USD-target locks, each rotation bumps the next target by your Target Increment (USD) so consecutive cycles aim higher. For short ≥ long locks the target field is unused, so the form hides it and shows an "unused for short ≥ long" placeholder in its slot.
Long-bias seed rule
The Auto-Cycle form requires
seedLongUsd > seedShortUsd. Equal seeds and short-biased seeds are rejected. The reason is twofold:- For short ≥ long, equal or short-biased seeds would re-trigger the lock on the first position update after rotation, burning a cycle on every tick until the max is hit.
- For USD target, the auto-cycle premise is a long-bias spread; without it the next cycle starts with the same imbalance the previous cycle just exited.
The default starter values (
seedLongUsd = 500, seedShortUsd = 250) satisfy this rule.Worked example
Settings: trigger kind = short ≥ long, Auto-Cycle enabled,
seedLongUsd = 500, seedShortUsd = 250, maxCycles = 10.You ran a long grid through a pump on HYPEUSDT. Current state:
| Value | |
|---|---|
| Your long notional | $400 |
| Your short notional | $400 |
| Combined PnL | $+18 |
Step 1: Trigger fires
Your short ($400) has caught up to your long ($400). The lock fires. The $+18 of combined PnL is what gets locked in.
Step 2: Reduce sequence
The bot cancels open orders, reduces both sides to flat, and freezes the realized PnL at $18. The cell now reads
FROZEN 18 / short ≥ long.Step 3: Auto-Cycle reseeds
Cycle count becomes 1. The bot opens a $500 long market and a $250 short market. The lock rotates back to watching and the trigger is reactivated.
Step 4: Next cycle
After the seeds land, your long is $500 and your short is $250. The trigger condition is false, so the lock waits. The grid runs normally until either the trigger fires again (cycle 2) or you hit the max cycle count.
Interaction with other features
| Feature | Interaction |
|---|---|
| EXO indicator | Auto-Cycle requires EXO to be enabled on the long side. The form refuses to enable Auto-Cycle otherwise. The lock itself does not depend on EXO. |
| Hedge Guard | Hedge Guard still runs while Profit Lock is watching. It does not delay or modify a lock trigger. |
| Position Balancer | Independent. Both can run on the same pair. |
| Rebalancer | The reduce sequence cancels rebalancer-issued orders along with grid orders. |
Tuning tips
| If you want... | Adjust this |
|---|---|
| To bank a fixed dollar amount and stop | Use the USD target kind with Auto-Cycle off |
| To roll a long-biased pair through repeated short-buildups | Use short ≥ long with Auto-Cycle on |
| Each USD-target cycle to aim higher than the last | Raise targetIncrementUsd |
| The long side to start each cycle further ahead of the short | Raise seedLongUsd relative to seedShortUsd |
| To stop after a fixed number of rotations | Lower maxCycles |
Troubleshooting
| Symptom | Likely cause |
|---|---|
| Lock never fires for short ≥ long | Your long notional is still larger. Check the long and short values in the modal's lock state panel. |
| Lock fires but no frozen value appears | A reduce-only order failed. Open the modal and re-run trigger actions, or close the remaining side manually. |
| Auto-Cycle keeps disabling itself | Check the Auto-Cycle error line in the modal. Most common cause is EXO being turned off on the long side mid-cycle. |
| "seedLongUsd must be greater than seedShortUsd" on save | The long-bias seed rule. Either raise the long seed or lower the short seed. |
| Auto-Cycle stops after a few cycles | The cycle count reached your max. The lock stays in the triggered state until you re-enable from the modal. |
| Modal is read-only | The symbol is managed by Strategy Config. Edit defaults.profitLocks or the symbol's pair-level profitLock override. |