Polymarket Bot Tutorial · Chapitre 20 sur 32
Suivez les whale wallets Polymarket et copiez les trades des meilleurs performeurs de manière programmatique : identifiez les wallets rentables via le leaderboard et l'analyse on-chain, répliquez leurs trades avec des règles de taille et de timing.
Ce que couvre ce chapitre
Copier les wallets gagnants sur Polymarket est une idée populaire, mais les véritables whales sur Polymarket font surtout de l'arbitrage en fin de fenêtre sur des marchés résolus, et non des paris directionnels. Ce chapitre présente la recherche honnête issue de l'analyse on-chain : quels wallets copier réellement, pourquoi la plupart ne valent pas la peine d'être copiés, et les mathématiques du position sizing.
- Identifier les wallets rentables
- Détection des trades on-chain
- Position sizing par rapport à la whale
- Latency : à partir de quand est-ce trop tard
- Filters : ne suivre que les wallets avec un edge vérifié
- Code : détecter un event d'achat d'une whale, placer une copie dimensionnée
Identifier les wallets rentables
Le principe du whale-copying est que certains wallets sont régulièrement rentables et que copier leurs entrées capte une partie de leur edge. L'analyse on-chain des top wallets de Polymarket en 2025-26 a produit un résultat sobre : la plupart des whales visibles font de l'arbitrage de fin de fenêtre sur des marchés résolus, et non du directional trading.
Profil que nous avons mesuré sur trois wallets whales candidats :
- "hhhhhh6" (taux de réussite de 98,5 %, volume de $n M) - 88 % des entrées à des prix ≥0,95, timestamp médian d'entrée à 226 s sur une fenêtre de 300 s. Pur arb de rendement de fin de parcours, pas directionnel.
- "anonymous" (taux de réussite de 20 %) - joueur dégénéré. Le copier fait perdre de l'argent.
- "Jkim123" (taux de réussite de 53,5 %) - pile ou face. Pas un signal qui mérite d'être copié.
0 % des trades de ces whales ont eu lieu dans les 120 premières secondes d'une fenêtre de 5 minutes. Le signal prédictif (s'il existe) viendrait des grosses entrées en DÉBUT de fenêtre - mais ces wallets ne sont pas ceux qui dominent le leaderboard, parce que c'est difficile.
Détection des trades on-chain
Détecter les trades d'un wallet cible nécessite soit d'interroger en boucle le data-api de Polymarket, soit de s'abonner aux events on-chain de transfert CTF. L'option data-api est plus simple.
def watch_wallet(wallet_addr, last_seen_ts=0):
while True:
url = f"https://data-api.polymarket.com/activity?user={wallet_addr}&limit=100"
events = requests.get(url).json()
for ev in events:
ts = int(ev.get("timestamp", 0))
if ts <= last_seen_ts: continue
if ev["type"] == "TRADE":
process_whale_trade(ev)
last_seen_ts = max(last_seen_ts, ts)
time.sleep(5)
Un polling de cinq secondes est le plancher pratique pour le data-api. En dessous, vous allez atteindre les rate limits. Pour une détection en sous-seconde, abonnez-vous aux events on-chain ERC-1155 TransferSingle du contrat CTF filtrés par l'adresse proxy de la whale.
Position sizing par rapport à la whale
Si vous dimensionnez votre copie comme une fraction constante du trade de la whale, vous héritez de son profil de risque. Deux alternatives pratiques.
- Basé sur un plafond : dimensionner chaque copie à un montant fixe en dollars (10 à 50 $), quelle que soit la taille de la whale. La croissance est plus lente, mais la perte par trade est bornée.
- Basé sur le taux de réussite : dimensionner la copie en fonction du taux de réussite récent de la whale. WR supérieur à 60 % → copie pleine taille ; 40 à 60 % → demi-taille ; en dessous de 40 % → ignorer.
L'approche basée sur un plafond est la plus sûre pour un premier déploiement. Ne passez à l'approche pondérée par le taux de réussite qu'après avoir mesuré le taux de réussite réel de la whale sur VOS copies (qui est généralement plus faible que son chiffre annoncé, parce que vous arrivez en retard).
Latency : à partir de quand est-ce trop tard
Le trade de la whale est visible publiquement dans un délai de 1 à 2 secondes après l'exécution. Le copier exige donc une latence de lecture plus rapide que cela, plus la latence de placement de votre propre ordre.
De bout en bout pour un copy bot classique : 5 à 10 secondes de polling + 200 ms de placement d'ordre = 5 à 15 secondes au total. Au moment où votre copie se déclenche, le signal de la whale est déjà intégré dans le prix.
Pour 99 % des copies, c'est trop tard sur les marchés étroits de Polymarket. L'entrée de la whale a déplacé le mid de 1 à 2 cents ; vous payez cette prime de 1 à 2 cents par rapport à son prix d'entrée. Si son edge était de 3 c, la moitié a déjà disparu quand vous arrivez.
Les copy bots qui fonctionnent font soit (a) du ciblage sur des marchés à mouvement lent où 30 s de latence ne changent rien, soit (b) de l'abonnement à des events on-chain pour réagir en sous-seconde.
Filters : ne suivre que les wallets avec un edge vérifié
Trois filtres avant d'ajouter un wallet à votre liste de copie.
- 30+ trades clôturés dans l'historique du wallet. Les petits échantillons ne sont que du bruit.
- Win rate à vie > 60 %, OU expected value positive par trade sur la base des prix d'entrée. L'une des deux conditions ; les deux, c'est mieux.
- Le pattern n'est PAS de l'arbitrage de fin de fenêtre. Vérifiez les secondes médianes jusqu'à la résolution au moment de l'entrée ; si c'est proche de 0, le wallet fait de l'arbitrage de rendement de fin de parcours que vous ne pouvez pas reproduire.
La plupart des whales candidates échouent à l'un de ces trois critères. Le pool de wallets réellement copiables est petit. Maintenir la liste exige une revalidation périodique - des wallets rentables le mois dernier ne le sont pas forcément ce mois-ci.
Code : détecter un event d'achat d'une whale, placer une copie dimensionnée
Référence : détecter un event CTF TransferSingle pour une whale suivie, déclencher un achat copié dimensionné.
from web3 import Web3
w3 = Web3(Web3.WebsocketProvider(POLYGON_WSS))
ctf = w3.eth.contract(address=CTF_ADDR, abi=CTF_ABI)
WHALES = {"0xabc...": {"fraction": 0.05, "cap": 50}}
def on_transfer(event):
to = event.args["to"].lower()
if to not in WHALES: return
cfg = WHALES[to]
token_id = event.args.id
whale_size = event.args.value / 1e6
copy_size = min(cfg["cap"], whale_size * cfg["fraction"])
if copy_size < 5: return # not worth fees
book = fetch_book(str(token_id))
if book.best_ask:
place_fok(str(token_id), "BUY", book.best_ask + 0.01, copy_size)
# subscribe to ERC-1155 TransferSingle events from CTF
filt = ctf.events.TransferSingle.create_filter(fromBlock="latest")
while True:
for ev in filt.get_new_entries(): on_transfer(ev)
time.sleep(0.5)
Distinguez l'achat de la vente en vérifiant from (zero address = mint = la whale a acheté) vs to (zero address = burn = vendu).





