← Назад
"""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")