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.
| Strategy type | Maker rebate |
|---|---|
| Asset | Multi-market |
| Timeframe | Event-driven |
| Market type | All 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:
- 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. - Fill check (every 2 min): polls the CLOB for fills on outstanding orders. On fill, the order graduates to a held position.
- 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 stopMAX_DRAWDOWN_PCT(default 40% from peak): drawdown circuit breakerMAX_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 restartMAX_ORDER_AGE_H(default 48h): cancels orders that have been sitting unfilledMIN_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.jspolymarket-limits.js- README with risk-gate tuning notes and a worked example of running alongside the scalpers
Configuration
| Flag | Default | Description |
|---|---|---|
| --live | — | Place real orders. Default is dry-run. |
| --sim-balance 50 | 50 | Starting balance in dry-run mode (USD). |
| --bet-size 2 | 2 | Fixed bet size per order in USD. |
| --min-price 0.20 | 0.20 | Minimum outcome price to bid on. |
| --max-price 0.50 | 0.50 | Maximum outcome price to bid on. |
| --min-volume 5000 | 5000 | Minimum 24h volume filter (USD). |
| --min-hours 24 | 24 | Minimum hours to market close before bidding. |
| --max-order-age 48 | 48 | Cancel unfilled orders older than N hours. |
| --max-loss 0 | 0 | Daily loss limit in USD. 0 = disabled. |
| --max-drawdown 0.40 | 0.40 | Drawdown circuit breaker (fraction of peak balance). |
| --max-consec-losses 8 | 8 | Consecutive loss limit before cooldown. |