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:
@@ -61,12 +61,17 @@ _CB_COLS = {
|
||||
}
|
||||
|
||||
|
||||
async def _trades_for_system(db: AsyncSession, wallet: str, since, system: str):
|
||||
async def _trades_for_system(db: AsyncSession, wallet: str, since, system: str, limit: int | None = None):
|
||||
"""Closed, priced trades for `wallet` since `since`, filtered to the
|
||||
given system by joining the trigger post's source.
|
||||
|
||||
sys2 = trigger_post.source in System-2 set; sys1 = everything else
|
||||
(currently only "truth"). Trades with no trigger post → treated sys1.
|
||||
sys2 = trigger_post.source in System-2 set OR adopted trade (identified
|
||||
by hl_order_id starting with "adopted:" or sys2_mode being non-NULL).
|
||||
sys1 = everything else (currently only "truth").
|
||||
|
||||
Important: adopted trades have trigger_post_id=NULL so their Post join
|
||||
returns NULL source — they must be identified by the trade row itself,
|
||||
not the linked post.
|
||||
"""
|
||||
from app.models import Post
|
||||
from app.services.signal_categories import SYSTEM_2_SOURCES
|
||||
@@ -80,10 +85,17 @@ async def _trades_for_system(db: AsyncSession, wallet: str, since, system: str):
|
||||
BotTrade.pnl_usd.is_not(None),
|
||||
)
|
||||
.order_by(BotTrade.closed_at.desc())
|
||||
.limit(limit * 4 if limit else None) # fetch a small multiple to account for system filtering
|
||||
)
|
||||
out = []
|
||||
for trade, src in rows.all():
|
||||
is_s2 = (src or "").lower() in SYSTEM_2_SOURCES
|
||||
# Adopted trades: trigger_post_id=NULL, hl_order_id starts with "adopted:"
|
||||
# or sys2_mode is set. Check trade row directly before falling back to source.
|
||||
is_s2 = (
|
||||
(trade.hl_order_id or "").startswith("adopted:")
|
||||
or trade.sys2_mode is not None
|
||||
or (src or "").lower() in SYSTEM_2_SOURCES
|
||||
)
|
||||
if (system == "sys2") == is_s2:
|
||||
out.append(trade)
|
||||
return out
|
||||
@@ -124,9 +136,10 @@ async def check_and_trip(
|
||||
system, wallet, today_pnl, dd_limit)
|
||||
|
||||
if reason is None:
|
||||
# Consecutive losses within this system (all-time, most recent N).
|
||||
# Consecutive losses within this system — only need the most recent
|
||||
# CB_CONSEC_LOSSES trades; no reason to scan full history.
|
||||
all_sys = await _trades_for_system(
|
||||
db, wallet, datetime(1970, 1, 1), system,
|
||||
db, wallet, datetime(1970, 1, 1), system, limit=CB_CONSEC_LOSSES,
|
||||
)
|
||||
recent = all_sys[:CB_CONSEC_LOSSES]
|
||||
if len(recent) >= CB_CONSEC_LOSSES and all((t.pnl_usd or 0) < 0 for t in recent):
|
||||
|
||||
Reference in New Issue
Block a user