fix: pre-launch hardening — HYPE price feed, KOL wallet cleanup, Telegram Trump alert, rate limiting, brittle test

Batch of the pre-launch audit campaign (BUG-01…14 plus three new features):

Pricing / TP-SL protection
- Add app/services/hl_price_feed.py: supplemental HL allMids poller for
  HL-native assets (HYPE, PURR) not listed on Binance. Pumps price_store +
  tp_sl_monitor.on_price_tick so bot trades on these assets keep full
  stop-loss / take-profit / trailing protection instead of max-hold only.
- Wire feed into main.py lifespan (startup task + graceful shutdown cancel).

Telegram
- Add format_trump_mention + PATH B in _dispatch: crypto-relevant Trump
  posts with no directional signal (relevant=True, signal=hold) now alert
  the public channel only (no per-subscriber noise).
- Rate limiter (slowapi) on the API; assorted bot/digest fixes.

KOL on-chain
- seed_kol_wallets.py: KOL_FEEDS coverage cross-check; reversibly deactivate
  orphaned wallets (handle not in KOL_FEEDS → can never produce divergence)
  so the scanner stops burning cycles on them.

Tests / misc
- Fix brittle test_macro_ahr999_uses_same_formula_as_scanner: mock now uses
  realistic ms timestamps so the in-progress-day drop fires, matching the
  fetcher's bar count (was 0.3179 vs 0.3178 off-by-one).
- Refresh stale notify_signal comment in truth_social.py.

Frontend reduce-action type fix lives in the sibling repo.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
k
2026-05-29 11:57:19 +08:00
parent 6471e44aac
commit d6c802ef26
40 changed files with 1833 additions and 209 deletions
+18 -36
View File
@@ -1,6 +1,11 @@
"""
历史帖子价格回溯
对 DB 中没有价格数据的帖子,从 Binance 拉历史 K 线计算涨跌幅
Historical price backfill for already-relevant posts.
Important safety rule:
This job only fills missing price fields. It must NEVER rewrite the post's
semantic classification (`relevant`, `sentiment`, signal direction) from a
keyword heuristic, otherwise historical truth rows become a mixed dataset of
AI-scored rows + script-guessed rows.
"""
import asyncio
@@ -53,17 +58,21 @@ def _pct_change(klines: list, from_ms: int, delta_minutes: int) -> Optional[floa
async def backfill_price_impact(db_session_factory, asset: str = "BTC") -> None:
"""
对 DB 中 relevant=True 但没有价格数据的帖子补充价格回溯。
对 relevant=False 的帖子,做简单判断(标题含 crypto/bitcoin/btc 关键词则标记为相关)。
"""Fill price-impact fields for posts that are already relevant.
The semantic label must come from the original analyzer, not from this
backfill job. This task only enriches rows with price-at-post and
subsequent returns.
"""
symbol = "BTCUSDT" if asset == "BTC" else "ETHUSDT"
async with db_session_factory() as db:
# 拿所有没有价格数据的帖子
# Only touch rows whose semantic classification already exists.
result = await db.execute(
select(Post)
.where(Post.relevant == True)
.where(Post.price_at_post == None)
.where(Post.price_impact_asset == asset)
.order_by(Post.published_at.asc())
)
posts = result.scalars().all()
@@ -72,18 +81,6 @@ async def backfill_price_impact(db_session_factory, asset: str = "BTC") -> None:
if not posts:
return
# 关键词判断是否与加密相关(快速,不用 Claude API)
crypto_keywords = [
"bitcoin", "btc", "crypto", "cryptocurrency", "blockchain",
"ethereum", "eth", "digital currency", "defi", "coinbase",
"sec", "regulation", "tariff", "dollar", "inflation", "fed",
"economy", "market", "trade", "sanctions", "iran", "china",
]
def is_relevant(text: str) -> bool:
t = text.lower()
return any(kw in t for kw in crypto_keywords)
saved = 0
errors = 0
@@ -95,18 +92,6 @@ async def backfill_price_impact(db_session_factory, asset: str = "BTC") -> None:
start_ms = int(published_at.timestamp() * 1000)
# 判断相关性(用关键词,不消耗 Claude API)
relevant = is_relevant(post.text)
sentiment = "neutral"
if relevant:
t = post.text.lower()
bullish_kw = ["great", "win", "winning", "strong", "best", "love", "beautiful", "tremendous", "amazing", "pro-crypto", "bitcoin reserve"]
bearish_kw = ["bad", "terrible", "war", "crisis", "sanction", "ban", "regulate", "crack", "fraud", "scam"]
if any(k in t for k in bullish_kw):
sentiment = "bullish"
elif any(k in t for k in bearish_kw):
sentiment = "bearish"
# 拉 Binance 历史价格
klines = await _fetch_klines(symbol, start_ms, limit=FETCH_WINDOW_MINUTES)
@@ -120,13 +105,10 @@ async def backfill_price_impact(db_session_factory, asset: str = "BTC") -> None:
result = await db.execute(select(Post).where(Post.id == post.id))
p = result.scalar_one_or_none()
if p:
p.relevant = relevant
p.sentiment = sentiment
p.price_impact_asset = asset if relevant else None
p.price_at_post = price_at_post
p.price_impact_m5 = m5 if relevant else None
p.price_impact_m15 = m15 if relevant else None
p.price_impact_m1h = m1h if relevant else None
p.price_impact_m5 = m5
p.price_impact_m15 = m15
p.price_impact_m1h = m1h
await db.commit()
saved += 1