feat(manifold): audit matching quality with ManifoldMatchResult and manifold_match_audit table
CI/CD / build-and-push (push) Successful in 14s
CI/CD / build-and-push (push) Successful in 14s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+83
-2
@@ -36,11 +36,15 @@ class Database:
|
||||
entry_price, shares, fee_usdc, net_cost, timestamp, reasoning, paper,
|
||||
edge_gross, edge_net, prior_prob, final_prob,
|
||||
mid_price, spread_estimate, commission, family_key,
|
||||
feat_fg_lo, feat_mom_lo, feat_news_lo, feat_mfld_lo, feat_btc_dom_lo
|
||||
feat_fg_lo, feat_mom_lo, feat_news_lo, feat_mfld_lo, feat_btc_dom_lo,
|
||||
mfld_market_id, mfld_market_title, mfld_market_url,
|
||||
mfld_prob_raw, mfld_prob_final, mfld_inverted,
|
||||
mfld_match_score, mfld_match_reason, mfld_match_status
|
||||
) VALUES (
|
||||
$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,
|
||||
$13,$14,$15,$16,$17,$18,$19,$20,
|
||||
$21,$22,$23,$24,$25
|
||||
$21,$22,$23,$24,$25,
|
||||
$26,$27,$28,$29,$30,$31,$32,$33,$34
|
||||
)
|
||||
ON CONFLICT (id) DO NOTHING
|
||||
""",
|
||||
@@ -53,6 +57,10 @@ class Database:
|
||||
# Phase 6 feature log-odds
|
||||
trade.feat_fg_lo, trade.feat_mom_lo, trade.feat_news_lo,
|
||||
trade.feat_mfld_lo, trade.feat_btc_dom_lo,
|
||||
# Manifold audit fields
|
||||
trade.mfld_market_id, trade.mfld_market_title, trade.mfld_market_url,
|
||||
trade.mfld_prob_raw, trade.mfld_prob_final, trade.mfld_inverted,
|
||||
trade.mfld_match_score, trade.mfld_match_reason, trade.mfld_match_status,
|
||||
)
|
||||
|
||||
async def save_daily_metrics(self, metrics: dict) -> None:
|
||||
@@ -493,6 +501,79 @@ class Database:
|
||||
return result
|
||||
|
||||
|
||||
async def save_manifold_audit(
|
||||
self,
|
||||
audit_id: str,
|
||||
poly_market_id: str,
|
||||
poly_question: str,
|
||||
search_query: str,
|
||||
mfld_market_id: Optional[str],
|
||||
mfld_market_title: Optional[str],
|
||||
mfld_market_url: Optional[str],
|
||||
prob_raw: Optional[float],
|
||||
prob_final: Optional[float],
|
||||
inverted: bool,
|
||||
match_score: Optional[float],
|
||||
match_reason: Optional[str],
|
||||
match_status: str,
|
||||
) -> None:
|
||||
async with self._pool.acquire() as conn:
|
||||
await conn.execute("""
|
||||
INSERT INTO manifold_match_audit (
|
||||
id, poly_market_id, poly_question, search_query,
|
||||
mfld_market_id, mfld_market_title, mfld_market_url,
|
||||
prob_raw, prob_final, inverted,
|
||||
match_score, match_reason, match_status, used_in_trade
|
||||
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,FALSE)
|
||||
""",
|
||||
audit_id, poly_market_id, poly_question, search_query,
|
||||
mfld_market_id, mfld_market_title, mfld_market_url,
|
||||
prob_raw, prob_final, inverted,
|
||||
match_score, match_reason, match_status,
|
||||
)
|
||||
|
||||
async def mark_manifold_audit_used(self, audit_id: str) -> None:
|
||||
async with self._pool.acquire() as conn:
|
||||
await conn.execute(
|
||||
"UPDATE manifold_match_audit SET used_in_trade = TRUE WHERE id = $1",
|
||||
audit_id,
|
||||
)
|
||||
|
||||
async def get_manifold_matches(self, limit: int = 50) -> dict:
|
||||
async with self._pool.acquire() as conn:
|
||||
summary = await conn.fetchrow("""
|
||||
SELECT
|
||||
COUNT(*) FILTER (WHERE match_status = 'accepted') AS total_accepted,
|
||||
COUNT(*) FILTER (WHERE match_status = 'rejected') AS total_rejected,
|
||||
COUNT(*) FILTER (WHERE match_status = 'no_results') AS total_no_results,
|
||||
AVG(match_score) FILTER (WHERE match_status = 'accepted') AS avg_match_score
|
||||
FROM manifold_match_audit
|
||||
""")
|
||||
mfld_dominated = await conn.fetchrow("""
|
||||
SELECT COUNT(*) AS cnt FROM trades
|
||||
WHERE feat_mfld_lo IS NOT NULL
|
||||
AND ABS(feat_mfld_lo) > 0.0001
|
||||
AND ABS(feat_mfld_lo) > ABS(COALESCE(feat_fg_lo, 0))
|
||||
AND ABS(feat_mfld_lo) > ABS(COALESCE(feat_mom_lo, 0))
|
||||
AND ABS(feat_mfld_lo) > ABS(COALESCE(feat_news_lo, 0))
|
||||
AND ABS(feat_mfld_lo) > ABS(COALESCE(feat_btc_dom_lo, 0))
|
||||
""")
|
||||
rows = await conn.fetch(
|
||||
"SELECT * FROM manifold_match_audit ORDER BY timestamp DESC LIMIT $1",
|
||||
limit,
|
||||
)
|
||||
return {
|
||||
"summary": {
|
||||
"total_accepted": int(summary["total_accepted"] or 0),
|
||||
"total_rejected": int(summary["total_rejected"] or 0),
|
||||
"total_no_results": int(summary["total_no_results"] or 0),
|
||||
"avg_match_score": _f(summary["avg_match_score"]),
|
||||
"trades_dominated_by_mfld": int(mfld_dominated["cnt"] or 0),
|
||||
},
|
||||
"recent_matches": [dict(r) for r in rows],
|
||||
}
|
||||
|
||||
|
||||
def _f(v) -> Optional[float]:
|
||||
"""None-safe float cast for asyncpg Decimal/None values."""
|
||||
return float(v) if v is not None else None
|
||||
|
||||
Reference in New Issue
Block a user