contrarian — GTC maker bids on underdog outcomes

GTC maker bids on 20-50¢ underdog outcomes across all Polymarket markets. Zero taker fees, 30-min scan loop, multi-layer risk stack. Inspired by @Car's +$22K strategy.

Version v1.0.0 · One-time payment · Source code download
Strategy typeMaker rebate
AssetMulti-market
TimeframeEvent-driven
Market typeAll Polymarket markets
Minimum capital$50
Dependencies@polymarket/clob-client, ethers

What it does

contrarian scans every active Polymarket market every 30 minutes, finds outcomes priced between 20¢ and 50¢, and posts GTC (good-til-cancelled) limit orders to buy them. Because the orders rest on the book as maker orders, there is no taker fee, and they are eligible for Polymarket's maker rewards program. The bot waits for takers to come to it, then holds to resolution.

The edge

The 20-50¢ band is the "underdog sweet spot": not penny tickets and not consensus plays. Markets in this band have a structural over-correction: the crowd treats a 30¢ outcome as if there's a 30% chance, but in many categories the realized rate is closer to 35-40%. The strategy is documented to have produced +$22K net PnL for @Car (wallet 0x7c3db7...) at a 50% win rate on 25-50¢ entries.

The fee math is the killer feature. Taker fees on 30¢ entries cost 0.6-1.2% of the bet. Maker entries at 30¢ cost zero, plus they earn rewards. A 50% win rate at 30¢ entry is +$0.20 expected per share before fees, and the maker rebate adds on top instead of eating into it.

How it works

The bot runs three concurrent loops:

  1. Scan (every 30 min): pulls all active markets from Polymarket Gamma API, filters by volume, hours-to-close, and the 20-50¢ band. Posts a GTC bid at $0.20-$0.50 on every matching outcome up to MAX_PENDING_ORDERS (20) simultaneous orders.
  2. Fill check (every 2 min): polls the CLOB for fills on outstanding orders. On fill, the order graduates to a held position.
  3. Resolution poll (every 5 min): checks every held position for resolution. On WIN, payout is $1.00/share; on LOSS, $0.00/share.

Six independent risk gates sit on top:

  • MAX_LOSS: hard daily PnL stop
  • MAX_DRAWDOWN_PCT (default 40% from peak): drawdown circuit breaker
  • MAX_CONSEC_LOSSES (default 8): triggers an escalating cooldown (1h × 2^level)
  • MAX_ERRORS_WINDOW (10 errors in 5 min): hard exit, expects a wrapper to restart
  • MAX_ORDER_AGE_H (default 48h): cancels orders that have been sitting unfilled
  • MIN_BALANCE ($2): stops posting new orders if cash gets too thin

Sample output

[24/05/2026, 12:00:14] Scanning 847 active markets... [24/05/2026, 12:00:18] 23 candidates in 20-50¢ band after filters [24/05/2026, 12:00:19] [LIVE] BUY (GTC) 10sh @ $0.250 ($2.50, zero fee) [24/05/2026, 12:00:21] [LIVE] BUY (GTC) 5sh @ $0.400 ($2.00, zero fee) [26/05/2026, 14:33:02] FILL "Will Smith win Best Actor?" — Yes @ $0.31 [28/05/2026, 18:00:00] RESOLVED WIN "Will Smith win Best Actor?" — +$2.85

Design targets

The fee math gives you the break-even line: at $0.30 entry with zero fees, win rate ≥ 30% is profitable. The strategy's design target is 35-45% realized WR across the basket of underdog markets, with bet sizes (--bet-size 2 default) intentionally small so a long cold streak does not eat the bank.

Capital efficiency: with 20 pending orders × $2 = $40 in resting orders, plus held positions, $50 is the absolute minimum bank. The recommended starting bank is $100 so the drawdown stop doesn't trigger immediately on a normal losing streak.

FAQ

Why GTC instead of FOK?

FOK pays taker fees (0.4-1.5% depending on price band) and competes with the existing book. GTC waits for someone to take your bid, which means you decide the price and the only opportunity cost is the time the capital sits locked.

How does this compare to no-bot?

no-bot is a stricter variant: it only bids "No" on binary yes/no markets and adds a sports-keyword filter. contrarian bids on any underdog, in any market shape, including the "Yes" side. Run them together for diversification, or run no-bot if you specifically want the "nothing ever happens" thesis.

What's included

  • others/contrarian.js
  • polymarket-limits.js
  • README with risk-gate tuning notes and a worked example of running alongside the scalpers

Configuration

FlagDefaultDescription
--livePlace real orders. Default is dry-run.
--sim-balance 5050Starting balance in dry-run mode (USD).
--bet-size 22Fixed bet size per order in USD.
--min-price 0.200.20Minimum outcome price to bid on.
--max-price 0.500.50Maximum outcome price to bid on.
--min-volume 50005000Minimum 24h volume filter (USD).
--min-hours 2424Minimum hours to market close before bidding.
--max-order-age 4848Cancel unfilled orders older than N hours.
--max-loss 00Daily loss limit in USD. 0 = disabled.
--max-drawdown 0.400.40Drawdown circuit breaker (fraction of peak balance).
--max-consec-losses 88Consecutive loss limit before cooldown.

Related bots