Files
polymarket-bot/bot/main.py
T
2026-04-13 16:05:45 +00:00

121 lines
3.8 KiB
Python

"""
Polymarket Trading Bot — Main Entry Point
"""
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())