feat: Add Polymarket API client for enhanced market price fetching and include local time in bot output.
This commit is contained in:
+6
-1
@@ -170,10 +170,15 @@ def start_bot():
|
|||||||
lock_status = "⚖️均衡"
|
lock_status = "⚖️均衡"
|
||||||
confidence = "📊"
|
confidence = "📊"
|
||||||
|
|
||||||
|
# 提取修复后的精确当地时间
|
||||||
|
local_time = s.get("local_time", "")
|
||||||
|
time_only = local_time.split(" ")[1] if " " in local_time else ""
|
||||||
|
time_suffix = f" | 🕒{time_only}" if time_only else ""
|
||||||
|
|
||||||
msg_lines.append(
|
msg_lines.append(
|
||||||
f"{confidence} <b>{i}. {city} {option}</b>\n"
|
f"{confidence} <b>{i}. {city} {option}</b>\n"
|
||||||
f" 💡 {analysis}\n"
|
f" 💡 {analysis}\n"
|
||||||
f" 📊 {direction} | {lock_status}\n"
|
f" 📊 {direction} | {lock_status}{time_suffix}\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
bot.send_message(message.chat.id, "\n".join(msg_lines), parse_mode="HTML")
|
bot.send_message(message.chat.id, "\n".join(msg_lines), parse_mode="HTML")
|
||||||
|
|||||||
@@ -246,20 +246,34 @@ def main():
|
|||||||
# --- 价格获取逻辑 ---
|
# --- 价格获取逻辑 ---
|
||||||
buy_yes_price = market.get("buy_yes_live")
|
buy_yes_price = market.get("buy_yes_live")
|
||||||
buy_no_price = market.get("buy_no_live")
|
buy_no_price = market.get("buy_no_live")
|
||||||
current_price = 0.5
|
|
||||||
gamma_prices = market.get("prices", [])
|
# 如果批量接口没拿到,尝试单独查询 orderbook
|
||||||
if isinstance(gamma_prices, str):
|
if buy_yes_price is None or buy_no_price is None:
|
||||||
try:
|
ts = market.get("tokens", [])
|
||||||
gamma_prices = json.loads(gamma_prices)
|
if isinstance(ts, str):
|
||||||
except:
|
try:
|
||||||
gamma_prices = []
|
ts = json.loads(ts)
|
||||||
if gamma_prices and len(gamma_prices) > 0:
|
except:
|
||||||
current_price = float(gamma_prices[0])
|
ts = []
|
||||||
|
if ts and len(ts) >= 2:
|
||||||
if buy_yes_price is None:
|
prices = polymarket.get_buy_prices(ts[0], ts[1])
|
||||||
buy_yes_price = current_price
|
if prices:
|
||||||
if buy_no_price is None:
|
buy_yes_price = prices.get("buy_yes")
|
||||||
buy_no_price = 1.0 - current_price
|
buy_no_price = prices.get("buy_no")
|
||||||
|
|
||||||
|
# 最后回退:使用 gamma 概率
|
||||||
|
if buy_yes_price is None or buy_no_price is None:
|
||||||
|
gamma_prices = market.get("prices", [])
|
||||||
|
if isinstance(gamma_prices, str):
|
||||||
|
try:
|
||||||
|
gamma_prices = json.loads(gamma_prices)
|
||||||
|
except:
|
||||||
|
gamma_prices = []
|
||||||
|
current_price = float(gamma_prices[0]) if gamma_prices else 0.5
|
||||||
|
if buy_yes_price is None:
|
||||||
|
buy_yes_price = current_price
|
||||||
|
if buy_no_price is None:
|
||||||
|
buy_no_price = 1.0 - current_price
|
||||||
|
|
||||||
# C. 准备缓存
|
# C. 准备缓存
|
||||||
temp_unit = weather_data.get("open-meteo", {}).get(
|
temp_unit = weather_data.get("open-meteo", {}).get(
|
||||||
@@ -454,7 +468,7 @@ def main():
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
final_signals.update(cached_signals)
|
final_signals.update(all_markets_cache)
|
||||||
|
|
||||||
with open("data/active_signals.json", "w", encoding="utf-8") as f:
|
with open("data/active_signals.json", "w", encoding="utf-8") as f:
|
||||||
json.dump(final_signals, f, ensure_ascii=False, indent=2)
|
json.dump(final_signals, f, ensure_ascii=False, indent=2)
|
||||||
|
|||||||
@@ -107,7 +107,8 @@ class PolymarketClient:
|
|||||||
return float(book["bids"][0].get("price"))
|
return float(book["bids"][0].get("price"))
|
||||||
|
|
||||||
# 如果 orderbook 拿不到,尝试直接查 price 接口
|
# 如果 orderbook 拿不到,尝试直接查 price 接口
|
||||||
res = self._request("GET", "/price", params={"token_id": token_id})
|
side_val = "SELL" if side == "ask" else "BUY"
|
||||||
|
res = self._request("GET", "/price", params={"token_id": token_id, "side": side_val})
|
||||||
if res and isinstance(res, dict) and "price" in res:
|
if res and isinstance(res, dict) and "price" in res:
|
||||||
return float(res["price"])
|
return float(res["price"])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -202,19 +203,30 @@ class PolymarketClient:
|
|||||||
for i in range(0, len(token_requests), 50):
|
for i in range(0, len(token_requests), 50):
|
||||||
batch = token_requests[i : i + 50]
|
batch = token_requests[i : i + 50]
|
||||||
# 构建用于请求的 json 对象
|
# 构建用于请求的 json 对象
|
||||||
payload = [{"token_id": r["token_id"], "side": "buy"} for r in batch]
|
# side 映射: ask -> SELL (我们要买入就要看卖单), bid -> BUY (我们要卖出就要看买单)
|
||||||
|
payload = []
|
||||||
|
for r in batch:
|
||||||
|
side_val = "SELL" if r.get("side") == "ask" else "BUY"
|
||||||
|
payload.append({"token_id": r["token_id"], "side": side_val})
|
||||||
|
|
||||||
response = self.session.post(url, json=payload, timeout=20)
|
response = self.session.post(url, json=payload, timeout=20)
|
||||||
|
logger.debug(f"批量价格请求: 状态码={response.status_code}, 返回数据={response.text[:200]}")
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
results = response.json()
|
results = response.json()
|
||||||
# 结果通常是 { "token_id": "price", ... }
|
# 结果通常是 { "token_id": "price", ... } 或 [{ "token_id": "...", "price": "..." }, ...]
|
||||||
if isinstance(results, dict):
|
if isinstance(results, dict):
|
||||||
for tid, p in results.items():
|
for tid, p in results.items():
|
||||||
all_prices[tid] = float(p)
|
all_prices[tid] = float(p)
|
||||||
|
elif isinstance(results, list):
|
||||||
|
for item in results:
|
||||||
|
if "token_id" in item and "price" in item:
|
||||||
|
all_prices[item["token_id"]] = float(item["price"])
|
||||||
|
else:
|
||||||
|
logger.warning(f"批量价格返回非dict格式: {type(results)}")
|
||||||
|
|
||||||
return all_prices
|
return all_prices
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug(f"批量获取盘口价格失败: {e}")
|
logger.warning(f"批量获取盘口价格失败: {e}")
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def get_midpoint(self, token_id: str) -> Optional[float]:
|
def get_midpoint(self, token_id: str) -> Optional[float]:
|
||||||
|
|||||||
@@ -211,12 +211,22 @@ class WeatherDataCollector:
|
|||||||
data = response.json()
|
data = response.json()
|
||||||
|
|
||||||
current = data.get("current_weather", {})
|
current = data.get("current_weather", {})
|
||||||
|
utc_offset = data.get("utc_offset_seconds", 0)
|
||||||
|
timezone_name = data.get("timezone", "UTC")
|
||||||
|
|
||||||
|
# 计算精确的当地时间而不是气象站 bucket 时间
|
||||||
|
now_utc = datetime.utcnow()
|
||||||
|
local_now = now_utc + timedelta(seconds=utc_offset)
|
||||||
|
local_time_str = local_now.strftime("%Y-%m-%d %H:%M")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"source": "open-meteo",
|
"source": "open-meteo",
|
||||||
"timestamp": datetime.utcnow().isoformat(),
|
"timestamp": now_utc.isoformat(),
|
||||||
|
"timezone": timezone_name,
|
||||||
|
"utc_offset": utc_offset,
|
||||||
"current": {
|
"current": {
|
||||||
"temp": current.get("temperature"),
|
"temp": current.get("temperature"),
|
||||||
"local_time": current.get("time", "").replace("T", " "),
|
"local_time": local_time_str,
|
||||||
},
|
},
|
||||||
"daily": data.get("daily", {}),
|
"daily": data.get("daily", {}),
|
||||||
"unit": "fahrenheit" if use_fahrenheit else "celsius",
|
"unit": "fahrenheit" if use_fahrenheit else "celsius",
|
||||||
|
|||||||
Reference in New Issue
Block a user