""" Polymarket Trading Bot — Main Entry Point # ci-test: 2026-04-13 """ import asyncio import logging import os from contextlib import asynccontextmanager from bot.data.polymarket import PolymarketClient from bot.data.external import ExternalDataClient from bot.strategy.bayesian import BayesianStrategy from bot.risk.manager import RiskManager from bot.executor.paper import PaperExecutor from bot.metrics.tracker import MetricsTracker from bot.data.db import Database logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s", ) log = logging.getLogger("bot.main") PAPER_MODE = os.getenv("PAPER_MODE", "true").lower() == "true" PAPER_BANKROLL = float(os.getenv("PAPER_BANKROLL", "10000")) async def run_trading_loop( poly: PolymarketClient, external: ExternalDataClient, strategy: BayesianStrategy, risk: RiskManager, executor: PaperExecutor, metrics: MetricsTracker, ) -> None: """Main trading loop — runs every 60 seconds.""" log.info("Trading loop started. PAPER_MODE=%s", PAPER_MODE) while True: try: # 1. Fetch active crypto/finance markets markets = await poly.get_active_markets() log.info("Found %d active markets", len(markets)) for _m in markets: log.info(" [market] %s | ends: %s | yes_price: %.3f", _m.question, _m.end_date, _m.yes_price) # 2. Get external signals ext_data = await external.get_all_signals() for market in markets: # 3. Estimate true probability signal = await strategy.evaluate(market, ext_data) if signal is None: continue log.info( "Signal: market=%s poly_price=%.3f our_estimate=%.3f confidence=%.2f", market.question[:50], signal.polymarket_price, signal.estimated_prob, signal.confidence, ) # 4. Risk check + position sizing order = risk.size_order(signal, executor.get_portfolio()) if order is None: log.debug("Risk manager rejected order for %s", market.id) continue # 5. Execute (paper or real) trade = await executor.execute(order) if trade: await metrics.record_trade(trade) log.info("Trade executed: %s", trade) # 6. Update daily metrics await metrics.update_daily_summary() except Exception as e: log.error("Error in trading loop: %s", e, exc_info=True) await asyncio.sleep(60) async def main() -> None: if PAPER_MODE: log.info("=" * 60) log.info(" PAPER TRADING MODE — No real money at risk") log.info(" Bankroll: $%.2f simulated", PAPER_BANKROLL) log.info("=" * 60) else: log.warning("REAL TRADING MODE ACTIVE — Real money at risk!") db = Database() await db.connect() await db.run_migrations() poly = PolymarketClient() external = ExternalDataClient() strategy = BayesianStrategy() risk = RiskManager(max_position_pct=0.05, max_exposure_pct=0.30) executor = PaperExecutor(db=db, bankroll=PAPER_BANKROLL) if PAPER_MODE else None metrics = MetricsTracker(db=db) if executor is None: # Import real executor only when explicitly needed from bot.executor.real import RealExecutor # noqa executor = RealExecutor(db=db) if PAPER_MODE: await executor.initialize() try: await run_trading_loop(poly, external, strategy, risk, executor, metrics) finally: await db.disconnect() if __name__ == "__main__": asyncio.run(main())