修复概率引擎与 Polymarket 桶不匹配导致 model_p 始终为 None 的问题

_distribution_probability_for_market 新增高斯 CDF fallback:
当离散概率分布桶与 Polymarket 市场桶无精确重叠时(如 NYC 分布 56-59F
但市场桶为 51-70F),用分布的 mu/sigma 构建正态分布计算 CDF 概率,
不再直接返回 None,保证 scan_rows 正常生成。
This commit is contained in:
2569718930@qq.com
2026-05-25 02:51:58 +08:00
parent 032d46ec1d
commit d2a9e9a9b3
+53 -2
View File
@@ -1628,9 +1628,60 @@ class PolymarketReadOnlyLayer:
probability = max(0.0, min(1.0, probability))
total += probability
matched += 1
if matched <= 0:
if matched > 0:
return max(0.0, min(1.0, total))
# Fallback: use Gaussian CDF when no distribution bucket matches the
# market bucket exactly. Compute mu/sigma from the distribution, then
# integrate the Gaussian tail or band that corresponds to the market.
values = []
weights = []
for row in probability_distribution:
v = _safe_float(row.get("value"))
p = _safe_float(row.get("probability"))
if v is not None and p is not None:
prob = p / 100.0 if p > 1.0 else p
values.append(v)
weights.append(max(0.0, prob))
if len(values) < 2:
return None
return max(0.0, min(1.0, total))
total_weight = sum(weights)
if total_weight <= 0:
return None
mu = sum(v * w for v, w in zip(values, weights)) / total_weight
variance = sum(w * (v - mu) ** 2 for v, w in zip(values, weights)) / total_weight
sigma = math.sqrt(max(variance, 0.01))
unit = str(temp_symbol or "C").upper()
bucket_range = self._extract_market_bucket_range(market)
lower = bucket_range[0] if bucket_range else None
upper = bucket_range[1] if bucket_range else None
direction = self._extract_market_bucket_direction(market)
if lower is not None:
lower = self._convert_temp_to_market_unit(
lower, source_symbol=None, market_unit=(bucket_range[2] if bucket_range else unit),
) or lower
if upper is not None:
upper = self._convert_temp_to_market_unit(
upper, source_symbol=None, market_unit=(bucket_range[2] if bucket_range else unit),
) or upper
def _norm_cdf(x: float) -> float:
return 0.5 * (1.0 + math.erf((x - mu) / (sigma * math.sqrt(2.0))))
if lower is not None and upper is not None:
prob = _norm_cdf(upper + 0.5) - _norm_cdf(lower - 0.5)
elif lower is not None and direction == "above":
prob = 1.0 - _norm_cdf(lower - 0.5)
elif lower is not None and direction == "below":
prob = _norm_cdf(lower + 0.5)
elif lower is not None:
prob = _norm_cdf(lower + 1.5) - _norm_cdf(lower - 0.5)
else:
return None
return max(0.0, min(1.0, prob))
def _load_markets(self, active_only: bool = True) -> List[Dict[str, Any]]:
now = time.time()