폴리마켓 날씨 트레이딩 봇 with Claude
Wikiprompt, 무료 프롬프트 백과사전에서
폴리마켓 날씨 트레이딩 봇 with Claude 폴리마켓 날씨 시장에서 NOAA 예보와 켈리 기준 포지션 크기를 사용해 거래하는 Python 봇을 생성하기 위한 상세한 프롬프트입니다.
프롬프트 내용저장
🌐
# config.py
CITIES = {
"NYC": {"station": "KLGA", "name": "LaGuardia"},
"Chicago": {"station": "KMDW", "name": "Midway"},
"Miami": {"station": "KMIA", "name": "Miami Intl"},
"LA": {"station": "KLAX", "name": "Los Angeles Intl"},
"Dallas": {"station": "KDAL", "name": "Love Field"},
}
EDGE_THRESHOLD = 0.08 # 8% minimum edge
KELLY_FRACTION = 0.15 # 15% fractional Kelly
MAX_POSITION_SIZE = 50.0 # USD cap per trade
POLL_INTERVAL_HOURS = 1
API_BASE = "https://clob.polymarket.com"
OPEN_METEO_BASE = "https://api.open-meteo.com/v1/forecast"
```
```python
# weather_bot.py
import json
import logging
import math
import time
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Tuple
import requests
import pandas as pd
import numpy as np
from scipy import stats
import config
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
handlers=[
logging.FileHandler("weather_bot.log"),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
class PolymarketWeatherBot:
def __init__(self):
self.config = config
self.session = requests.Session()
self.positions = {} # market_id -> position info
self.pnl = 0.0
self.trade_log = []
def get_active_temperature_markets(self) -> List[Dict]:
"""Fetch active temperature markets from Polymarket CLOB API."""
url = f"{self.config.API_BASE}/markets"
params = {
"active": "true",
"closed": "false",
"limit": 100,
"tag": "weather"
}
try:
resp = self.session.get(url, params=params, timeout=30)
resp.raise_for_status()
markets = resp.json()
# Filter for temperature-related markets
temp_markets = [
m for m in markets
if "temperature" in m.get("question", "").lower()
or "high" in m.get("question", "").lower()
or "low" in m.get("question", "").lower()
]
logger.info(f"Found {len(temp_markets)} active temperature markets")
return temp_markets
except Exception as e:
logger.error(f"Failed to fetch markets: {e}")
return []
def parse_market_details(self, market: Dict) -> Tuple[Optional[str], Optional[str]]:
"""Extract city and date from market question."""
question = market.get("question", "")
# Example: "What will the high temperature be in NYC on 2024-03-15?"
for city_key, city_info in self.config.CITIES.items():
if city_key.lower() in question.lower() or city_info["name"].lower() in question.lower():
# Try to extract date
for word in question.split():
if len(word) == 10 and word[4] == "-" and word[7] == "-":
try:
datetime.strptime(word, "%Y-%m-%d")
return city_key, word
except ValueError:
continue
# If no date found, assume tomorrow
return city_key, (datetime.now() + timedelta(days=1)).strftime("%Y-%m-%d")
return None, None
def get_gfs_ensemble_forecast(self, city_key: str, date_str: str) -> Optional[np.ndarray]:
"""Fetch 31-member GFS ensemble forecast for a city."""
city_info = self.config.CITIES[city_key]
station = city_info["station"]
# Open-Meteo ensemble API
params = {
"latitude": self._get_city_coords(city_key)[0],
"longitude": self._get_city_coords(city_key)[1],
"hourly": "temperature_2m",
"models": "gfs_seamless",
"ensemble": "true",
"past_days": "0",
"forecast_days": "7",
"timezone": "UTC"
}
try:
resp = self.session.get(self.config.OPEN_METEO_BASE, params=params, timeout=30)
resp.raise_for_status()
data = resp.json()
# Extract ensemble members for the target date
target_date = datetime.strptime(date_str, "%Y-%m-%d")
hourly_data = data.get("hourly", {})
times = hourly_data.get("time", [])
# Find indices for target date (daily max)
daily_maxes = []
for member_idx in range(31): # 31 ensemble members
member_key = f"temperature_2m_{member_idx}" if member_idx > 0 else "temperature_2m"
if member_key not in hourly_data:
continue
temps = hourly_data[member_key]
day_temps = []
for i, t in enumerate(times):
dt = datetime.fromisoformat(t)
if dt.date() == target_date.date():
day_temps.append(temps[i])
if day_temps:
daily_maxes.append(max(day_temps))
if daily_maxes:
return np.array(daily_maxes)
return None
except Exception as e:
logger.error(f"Failed to fetch forecast for {city_key}: {e}")
return None
def _get_city_coords(self, city_key: str) -> Tuple[float, float]:
"""Get coordinates for a city (approximate, for forecast)."""
coords = {
"NYC": (40.7128, -74.0060),
"Chicago": (41.8781, -87.6298),
"Miami": (25.7617, -80.1918),
"LA": (34.0522, -118.2437),
"Dallas": (32.7767, -96.7970)
}
return coords.get(city_key, (0, 0))
def calculate_bucket_probabilities(self, ensemble_forecast: np.ndarray, market: Dict) -> Dict[str, float]:
"""Calculate probability for each price bucket based on ensemble."""
# Parse market outcomes/buckets
outcomes = market.get("outcomes", [])
if not outcomes:
return {}
# Convert outcomes to numeric buckets
buckets = []
for outcome in outcomes:
try:
# Handle formats like ">=80", "<70", "75-80", "75"
if ">=" in outcome:
lower = int(outcome.replace(">=", ""))
buckets.append((lower, float('inf')))
elif "<" in outcome:
upper = int(outcome.replace("<", ""))
buckets.append((-float('inf'), upper))
elif "-" in outcome:
parts = outcome.split("-")
buckets.append((int(parts[0]), int(parts[1])))
else:
val = int(outcome)
buckets.append((val, val))
except (ValueError, IndexError):
continue
if not buckets:
return {}
# Fit normal distribution to ensemble
mu = np.mean(ensemble_forecast)
sigma = np.std(ensemble_forecast)
# Calculate probabilities for each bucket
probabilities = {}
for i, (lower, upper) in enumerate(buckets):
if upper == float('inf'):
prob = 1 - stats.norm.cdf(lower, mu, sigma)
elif lower == -float('inf'):
prob = stats.norm.cdf(upper, mu, sigma)
else:
prob = stats.norm.cdf(upper, mu, sigma) - stats.norm.cdf(lower, mu, sigma)
probabilities[outcomes[i]] = max(0.0, min(1.0, prob))
return probabilities
def calculate_edge(self, calculated_prob: float, market_price: float) -> float:
"""Calculate edge as difference between calculated probability and market price."""
return calculated_prob - (market_price / 100.0)
def kelly_criterion(self, prob: float, price: float, fraction: float = 0.15) -> float:
"""Calculate Kelly criterion position size."""
# Convert price to decimal odds
odds = 1.0 / (price / 100.0)
# Kelly formula: f* = (bp - q) / b
# where b = odds - 1, p = probability, q = 1 - p
b = odds - 1
p = prob
q = 1 - p
if b <= 0:
return 0
kelly = (b * p - q) / b
return max(0, kelly * fraction)
def place_order(self, market_id: str, outcome: str, size: float, price: int) -> bool:
"""Place a buy order on Polymarket."""
# This would integrate with Polymarket's CLOB API
# For demo purposes, we just log it
logger.info(f"PLACE ORDER: market={market_id}, outcome={outcome}, size=${size:.2f}, price={price}¢")
# Simulate order placement
order = {
"market_id": market_id,
"outcome": outcome,
"size": size,
"price": price,
"timestamp": datetime.now().isoformat()
}
# Store position
self.positions[market_id] = {
"outcome": outcome,
"size": size,
"entry_price": price,
"entry_time": datetime.now()
}
return True
def check_and_close_positions(self, markets: List[Dict]) -> None:
"""Check if any positions have resolved and update P&L."""
for market in markets:
market_id = market.get("id")
if market_id in self.positions:
if market.get("closed"):
position = self.positions.pop(market_id)
# Calculate P&L based on resolution
winning_outcome = market.get("winning_outcome")
if winning_outcome == position["outcome"]:
profit = position["size"] * (100 - position["entry_price"]) / 100
self.pnl += profit
logger.info(f"POSITION WON: market={market_id}, profit=${profit:.2f}")
else:
loss = position["size"]
self.pnl -= loss
logger.info(f"POSITION LOST: market={market_id}, loss=${loss:.2f}")
def log_trade(self, market_id: str, forecast: np.ndarray, market_price: float,
calc_prob: float, edge: float) -> None:
"""Log trade details."""
trade_entry = {
"timestamp": datetime.now().isoformat(),
"market_id": market_id,
"forecast_mean": float(np.mean(forecast)),
"forecast_std": float(np.std(forecast)),
"market_price": market_price,
"calculated_probability": calc_prob,
"edge_percentage": edge * 100
}
self.trade_log.append(trade_entry)
logger.info(f"TRADE LOG: {json.dumps(trade_entry)}")
def run(self) -> None:
"""Main bot loop."""
logger.info("Starting Polymarket Weather Bot")
while True:
try:
# 1. Fetch active markets
markets = self.get_active_temperature_markets()
# 9. Check for resolved positions
self.check_and_close_positions(markets)
# 2-6. Process each market
for market in markets:
city, date_str = self.parse_market_details(market)
if not city or not date_str:
continue
# 3. Get ensemble forecast
forecast = self.get_gfs_ensemble_forecast(city, date_str)
if forecast is None:
continue
# 4. Calculate probabilities
probabilities = self.calculate_bucket_probabilities(forecast, market)
if not probabilities:
continue
# 5-6. Compare and trade
for outcome, calc_prob in probabilities.items():
# Get market price for this outcome
outcome_data = market.get("outcomePrices", [])
if not outcome_data:
continue
try:
market_price = float(outcome_data[market["outcomes"].index(outcome)]) * 100
except (ValueError, IndexError):
continue
# 5. Calculate edge
edge = self.calculate_edge(calc_prob, market_price)
# 6. Trade if edge > threshold
if edge > self.config.EDGE_THRESHOLD:
# 6. Kelly sizing
kelly_size = self.kelly_criterion(
calc_prob, market_price, self.config.KELLY_FRACTION
)
# 7. Cap position size
position_size = min(kelly_size * 100, self.config.MAX_POSITION_SIZE)
if position_size > 0:
# 8. Log trade
self.log_trade(
market["id"], forecast, market_price, calc_prob, edge
)
# Place order
self.place_order(
market["id"], outcome, position_size, int(market_price)
)
# Sleep until next poll
logger.info(f"Sleeping for {self.config.POLL_INTERVAL_HOURS} hour(s)")
time.sleep(self.config.POLL_INTERVAL_HOURS * 3600)
except KeyboardInterrupt:
logger.info("Bot stopped by user")
break
except Exception as e:
logger.error(f"Unexpected error: {e}")
time.sleep(60)
if __name__ == "__main__":
bot = PolymarketWeatherBot()
bot.run()
전체 프롬프트를 보려면 로그인하세요
Continue with:
By logging in, you agree to our Terms of Use and Privacy Policy
사용법
이 프롬프트는 coding와 함께 사용하도록 설계되었습니다. 위의 프롬프트 내용을 복사하여 원하는 AI 도구에 붙여넣으세요.
최상의 결과를 얻으려면 자리 표시자(대괄호 또는 대문자로 표시)를 특정 요구 사항으로 사용자 지정할 수 있습니다.
토론
댓글 0개