Бот для автоматической торговли на погодных рынках Polymarket. Сканирует температурные рынки по 60 городам, прогнозирует через Open-Meteo/WeatherAPI, находит edge и размещает лимитные ордера через CLOB API.
/home/app/polymarket-weather-bot/
| Файл | Назначение |
|---|---|
bot.py |
Точка входа: FastAPI + APScheduler, веб-дашборд |
scanner.py |
Gamma API — находит активные погодные рынки (49 highest + 8 lowest temp) |
forecaster.py |
Open-Meteo/WeatherAPI — прогноз + вероятностная модель (norm CDF) |
analyzer.py |
Поиск edge: model_prob vs market_price, тиры weak/medium/strong |
executor.py |
CLOB ордера через py-clob-client, retry + idempotency guard |
resolver.py |
Resolution: фактическая погода → outcome → P&L |
risk.py |
Kill switch, лимиты позиций, cooldown, max daily loss |
db.py |
SQLite: thread-local connections, WAL, миграции |
config.py |
Все настройки + CITY_COORDS (единый источник городов) |
cancel_stale.py |
Утилита отмены старых ордеров |
Основные переменные в .env и config.py:
| Параметр | Текущее | Описание |
|---|---|---|
| DRY_RUN | false | LIVE — реальные ордера |
| BET_SIZE | $1.0 | Базовый размер ставки (реальный min ~$3.50) |
| BANKROLL | $25 | Банкролл для risk limits |
| DASH_USER | rick | Basic Auth логин дашборда |
| DASH_PASS | wb2026secure | Basic Auth пароль дашборда |
| KELLY_BANKROLL | $25 | Банкролл для Kelly sizing ($1.33-$3 ставки) |
| MIN_EDGE | 8% | Минимальный edge (with k=5 shrinkage, sweet spot 8-18%) |
| MAX_EDGE | 18% | Максимальный edge (18%+ = model disagrees too much) |
| BLOCK_YES_SIDE | true | YES заблокирован (42.9% WR, -$13.49) |
| MIN_BUY_PRICE | $0.72 | Мин цена покупки (<72¢ = 55-68% WR) |
| MAX_BUY_PRICE | $0.85 | Макс цена покупки (>85¢ R:R < 0.18:1) |
| MIN_VOLUME | $1000 | Минимальный объём рынка |
| SCAN_INTERVAL_SEC | 1800 | Сканирование каждые 30 мин (1 round/day) |
| RESOLVE_CHECK_SEC | 1800 | Проверка resolution каждые 30 мин |
| MAX_DAILY_LOSS | $20 | Kill switch при дневном убытке |
| MAX_OPEN_POSITIONS | 10 | Максимум открытых позиций (макс ~$30 deployed) |
# PM2
pm2 restart weather-bot
pm2 logs weather-bot --lines 30
pm2 monit
# Дашборд
https://dashboard.szhub.space/weather-bot/
# API endpoints
GET /api/status # Статус бота
GET /api/trades # Список трейдов
GET /api/markets # Активные рынки
GET /api/stats/today # Статистика дня
GET /api/stats/history # Исторические данные
GET /api/stats/resolution # Результаты resolution
POST /api/scan # Запуск сканирования
POST /api/resolve # Запуск resolution
SQLite: /home/app/polymarket-weather-bot/data/weather-bot.db
Таблицы: markets, trades, forecasts, daily_stats, bot_state, forecast_cache
Миграции — автоматические через _run_migrations() в db.py при старте.
| Кошелёк | Адрес | Роль |
|---|---|---|
| EOA | 0x1aec730EDA0EC7BCcF2bbA5D14aa809c8AA722d1 |
Подписывает транзакции |
| Gnosis Safe | 0x3643914646900cA7A5df15B8f5d1Cc5E32728c1a |
wc.address, SIGNATURE_TYPE=2, держит USDC.e |
| Poly Proxy | 0x1566a0dF379873C559cFf9Cf35C9e77EB30F5627 |
counterfactual, wc.get_poly_proxy_address() |
Collateral flow (CLOB V2, после 28 Apr 2026):
wrap_usdc_to_pusd() в executor.py: Safe → Collateral Onramp (0x93070a...) → pUSDrecover_proxy_usdc(): sweep USDC с Poly Proxy на Safe через ProxyFactory.proxy()⚠️ Грабли:
transfer_usdc() туда = деньги зависаютupdate_balance_allowance() НЕ синхронизирует CLOB balance с on-chaindatabase is locked. НЕ вызывать conn.close() — thread-local переиспользуетm.date < date('now'), не <=first_seen не теряется при обновлении маркетовZoneInfo(city_tz) вместо UTC, предотвращает off-by-one для Tokyo/Seoul/Aucklandcleanup_old_forecasts(7) при каждом скане, предотвращает DB bloatshares * 0.02 * price * (1-price)shares * price (MIN_SHARES=5 может увеличить стоимость)asyncio.to_thread + 60s cache, не блокирует event loop| Файл | Описание |
|---|---|
docs/COMPETITIVE_ANALYSIS.md |
Конкурентный анализ: 15 конкурентов, SWOT, actionable выводы |
docs/SCREENER_SPEC.md |
Спека Polymarket Screener (5-я вкладка) |
docs/DEVELOPER_PROGRAM.md |
Builder Program ресёрч, SaaS стратегия |
config.py → CITY_COORDS (slug, lat, lon, tz, name)scanner.py → POLYMARKET_CITIES (и/или LOWEST_TEMP_CITIES)CITIES_BY_NAME сгенерируется автоматически.env: DRY_RUN=falsePRIVATE_KEY, PROXY_ADDRESS, TRADE_PROXYpm2 restart weather-botcd /home/app/polymarket-weather-bot && source venv/bin/activate
python -c "from resolver import get_resolution_stats; import json; print(json.dumps(get_resolution_stats(), indent=2))"
В db.py → _run_migrations() добавить tuple в список migrations:
("table_name", "column_name", "COLUMN_TYPE"),
github.com/Zserg5585/polymarket-weather-bot (private)origin с PAT в URL (паттерн как у futures-screener/knowledge-base).gitignore прикрывает: .env, .env.bak*, .env.* (кроме .env.example), venv/, *.db, logs/.env (gitignored). BUILDER_CODE в executor.py — публичный, не ключgit push origin master (токен уже в remote URL)