feat(kol-v2): fix soft-signal recall — bullish/bearish over mention, category tickers
Two failure modes addressed: 1. Soft/indirect bullish signals classified as 'mention' instead of 'bullish' The prompt now explicitly lists casual English and Chinese expressions that count as bullish/bearish (not mention): - EN: 'looks interesting here', 'has room to run', 'wouldn't be short' - ZH: '感觉还有空间', '可以关注', '这里不错', '有上涨空间' mention is now reserved for ZERO directional lean (historical refs, neutral examples). Previously the vague boundary caused the model to use mention conservatively, losing real signals. 2. Category-level calls lost when no specific ticker named 'memecoin season', 'memes look good', '梗币最近不错' had no ticker to attach to. Added synthetic tickers: MEME, ALTCOIN, DEFI, AI — the model uses these when the view is about the category, not a specific coin. Normalizer allows synthetic tickers through the len>12 guard. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -107,10 +107,28 @@ TICKERS:
|
||||
- action values:
|
||||
"buy"/"sell" → author explicitly states a position action ("I bought", "we are long", "我们减仓了", "added to my bag", "taking profits", "已建仓", "我加仓了", "建了仓")
|
||||
"reduce" → partially exiting or taking profits on an existing long ("trimming", "taking some off", "减了一部分", "止盈了一些")
|
||||
"bullish"/"bearish" → directional view without explicit position statement
|
||||
"mention" → ticker appears but no clear stance — use sparingly, only when ticker is central to the post
|
||||
"bullish" → ANY expression of upside view, including SOFT/INDIRECT/CASUAL language. Err on the side of bullish over mention.
|
||||
English soft bullish: "X looks interesting here", "I like X at these levels", "X has room to run",
|
||||
"wouldn't be short X", "X is setting up well", "compelling setup in X", "X is undervalued",
|
||||
"I'd be a buyer of X", "X deserves attention here", "keeping an eye on X"
|
||||
Chinese soft bullish: "感觉还有空间", "这里可以关注", "值得关注", "看好", "还有机会",
|
||||
"这个位置不错", "可以考虑", "有上涨空间", "这波不错", "可以关注一下", "挺有意思的"
|
||||
"bearish" → ANY expression of downside view or caution, including soft signals.
|
||||
English soft bearish: "X looks extended", "I'd be careful here", "not touching X",
|
||||
"X has further to fall", "selling into strength on X", "X is a trap"
|
||||
Chinese soft bearish: "感觉要跌", "要小心", "不敢碰", "还会跌", "高位了", "风险很大"
|
||||
"mention" → ticker appears but author has ZERO directional lean — pure neutral reference,
|
||||
historical context only, or just used as an example. If there is ANY lean at all,
|
||||
use bullish or bearish instead. Reserve mention for truly neutral uses like:
|
||||
"BTC started in 2009" or "unlike ETH, which uses proof-of-stake"
|
||||
- Dedupe per ticker — at most one entry per symbol; pick the strongest action.
|
||||
- Do NOT invent tickers. Skip "$XYZ" if unsure it is a real crypto token.
|
||||
- For CATEGORY-LEVEL calls (no specific ticker named), use these synthetic tickers:
|
||||
"MEME" → author is bullish/bearish on memecoins as a category ("memes look good", "memecoin season", "梗币最近不错")
|
||||
"ALTCOIN" → author is bullish/bearish on altcoins broadly ("alts are waking up", "山寨季", "altseason")
|
||||
"DEFI" → author is bullish/bearish on DeFi protocols broadly
|
||||
"AI" → author is bullish/bearish on AI-related tokens broadly
|
||||
Only use synthetic tickers when the view is genuinely about the category, not just a passing mention.
|
||||
- conviction: 0.8+ = explicit + repeated + sized or timed; 0.5–0.7 = clear view, no commitment; <0.5 = passing reference.
|
||||
- timeframe: "immediate" = acting now or within 24h; "days" = 1–7d; "weeks" = 1–4w; "months" = 1+ months; "unspecified" = not stated.
|
||||
- Do not include fiat (USD/CNY/JPY) or stablecoins (USDT/USDC/DAI/FRAX/USDE) unless the post's main thesis is about them.
|
||||
@@ -246,12 +264,19 @@ async def extract_kol_signal(
|
||||
valid_actions = {"buy", "sell", "reduce", "bullish", "bearish", "mention"}
|
||||
valid_timeframes = {"immediate", "days", "weeks", "months", "unspecified"}
|
||||
valid_post_types = {"trade_update", "macro_thesis", "research", "news_recap", "opinion", "other"}
|
||||
# Synthetic category tickers — allowed even though they're not real on-chain tokens.
|
||||
# Used when the KOL expresses a view on a category without naming specific coins.
|
||||
SYNTHETIC_TICKERS = {"MEME", "ALTCOIN", "DEFI", "AI"}
|
||||
|
||||
for t in tickers:
|
||||
if not isinstance(t, dict):
|
||||
continue
|
||||
sym = (t.get("ticker") or "").strip().upper()
|
||||
if not sym or len(sym) > 12:
|
||||
if not sym:
|
||||
continue
|
||||
# Allow synthetic category tickers; reject anything else > 12 chars
|
||||
# (12 chars covers most real tickers; synthetic ones are all ≤ 7 chars)
|
||||
if sym not in SYNTHETIC_TICKERS and len(sym) > 12:
|
||||
continue
|
||||
action = (t.get("action") or "mention").lower()
|
||||
if action not in valid_actions:
|
||||
|
||||
Reference in New Issue
Block a user