Add debug logging for Polymarket market scans
This commit is contained in:
@@ -0,0 +1,84 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import importlib
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any, Dict, Optional
|
||||||
|
|
||||||
|
|
||||||
|
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
if str(PROJECT_ROOT) not in sys.path:
|
||||||
|
sys.path.insert(0, str(PROJECT_ROOT))
|
||||||
|
|
||||||
|
|
||||||
|
def _safe_float(value: Optional[str]) -> Optional[float]:
|
||||||
|
if value is None:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
return float(value)
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _bucket_from_temp(value: Optional[str]) -> Optional[Dict[str, Any]]:
|
||||||
|
temp = _safe_float(value)
|
||||||
|
if temp is None:
|
||||||
|
return None
|
||||||
|
return {
|
||||||
|
"value": temp,
|
||||||
|
"temp": temp,
|
||||||
|
"label": f"{temp:g}°C",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Print a read-only Polymarket market-scan diagnostic payload.",
|
||||||
|
)
|
||||||
|
parser.add_argument("--city", required=True, help="City key or display name.")
|
||||||
|
parser.add_argument("--date", required=True, help="Target date, YYYY-MM-DD.")
|
||||||
|
parser.add_argument(
|
||||||
|
"--bucket-temp",
|
||||||
|
help="Optional model/probability bucket temperature in Celsius.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--model-probability",
|
||||||
|
help="Optional model probability. Accepts 0-1 or 0-100.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--market-slug",
|
||||||
|
help="Optional Polymarket event/market slug.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--debug-log",
|
||||||
|
action="store_true",
|
||||||
|
help="Also enable POLYMARKET_MARKET_SCAN_DEBUG for this process.",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.debug_log:
|
||||||
|
os.environ["POLYMARKET_MARKET_SCAN_DEBUG"] = "true"
|
||||||
|
|
||||||
|
model_probability = _safe_float(args.model_probability)
|
||||||
|
if model_probability is not None and model_probability > 1.0:
|
||||||
|
model_probability = model_probability / 100.0
|
||||||
|
|
||||||
|
module = importlib.import_module("src.data_collection.polymarket_readonly")
|
||||||
|
layer = module.PolymarketReadOnlyLayer()
|
||||||
|
scan = layer.build_market_scan(
|
||||||
|
city=args.city,
|
||||||
|
target_date=args.date,
|
||||||
|
temperature_bucket=_bucket_from_temp(args.bucket_temp),
|
||||||
|
model_probability=model_probability,
|
||||||
|
forced_market_slug=args.market_slug,
|
||||||
|
)
|
||||||
|
|
||||||
|
print(json.dumps(scan, ensure_ascii=False, indent=2, default=str))
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
@@ -407,6 +407,21 @@ class PolymarketReadOnlyLayer:
|
|||||||
self._clob_unavailable_reason: Optional[str] = None
|
self._clob_unavailable_reason: Optional[str] = None
|
||||||
self._ws_quote_cache = PolymarketWsQuoteCache.from_env()
|
self._ws_quote_cache = PolymarketWsQuoteCache.from_env()
|
||||||
|
|
||||||
|
def _market_scan_debug_enabled(self) -> bool:
|
||||||
|
return (
|
||||||
|
str(os.getenv("POLYMARKET_MARKET_SCAN_DEBUG", "false")).strip().lower()
|
||||||
|
in {"1", "true", "yes", "on"}
|
||||||
|
)
|
||||||
|
|
||||||
|
def _debug_market_scan(self, message: str, **payload: Any) -> None:
|
||||||
|
if not self._market_scan_debug_enabled():
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
details = json.dumps(payload, ensure_ascii=False, default=str)
|
||||||
|
except Exception:
|
||||||
|
details = str(payload)
|
||||||
|
logger.info(f"POLYMARKET_MARKET_SCAN_DEBUG {message} {details}")
|
||||||
|
|
||||||
def build_market_scan(
|
def build_market_scan(
|
||||||
self,
|
self,
|
||||||
city: Any,
|
city: Any,
|
||||||
@@ -451,14 +466,17 @@ class PolymarketReadOnlyLayer:
|
|||||||
|
|
||||||
if not self.enabled:
|
if not self.enabled:
|
||||||
scan["reason"] = "Market scan disabled by POLYMARKET_MARKET_SCAN_ENABLED."
|
scan["reason"] = "Market scan disabled by POLYMARKET_MARKET_SCAN_ENABLED."
|
||||||
|
self._debug_market_scan("disabled", city=city_key, date=date_str)
|
||||||
return scan
|
return scan
|
||||||
|
|
||||||
if not city_key or city_key not in CITY_REGISTRY:
|
if not city_key or city_key not in CITY_REGISTRY:
|
||||||
scan["reason"] = "City is not supported by the Polymarket market layer."
|
scan["reason"] = "City is not supported by the Polymarket market layer."
|
||||||
|
self._debug_market_scan("unsupported_city", city=city, normalized=city_key)
|
||||||
return scan
|
return scan
|
||||||
|
|
||||||
if not date_str:
|
if not date_str:
|
||||||
scan["reason"] = "Missing target date for market discovery."
|
scan["reason"] = "Missing target date for market discovery."
|
||||||
|
self._debug_market_scan("missing_date", city=city_key)
|
||||||
return scan
|
return scan
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -474,10 +492,18 @@ class PolymarketReadOnlyLayer:
|
|||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.warning(f"Polymarket market discovery failed ({city_key}): {exc}")
|
logger.warning(f"Polymarket market discovery failed ({city_key}): {exc}")
|
||||||
scan["reason"] = "Market discovery failed."
|
scan["reason"] = "Market discovery failed."
|
||||||
|
self._debug_market_scan("discovery_exception", city=city_key, error=str(exc))
|
||||||
return scan
|
return scan
|
||||||
|
|
||||||
if not market:
|
if not market:
|
||||||
scan["reason"] = reason or "No active Polymarket market matched city/date."
|
scan["reason"] = reason or "No active Polymarket market matched city/date."
|
||||||
|
self._debug_market_scan(
|
||||||
|
"no_market",
|
||||||
|
city=city_key,
|
||||||
|
date=date_str,
|
||||||
|
forced_slug=requested_slug,
|
||||||
|
reason=scan["reason"],
|
||||||
|
)
|
||||||
return scan
|
return scan
|
||||||
|
|
||||||
market_date = self._extract_market_date(market)
|
market_date = self._extract_market_date(market)
|
||||||
@@ -528,6 +554,13 @@ class PolymarketReadOnlyLayer:
|
|||||||
scan["selected_slug"] = market_slug
|
scan["selected_slug"] = market_slug
|
||||||
scan["liquidity"] = liquidity
|
scan["liquidity"] = liquidity
|
||||||
scan["volume"] = volume
|
scan["volume"] = volume
|
||||||
|
self._debug_market_scan(
|
||||||
|
"not_tradable",
|
||||||
|
city=city_key,
|
||||||
|
date=date_str,
|
||||||
|
slug=market_slug,
|
||||||
|
trade_state=trade_state,
|
||||||
|
)
|
||||||
return scan
|
return scan
|
||||||
|
|
||||||
tokens = self._extract_market_tokens(market)
|
tokens = self._extract_market_tokens(market)
|
||||||
@@ -539,6 +572,13 @@ class PolymarketReadOnlyLayer:
|
|||||||
scan["selected_slug"] = market_slug
|
scan["selected_slug"] = market_slug
|
||||||
scan["liquidity"] = liquidity
|
scan["liquidity"] = liquidity
|
||||||
scan["volume"] = volume
|
scan["volume"] = volume
|
||||||
|
self._debug_market_scan(
|
||||||
|
"missing_tokens",
|
||||||
|
city=city_key,
|
||||||
|
date=date_str,
|
||||||
|
slug=market_slug,
|
||||||
|
token_count=len(tokens),
|
||||||
|
)
|
||||||
return scan
|
return scan
|
||||||
|
|
||||||
yes_prices = self._get_token_market_data(str(yes_token.get("token_id")))
|
yes_prices = self._get_token_market_data(str(yes_token.get("token_id")))
|
||||||
@@ -663,6 +703,31 @@ class PolymarketReadOnlyLayer:
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
self._debug_market_scan(
|
||||||
|
"scan_ready",
|
||||||
|
city=city_key,
|
||||||
|
date=date_str,
|
||||||
|
selected_slug=market_slug,
|
||||||
|
market_price=scan.get("market_price"),
|
||||||
|
yes_buy=scan.get("yes_buy"),
|
||||||
|
yes_sell=scan.get("yes_sell"),
|
||||||
|
no_buy=scan.get("no_buy"),
|
||||||
|
no_sell=scan.get("no_sell"),
|
||||||
|
price_analysis_available=bool(price_analysis and price_analysis.get("available")),
|
||||||
|
all_buckets_count=len(all_buckets),
|
||||||
|
top_buckets=[
|
||||||
|
{
|
||||||
|
"temp": row.get("temp"),
|
||||||
|
"yes_buy": row.get("yes_buy"),
|
||||||
|
"market_price": row.get("market_price"),
|
||||||
|
"quote_source": row.get("quote_source"),
|
||||||
|
"slug": row.get("slug"),
|
||||||
|
}
|
||||||
|
for row in all_buckets[:6]
|
||||||
|
if isinstance(row, dict)
|
||||||
|
],
|
||||||
|
websocket=scan.get("websocket"),
|
||||||
|
)
|
||||||
return scan
|
return scan
|
||||||
|
|
||||||
def _hydrate_bucket_prices(self, buckets: List[Dict[str, Any]]) -> None:
|
def _hydrate_bucket_prices(self, buckets: List[Dict[str, Any]]) -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user