{"slug": "show-hn-polymm-the-polymarket-market-making-bot-behind-my-5k-wallet", "title": "Show HN: Polymm – the Polymarket market-making bot behind my $5k wallet", "summary": "A retired Python market-making bot for Polymarket, built by a developer known as b00k13, netted about $5,000 in early 2026 before becoming unprofitable due to speed limitations. The bot executed cross-venue arbitrage on sports markets using the-odds-api for fair odds, but its Python-based execution was too slow to defend its edge, leading to a Rust rewrite. The code is open-sourced as a foundation, with the scrapers removed and the edge dependent on fresher odds and faster execution.", "body_md": "**The retired Python bot behind a public Polymarket wallet.** It market-made on Polymarket's sports markets (esports and traditional) for a few months in early 2026 and finished up about **$5k** net, every trade on-chain at [@b00k13](https://polymarket.com/@b00k13). This repo is the actual code, plus the analytics I built to work out why the \"guaranteed\" strategy still bled money on the parts that were meant to be safe.\n\nMost \"I built a Polymarket bot\" repos are a README and a dream. This one traded real money and leaves a public wallet you can reconcile it against. At some point it also mostly stopped being profitable, and the write-ups at the bottom are honest about why.\n\nIt was built almost entirely with AI, in my spare time. That's not an excuse for the quality. You may find bugs. There are certainly things to improve. But it's still the exact bot that I used and it could be a good basis for you if you want to get into Polymarket market making.\n\nI'm giving this away because the code was never the hard part. The edge was **fresh odds and speed**, and here both are on you:\n\n- This is the\n**retired Python version**. The bot I run now is a Rust rewrite and it's not in this repo. **The scrapers aren't included.** The bot reads odds from a source you supply. It ships with a[the-odds-api](https://the-odds-api.com)path - a public, paid API - and the private scraping pipeline that was half the edge is gone.- It got\n**too slow** to defend its edge, which is exactly why it stopped making money.\n\nSo treat it as a working foundation, not a money printer. The strategy is sound and the plumbing works. Whether it earns is down to what you bring: faster and fresher odds, sharper execution, tighter risk. Put the work in and it can pay. Run it as-is and you'll donate to quicker bots.\n\nCross-venue arbitrage, captured by market-making. In plain terms:\n\n**Get a fair price.** Pull bookmaker odds (via the-odds-api) and strip the bookmaker's margin to a fair probability for each side. That fair value is the whole game, and it's only ever as good as your odds are fresh.**Quote it.** Post limit orders on the matching Polymarket market, a cent above the best bid, only where there's enough edge between your fair value and the price (`min_edge`\n\n, 5% by default).**Hedge to lock the arb.** When one side fills, place the opposite outcome so you own both sides of the match for under $1 a share. That's a profit locked in whoever wins.**The residual.** You can't always get both legs. When one fills and the hedge doesn't, you're left holding a directional bet. Each of those went on at a 7%+ edge, so a book of them*should*be profitable. Working out why mine wasn't is the second write-up below.\n\nThe bot (`src/main.py`\n\n) is a single async orchestrator running roughly ten concurrent loops. The pieces:\n\n| Layer | What it does |\n|---|---|\n`services/` |\nFetch and aggregate odds (`odds_service` , `odds_api_service` ) |\n`core/` |\nDe-vig maths, market parsing, team matching (`vig_removal` , `market_parser` , `match_id` ) |\n`scanning/` |\nCompare fair value to Polymarket prices, find edges (`opportunity_scanner` ) |\n`execution/` |\nPlace orders, size hedges, track positions (`order_executor` , `hedge_finder` , `order_watcher` ) |\n`monitoring/` |\nWatch for outbids and edge loss, chase hedges (`hedge_seeker` , `order_monitor` ) |\n`polymarket/` |\nThe two live websockets - fills (`user_websocket` ) and order book (`book_websocket` ) |\n`state/` |\nMatch-level state and the reactive event system (`bot_state` , `reactive_handler` ) |\n\nThe reactive system is the interesting bit - when the fair value moves against a resting order, it emits an `EDGE_LOST`\n\nevent and cancels before the order gets picked off. In practice, not fast enough - which is the whole story of the autopsy below.\n\nThe data path:\n\n``` php\nodds source -> Supabase -> OddsService -> OpportunityScanner -> OrderExecutor -> Polymarket\n                                                   ^                                  |\n                                                   +-------- book / user websockets --+\n```\n\n`src/data/`\n\nwrites odds, fills and positions to Supabase. The table schemas are in `sql/`\n\n.\n\nHeads up: this needs your own infrastructure and it will not trade out of the box without it.\n\n`pip install -r requirements.txt`\n\n- Copy\n`.env.example`\n\nto`.env`\n\nand fill it in - a Polymarket wallet, a the-odds-api key, and a Supabase project. - Create the tables from\n`sql/`\n\nin your Supabase project. `python -m src.main`\n\n`default_shares`\n\nis 10, so it starts tiny by design. Watch it for a while before you give it size, and read the autopsy first so you know what you're up against.\n\nI built a second project just to debug the first. These five scripts run against **any public Polymarket wallet** - no private data, just point them at a funder address:\n\n| Script | What it tells you |\n|---|---|\n`capital_analysis.py` |\nOverall portfolio P&L |\n`realized_pnl_by_month.py` |\nRealised P&L, month by month |\n`polymarket_attribution.py` |\nSplits P&L into the arb and the directional residual |\n`position_breakdown.py` |\nOpen positions, normalised per market |\n`underdog_analysis.py` |\nFavourite vs underdog win-rate and ROI |\n\nRun one with, e.g., `python -m analytics.capital_analysis`\n\n.\n\n```\nsrc/         the bot\nanalytics/   wallet-analysis scripts\nsql/         Supabase table schemas\ntests/       the test suite\n```\n\nThe full story, with the real numbers, is on the blog:\n\n[Everyone shows the wins. I'm showing the wallet.](https://kacho.io/why-kacho-io)- why I build in public.[I ran an arbitrage bot on Polymarket. Here are the real numbers.](https://kacho.io/polymarket-arbitrage-real-numbers)- the strategy and the P&L: the arb made**+$8,293**, the forced directional bets lost**-$3,184**, ~$5k net.[Adverse selection eating away my Polymarket bot arbitrage profits.](https://kacho.io/why-my-polymarket-arbitrage-bot-lost-money)- the autopsy: why a book of +EV bets lost money.[I recorded Polymarket's 5-minute crypto markets for two months. Here's the dataset.](https://kacho.io/polymarket-5min-crypto-dataset)- a free dataset from a related experiment.\n\nMIT - do what you like with it. If you build something interesting on top, I'd genuinely like to see it. The wallet's public if you want to pick any of the numbers apart.", "url": "https://wpnews.pro/news/show-hn-polymm-the-polymarket-market-making-bot-behind-my-5k-wallet", "canonical_source": "https://github.com/kachence/polymm", "published_at": "2026-07-21 16:56:41+00:00", "updated_at": "2026-07-21 17:13:19.207478+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools"], "entities": ["Polymarket", "b00k13", "the-odds-api", "Supabase", "Python", "Rust"], "alternates": {"html": "https://wpnews.pro/news/show-hn-polymm-the-polymarket-market-making-bot-behind-my-5k-wallet", "markdown": "https://wpnews.pro/news/show-hn-polymm-the-polymarket-market-making-bot-behind-my-5k-wallet.md", "text": "https://wpnews.pro/news/show-hn-polymm-the-polymarket-market-making-bot-behind-my-5k-wallet.txt", "jsonld": "https://wpnews.pro/news/show-hn-polymm-the-polymarket-market-making-bot-behind-my-5k-wallet.jsonld"}}