diff --git a/bot.py b/bot.py index e36850f..54ab73f 100644 --- a/bot.py +++ b/bot.py @@ -1,6 +1,7 @@ from __future__ import annotations import datetime as dt +from http import client import json import time import uuid @@ -19,22 +20,37 @@ def _parse_iso_z(s: str) -> dt.datetime: # Example: "2023-11-07T05:31:56Z" return dt.datetime.fromisoformat(s.replace("Z", "+00:00")) +def discover_open_crypto_15m_markets(client: KalshiClient, symbols: list[str]) -> dict[str, dict]: + """ + Discover open 15-minute crypto markets by scanning open markets directly. + Returns mapping: symbol -> market_dict (nearest close) + """ + data = client.get_markets(series_ticker=None, status="open", limit=500) + markets = data.get("markets", []) -def discover_crypto_15m_series(client: KalshiClient, category: str, title_contains: str, symbols: List[str]) -> Dict[str, str]: - """ - Returns mapping symbol -> series_ticker by scanning /series?category=crypto. - """ - data = client.get_series_list(category=category) - series = data.get("series", []) - out: Dict[str, str] = {} - for s in series: - title = (s.get("title") or "").upper() - if title_contains.upper() not in title: + now = dt.datetime.now(dt.timezone.utc) + per_symbol: dict[str, dict] = {} + + for m in markets: + title = (m.get("title") or "").upper() + if "UP OR DOWN" not in title: continue + if "15" not in title: + continue + for sym in symbols: - if sym.upper() in title and sym.upper() not in out: - out[sym.upper()] = s["ticker"] - return out + if sym.upper() not in title: + continue + + close_time = _parse_iso_z(m["close_time"]) + if close_time <= now: + continue + + prev = per_symbol.get(sym) + if prev is None or close_time < _parse_iso_z(prev["close_time"]): + per_symbol[sym] = m + + return per_symbol def choose_current_market(client: KalshiClient, series_ticker: str) -> Optional[dict]: @@ -92,12 +108,6 @@ def main() -> None: mode = cfg["mode"] client = KalshiClient.from_env() - series_map = discover_crypto_15m_series( - client, - category=cfg["category"], - title_contains=cfg["series_title_contains"], - symbols=cfg["symbols"], - ) if len(series_map) == 0: raise RuntimeError("Could not discover any matching 15-min crypto series. Check title/category filters.") @@ -125,11 +135,12 @@ def main() -> None: now = dt.datetime.now(dt.timezone.utc) - for sym, series_ticker in series_map.items(): - try: - m = choose_current_market(client, series_ticker) - if not m: - continue + symbols = cfg["symbols"] + + markets_by_symbol = discover_open_crypto_15m_markets(client, symbols) + + for sym, m in markets_by_symbol.items(): + market_ticker = m["ticker"] close_time = _parse_iso_z(m["close_time"])