fix(strategy): use word-boundary token matching for short crypto tickers to prevent false positives
CI/CD / build-and-push (push) Successful in 8s
CI/CD / build-and-push (push) Successful in 8s
Substring matching over question_lower flagged non-crypto markets as crypto: 'dissolved' matched 'sol', 'Canada' matched 'ada', 'Seth' matched 'eth'. Those false flags armed the BTC-dominance signal (btc_dom_lo=+0.06 observed on politics markets in production). Short tickers (btc, eth, sol, xrp, doge, ltc, bnb, ada, avax) now go through has_token(), which requires non-alphanumeric boundaries so 'ETH', '$ETH' and 'ETH/USD' still match. Long unambiguous names (bitcoin, ethereum, solana, cardano, ...) remain substring checks. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
4002f03d0c
commit
f5ac302a86
@@ -13,6 +13,7 @@ Polymarket might reflect in a slow-moving order book.
|
||||
import logging
|
||||
import math
|
||||
import os
|
||||
import re
|
||||
import uuid
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime, timedelta, timezone
|
||||
@@ -159,6 +160,21 @@ def _days_to_resolution(end_date: str) -> int:
|
||||
return 30
|
||||
|
||||
|
||||
def has_token(text: str, token: str) -> bool:
|
||||
"""
|
||||
True if `token` appears in `text` as a standalone word.
|
||||
|
||||
Short crypto tickers (eth, sol, ada, …) must NOT match inside ordinary
|
||||
words — "Seth", "dissolved", "Canada" — but must still match the usual
|
||||
market phrasings: "ETH", "$ETH", "ETH/USD", "SOL reach $200". Boundaries
|
||||
are any non-alphanumeric character (or start/end of string), so "$" and
|
||||
"/" delimit correctly.
|
||||
"""
|
||||
return re.search(
|
||||
rf"(?<![A-Za-z0-9]){re.escape(token)}(?![A-Za-z0-9])", text, re.IGNORECASE
|
||||
) is not None
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Phase 3 — GNews priority scoring
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
@@ -345,13 +361,18 @@ class BayesianStrategy:
|
||||
"below", "under", "less than", "lower", "drop",
|
||||
])
|
||||
|
||||
is_btc = "btc" in question_lower or "bitcoin" in question_lower
|
||||
is_eth = "eth" in question_lower or "ethereum" in question_lower
|
||||
is_sol = "sol" in question_lower or "solana" in question_lower
|
||||
is_xrp = "xrp" in question_lower or "ripple" in question_lower
|
||||
is_doge = "doge" in question_lower or "dogecoin" in question_lower
|
||||
# Short tickers need word boundaries: "Seth" contains "eth",
|
||||
# "dissolved" contains "sol", "Canada" contains "ada". Long
|
||||
# unambiguous names (bitcoin, ethereum, …) stay as substrings.
|
||||
is_btc = has_token(question_lower, "btc") or "bitcoin" in question_lower
|
||||
is_eth = has_token(question_lower, "eth") or "ethereum" in question_lower
|
||||
is_sol = has_token(question_lower, "sol") or "solana" in question_lower
|
||||
is_xrp = has_token(question_lower, "xrp") or "ripple" in question_lower
|
||||
is_doge = has_token(question_lower, "doge") or "dogecoin" in question_lower
|
||||
is_altcoin = is_sol or is_xrp or is_doge or any(
|
||||
w in question_lower for w in ["ltc", "litecoin", "bnb", "ada", "cardano", "avax", "avalanche"]
|
||||
has_token(question_lower, t) for t in ["ltc", "bnb", "ada", "avax"]
|
||||
) or any(
|
||||
w in question_lower for w in ["litecoin", "cardano", "avalanche"]
|
||||
)
|
||||
is_general_crypto = any(
|
||||
w in question_lower for w in ["crypto", "market cap", "total market", "altcoin", "defi"]
|
||||
|
||||
Reference in New Issue
Block a user