feat(bot): add [CYCLE SUMMARY] diagnostic block at end of each cycle
CI/CD / build-and-push (push) Successful in 2m16s

BayesianStrategy now tracks per-cycle counters (reset each cycle):
  - skip_prior_extreme, skip_family
  - skip_edge_net_nonpositive (edge_net ≤ 0)
  - skip_edge_net_below_regime (0 < edge_net < regime_min)
  - evaluated_edges list for max/pct computations

main.py logs one structured [CYCLE SUMMARY] block per cycle with:
  markets_total, markets_uncertainty_zone, max_edge_gross, max_edge_net,
  pct_edge_gross_gt_002, pct_edge_gross_gt_004, all blocked_by_* counters,
  trades_executed, gnews_queries_used/cap

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
chemavx
2026-04-16 15:55:22 +00:00
parent 63d9f637ff
commit 411d346261
2 changed files with 82 additions and 3 deletions
+42
View File
@@ -184,10 +184,41 @@ class BayesianStrategy:
self._signal_count = 0
self._news = news
self._news_queries_this_cycle = 0
# Per-cycle counters — reset by reset_cycle(), read by get_cycle_stats()
self._skip_family: int = 0
self._skip_prior_extreme: int = 0
self._skip_edge_net_nonpositive: int = 0 # edge_net <= 0
self._skip_edge_net_below_regime: int = 0 # 0 < edge_net < regime_min
# (edge_gross, edge_net, regime_min) for every market that reached the
# edge computation stage (passed prior-extreme, family, unsupported filters)
self._evaluated_edges: list[tuple[float, float, float]] = []
def reset_cycle(self) -> None:
"""Call once at the start of each trading cycle to reset per-cycle counters."""
self._news_queries_this_cycle = 0
self._skip_family = 0
self._skip_prior_extreme = 0
self._skip_edge_net_nonpositive = 0
self._skip_edge_net_below_regime = 0
self._evaluated_edges = []
def get_cycle_stats(self) -> dict:
"""Return per-cycle counters for the [CYCLE SUMMARY] log block."""
edges = self._evaluated_edges
all_gross = [g for g, n, r in edges]
all_net = [n for g, n, r in edges]
return {
"skip_family": self._skip_family,
"skip_prior_extreme": self._skip_prior_extreme,
"skip_edge_net_nonpositive": self._skip_edge_net_nonpositive,
"skip_edge_net_below_regime": self._skip_edge_net_below_regime,
"gnews_queries_used": self._news_queries_this_cycle,
"max_edge_gross": max(all_gross) if all_gross else 0.0,
"max_edge_net": max(all_net) if all_net else 0.0,
"evaluated_count": len(edges),
"gross_gt_002": sum(1 for g in all_gross if g > 0.02),
"gross_gt_004": sum(1 for g in all_gross if g > 0.04),
}
async def evaluate(
self,
@@ -260,12 +291,14 @@ class BayesianStrategy:
prior = max(0.05, min(0.95, market.yes_price))
if market.yes_price < 0.08:
self._skip_prior_extreme += 1
log.info(
"SKIP_PRIOR_EXTREME %-50s | cat=%-12s | prior=%.3f | reason=prior<0.08",
market.question[:50], category, market.yes_price,
)
return None
if market.yes_price > 0.92:
self._skip_prior_extreme += 1
log.info(
"SKIP_PRIOR_EXTREME %-50s | cat=%-12s | prior=%.3f | reason=prior>0.92",
market.question[:50], category, market.yes_price,
@@ -275,6 +308,7 @@ class BayesianStrategy:
# ── Phase 2: family deduplication ────────────────────────────────────
family = market_family_key(market)
if family in occupied_families:
self._skip_family += 1
log.info(
"SKIP_FAMILY %-50s | cat=%-12s | family=%s",
market.question[:50], category, family,
@@ -366,6 +400,9 @@ class BayesianStrategy:
# mid_price falls back to yes_price; live order-book data is a future enhancement
mid_price = market.yes_price
# Record for cycle summary — every market that reached edge computation
self._evaluated_edges.append((edge_gross, edge_net, regime_min))
# Confidence based on signal agreement
agreement = sum(1 for a in adjustments if (a > 0) == (total_adj > 0))
confidence = min(confidence_cap, 0.4 + (agreement / max(len(adjustments), 1)) * 0.5)
@@ -378,6 +415,11 @@ class BayesianStrategy:
can_trade = passed_net and confidence >= MIN_CONFIDENCE
if not can_trade:
# Increment the appropriate edge-net counter
if edge_net <= 0:
self._skip_edge_net_nonpositive += 1
else:
self._skip_edge_net_below_regime += 1
skip_parts: list[str] = []
if not passed_gross:
skip_parts.append(f"edge_gross={edge_gross:.3f}<{regime_min:.2f}(regime)")