Running a Trading Bot 24/7 on Windows: Restarts, State, and Health

🌐 한국어

Building a bot and keeping it alive 24 hours a day are two different jobs. These are the unglamorous but decisive techniques I settled on while running a console bot unattended on a Windows desktop.

⚠️ Live automated trading can lose money through software and network failures. This article is for educational and informational purposes and is not investment advice.

1. Make the Console Act Like a Tray App — Minimize on Start

Leave a console bot running around the clock and the window permanently occupies your desktop. On Windows you can call into user32.dll directly to minimize or hide the window the moment it starts.

var user32 = syscall.NewLazyDLL("user32.dll")

var showWindow = user32.NewProc("ShowWindow")

const swHide, swShowMin = 0, 2

// Minimize the console at startup (retry briefly until the handle is ready)

func minimizeConsoleOnStart() {

    go func() {

        for i := 0; i < 20; i++ {

            if hwnd := getConsoleWindow(); hwnd != 0 {

                showWindow.Call(hwnd, swShowMin)

                return

            }

            time.Sleep(100 * time.Millisecond)

        }

    }()

}

The handle may not be ready immediately, so the short retry loop is the point. Wire show, hide, and minimize to dashboard buttons and you can pull the bot's window in and out from the browser. Since this code is OS-specific, isolate it behind a build tag — something like window_ctrl_windows.go — so builds for other platforms don't break.

2. Bring It Back When It Dies — Automatic Restart

No matter how well you build it, processes die. Panics, memory, OS updates. So put a thin wrapper in front that watches and restarts. A batch script is enough; you don't need a separate tool.

:loop

StockBot.exe

echo [%date% %time%] bot exit detected — restarting in 5s

timeout /t 5 /nobreak

goto loop

Whenever the bot terminates for any reason, the loop runs it again. For something more robust, use the Windows Task Scheduler with "restart on failure" or run-at-boot, so the bot recovers hands-free even after a reboot. Always include a short wait (5 seconds, say) to prevent a runaway restart loop.

3. Remember Across Restarts — State Persistence

Automatic restart only works if a restart doesn't lose state. If positions and baselines live only in memory, the revived bot has no idea what it's holding. So persist the critical state to files.

bot_state.json  : run state (whether it's running, etc.)

positions.json  : current positions (quantity, average price, entry time)

baseline.json   : today's baseline (with the date included)

The date check on recovery matters. If the stored baseline's date isn't today, discard it and capture a fresh one — this is what prevents the disaster of judging today with yesterday's data. Saving can be frequent, so just overwrite the file whenever state changes; the data is small enough that the cost is negligible.

if saved.TradingDate != today {

    baseline = nil // date changed -> discard and re-capture

}

4. Prove It's Alive — Health Checks and Alerts

The final piece of unattended operation is being able to tell from the outside that the bot is alive and healthy.

  • Health endpoint: an unauthenticated /health that external monitoring can poll for process liveness.
  • Data freshness monitoring: warn if real-time data stops arriving for a set period, and re-establish the connection if it goes on longer.
  • Alerts on key events: push entries, exits, errors, and restarts to a messenger immediately. Nobody can watch a screen all day.

Summary

  • Minimize the console at startup to behave like a tray app, and isolate window control behind build tags
  • Restart automatically via a watcher wrapper or the scheduler, always with a delay to prevent restart storms
  • Persist state to files and recover with a date check — the precondition for restarts working at all
  • Confirm liveness from outside with health, freshness, and alerts

The real difficulty with a bot isn't the first run — it's running a week, then a month, untouched. This dull skeleton, the one that revives after dying and never loses its state, is what actually sustains unattended operation. Far more than a clever strategy.

댓글

이 블로그의 인기 게시물

한국투자증권 KIS API로 실시간 시세 받기 (WebSocket 실전)

파이썬으로 업비트 API 연동하기 — 시세 조회부터 주문까지 기초

Go로 자동매매 신호봇 프레임워크 설계하기