Bot Restarts: Why a Bot Forgets Its Position When Switched Off and On
An automated trading bot will eventually stop: for a code change, a power outage, or a program crash. The problem is not the stop but the moment it starts again. The position is still in the account, while the bot begins with no memory of it.
Where Does a Bot Keep Its Memory?
While running, the bot knows whether it is long or short, its entry price, where the stop is, and how many times it has averaged down. Most of that information lives in program memory, which disappears when the program exits.
If held only in memory, it disappears
· Current direction (long / short)
· Entry price and entry time
· Stop-loss and target prices
· The current averaging-down stage
· IDs of orders already submitted
What remains at the exchange
· Actual position quantity and average entry price
· Unfilled limit orders
─────────────
Immediately after restart
Account = a position exists
Bot = believes there is no position
This mismatch is the starting point of every restart incident. From the bot's perspective, it has just been born, so “I hold nothing” is the default. The account, however, remained active throughout the shutdown. Handling this difference shares its roots with position reconciliation, but a restart is a moment when that mismatch definitely occurs.
What an Amnesiac Bot Does on Its First Cycle
Most bots inspect market prices and calculate signals as soon as they start. If the bot believes it has no position, it simply enters a new one when a signal qualifies.
Before restart
BTC long 0.1 · Entry 100,000
20x · Margin 500
Stop 97,000 (stored only in bot memory)
Bot stops → Code edited → Bot restarted
First startup cycle
Position known to bot = 0
Long signal → New entry of 0.1
Actual account
0.1 + 0.1 = 0.2 contracts
Margin 1,000
─────────────
Price falls −3% to 97,000
Planned stop-loss amount: −300
Actual loss: −600
Quantity the bot closes: only 0.1
The result resembles a duplicate order. The cause differs: there, a response was lost; here, memory was lost, so the same entry happens twice. The last line is particularly bad. Because the bot manages only the 0.1 it submitted, the remaining 0.1 stays in the account even after the stop triggers. A position with nobody managing its stop has been created.
The opposite direction is also possible. If a short signal appears after restart, the bot enters a short because it believes it is flat. The account either holds the existing 0.1 long and a new 0.1 short simultaneously in hedge mode, or the long is offset and disappears in one-way mode. Either way, the bot's records and the account tell completely different stories.
Do Not Place Orders on the First Cycle
The first step is simple. Instead of making a decision immediately after startup, check the current state first.
1. Query positions from the exchange
2. Query open orders from the exchange
3. Read saved internal records
4. Compare both sources and establish the state
5. Only then start calculating signals
─────────────
If a query fails
→ No orders · Retry
→ If failures continue, send an alert and wait
Never do this
Treat a failed query as no position
The final line is the most common practical mistake. If a failed query produces an empty value and that value is read as no position, the bot confidently enters again. Unknown and absent are different. In an unknown state, the correct response is to place no orders. This is the same principle discussed in WebSocket disconnections: silence must not be interpreted as information.
What Needs to Be Saved?
Some information cannot be recovered from an exchange query. The exchange provides quantity and average entry price, but only the bot knows why it opened the position.
The exchange can tell you
· Direction, quantity, and average entry price
· Unrealized P&L and open orders
The exchange does not know
· Which signal caused the entry
· Which averaging-down stage is current
· The planned price of the next addition
· Highest and lowest prices since entry
· The order label assigned to the trade
─────────────
Therefore
Quantity = the exchange is authoritative
Context = my file is authoritative
If they conflict, the exchange takes precedence
State must therefore be written to a file whenever the trade changes, instead of remaining only in memory. Record changes when entering, adding, moving a stop, or closing: at the moment a value changes. Saving in batches every few minutes means changes since the last save disappear on restart.
A Gap in Save Timing Leaves an Incomplete Record
What happens if the program crashes after submitting an order but before writing the record? The remaining evidence depends on the order of events.
① Order → Crash → Record never written
Account position exists · Record absent
→ Ghost position after restart
② Record first → Crash → Order never submitted
Account position absent · Record exists
→ Ghost record after restart
─────────────
Which is safer?
② is preferable: trying and failing
to close a nonexistent position is better
than abandoning an existing one
The real solution
Overwrite state from an exchange query at startup
→ Both ① and ② are reconciled
No sequence can eliminate the possibility of crashing between the steps. Instead of trying to make the sequence perfect, impose the rule that startup must always reconcile. Starting from the assumption that records may be wrong makes an incomplete record something to correct, rather than an incident.
The program can also crash while writing a file, leaving it corrupt and unreadable. Writing the entire contents to a temporary file and then renaming it leaves either the old contents or the new contents, never an intermediate state.
Restarts Arrive Without Warning
Not every restart is planned. Unexpected ones are often more common.
Planned
· Restart after a code change
· Configuration changes or server migration
Unexpected
· Power outage or forced PC shutdown
· Program crash
· Automatic operating-system update and reboot
· Forced termination due to insufficient memory
─────────────
What they share
There is no time to clean up before leaving
→ You cannot rely on saving just before shutdown
Cleanup code that handles shutdown signals is useful, but cannot be your only protection. When power disappears, no cleanup code runs. Save whenever values change, rather than only when shutting down.
Automatically starting the bot after a reboot belongs to the same discussion. However, state recovery must be in place before automatic restart is enabled. Without recovery, a single power outage can make the bot submit a duplicate entry by itself. Temporarily blocked queries during exchange scheduled maintenance should be handled the same way: if the state is unknown, stop.
What to Check Before Restarting
When restarting manually, you can choose the timing. That alone eliminates many incidents.
Before stopping
· Check whether a position exists
· If so, is its stop placed at the exchange?
(If only in bot memory, it is unprotected)
· Record the list of open orders
· Prefer restarting while flat, if possible
After starting
· Does the bot's recognized quantity equal the exchange quantity?
· Is only one process running?
· Inspect the logs before the first order is sent
─────────────
The most dangerous combination
An open position + a stop held only inside the bot
+ a restart that takes a long time
Here is what that last combination means. If a stop loss exists only as bot logic that watches prices and closes at market, rather than as an actual exchange order, the position has no stop while the bot is off. Whether restart takes five minutes or an hour, it remains unprotected throughout. During development with frequent restarts, placing the stop as an exchange order is safer.
Do not skip checking that only one process is running. If a new process starts before the old one has stopped, two bots place orders in the same account. Even excellent state recovery cannot solve this: each bot recovers independently and submits its own orders.
How to Verify Recovery
Restart recovery is invisible during normal operation and reveals itself when an incident occurs. It therefore needs deliberate testing.
1. Enter in simulation or with a small amount
2. Force-terminate the bot
(Force it; do not use a normal shutdown)
3. Start it again
4. Check the logs
· Did it recognize the position?
· Do quantity and average price match the exchange?
· Did it restore the stop price?
· Did it avoid a new entry?
─────────────
Additional tests
· Delete the state file and start
· Deliberately corrupt the state file and start
→ In both cases, it should stop without orders
The last two lines are essential. If a missing or corrupt state file causes the bot to quietly start from scratch, that is the most expensive failure mode. When the file is wrong, the appropriate response is to stop and alert. General integration and authentication are covered in the exchange API integration guide.
Summary
② Account positions remain
③ Immediately after restart, the bot believes there is no position
④ A signal in that state can double the quantity
⑤ Closing only its own quantity leaves half unmanaged
⑥ Place no orders on the first startup cycle
⑦ A failed query must not mean no position
⑧ The exchange is authoritative for quantity; internal records for context
⑨ Save on every change, not only at shutdown
⑩ Write to a temporary file, then rename, to avoid corruption
⑪ A stop held only in the bot leaves the position unprotected while off
⑫ Verify recovery by testing forced termination yourself
In one sentence: assume the bot can crash at any time, and make it query the account again every time it starts. With this structure, restarting becomes a routine operation rather than an incident.
Caution
The quantities, prices, margins, leverage, and P&L figures here are hypothetical examples explaining the structure, not measurements from a specific exchange. Position and order queries, one-way and hedge-mode behavior, persistence of conditional orders after restart, and query rate limits differ by exchange. Check your exchange's documentation and test with a small amount. Leveraged trading can lose all principal, and you are responsible for investment decisions and their results.
NOONOO TRADING invites you to follow live trading in our free chat.
Start in the bot📈 OKX trading fee discount for new registrations
Register for the OKX Fee Discount →