Automated trading system exploiting latency between Chainlink oracle updates and Polymarket CLOB repricing on 15-min BTC/ETH/XRP/SOL markets.
Quick Start | How It Works | Results | Usage | Configuration | Disclaimer
pip install https://github.com/JonathanPetersonn/oracle-lag-sniper/releases/latest/download/oracle_lag_sniper-1.2.0-py3-none-any.whl
curl -LO https://raw.githubusercontent.com/JonathanPetersonn/oracle-lag-sniper/v1.2.0/.env.example
cp .env.example .env # On Windows: move .env.example .envOr download the wheel manually from the Releases page.
The .env file controls everything: mode (demo/live), risk limits, and which assets to trade. No API keys needed to run demo — the default oracle source uses Polymarket's public relay. See Configuration for all options. Once your .env is ready:
On Linux/macOS:
oracle-lag-sniper run --dry-run # validate config
oracle-lag-sniper run # start (demo by default)On Windows:
python -m oracle_lag_sniper run --dry-run
python -m oracle_lag_sniper runOr run with Docker (requires cloning the repo, the image pulls the latest stable release automatically):
git clone https://github.com/JonathanPetersonn/oracle-lag-sniper.git
cd oracle-lag-sniper
cp .env.example .env
docker compose up # demo
docker compose --profile live up # livePolymarket runs 15-minute prediction markets on crypto prices. Each market asks a simple question: will BTC (or ETH, XRP, SOL) go up or down in the next 15 minutes? You buy a YES or NO token, and if you're right, you get paid.
Each market settles using a Chainlink price feed - a trusted third-party data source that Polymarket's contracts use to decide who wins. Not Binance, not Coinbase - specifically Chainlink. This strategy reads the same Chainlink feed, so it sees the exact same price data that will determine the final outcome. Any other price source would be slightly different, and even a tiny difference matters when you're betting on small moves.
The Chainlink feed updates in under a second. But the traders on Polymarket - both people and bots - don't adjust their orders that fast. It takes them roughly 55 seconds on average to react. This is normal in any market: new information arrives, and it takes time for participants to see it, process it, and update their prices. It happens everywhere from stock exchanges to sports betting.
During that ~55-second window, one side of the bet is too cheap. Say the price feed already shows BTC ticking up, but the YES token still reflects the old price - it costs less than it should. This strategy reads the feed in real time, spots that gap, and buys the underpriced side before the rest of the market catches up.
The strategy checks three things before buying: the price has moved enough (at least 0.07% from the market's open), there's enough time left (at least 5 minutes), and the token is cheap enough (at most $0.62). All three must be true at the same time. The market resolves 15 minutes later - you either collect the payout or lose your stake.
Over 3 weeks of historical data, the strategy found about 5,000 moments where the market hadn't caught up to the price feed yet. It bought the cheap side each time and was right roughly 6 out of 10 trades. Because winning trades pay more than losing trades cost (you buy cheap tokens that pay out $1), even a 60% win rate produces a strong overall profit. The backtest was stress-tested with 7 different checks designed to disprove it, and a 60/40 data split (more on that below).
| Asset | Trades | Win Rate | Profit | Avg Return |
|---|---|---|---|---|
| BTC | 1,014 | 61.5% | $11,550 | 11.4% |
| ETH | 1,302 | 62.7% | $19,268 | 14.8% |
| XRP | 1,342 | 61.4% | $15,599 | 11.6% |
| SOL | 1,359 | 60.1% | $12,826 | 9.4% |
| Total | 5,017 | 61.4% | $59,244 | 11.8% |
The results are consistent across all four coins. ETH was the most profitable (highest win rate and return), while SOL was the weakest but still clearly positive. This consistency suggests the strategy is capturing a real pattern in how these markets reprice, not something specific to one coin. Dataset: 8,876 resolved markets, 146K price points, Feb 2026 (~3 weeks).
Cumulative profit over time for each asset. All four lines trend upward steadily - no sudden jumps or single lucky days carrying the results. The profit accumulates gradually across thousands of small trades.
To make sure these results aren't just the strategy memorizing past data, the dataset was split in two by date: the first 60% was used during development, and the last 40% was hidden completely. The strategy never saw the second half while it was being built. Both halves performed nearly the same - 61.9% vs 60.7% win rate - which means the pattern holds on data it's never seen before.
The strategy was profitable on 20 out of 24 days (83%). The biggest drop from peak profit was $4,734, which recovered within a few days. Losing streaks happen (the longest was 23 in a row), but they average only 2-3 losses before a recovery, because each trade risks a small fixed amount ($5 by default).
See notebooks/backtest_analysis.ipynb for full analysis: profit distributions, entry timing, win rate breakdowns, and daily performance.
For detailed methodology, all 7 stress tests, frozen parameters, architecture, and known limitations, see RESEARCH.md.
# Trading daemon
oracle-lag-sniper run # mode from .env (default: demo)
oracle-lag-sniper run --mode live # live
oracle-lag-sniper run --dry-run # validate config
# Backtest
oracle-lag-sniper backtest # full report + all 7 falsification tests
oracle-lag-sniper backtest --entry-test # entry price sensitivity
oracle-lag-sniper backtest --delta-test # delta threshold sensitivity
oracle-lag-sniper backtest --cross-test # 27-combo grid search
# Data pipeline
oracle-lag-sniper data refresh # fetch all data in ordercp .env.example .envMODE=demo # "demo" or "live"
ORACLE_SOURCE=polymarket # "polymarket" (default, no keys) or "chainlink" (direct)
POLY_PRIVATE_KEY= # 0x... (live only)
POLY_FUNDER= # proxy wallet
POLY_SIGNATURE_TYPE=1 # 0=EOA, 1=POLY_PROXY, 2=GNOSIS_SAFE
TELEGRAM_BOT_TOKEN= # optional
TELEGRAM_CHAT_ID=
COMMENTS_ENABLED=false # watch market comments (console)
COMMENTS_INTERVAL=30 # seconds between comment polls
NOTIONAL_PER_TRADE=5 # 5 USD max per trade
DAILY_PNL_LIMIT=-150
MAX_CONCURRENT_POSITIONS=16 # 4 assets × 4 overlapping windows; 16+ recommended
ASSETS=btc,eth,xrp,sol
# Chainlink API keys (only needed for ORACLE_SOURCE=chainlink or data pipeline)
CHAINLINK_API_KEY= # get keys at https://pm-ds-request.streams.chain.link/
CHAINLINK_API_SECRET=
# Auto-redeem (gasless via Polymarket relayer)
BUILDER_API_KEY=
BUILDER_SECRET=
BUILDER_PASSPHRASE=
REDEEM_ENABLED=true # set false to disable
REDEEM_INTERVAL=120 # seconds between redeem sweepsBy default, the bot uses Polymarket's RTDS relay for oracle prices — no API keys needed to get started. For direct Chainlink access, set ORACLE_SOURCE=chainlink and get keys free at pm-ds-request.streams.chain.link (listed in Polymarket docs). Chainlink keys are always required for the data pipeline (oracle-lag-sniper data refresh).
Strategy parameters are frozen in config.py. Everything else is in .env, set before startup.
When a market resolves and you hold winning tokens, the system can automatically cash them in for USDC using Polymarket's gasless relayer. To enable this, fill in the BUILDER_* credentials in .env. The system checks for redeemable tokens every REDEEM_INTERVAL seconds.
EOA wallets (signature type 0) don't support auto-redeem. Proxy and Gnosis Safe wallets (types 1 and 2) do.
- Fill credentials in
.env - Set
POLY_FUNDERto your proxy wallet (holds USDC) - Run demo first, check signal timing in logs
- Review risk settings (
DAILY_PNL_LIMIT,MAX_CONCURRENT_POSITIONS) MODE=liveor--mode live
Optional Telegram integration for notifications and remote control. Set TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID in .env to enable.
- Notifications: get alerts on trade entries, exits, errors, and daily P&L summaries
- Commands: check status, view open positions, and pause/resume trading directly from Telegram
oracle-lag-sniper data refresh| Step | Time | What it does |
|---|---|---|
fetch_markets |
~5 min | Market metadata from Gamma API |
fetch_ticks |
~2 min | YES token price ticks from CLOB |
fetch_prices |
~45 min | Oracle prices from Chainlink Data Streams |
build_csv |
<1 sec | Join into per-asset CSVs |
fetch_binance |
~45 min | Binance spot prices for cross-validation |
build_combined_csv |
<1 sec | Merge CSVs + Binance |
All steps resume from where they left off.
If you found this project helpful, instead of donating to me, I'd love for you to support UNICEF's work for children in Africa. Every contribution helps provide food, clean water, education, and healthcare to children who need it most.
See LICENSE for details.



