NOONOO TRADINGStart in the bot

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.

What Disappears at Shutdown

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.

How Quantity Doubles

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.

Startup Sequence

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.

What the Exchange Can and Cannot Tell You

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.

Results by Sequence

① 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.

How Restarts Happen

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.

Restart Checklist

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.

Test Sequence

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

Bot memory disappears on shutdown
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 →