feat: implement PolymarketReadOnlyLayer for data collection and add comprehensive unit tests
This commit is contained in:
@@ -1023,7 +1023,12 @@ class PolymarketReadOnlyLayer:
|
||||
preferred_temp=preferred_temp,
|
||||
)
|
||||
|
||||
cache_key = f"{city_key}|{target_date}"
|
||||
preferred_temp_key = (
|
||||
f"{float(preferred_temp):.2f}"
|
||||
if preferred_temp is not None
|
||||
else "none"
|
||||
)
|
||||
cache_key = f"{city_key}|{target_date}|{preferred_temp_key}"
|
||||
now = time.time()
|
||||
|
||||
with self._lock:
|
||||
@@ -1037,7 +1042,12 @@ class PolymarketReadOnlyLayer:
|
||||
|
||||
scored: List[Tuple[float, Dict[str, Any]]] = []
|
||||
for market in markets:
|
||||
score = self._score_market(city_key, target_date, market)
|
||||
score = self._score_market(
|
||||
city_key,
|
||||
target_date,
|
||||
market,
|
||||
preferred_temp=preferred_temp,
|
||||
)
|
||||
if score <= 0:
|
||||
continue
|
||||
scored.append((score, market))
|
||||
@@ -1046,7 +1056,12 @@ class PolymarketReadOnlyLayer:
|
||||
if not scored:
|
||||
broader = self._load_markets(active_only=False)
|
||||
for market in broader:
|
||||
score = self._score_market(city_key, target_date, market)
|
||||
score = self._score_market(
|
||||
city_key,
|
||||
target_date,
|
||||
market,
|
||||
preferred_temp=preferred_temp,
|
||||
)
|
||||
if score <= 0:
|
||||
continue
|
||||
scored.append((score, market))
|
||||
@@ -1196,7 +1211,13 @@ class PolymarketReadOnlyLayer:
|
||||
|
||||
return None, f"Specified market_slug not found: {normalized_slug}"
|
||||
|
||||
def _score_market(self, city_key: str, target_date: str, market: Dict[str, Any]) -> float:
|
||||
def _score_market(
|
||||
self,
|
||||
city_key: str,
|
||||
target_date: str,
|
||||
market: Dict[str, Any],
|
||||
preferred_temp: Optional[float] = None,
|
||||
) -> float:
|
||||
city_tokens = CITY_TOKEN_INDEX.get(city_key, [city_key])
|
||||
text_parts = [
|
||||
market.get("question"),
|
||||
@@ -1271,6 +1292,32 @@ class PolymarketReadOnlyLayer:
|
||||
or 0.0
|
||||
)
|
||||
score += min(volume / 50000.0, 8.0)
|
||||
|
||||
if preferred_temp is not None:
|
||||
market_temp = self._extract_market_bucket_temp(market)
|
||||
bucket_range = self._extract_market_bucket_range(market)
|
||||
direction = self._extract_market_bucket_direction(market)
|
||||
if market_temp is not None:
|
||||
diff = abs(float(market_temp) - float(preferred_temp))
|
||||
score += max(-40.0, 60.0 - diff * 15.0)
|
||||
|
||||
if bucket_range is not None:
|
||||
lower, upper, _unit = bucket_range
|
||||
contains_preferred = False
|
||||
if upper is not None:
|
||||
contains_preferred = lower <= float(preferred_temp) <= upper
|
||||
elif direction == "above":
|
||||
contains_preferred = float(preferred_temp) >= lower
|
||||
elif direction == "below":
|
||||
contains_preferred = float(preferred_temp) <= lower
|
||||
else:
|
||||
contains_preferred = abs(float(preferred_temp) - lower) <= 0.51
|
||||
|
||||
if contains_preferred:
|
||||
if upper is not None or direction == "exact":
|
||||
score += 28.0
|
||||
else:
|
||||
score += 18.0
|
||||
return score
|
||||
|
||||
def _is_temperature_market(self, market: Dict[str, Any]) -> bool:
|
||||
|
||||
@@ -442,3 +442,45 @@ def test_build_top_temperature_buckets_dedupes_same_temperature():
|
||||
"highest-temperature-in-ankara-on-march-12-2026-14c-or-higher|yes"
|
||||
)
|
||||
assert all(not str(row.get("label") or "").startswith("<=") for row in rows)
|
||||
|
||||
|
||||
def test_find_primary_market_prefers_preferred_temperature_and_cache_key():
|
||||
layer = PolymarketReadOnlyLayer()
|
||||
markets = [
|
||||
{
|
||||
"slug": "highest-temperature-in-madrid-on-april-23-2026-22corbelow",
|
||||
"question": "Will the highest temperature in Madrid be 22C or below on April 23?",
|
||||
"volumeNum": 900000,
|
||||
"active": True,
|
||||
"closed": False,
|
||||
"acceptingOrders": True,
|
||||
"enableOrderBook": True,
|
||||
},
|
||||
{
|
||||
"slug": "highest-temperature-in-madrid-on-april-23-2026-27c",
|
||||
"question": "Will the highest temperature in Madrid be 27C on April 23?",
|
||||
"volumeNum": 1000,
|
||||
"active": True,
|
||||
"closed": False,
|
||||
"acceptingOrders": True,
|
||||
"enableOrderBook": True,
|
||||
},
|
||||
]
|
||||
|
||||
layer._load_markets = lambda active_only=True: markets
|
||||
|
||||
selected_27, reason_27 = layer._find_primary_market(
|
||||
"madrid",
|
||||
"2026-04-23",
|
||||
preferred_temp=27.0,
|
||||
)
|
||||
selected_22, reason_22 = layer._find_primary_market(
|
||||
"madrid",
|
||||
"2026-04-23",
|
||||
preferred_temp=22.0,
|
||||
)
|
||||
|
||||
assert reason_27 is None
|
||||
assert reason_22 is None
|
||||
assert selected_27["slug"] == "highest-temperature-in-madrid-on-april-23-2026-27c"
|
||||
assert selected_22["slug"] == "highest-temperature-in-madrid-on-april-23-2026-22corbelow"
|
||||
|
||||
Reference in New Issue
Block a user