| |
| """ |
| π Polymarket Bot β Backtester / Scanner de marchΓ©s. |
| Test rapide des stratΓ©gies sur les marchΓ©s actuels sans placer d'ordres. |
| """ |
| import asyncio |
| import json |
| import logging |
| import time |
| from datetime import datetime |
|
|
| from polymarket_bot import ( |
| BotConfig, GammaClient, CLOBDataClient, |
| ArbitrageStrategy, ValueBetStrategy, LeaderFollowerStrategy, |
| ) |
|
|
| logging.basicConfig( |
| level=logging.INFO, |
| format="%(asctime)s | %(name)-20s | %(levelname)-5s | %(message)s", |
| datefmt="%H:%M:%S", |
| ) |
| logger = logging.getLogger("scanner") |
|
|
|
|
| async def scan_markets(): |
| """Scanne les marchΓ©s actuels pour les opportunitΓ©s.""" |
| print(""" |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ |
| β π POLYMARKET MARKET SCANNER β SINGLE PASS π β |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ |
| """) |
|
|
| config = BotConfig(dry_run=True) |
| gamma = GammaClient() |
| clob = CLOBDataClient() |
|
|
| |
| logger.info("Loading markets from Gamma API...") |
| markets = await gamma.get_all_active_markets() |
| logger.info(f"Loaded {len(markets)} active markets") |
|
|
| |
| filtered = [ |
| m for m in markets |
| if m.volume >= config.min_market_volume |
| and not m.closed |
| and m.active |
| and m.yes_token |
| and m.no_token |
| and not any(tag in config.excluded_tags for tag in m.tags) |
| ] |
| logger.info(f"After filtering: {len(filtered)} markets") |
|
|
| |
| print("\nπ TOP 10 MARCHΓS PAR VOLUME:") |
| print("-" * 80) |
| sorted_markets = sorted(filtered, key=lambda m: m.volume, reverse=True)[:10] |
| for i, m in enumerate(sorted_markets, 1): |
| yes = m.yes_token |
| no = m.no_token |
| spread = 1.0 - (yes.price + no.price) if yes and no else 0 |
| print( |
| f" {i:2d}. {m.question[:60]:<60s}\n" |
| f" Volume: ${m.volume:>12,.0f} | YES: {yes.price:.2f} | NO: {no.price:.2f} | " |
| f"Spread: {spread:+.4f}" |
| ) |
|
|
| |
| print("\n\nπ SCANNING STRATEGIES...") |
| print("=" * 80) |
|
|
| |
| print("\nπ STRATΓGIE 1: ARBITRAGE") |
| print("-" * 40) |
| arb = ArbitrageStrategy(config, clob) |
| arb_signals = await arb.scan(filtered[:50]) |
|
|
| if arb_signals: |
| for s in arb_signals[:10]: |
| meta = s.metadata |
| print( |
| f" π° {s.action} | Spread: {meta.get('spread', 0):.4f} | " |
| f"Size: ${s.size_usd:.2f} | Expected: ${s.expected_profit:.2f}\n" |
| f" {meta.get('question', '')[:70]}" |
| ) |
| else: |
| print(" Aucune opportunitΓ© d'arbitrage dΓ©tectΓ©e (normal β marchΓ©s efficaces)") |
|
|
| |
| print("\n\nπ‘ STRATΓGIE 2: VALUE BET") |
| print("-" * 40) |
| vb = ValueBetStrategy(config, clob) |
| vb_signals = await vb.scan(filtered[:30]) |
|
|
| if vb_signals: |
| for s in vb_signals[:10]: |
| meta = s.metadata |
| print( |
| f" π {s.action} | Edge: {meta.get('edge', 0):.4f} | " |
| f"Kelly: {meta.get('kelly_frac', 0):.4f} | " |
| f"Size: ${s.size_usd:.2f}\n" |
| f" {meta.get('question', '')[:70]}" |
| ) |
| else: |
| print(" Pas assez d'historique pour dΓ©tecter des signaux (nΓ©cessite plusieurs cycles)") |
|
|
| |
| print("\n\nπ STRATΓGIE 3: LEADER-FOLLOWER") |
| print("-" * 40) |
| lf = LeaderFollowerStrategy(config, clob) |
| lf_pairs = lf._find_correlated_pairs(filtered[:30]) |
| if lf_pairs: |
| print(f" {len(lf_pairs)} paires corrΓ©lΓ©es dΓ©tectΓ©es:") |
| for leader, follower, sim in lf_pairs[:5]: |
| print( |
| f" π SimilaritΓ©: {sim:.4f}\n" |
| f" Leader: {leader.question[:60]}\n" |
| f" Follower: {follower.question[:60]}" |
| ) |
| else: |
| print(" Aucune paire fortement corrΓ©lΓ©e trouvΓ©e") |
|
|
| |
| total_signals = len(arb_signals) + len(vb_signals) |
| total_expected = sum(s.expected_profit for s in arb_signals + vb_signals) |
|
|
| print(f""" |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ |
| β π SCAN SUMMARY β |
| β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£ |
| β Markets scanned: {len(filtered):>6d} |
| β Arb signals: {len(arb_signals):>6d} |
| β Value bet signals: {len(vb_signals):>6d} |
| β Correlated pairs: {len(lf_pairs):>6d} |
| β Total expected: ${total_expected:>10,.2f} |
| β Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ""") |
|
|
| |
| scan_results = { |
| "timestamp": datetime.now().isoformat(), |
| "markets_scanned": len(filtered), |
| "arb_signals": len(arb_signals), |
| "vb_signals": len(vb_signals), |
| "lf_pairs": len(lf_pairs), |
| "arb_details": [ |
| { |
| "market": s.metadata.get("question", ""), |
| "spread": s.metadata.get("spread", 0), |
| "expected_profit": s.expected_profit, |
| "size_usd": s.size_usd, |
| } |
| for s in arb_signals |
| ], |
| } |
| with open("scan_results.json", "w") as f: |
| json.dump(scan_results, f, indent=2) |
| logger.info("Results saved to scan_results.json") |
|
|
| await gamma.close() |
| await clob.close() |
|
|
|
|
| if __name__ == "__main__": |
| asyncio.run(scan_markets()) |
|
|