← Назад"""Weather Bot Configuration"""
import os
from dotenv import load_dotenv
load_dotenv()
# === Server ===
PORT = int(os.getenv("PORT", 3201))
HOST = os.getenv("HOST", "0.0.0.0")
# === Polymarket Wallet ===
PRIVATE_KEY = os.getenv("PRIVATE_KEY", "")
PROXY_ADDRESS = os.getenv("PROXY_ADDRESS", "")
SIGNATURE_TYPE = int(os.getenv("SIGNATURE_TYPE", 2))
CHAIN_ID = 137 # Polygon
# === Bot Settings ===
DRY_RUN = os.getenv("DRY_RUN", "true").lower() == "true"
BET_SIZE = float(os.getenv("BET_SIZE", 1.0))
BANKROLL = float(os.getenv("BANKROLL", 100))
MAX_DAILY_LOSS = float(os.getenv("MAX_DAILY_LOSS", 20))
MAX_OPEN_POSITIONS = int(os.getenv("MAX_OPEN_POSITIONS", 20))
MAX_PER_MARKET = float(os.getenv("MAX_PER_MARKET", 5))
MIN_EDGE = float(os.getenv("MIN_EDGE", 0.08)) # 8% (was 5% — too many false signals)
MIN_VOLUME = float(os.getenv("MIN_VOLUME", 1000))
COOLDOWN_SAME_MARKET = 3600 # 1 hour
MIN_PRICE = float(os.getenv("MIN_PRICE", 0.05)) # Don't bid below 5¢ — orders never fill
KELLY_FRACTION = float(os.getenv("KELLY_FRACTION", 0.20)) # Fractional Kelly (20% = conservative)
MIN_BET = float(os.getenv("MIN_BET", 1.0)) # Minimum bet size in $
MAX_ENSEMBLE_STD = float(os.getenv("MAX_ENSEMBLE_STD", 7.0)) # Skip if ensemble spread > 7°F (no consensus)
MAX_SLIPPAGE = float(os.getenv("MAX_SLIPPAGE", 0.03)) # Max spread (yes+no deviation from 1.0) — 3¢
# === Scan Intervals ===
SCAN_INTERVAL_SEC = 900 # scan markets every 15 min (49 cities = ~200 API calls)
RESOLVE_CHECK_SEC = 600 # check resolutions every 10 min
RESOLVE_MIN_HOURS = int(os.getenv("RESOLVE_MIN_HOURS", 18)) # Wait N hours after market date ends before resolving (Open-Meteo archive needs time to finalize)
SUMMARY_HOUR = 23 # daily summary at 23:00
SUMMARY_MINUTE = 59
# === Probability Model ===
# Uncertainty (sigma) in °F by days ahead
# Based on NWS MAE data: same-day ~2.5F, day-1 ~3F, day-2 ~3.5F, day-3 ~4F
# Sigma ≈ MAE × 1.25 to account for tails
SIGMA_BY_DAYS = {
0: 3.0, # same day (was 1.5 — too tight, caused overconfidence)
1: 3.5, # was 2.0
2: 4.0, # was 2.5
3: 5.0, # was 4.0
4: 5.5, # was 4.0
5: 6.0, # was 4.5
}
DEFAULT_SIGMA = 7.0 # 6+ days ahead (was 6.0)
# === Edge Thresholds ===
EDGE_TIERS = [
{"min_edge": 0.20, "label": "strong", "bet_multiplier": 3.0},
{"min_edge": 0.10, "label": "medium", "bet_multiplier": 2.0},
{"min_edge": 0.05, "label": "weak", "bet_multiplier": 1.0},
]
# === Cities → Coordinates (single source of truth) ===
# Keyed by Polymarket slug. Used by scanner, forecaster, resolver.
CITY_COORDS = {
"nyc": {"lat": 40.71, "lon": -74.01, "tz": "America/New_York", "name": "New York City"},
"london": {"lat": 51.51, "lon": -0.13, "tz": "Europe/London", "name": "London"},
"seoul": {"lat": 37.57, "lon": 126.98, "tz": "Asia/Seoul", "name": "Seoul"},
"tokyo": {"lat": 35.68, "lon": 139.69, "tz": "Asia/Tokyo", "name": "Tokyo"},
"paris": {"lat": 48.86, "lon": 2.35, "tz": "Europe/Paris", "name": "Paris"},
"miami": {"lat": 25.76, "lon": -80.19, "tz": "America/New_York", "name": "Miami"},
"toronto": {"lat": 43.65, "lon": -79.38, "tz": "America/Toronto", "name": "Toronto"},
"hong-kong": {"lat": 22.32, "lon": 114.17, "tz": "Asia/Hong_Kong", "name": "Hong Kong"},
"moscow": {"lat": 55.76, "lon": 37.62, "tz": "Europe/Moscow", "name": "Moscow"},
"houston": {"lat": 29.76, "lon": -95.37, "tz": "America/Chicago", "name": "Houston"},
"denver": {"lat": 39.74, "lon": -104.99, "tz": "America/Denver", "name": "Denver"},
"shanghai": {"lat": 31.23, "lon": 121.47, "tz": "Asia/Shanghai", "name": "Shanghai"},
"wuhan": {"lat": 30.59, "lon": 114.31, "tz": "Asia/Shanghai", "name": "Wuhan"},
"ankara": {"lat": 39.93, "lon": 32.86, "tz": "Europe/Istanbul", "name": "Ankara"},
"warsaw": {"lat": 52.23, "lon": 21.01, "tz": "Europe/Warsaw", "name": "Warsaw"},
"munich": {"lat": 48.14, "lon": 11.58, "tz": "Europe/Berlin", "name": "Munich"},
"amsterdam": {"lat": 52.37, "lon": 4.90, "tz": "Europe/Amsterdam", "name": "Amsterdam"},
"tel-aviv": {"lat": 32.09, "lon": 34.78, "tz": "Asia/Jerusalem", "name": "Tel Aviv"},
"madrid": {"lat": 40.42, "lon": -3.70, "tz": "Europe/Madrid", "name": "Madrid"},
"los-angeles": {"lat": 34.05, "lon": -118.24, "tz": "America/Los_Angeles", "name": "Los Angeles"},
"chicago": {"lat": 41.88, "lon": -87.63, "tz": "America/Chicago", "name": "Chicago"},
"seattle": {"lat": 47.61, "lon": -122.33, "tz": "America/Los_Angeles", "name": "Seattle"},
"san-francisco": {"lat": 37.77, "lon": -122.42, "tz": "America/Los_Angeles", "name": "San Francisco"},
"sydney": {"lat": -33.87, "lon": 151.21, "tz": "Australia/Sydney", "name": "Sydney"},
"mumbai": {"lat": 19.08, "lon": 72.88, "tz": "Asia/Kolkata", "name": "Mumbai"},
"berlin": {"lat": 52.52, "lon": 13.41, "tz": "Europe/Berlin", "name": "Berlin"},
"rome": {"lat": 41.90, "lon": 12.50, "tz": "Europe/Rome", "name": "Rome"},
"bangkok": {"lat": 13.76, "lon": 100.50, "tz": "Asia/Bangkok", "name": "Bangkok"},
"singapore": {"lat": 1.35, "lon": 103.82, "tz": "Asia/Singapore", "name": "Singapore"},
"dubai": {"lat": 25.20, "lon": 55.27, "tz": "Asia/Dubai", "name": "Dubai"},
"beijing": {"lat": 39.90, "lon": 116.41, "tz": "Asia/Shanghai", "name": "Beijing"},
"osaka": {"lat": 34.69, "lon": 135.50, "tz": "Asia/Tokyo", "name": "Osaka"},
"mexico-city": {"lat": 19.43, "lon": -99.13, "tz": "America/Mexico_City", "name": "Mexico City"},
"buenos-aires": {"lat": -34.60, "lon": -58.38, "tz": "America/Argentina/Buenos_Aires", "name": "Buenos Aires"},
"cairo": {"lat": 30.04, "lon": 31.24, "tz": "Africa/Cairo", "name": "Cairo"},
"lagos": {"lat": 6.52, "lon": 3.38, "tz": "Africa/Lagos", "name": "Lagos"},
"nairobi": {"lat": -1.29, "lon": 36.82, "tz": "Africa/Nairobi", "name": "Nairobi"},
"johannesburg": {"lat": -26.20, "lon": 28.05, "tz": "Africa/Johannesburg", "name": "Johannesburg"},
"sao-paulo": {"lat": -23.55, "lon": -46.63, "tz": "America/Sao_Paulo", "name": "São Paulo"},
"lima": {"lat": -12.05, "lon": -77.04, "tz": "America/Lima", "name": "Lima"},
"atlanta": {"lat": 33.75, "lon": -84.39, "tz": "America/New_York", "name": "Atlanta"},
"austin": {"lat": 30.27, "lon": -97.74, "tz": "America/Chicago", "name": "Austin"},
"busan": {"lat": 35.18, "lon": 129.08, "tz": "Asia/Seoul", "name": "Busan"},
"chongqing": {"lat": 29.56, "lon": 106.55, "tz": "Asia/Shanghai", "name": "Chongqing"},
"chengdu": {"lat": 30.57, "lon": 104.07, "tz": "Asia/Shanghai", "name": "Chengdu"},
"shenzhen": {"lat": 22.54, "lon": 114.06, "tz": "Asia/Shanghai", "name": "Shenzhen"},
"guangzhou": {"lat": 23.13, "lon": 113.26, "tz": "Asia/Shanghai", "name": "Guangzhou"},
"taipei": {"lat": 25.03, "lon": 121.57, "tz": "Asia/Taipei", "name": "Taipei"},
"jakarta": {"lat": -6.21, "lon": 106.85, "tz": "Asia/Jakarta", "name": "Jakarta"},
"manila": {"lat": 14.60, "lon": 120.98, "tz": "Asia/Manila", "name": "Manila"},
"kuala-lumpur": {"lat": 3.14, "lon": 101.69, "tz": "Asia/Kuala_Lumpur", "name": "Kuala Lumpur"},
"helsinki": {"lat": 60.17, "lon": 24.94, "tz": "Europe/Helsinki", "name": "Helsinki"},
"istanbul": {"lat": 41.01, "lon": 28.98, "tz": "Europe/Istanbul", "name": "Istanbul"},
"milan": {"lat": 45.46, "lon": 9.19, "tz": "Europe/Rome", "name": "Milan"},
"jeddah": {"lat": 21.49, "lon": 39.19, "tz": "Asia/Riyadh", "name": "Jeddah"},
"lucknow": {"lat": 26.85, "lon": 80.95, "tz": "Asia/Kolkata", "name": "Lucknow"},
"karachi": {"lat": 24.86, "lon": 67.01, "tz": "Asia/Karachi", "name": "Karachi"},
"panama-city": {"lat": 8.98, "lon": -79.52, "tz": "America/Panama", "name": "Panama City"},
"wellington": {"lat": -41.29, "lon": 174.78, "tz": "Pacific/Auckland", "name": "Wellington"},
"cape-town": {"lat": -33.93, "lon": 18.42, "tz": "Africa/Johannesburg", "name": "Cape Town"},
}
# Auto-generated lookup by city name (lowercase) for resolver
# Maps "new york city" → {lat, lon, tz, name}, "hong kong" → ..., etc.
CITIES_BY_NAME = {data["name"].lower(): data for data in CITY_COORDS.values()}
# === Gamma API ===
GAMMA_API_URL = "https://gamma-api.polymarket.com"
# === Weather APIs ===
# Primary: WeatherAPI.com (1M calls/month free, get key at https://weatherapi.com)
WEATHER_API_KEY = os.getenv("WEATHER_API_KEY", "")
WEATHER_API_URL = "http://api.weatherapi.com/v1/forecast.json"
# Fallback: Open-Meteo (no key, but aggressive rate limits)
OPEN_METEO_URL = "https://api.open-meteo.com/v1/forecast"
# Ensemble API: 51-member GFS for probabilistic forecasts (no key needed)
OPEN_METEO_ENSEMBLE_URL = "https://ensemble-api.open-meteo.com/v1/ensemble"
ENSEMBLE_MODEL = "gfs_seamless" # 31 members (control + member01..member30)
ENSEMBLE_MEMBERS = 31 # temperature_2m (control) + member01..member30
ENSEMBLE_MODEL_ECMWF = "ecmwf_ifs025" # 51 members (control + member01..member50)
# METAR observations (Aviation Weather Center — free, no key)
METAR_API_URL = "https://aviationweather.gov/api/data/metar"
# Forecast cache TTL — weather doesn't change every 15 min
FORECAST_CACHE_TTL = int(os.getenv("FORECAST_CACHE_TTL", 7200)) # 2 hours
# === CLOB API ===
CLOB_API_URL = "https://clob.polymarket.com"
# === Trade Proxy (bypass geoblock) ===
# Supports HTTP, HTTPS, SOCKS5 — e.g. socks5://user:pass@host:port
TRADE_PROXY = os.getenv("TRADE_PROXY", "")
# === Logging ===
LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO")