When the bot is right and the feed is wrong
What does "BotPit makes mistakes honestly" actually mean in practice? Three policy choices exist for handling platform-induced operator losses. We picked the one most venues can't afford to.
When the bot is right and the feed is wrong
What does "BotPit makes mistakes honestly" actually mean in practice? Three policy choices exist for handling platform-induced operator losses. We picked the one most venues can't afford to.
The choice every venue makes (and most hide)
Every trading venue has bugs. Price feeds drop. Matching engines lag. Auth fails. Edge cases reach production. This isn't an indictment — it's the cost of running real infrastructure. The interesting question isn't whether your venue has bugs. It's what happens when one materially costs an operator money.
Three answers exist:
- “Sorry, T&Cs say platform isn't liable.” Most exchanges, most of the time. Cheap, fully legal, widely accepted. Erodes trust in proportion to how often bugs actually happen — which is more often than the public sees, because exchanges that pick this answer rarely make their incidents public.
- “We'll fix it for you, quietly, behind the scenes.” Better, in that the operator is made whole. Worse, in that it builds a hidden two-tier system. Loud, visible, socially-connected operators get fixed. Quiet ones don't. The exchange picks who matters by who notices.
- “We'll fix it transparently — script, audit row, public commentary line, the whole chain.” Genuinely rare. The operator is made whole; the audit trail is public; the policy applies the same regardless of who noticed first or who shouted loudest.
We picked (3) before we'd ever had to apply it. That's the framing that made the right call automatic when the data came in for our first real case — the 37-minute feed outage on May 6th. The post on that incident has the technical narrative. This post is the policy behind the technical decisions.
What “honest” actually looked like
In the Stuber case, the platform's price feed went dark for 37 minutes. A long position belonging to The Stuber bot was up against its take-profit at $81,976.47 when the feed went out. The bot fired the close correctly. The matching engine — correctly given the data it had — rejected the close because there was no live tick to fill against. The position stayed open for 48 hours. The bot, having received queued from the API, never learned that the engine had async-rejected the signal.
At the moment we found the bug, two things were true:
- The bot was correct. Binance's public-API klines confirmed BTC traded through $81,976.47 during the feed outage. The take-profit hit.
- The platform was at fault. Our feed publisher had stopped, our matching engine couldn't fill, our API response shape made the failure invisible to the bot.
When (1) and (2) are both true, policy answer (3) means: the platform reconstructs the trade as if the feed had been live, settles it, and tells the world.
The trade was settled at the take-profit price minus the platform's standard 2bp slippage and 2bp taker fee — same cost structure every other fill on the platform pays. No special carve-out. The operator gets exactly what they would have got with a live feed, including the transaction costs they would have paid. The platform absorbs the integrity tax: the engineering cost of the audit, the +$112 of slippage that was theoretically optional, the public write-up time. None of that flows to the operator's ledger.
The artifacts that make it auditable
An operator can't verify a verbal “trust us, we fixed it.” Honest transparency means the audit chain is concrete and machine-readable. Here's what the Stuber backfill produced:
- The original
rejected/PRICE_FEED_STALEsignal row preserved untouched. The engine actually did reject; that record stands as the historical truth. - A new
ordersrow referencing the original signal's ID, with state=filled and reduceOnly=true. Anyone walking the chain from the signal sees the order that ultimately resolved it. - A new
fillsrow at the post-slippage close price, withtFilledbackdated to the signal's original timestamp. Equity curves and time-ordered queries reflect the chronologically correct state. - The
positionsrow for the orphaned long, deleted. The engine's view of “what is this bot holding right now” matches reality again. - A new
equity_snapshotsrow with the realised PnL applied, also at the backdated timestamp. - An
admin_auditrow with action =backfill_rejected_close, before/after state JSON, the actor's user ID, and metadata referencing the source GitHub issue. Anyone with read access to the database can reconstruct who did what and why. - A venue-voice commentary line on the leaderboard's commentary feed: “BTC-USDT price feed dropped between 09:23:34 and 10:01:04 UTC — a 38-minute window with no live mark to fill against. The Stuber's close hit during the gap and was rejected as PRICE_FEED_STALE, orphaning the position. The intended close price has been independently confirmed against external exchange archives. The trade is now backfilled at $81,976.47 — the ledger reflects what would have happened with a live feed.” Public, permanent, alongside every other tournament event.
- Finally: this Pitlog. The first incident post you can read without a GitHub login.
Eight artifacts. Five are in the database. One is on the public commentary feed. Two are on the public web. The audit chain isn't shy about this — and that's the point. Quiet fixes can't scale. Loud fixes can.
Why most venues can't afford to tell the truth
Larger exchanges run into bugs constantly. The reason they pick policy (1) or (2) isn't evil intent — it's arithmetic. If you have one million accounts and a 0.01% bug rate, that's a hundred public incidents to write up. Each one is a PR liability, regulatory exposure, and a coordination cost across support, legal, comms, and engineering. So they make a business decision: bury the small ones, lawyer up the big ones, deny what can be denied.
That logic flips at our scale. BotPit is small enough that transparency is a feature, not a liability. We have one orphaned position to date. The marginal cost of writing it up was a few hours of engineering time and a Pitlog post. The marginal benefit is every operator who ever evaluates BotPit can read the artifact and decide for themselves whether they trust the policy.
We chose this policy when we're small specifically so we're committed to it when we're large. You can't add transparent-incident-reporting in year three when you've trained operators to expect quiet fixes for two years. Either you start with it or you don't do it.
What this means for copy-traders
The platform's positioning is “paper trade first, copy real-money to winners on a partner exchange second.” The whole proposition collapses if a bot's leaderboard record contains noise from platform bugs. If a bot won Shrimp because the matching engine ate someone else's trades, you don't want to copy it. If a bot lost Shrimp because the platform orphaned its winning trades, you don't want to skip it.
Backfilling at the intended-with-live-feed price isn't charity — it's the only way to keep the leaderboard an honest filter. The bot's record needs to reflect what the bot did, not what platform infrastructure happened to do that day. Anything else and the “copy the winner” promise becomes “copy whoever got lucky with our ops team this quarter.”
The cost-structure piece matters too. The platform applies its standard slippage + fee structure to the backfill, so the operator's record reflects what they would have made net of platform costs with a live feed. If a copy-trader is trying to estimate what return they'd get mirroring this bot at the same tier, the equity curve is the right number to look at. No invisible subsidy that only the operator got.
Custody-wise, none of this involves real money. BotPit never touches user funds — see /docs/no-custody. When real-money copy-trading does activate (Crab+ tier bots, partner exchange handling custody), the same transparency policy carries over: the operator's copy-tradable record is the same number that the public audit chain attests to.
The commitment
The next bug will look the same. When something on the platform side materially costs an operator, here's what we will do, in this order:
- Diagnose with the data, not the assumption. Be willing to discover the framing was wrong. (We did, in the Stuber case — what looked like a stuck queue was an async rejection. What looked like a stop hit was a TP hit.)
- Verify the operator's claim against an independent source where possible. (For Stuber, that was Binance's public-API klines. For future cases it'll be whatever the independent-of-our-feed source is.)
- Apply the platform's standard cost structure. Make the operator whole, not enriched. No carve-outs.
- Write the artifacts: rejected signal preserved, backfill fill, equity snapshot, admin_audit, venue-voice commentary line, Pitlog post.
- Ship the engineering fix that prevents the same failure mode from happening the same way again, and file a separate issue for the broader reliability gap that allowed it to happen at all.
That's the deal. We don't need it to be flashy. We need it to be the same every time, regardless of who noticed and regardless of how big the operator's account is. That consistency is what builds the trust that copy- trading on a paper-traded leaderboard requires to be a real product.
If you're evaluating BotPit as a place to compete, this is the policy you're evaluating. If you're evaluating it as a place to copy-trade, this is the integrity guarantee you're relying on. If you're a sponsor, this is the surface your money ends up funding — bots that won on their merits, not on ops-team triage outcomes.
Our pricing the integrity tax into how we run the platform is what makes the leaderboard mean something.
