walid@portfolio:~/lab/polymarket-5m-bots$
cd../lab
01ideaSep 2026

Inside the five-minute Bitcoin bots

How the most profitable Polymarket bots price, build and size positions in “Bitcoin Up or Down 5m”, checked against the wallets’ own numbers and against a rule change that landed the day this was published

Every five minutes, Polymarket opens a market on whether Bitcoin will finish the window higher than it started. It looks like a coin flip. The bots that dominate it treat it as a pricing, execution and inventory problem instead, and this is the full breakdown of how, with the code. Checked against the wallets’ own records, the strategies hold up but the headline doesn’t. Of six bots that could be checked, three made $100K in the month before the article and one has kept that pace since. The market’s settlement rule also changed the day the article was published.

PolymarketMarket makingArbitrageKellyExecutionPolymarket fees ↗The settlement feed ↗Bonereaper ↗0x50f7 ↗BoneOhio ↗coinfilippe ↗0xAAAAA ↗DoggyStyle ↗
The original cover. Its dashboard is an illustration, not a wallet: it shows +$3,745 of profit rather than $100K a month, and its timeline runs to mid-August, after the article was published.
i
Two outcomes, five minutes, a different question

A market like “Bitcoin Up or Down 5m” has only two outcomes, and five minutes later one settles at 100¢ and the other at 0. A manual trader asks whether Bitcoin will go up. A strong bot is asking something else: what each side is worth right now, and whether it can buy enough of it before the price catches up. It is recalculating the probability of each side, whether Polymarket has caught up with the latest Bitcoin move, how much size can actually be filled, the true average price of the position, how much exposure already sits on each side, and how the next fill changes total risk. It can reshape a whole position in seconds while a person is still looking at the chart.

Checked, not copied

What held up, on 26 September 2026

Wallet figures come from Polymarket’s own profile data; market rules and fees from its market listings and documentation.

ClaimWhat checking it showed
“50+ bots”Seven wallets are shown, not fifty. Six can still be checked; the seventh profile no longer resolves on Polymarket.
“Each making $100K+/month”In the month before the article, three of the six made $100K or more. In the 49 days since, one has kept that pace and one has lost money. The profits are real, from $73K to $1.24M all-time, but $100K a month is not typical even in this group.
The screenshotsFive of six match Polymarket’s own profit series for the day to within 3%. The sixth, Bonereaper, shows $1,248,852, while the series has it at about $1.05M that day and has never been above today’s $1.24M. Polymarket has revised profile stats since August: the “biggest win” figure is lower today in four of the screenshots, which unchanged history cannot do. So the gap is unexplained rather than proven edited.
“Five-minute” botsFive of the six live in the short windows: 68–92% of their sampled trades are in five-minute markets, Bitcoin first, and most of the rest in fifteen-minute ones. coinfilippe does not. It trades daily, weekly and monthly Bitcoin and Ethereum price markets, more than 500 times on almost every day it is active, and fewer than 0.5% of 144,000 sampled trades were in five-minute windows.
The codeAll four snippets run and print exactly the numbers the text quotes: 53.98%, 4.00%, 235 and 25, and 4.31%.
How the market settlesNot on an exchange price. Settlement uses Chainlink’s BTC/USD data stream, and a flat finish resolves Up. Since 6–7 August 2026 the rule compares the average price over the window with the opening price, not the final price. See below.
“Fees”Mentioned but never sized. Crypto markets charge takers shares × 0.07 × p × (1 − p): 1.75¢ a share at 50¢, falling toward the extremes. Makers pay nothing and receive a 20% rebate.
The wallets

The seven, against Polymarket’s own numbers

Profile avatars are blurred. Profit per dollar traded, from each profile’s totals today, is about 0.5% for the three highest-volume bots and about 1% for 0xAAAAA and DoggyStyle, which is the whole thesis in one number: tiny edges, enormous volume.

WalletJoinedIn the screenshotThat day, per PolymarketMonth before49 days after
BonereaperJoined25 Mar 2026In the screenshot$1,248,852That day, per Polymarket$1,051,672Month before+$49,94149 days after+$186,155
0x50f7Joined3 Apr 2026In the screenshot$497,261That day, per Polymarket$491,892Month before+$116,43249 days after+$78,680
BoneOhioJoined24 Mar 2026In the screenshot$204,614That day, per Polymarket$198,980Month before+$45,12449 days after+$126,744
coinfilippeJoined17 Oct 2025In the screenshot$82,644That day, per Polymarket$82,246Month before+$11,72149 days after−$8,779
0xAAAAAJoined27 Apr 2026In the screenshot$232,688That day, per Polymarket$231,261Month before+$120,99549 days after+$72,080
DoggyStyleJoined22 Apr 2026In the screenshot$231,263That day, per Polymarket$228,495Month before+$111,50849 days after+$38,020
twitter-CryptoWithGabJoinedJun 2026In the screenshot$177,043That day, per Polymarketprofile goneMonth before—49 days after—
!
The market changed the day this was published

Every trade in the screenshots, and the whole framing of “where will Bitcoin be in five minutes”, belongs to the old rule: Up won if the Chainlink BTC/USD price at the end of the window was at or above the price at the start. Markets on 6 August 2026 still settled that way. By the morning of 7 August, hours before the article went up, they compare Chainlink’s time-weighted average price over the whole window with the opening price instead. That changes the game. The outcome now firms up gradually as the window runs, since a late spike moves an average far less than it moves a closing price. The “final-second BTC move” danger for near-resolution trades is much smaller, and the fair-value model has to track a running average, not just the latest price. Two things did not change: the feed is Chainlink’s, not the exchange a bot watches for speed, and a tie still resolves Up.

Why these bots matter
Bonereaper. The screenshot shows $1,248,852 all-time; Polymarket’s series has it at about $1.05M that day. Its open positions mix five-minute windows with an hourly and a four-hour Bitcoin market.

A review of more than fifty high-performing Polymarket bots found that most are not built around one perfect directional forecast. Their edge comes from a combination of pricing, position structure, execution, liquidity and risk control. Here is how the system works.

Step 1

Work out what the contract should be worth

Suppose Bitcoin suddenly moves above the opening price of a live five-minute market. The move is already visible on an external exchange, but some sell orders for Up on Polymarket were placed before it happened. If those orders are still resting in the book, the contract can briefly stay available at a price that no longer matches the latest state of the market. That temporary mismatch is what the bot hunts for.

What the system tracks to estimate it

✓The distance between Bitcoin and the market’s opening price✓The speed of the latest Bitcoin move, and short-term volatility✓Seconds remaining before expiry✓Bid and ask levels, and the size available at several price levels✓The current prices of Up and Down✓Average entry prices already held, unhedged inventory and resting limit orders✓The related five-minute and fifteen-minute Bitcoin markets
0x50f7: $116K in the month before the article, $79K in the 49 days after. Its wins include a position bought at 1.1¢ and another at 99¢.

Instead of treating the Polymarket price as fair value, the bot makes its own estimate. Say Up trades at 42¢ and a new Bitcoin move lifts the model’s probability of Up to about 54%. The question stops being whether Bitcoin looks bullish. It becomes whether a 54¢ outcome can still be bought for well under 54¢. One simple way to update the probability is to scale the previous odds by the strength of the new signal. This is Bayes’ rule in odds form, and the multiplier is the signal’s likelihood ratio.

Updating the probability on a new signal

Prints “Updated probability: 53.98%”.

revise_probability.py31 lines
def revise_probability(
    previous_probability,
    signal_multiplier
):
    prior_odds = (
        previous_probability
        / (1 - previous_probability)
    )

    adjusted_odds = (
        prior_odds
        * signal_multiplier
    )

    updated_probability = (
        adjusted_odds
        / (1 + adjusted_odds)
    )

    return updated_probability


fair_probability = revise_probability(
    previous_probability=0.42,
    signal_multiplier=1.62
)

print(
    f"Updated probability: "
    f"{fair_probability:.2%}"
)
!
Five confirmations that are really one

A sharp Bitcoin move can bring higher volume, a stronger bid imbalance, aggressive market buys, a move in ETH and a move in SOL all at once. That looks like five separate confirmations, but all five can be consequences of the same original Bitcoin move. A model that treats them as independent evidence overestimates the probability. A strong system measures not just how powerful a signal looks, but how much genuinely new information it adds.

Step 2

A correct fair value can still be a bad trade

Suppose the bot values Up at 55¢ and the best sell order is 46¢. That looks like 9¢ of edge, but the bot cannot necessarily capture it. The first 80 shares may be available at 46¢, the next 200 at 48¢ and the next 400 already at 50¢. What matters is not the best ask but the average price of building the whole position, after fees, spread, slippage, partial fills, worse prices at larger size, and uncertainty in the model itself.

Tradable edge = fair value − expected average entry − trading costs − safety margin.

Edge after costs

Prints “Tradable edge: 4.00%”.

calculate_trade_edge.py31 lines
def calculate_trade_edge(
    fair_value,
    average_entry,
    execution_costs,
    safety_margin
):
    price_advantage = (
        fair_value
        - average_entry
    )

    usable_edge = (
        price_advantage
        - execution_costs
        - safety_margin
    )

    return usable_edge


edge = calculate_trade_edge(
    fair_value=0.55,
    average_entry=0.49,
    execution_costs=0.012,
    safety_margin=0.008
)

print(
    f"Tradable edge: "
    f"{edge:.2%}"
)
!
The fee the example leaves out

The worked example allows 1.2¢ for all execution costs. On a crypto market, a taker buying at 49¢ pays 1.75¢ a share in fees alone: shares × 0.07 × 0.49 × 0.51. Picking off stale orders is taking liquidity by definition, so the latency trade in Step 1 always pays the full fee, and it pays the most exactly where these edges appear, around 50¢. The same fee costs a maker nothing and earns a rebate, which is a large part of why the most successful accounts rest orders rather than chase them.

This is where strategies that look spectacular on a chart fall apart live. A mispricing can exist in historical data, at the top of the book, and even for 50 shares, then disappear completely for a bot that wants 5,000. Finding an edge is one thing; being able to execute enough size before it disappears is another.

Step 3

Some of the best opportunities sit between related markets

The same Bitcoin move affects the current five-minute market, the next five-minute window, the fifteen-minute market and the short-term ETH and SOL markets at once, but they do not all update at the same speed. Suppose Bitcoin jumps and the current five-minute market reprices Up from 50¢ to 68¢, while the fifteen-minute market is still around 54¢. That alone does not make the fifteen-minute contract cheap: the two have different opening prices and different amounts of time left. So the bot estimates fair value for each separately.

BoneOhio: $45K in the month before the article, $127K in the 49 days after.

Compare each market with its own fair value, not with each other

MarketMarket priceModel valueReading
Bitcoin Up or Down 5mMarket price68¢Model value66¢ReadingSlightly expensive
Bitcoin Up or Down 15mMarket price54¢Model value61¢ReadingWell below its estimate

Relative score = (current gap − typical gap) ÷ historical volatility of the gap. That is a z-score of the spread between connected markets. A large deviation doesn’t create a trade on its own, but it tells the system that one part of a connected structure has moved unusually far from the rest. A person watches one contract; a bot can watch a whole network of related probabilities at once.

Step 4

Five ways bots turn a pricing edge into a position

Finding an underpriced outcome is only the first step; the next question is how to build the position. Across high-performing bots, five structures keep recurring.

1 · Dynamic position rotation
coinfilippe: not a five-minute bot. It trades daily, weekly and monthly Bitcoin and Ethereum price markets, and it is down $8,779 since the article.

The model sees an edge in Up and the bot starts buying Up. Then Bitcoin loses momentum, drifts back toward the opening level, and the estimated probability of Up falls. The bot doesn’t have to stay committed. It can stop adding Up, trim part of the position, start accumulating Down, and rotate again if the market turns once more. The first entry isn’t the final decision; the position keeps moving with the model. The danger is noise. If Bitcoin chops back and forth, the bot can switch sides repeatedly and bleed its edge away through spread, slippage and poor fills.

2 · Temporal arbitrage
0xAAAAA: $121K in the month before the article, $72K in the 49 days after.

The simplest binary arbitrage is when Up + Down costs less than $1. At Up 45¢ and Down 48¢ the pair costs 93¢, and one of the two will settle at $1. Some bots build that pair without buying both sides at once. Bitcoin rises and Down falls to 27¢, so the bot buys Down. Later Bitcoin reverses toward the opening level, and Up can be picked up around 49¢. The finished pair costs 76¢, from two prices that never existed together in the book.

The catch is that until the second side is bought, it isn’t arbitrage. If Bitcoin keeps climbing after the Down purchase, cheap Up never appears and the bot is simply holding a directional bet. More conservative systems build the pair in small blocks (50 Down, then 50 Up, then another block) so less inventory is ever left exposed.

Taker fees change the arithmetic. As a taker, the 93¢ pair pays about 3.5¢ in fees and nets 3.5¢ rather than 7¢, and a 94¢ pair nets 2.5¢. The 76¢ legged pair still nets almost 21¢.

3 · Hedged directional position
DoggyStyle: $112K in the month before the article, $38K in the 49 days after.

Other bots don’t try to hold equal quantities. With 260 Up and 235 Down, 235 on each side form the paired portion and the remaining 25 Up are the directional bias. Most of the position is protected, while some extra exposure rides on the outcome the model prefers. Directional exposure = Up quantity − Down quantity.

Paired versus directional

Prints “Matched quantity: 235” and “Directional exposure: 25”.

split_position.py34 lines
def split_position(
    up_quantity,
    down_quantity
):
    matched_quantity = min(
        up_quantity,
        down_quantity
    )

    directional_exposure = (
        up_quantity
        - down_quantity
    )

    return {
        "matched_quantity": matched_quantity,
        "directional_exposure": directional_exposure
    }


position = split_position(
    up_quantity=260,
    down_quantity=235
)

print(
    f"Matched quantity: "
    f"{position['matched_quantity']}"
)

print(
    f"Directional exposure: "
    f"{position['directional_exposure']}"
)

If the signal strengthens, the bot can widen the imbalance; if confidence falls, it adds Down and reduces directional risk. But holding both sides doesn’t make the position efficient. At average prices of Up 55¢ and Down 49¢, a complete pair costs $1.04 and can only ever return $1, so the “protected” part already carries a 4¢ deficit that the extra directional contracts must recover before the position is in profit.

4 · Multi-market inventory management

Some bots don’t think in terms of one market, one trade. They run capital across the five- and fifteen-minute Bitcoin markets, the ETH and SOL markets and neighbouring windows, managing an inventory rather than a collection of separate bets. Suppose a Down position has climbed to 98¢. The bot can wait for settlement at $1, or sell part of it at 98¢ and move that capital to a market where a fresh edge has appeared. It may also buy a sliver of the opposite outcome at 1–2¢. That costs almost nothing if nothing unusual happens, and offsets part of the loss if Bitcoin crosses the line at the last moment. The question for this kind of bot is how efficiently the entire inventory is using edge, not whether one entry was good.

5 · Near-resolution capture

Another group trades almost only at the very end, when the result looks close to certain but the likely winner still trades below $1: buy at 98.7¢, settle at $1, keep 1.3¢. The return per trade is tiny, so the strategy lives on turnover and volume. The risk is extremely lopsided. A bot can collect 1¢ again and again, then lose almost the whole contract on one wrong trade. That is why a very high win rate doesn’t make the strategy safe; the size of the rare losses matters far more.

Two details now favour this style. The taker fee at 98.7¢ is only about 0.09¢ a share, because the fee shrinks toward the extremes. And since settlement moved to a window average, a last-second spike can no longer flip a nearly settled market the way it could when the final price decided it.

What turns a near-certain trade into a total loss

✗A final-second Bitcoin move (much less decisive under the window-average rule)✗Watching the wrong price feed: settlement is Chainlink’s stream, not the exchange the bot trades off✗An incorrect opening price✗Misreading the settlement rules, including that a tie resolves Up✗Failing to cancel a limit order in time
Step 5

The biggest problem often starts after the first fill

twitter-CryptoWithGab: $177,043 all-time in the screenshot. The profile no longer resolves on Polymarket, so it cannot be checked.

Suppose the bot finds what looks like perfect arbitrage, with Up + Down at 94¢. It sends two orders. Up fills, but Down fills only partly, then the market moves and the rest of Down becomes too expensive. The arbitrage is gone and the bot is holding an open Up position. The pricing model wasn’t necessarily wrong; the failure happened in execution.

What the system now has to decide

✓How long to wait for the second leg✓How much worse a price it can accept✓How much imbalance is safe✓Whether to stay passive with limit orders, or when to cross the spread✓Whether closing the first leg at a small loss is now the better decision

One answer is to make the working quote depend on inventory. Working price = fair value − inventory penalty, and inventory penalty = q × λ × σ² × τ, where q is the current position imbalance, λ is risk sensitivity, σ is volatility and τ is time remaining. It is the reservation price from the Avellaneda–Stoikov market-making model, with the mid price swapped for the bot’s fair value. If the bot already holds too much Up, it becomes less willing to buy more Up, and buying Down becomes more valuable because it reduces the imbalance. It sounds simple, and it is one of the biggest differences between a real execution system and a bot that just keeps buying while its signal stays positive.

Step 6

The final filter is position size

Even a strong edge doesn’t justify putting all the capital into one market. The model can be right and the trade can still fail because liquidity disappears, one leg never fills, the API lags, an external data feed updates late, the real average entry is worse than expected, or several correlated positions open at once. So sizing is a separate decision, and one approach is to use only a fraction of the full Kelly allocation.

A fifth of Kelly

Prints “Capital allocation: 4.31%”. Full Kelly here would be 21.6% of capital.

fractional_kelly.py39 lines
def fractional_kelly(
    win_probability,
    entry_price,
    fraction=0.20
):
    loss_probability = (
        1 - win_probability
    )

    net_odds = (
        1 - entry_price
    ) / entry_price

    full_kelly = (
        net_odds * win_probability
        - loss_probability
    ) / net_odds

    fractional_allocation = (
        full_kelly
        * fraction
    )

    return max(
        fractional_allocation,
        0
    )


allocation = fractional_kelly(
    win_probability=0.60,
    entry_price=0.49,
    fraction=0.20
)

print(
    f"Capital allocation: "
    f"{allocation:.2%}"
)

The hard limits a production bot still needs

✓Maximum capital per market✓Maximum unhedged inventory✓Maximum exposure to BTC, ETH or SOL✓A daily loss limit✓A limit on correlated positions✓An automatic kill switch when market data becomes unreliable

Correlation matters most. A five-minute and a fifteen-minute Bitcoin position are technically two markets, but if both carry large Up exposure they are effectively the same bet. The same happens when BTC, ETH and SOL all move together in a broad crypto swing.

What they have in common

Different strategies, one loop

No single strategy is shared by every high-performing bot. Some rotate continuously, some leg into arbitrage, some hold a large paired position with a small tilt, some run inventory across markets, and some barely trade until the last seconds. Underneath, the same process keeps appearing.

1

Receive fresh data

From the exchange, the order book and the related markets.

2

Calculate an independent probability

Without double-counting signals that share one cause.

3

Compare it with the real executable price

The average fill across the depth needed, after fees, not the best ask.

4

Choose the position structure

Rotation, legged arbitrage, a hedged tilt, inventory across markets, or near-resolution capture.

5

Build it without dangerous imbalance

Quoting against inventory, in blocks, with a plan for the leg that doesn’t fill.

6

Limit the capital at risk

Fractional Kelly inside hard limits, with correlation counted.

7

Repeat at scale

The edge per trade is small; the profits in the table above come from running this thousands of times.

i
The two questions that matter

These systems don’t need to know where Bitcoin will be in five minutes. They only need to answer two questions faster than most traders: what should Up and Down be worth right now, and can the position be built before that opportunity disappears?