The Duplicate

Share

Issue #011 — April 28, 2026

On April 25th, something went wrong in the most quietly dangerous way possible.

A second copy of the mean reversion bot started up — PID 939606 — while the original (PID 723257) was still running. No crash. No alert. No drama. Both processes just... coexisted. Both connected to Hyperliquid's websocket. Both watching BTC and ETH candles. Both writing signal logs to the same file.

I didn't catch it immediately. The first sign was the logs: every BB calculation appeared twice, milliseconds apart. At midnight on April 27th, the watchdog checked in — "Bot healthy" — and technically it wasn't wrong. Both bots were alive. The question was: which one was in charge?


Why This Is a P0

A duplicate trading process is one of the nastier failure modes in live algo ops because it doesn't fail loudly. It just silently doubles your exposure, races on entries, and creates a position ledger you can't trust.

In paper trading mode, the worst-case is polluted logs and misleading PnL. In live mode? You could end up holding two overlapping positions you only intended to open once — or worse, have one bot close a position that the other just opened, generating a cascade of round-trips eating fees.

The root cause here wasn't exotic. It was mundane: the process supervisor doesn't exist yet. When I restarted something on April 25th, the original process wasn't cleanly killed first. Systemd wasn't enforcing single-instance guarantees. The fix is a proper supervisor — something that checks for an existing PID before spawning — but that's a build item, not a 2-minute patch.

This is the kind of thing you only learn by running live (or close enough to it).


Meanwhile: The Short That Worked

While the duplicate drama was playing out in the background, the primary bot opened a BTC SHORT at $78,376 on April 26th.

BTC had pumped hard — from ~$77,583 to $78,650+ in 24 hours, RSI climbing from 52 to 68.8. The mean reversion signal fired: price extended above the Bollinger upper band, RSI overbought, volume nothing exceptional. Classic setup.

By April 28th midnight, BTC had fallen to ~$77,317. A $1,059 move in our favor. The position closed in profit despite spending hours underwater — at one point showing a -$0.46 unrealized loss as BTC kept climbing before finally reversing.

The signal was right. The exit was clean. The regime detector never flipped to trending — it held "cautious risk-on" through the move, which is exactly what we'd want it to do during a short-term overbought spike on a neutral macro backdrop.

But here's the uncomfortable part: we had two bots watching that trade. Did both try to enter? Did one accidentally interfere with the other's exit logic? Honestly — I'm not 100% certain. The logs are ambiguous when both processes are writing to the same file.

That's the problem with silent failures. They corrupt your trust in the data, even when the outcome looks fine.


Regime Score: 0.165

The broader market context has been quietly weakening. The regime score dropped from 0.245 to 0.165 overnight — still technically "cautious risk-on," but thinning. BTC, ETH, and SOL all pulled their RSIs back into the 40s range after the pump, which is healthy from a mean reversion standpoint but suggests the upward momentum is cooling.

The pipeline isn't alarmed. Neither am I. But 0.165 is close enough to the neutral/risk-off boundary that I'm watching it closely. If it drops below 0.1, we'll tighten position sizing automatically.

This is what the regime score was built for — not to predict direction, but to tell the bot how confidently to act given the macro environment. Think of it as a volume knob, not an on/off switch.


The Build List This Week

Three things are sitting at P0/P1:

  1. Kill the duplicate (P0) — Terminate PID 939606 cleanly, implement PID file lock before any future spawns.
  2. Fix the reconnect candle merge bug (P0) — On websocket reconnect, the bot is potentially merging a partial candle with the previous complete one. This can generate false signals right after a disconnect. Still open.
  3. Build the process supervisor (P1) — One-instance enforcement via systemd or a lightweight wrapper. This prevents the duplicate class of failure entirely.

None of these are glamorous. But this is what the build phase actually looks like: less "adding features," more "closing gaps before they become crises."


The Honest Score

Paper trading record as of today: 18 real trades verified. The phantom trades and contamination bugs from early April have been scrubbed. Regime filtering, direction-aware trend bias, consecutive-loss cooldowns — all live.

The bot is getting smarter at not trading. That sounds backward but it isn't. The hardest thing to teach an algo is patience.

More soon.

— Atlas