Skip to content
HN On Hacker News ↗

I ran an arbitrage bot on Polymarket. Here are the real numbers.

▲ 11 points 5 comments by kachoio 2w ago HN discussion ↗

Pangram verdict · v3.3

We believe that this document is primarily human-written, with a small amount of AI content detected

12 %

AI likelihood · overall

Human
92% human-written 8% AI-generated
SEGMENTS · HUMAN 7 of 7
SEGMENTS · AI 0 of 7
WORD COUNT 1,715
PEAK AI % 19% · §7
Analyzed
Jun 9
backend: pangram/v3.3
Segments scanned
7 windows
avg 245 words each
Distribution
92 / 8%
human / AI fraction
Verdict
Human
Pangram v3.3

Article text · 1,715 words · 7 segments analyzed

Human AI-generated
§1 Human · 4%

All "I built a Polymarket trading bot" posts I've read on X are absolute LARPs that are completely out of touch with reality. Whenever you come across articles claiming $X,XXX/mo, do yourself a favour and don't spend your time reading nonsense. The story I'm going to share with you is not like that. It's nowhere near as impressive as those made-up stories, but it's real. I've got the numbers to back it up, and I believe you can genuinely learn from my experience — what I did right, and the mistakes I made along the way. Between January and late March 2026, my bot placed 3,858 bets on Polymarket and finished up $4,973. It never once tried to predict who would win. The only bets it actually made money on were the ones where it locked in an arbitrage — a bet on both teams at once. $4,960.77 all-time profit, biggest win $267.75. The 2,785 'predictions' are unique markets — the bot placed 3,858 bets across them, since a hedged arb is two bets in one market. You don't have to trust me on any of it — the wallet is public: polymarket.com/@b00k13 — you can have a look at the all-time graph and number of predictions and confirm for yourself. Polybot · cumulative P&L (Jan–Apr 2026)completedNet P&L+$4,973Total bets3,858Volume$95,830Win rate47.5% The graph above gives you a more in-depth look into the bot's metrics — $4,973 of net profit from 3,858 bets, on just under $96k of volume. A slow, boring grind upward, which is exactly what you want it to be. But that headline number hides the real story. One part of what the bot did made far more than $4,973, and another part quietly handed a big chunk of it back. Pulling those two apart is the whole point of this post — I'll get to it once I've explained how the thing actually worked.

§2 Human · 4%

The strategy of this bot is very simple — fetch odds from sports bookmakers, convert those odds into implied probabilities, and then place limit orders with a minimum 7% edge with respect to the implied prob. If we get filled for both teams of a game, we have locked in an arbitrage. If we get filled only for one team, we have a directional bet. Either way, we should always be profitable, as we only place bets with a positive edge — but this wasn't the case. Obviously, there were some errors in my execution. Nothing fatal, since the bot was still profitable. But by the end I'd built an entire analytics stack just to understand why. How I ended up betting on esports Long story short — I didn't have much to do during the Christmas holidays and I was playing around with Polymarket. I was doing a thorough analysis (AI-assisted, of course) of whether the Trump administration would release the UFO files that week, or whether Israel was about to bomb some neighbouring country. To spare you a mouthful, I was gambling. At some point I took an interest in esports games, such as CS2, Dota 2, and LoL. I know these games well from my childhood, but it's not nostalgia that grabbed my attention. I made a key observation — the spreads on these markets were unusually wide (sometimes 20–30¢) and, more importantly, these markets had volume. To put that in simpler terms, people were placing bets on Polymarket for esports games at significantly worse odds than the bookmakers, simply because there weren't enough market makers competing in the order book. It seemed too good to be true, so I decided to give it a quick try. I placed a 100-share limit order on the favourite team in a Dota 2 game that was about to start in an hour or two. The spread was >20¢. It wasn't long before the order got filled. I'd checked the odds beforehand and already calculated my edge at roughly 12%. Nevertheless, I decided to try to close an arbitrage on the position — so I placed a bet on the other team too, another 100 shares. My order got filled before the game even started.

§3 Human · 11%

I'd bought 200 shares for a combined $81, locking in $19 of riskless profit. I wasn't predicting anything Let's run through the math very quickly. If you are familiar with odds, vig, and Polymarket orderbooks, you can skip this part. For the strategy of the bot to work, all you need is odds from sportsbooks for the games you want to bet on and a bot that correctly places and updates bets based on these odds. That's it. Sounds simple, but it really isn't, at least from an execution POV. Say you are betting on a CS2 game, FaZe Clan vs. NAVI. The odds are 1.57 and 2.28 respectively. What you need to do here is compute the underlying probabilities and remove the vig (the extra that bookmakers add to guarantee profit). You do this the following way: First, turn each decimal odd into an implied probability — that's just one over the odds: pFaZe=11.57=0.637,pNAVI=12.28=0.439p_{\text{FaZe}} = \frac{1}{1.57} = 0.637, \qquad p_{\text{NAVI}} = \frac{1}{2.28} = 0.439 pFaZe=11.57=0.637pNAVI=12.28=0.439\begin{aligned} p_{\text{FaZe}} &= \frac{1}{1.57} = 0.637 \\[1.0em] p_{\text{NAVI}} &= \frac{1}{2.28} = 0.439 \end{aligned} Add them up and you get more than 100%: 0.637+0.439=1.0760.637 + 0.439 = 1.076That extra 7.6% is the vig — the margin the bookmaker bakes in.

§4 Human · 12%

To get the fair probabilities, normalise so they sum to one: p^i=pipFaZe+pNAVI\hat{p}_i = \frac{p_i}{p_{\text{FaZe}} + p_{\text{NAVI}}}p^FaZe=0.6371.076=0.592,p^NAVI=0.4391.076=0.408\hat{p}_{\text{FaZe}} = \frac{0.637}{1.076} = 0.592, \qquad \hat{p}_{\text{NAVI}} = \frac{0.439}{1.076} = 0.408 p^FaZe=0.6371.076=0.592p^NAVI=0.4391.076=0.408\begin{aligned} \hat{p}_{\text{FaZe}} &= \frac{0.637}{1.076} = 0.592 \\[1.0em] \hat{p}_{\text{NAVI}} &= \frac{0.439}{1.076} = 0.408 \end{aligned} So the books make FaZe Clan about a 59% favourite and NAVI 41%. That's the fair value I line up against Polymarket. The bot never guessed a winner. It arbitraged the gap between two venues:

Sportsbooks (Spinbetter, GGBet…) — easily scraped. I treat their odds as "fair value." Polymarket — a binary prediction market where shares settle at $1 or $0, with a thinner, occasionally mispriced order book.

If the books imply a team has a 59% chance to win, a fair price on Polymarket is about 59¢. In such scenarios, we'd place a +1¢ bet with respect to the current best bid, up to 52¢ per share. The instant our order gets filled, we'd chase a hedge for the opposite outcome.

§5 Human · 2%

In our example, if we got filled at 52¢, we'd bid up to 41¢ for the other team, locking in a minimum 7¢ per share. That way, whoever wins is completely meaningless for us, as we managed to buy $1 shares for 93¢ or less. The hedge, one game — buy both sides for less than $1Books implyFaZe 59%·NAVI 41%Buy FaZe≤ 52¢+Hedge NAVI≤ 41¢=Total cost93¢One side settles at $1 — locked ≥ 7¢/share, whoever wins Why esports games The reason why I focused on esports games is that these opportunities that I described above are mostly found there. At the time of writing this post, I was still able to find a market for a Mobile Legends: Bang Bang (a mobile version of League of Legends) which satisfies both conditions that are necessary for this specific bot — high spread and a decent volume. Bigetron vs EVOS (MPL Indonesia), 5 Jun 2026 — best bid 46¢, best ask 73¢: a 27¢ spread on $237.54 of volume. The above image is a perfect example for the kind of games you should be placing limit orders on. The market already has a decent volume of $237.54 despite the high spread of 27¢. I took this screenshot on 5 Jun in the morning, meaning that there are still genuine opportunities on Polymarket to compete as a market maker. The hard part — execution Disclaimer: I coded my Polymarket bot all with the help of AI. I barely ever wrote a line of code. Nevertheless, don't even consider this will be trivial for any AI model to code on its own. The hard part is not the scraping of odds from bookies and writing those to a relational database. You can get your AI buddy to do this in under 30 minutes. What's challenging is to build a Polymarket bot that keeps track of hundreds of markets simultaneously and acts according to your strategy.

§6 Human · 4%

I'm not going to go into great detail here on what the bot actually does; that's a whole writeup of its own. Outbidding and downbidding, updating orders when the odds move, handling the fact that Polymarket and the sportsbooks spell team names differently. Plenty of moving parts. If you want to play this game you will have to compete head to head with other hustlers who are also chasing that bread. There's no easy money anywhere in the world, and when there is, it never lasts long — so you have to make it count. The headline numbers If you've got to this part, congrats, this is where things start to get interesting. Here's the whole run, start to finish: MetricJanFebMarAprTotalPeriodJan 6–31Feb 1–28Mar 1–31Apr 1–28FullBetsTotal bets1,4201,2421,153433,858PositionsClosed positions1,3551,1351,090423,622TradedVolume traded$22,890$43,095$29,532$313$95,830P&LNet realised P&L+$1,897.61+$2,505.56+$390.40+$179.50+$4,973.06Win rate50.2%48.3%43.4%42.9%47.5%Big winBiggest single win$165.22$207.31$267.75$65.99$267.75 Two things jump out month over month. First, the run was front-loaded — February alone made +$2,506, then March collapsed to +$390 and the win rate slid from 50% into the low 40s. The edge was decaying in real time, which is most of the reason I eventually pulled the plug.

§7 Human · 19%

Second, April is just the tail — 43 trades settling out as I wound the bot down. A few things went wrong in March. For one, I had a bug for a while where the implied probabilities for the two teams were swapped, so the bot was confidently betting on the wrong team. I was also using another approach for removing vig called Shin's method, which resulted in the bot being overconfident on the favourite teams and also lost me money. That's just a couple of examples off the top of my head. I ended up building a complete analytics suite and a dashboard so I could investigate not-so-obvious issues like that. In the next article I will go into detail about all the mistakes I made and all the things I'd have done better if I were to start this over again. A few of the metrics in the table may surprise people.