fix(critical): complementary market family grouping + Manifold inversion guard
CI/CD / build-and-push (push) Successful in 2m23s
CI/CD / build-and-push (push) Successful in 2m23s
FASE 1 — market_family_key() general election fix
General elections now group by office, not by party, so complementary
markets ("Republicans win Ohio governor" / "Democrats win Ohio governor")
share the same family key (ohio-gubernatorial-2026). The second market
is blocked by the occupied_families check rather than traded as independent.
Primaries still keep the party (texas-republican-2026) because each party
runs its own separate primary race.
FASE 2 — Manifold party inversion guard
_detect_party() identifies the winning side in both the Polymarket question
and the matched Manifold title. If they are confirmed opposites (republican
vs democrat), the probability is inverted (1 - prob) before use.
Full audit log per query:
poly_question / manifold_title / manifold_url / match_score /
prob_raw / inverted / prob_final
Root cause of Ohio Manifold:0.95 on both sides: both queries matched the
same Manifold market ("Republicans win Ohio governor" prob=0.95). For the
"Democrats win" query the inversion now produces prob_final=0.05 instead of
blindly applying 0.95 to the wrong direction.
FASE 4 — startup contradiction scan
get_open_position_details() added to db.py. main.py checks all open
positions at startup, warns on any family with >1 position, and recommends
keeping the one with the highest edge_net. No auto-close.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -89,6 +89,23 @@ class Database:
|
||||
)
|
||||
return {r["family_key"] for r in rows if r["family_key"]}
|
||||
|
||||
async def get_open_position_details(self) -> list[dict]:
|
||||
"""Return one row per open position with family_key and direction.
|
||||
|
||||
Used at startup to detect positions that share a family_key (same
|
||||
underlying event), which indicates a contradictory paper trade entered
|
||||
before the general-election family fix was deployed.
|
||||
"""
|
||||
async with self._pool.acquire() as conn:
|
||||
rows = await conn.fetch("""
|
||||
SELECT DISTINCT ON (market_id)
|
||||
market_id, question, direction, edge_net, family_key, timestamp
|
||||
FROM trades
|
||||
WHERE paper = TRUE
|
||||
ORDER BY market_id, timestamp DESC
|
||||
""")
|
||||
return [dict(r) for r in rows]
|
||||
|
||||
async def get_recent_trades(self, limit: int = 100) -> list[dict]:
|
||||
async with self._pool.acquire() as conn:
|
||||
rows = await conn.fetch(
|
||||
|
||||
Reference in New Issue
Block a user