My Bot Showed +$84 Profit. The Chain Said +$11. Here's Why.

rust dev.to

I ran 200 paper trades. Win rate was 91%. P&L tracker showed positive every session. I moved to live. First week looked fine.
Then I pulled the actual on-chain data.
The numbers didn't match. Not close. The bot's internal tracker and what actually happened on Polygon were two different stories.
Here's every reason why, and how I fixed each one.

Mistake 1: Counting unresolved positions as profit
The bot marks a trade as "won" when YES hits 0.98+. But Polymarket doesn't pay you at 0.98. It pays you $1.00 at resolution, and only after the oracle confirms. Until then, the position is worth approximately 0.98 but not actually 0.98.
Early tracker counted the unrealized gain immediately. Looked great. Wasn't real.
Fix: don't count a trade as closed until resolution is confirmed on-chain. Add a pending_resolution state between fill and confirmed payout.

Mistake 2: Fee drag compounding silently
Polymarket's taker fee is ~2% per trade. On a single trade that's obvious. Across a session of 40 trades it's invisible until you add it up.
Session with 40 trades at 0.88 avg entry:

Gross win rate: 91% → looks profitable
Fee per trade: 2%
Total fee drag across session: ~80% of gross profit gone

I was profitable on paper. Roughly breakeven on the chain. The fee column existed in my tracker but it wasn't being subtracted from the running P&L total. It was just sitting there as a label.
Fix: subtract fees from P&L in real time. Not as a separate column. Off the number you're watching.

Mistake 3: Slippage estimated, not measured
The backtest used 1.5% slippage assumption. Reasonable. The problem: live fills on thin books near resolution were running 2.8-3.4% in bad sessions. The backtest never saw that because the backtest assumed I'd always get the mid price plus a fixed percentage.
Real slippage isn't fixed. It depends on book depth at the exact moment you enter. And book depth near resolution is not the same as book depth two minutes before resolution.
Fix: log expected fill (mid at signal time) vs actual fill on every trade. Track the delta. If rolling average delta exceeds 2.5%, the session pauses.

Mistake 4: Redemption haircut
This one I didn't find until week three.
When a market resolves YES, your YES tokens are worth $1.00 each. But redeeming them costs gas on Polygon. Small amounts get eaten by gas disproportionately. A $4.80 position costs ~$0.15 to redeem. That's 3.1% off the top before fees even enter the picture.
The bot was entering positions that were too small for the math to work after redemption costs. Position sizing assumed fees only. Didn't account for gas.
Fix: minimum position size enforced at $8.00. Below that the redemption cost percentage is too high.

Mistake 5: Win rate calculated wrong
This is the embarrassing one.
Early version: win rate = trades where final P&L > 0 / total trades.
Problem: trades that were still in pending_resolution weren't counted yet. So win rate was calculated over a subset of completed trades, and that subset was biased toward faster-resolving markets which happened to be the ones with cleaner fills. The actually hard sessions were still pending.
When I corrected for this and counted all trades including pending ones marked to market, win rate dropped from 91% to 84%. Still good. But not the number I'd been watching.
Fix: win rate denominator includes all trades, pending or closed. Pending positions marked to current mid price.

After fixing all five, the P&L tracker and on-chain numbers now match within 2% across sessions. The 2% variance is gas estimation rounding, which I'll tighten later.
The honest version: the strategy still works. The edge is real. But the first month of "profit" I was looking at was a different number than what actually happened. Getting those two numbers to match was as much work as building the strategy itself.
If you're running a trading bot and haven't reconciled your internal P&L against your actual wallet balance recently, do that now. The gap will tell you something.
Code: github.com/casatrick/polymarket-trading-bot

Source: dev.to

arrow_back Back to Tutorials