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,
|
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()
|
now = time.time()
|
||||||
|
|
||||||
with self._lock:
|
with self._lock:
|
||||||
@@ -1037,7 +1042,12 @@ class PolymarketReadOnlyLayer:
|
|||||||
|
|
||||||
scored: List[Tuple[float, Dict[str, Any]]] = []
|
scored: List[Tuple[float, Dict[str, Any]]] = []
|
||||||
for market in markets:
|
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:
|
if score <= 0:
|
||||||
continue
|
continue
|
||||||
scored.append((score, market))
|
scored.append((score, market))
|
||||||
@@ -1046,7 +1056,12 @@ class PolymarketReadOnlyLayer:
|
|||||||
if not scored:
|
if not scored:
|
||||||
broader = self._load_markets(active_only=False)
|
broader = self._load_markets(active_only=False)
|
||||||
for market in broader:
|
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:
|
if score <= 0:
|
||||||
continue
|
continue
|
||||||
scored.append((score, market))
|
scored.append((score, market))
|
||||||
@@ -1196,7 +1211,13 @@ class PolymarketReadOnlyLayer:
|
|||||||
|
|
||||||
return None, f"Specified market_slug not found: {normalized_slug}"
|
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])
|
city_tokens = CITY_TOKEN_INDEX.get(city_key, [city_key])
|
||||||
text_parts = [
|
text_parts = [
|
||||||
market.get("question"),
|
market.get("question"),
|
||||||
@@ -1271,6 +1292,32 @@ class PolymarketReadOnlyLayer:
|
|||||||
or 0.0
|
or 0.0
|
||||||
)
|
)
|
||||||
score += min(volume / 50000.0, 8.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
|
return score
|
||||||
|
|
||||||
def _is_temperature_market(self, market: Dict[str, Any]) -> bool:
|
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"
|
"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)
|
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