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:
@@ -31,9 +31,10 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timezone
|
||||
from typing import Dict, Optional
|
||||
from typing import Optional
|
||||
|
||||
from sqlalchemy import select, update
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
@@ -66,14 +67,28 @@ ADOPTED_CATEGORY = "btc_bottom_reversal_long"
|
||||
# (each row would race to reduce the position). Process-local; with the
|
||||
# atomic duplicate check inside the lock, multi-process deploys are still
|
||||
# safe (losers would just see "already_adopted" on the second attempt).
|
||||
_adopt_locks: Dict[str, asyncio.Lock] = {}
|
||||
#
|
||||
# Capacity-capped at _ADOPT_LOCK_MAX (matches _WALLET_LOCK_MAX in bot_engine)
|
||||
# to prevent unbounded growth if many unique wallets pass through. LRU
|
||||
# eviction: evicting an in-flight lock is safe — the holder already holds a
|
||||
# reference; new adopt for that wallet just gets a fresh lock.
|
||||
_ADOPT_LOCK_MAX = 512
|
||||
_adopt_locks: OrderedDict[str, asyncio.Lock] = OrderedDict()
|
||||
|
||||
|
||||
def _wallet_adopt_lock(wallet: str) -> asyncio.Lock:
|
||||
lock = _adopt_locks.get(wallet)
|
||||
if lock is None:
|
||||
if len(_adopt_locks) >= _ADOPT_LOCK_MAX:
|
||||
# Evict LRU entry. The evicted lock object stays alive as long as
|
||||
# any coroutine holds a reference to it — eviction only means it
|
||||
# won't be reused, not that it's freed mid-acquire.
|
||||
_adopt_locks.popitem(last=False)
|
||||
lock = asyncio.Lock()
|
||||
_adopt_locks[wallet] = lock
|
||||
else:
|
||||
# Promote to MRU position.
|
||||
_adopt_locks.move_to_end(wallet)
|
||||
return lock
|
||||
|
||||
|
||||
@@ -311,6 +326,20 @@ async def _adopt_locked(wallet_l: str, asset_u: str, mode_n: str) -> AdoptionRes
|
||||
lev_info = target.get("leverage") or {}
|
||||
leverage = int(lev_info.get("value") or sub.leverage or 2)
|
||||
|
||||
# BUG-09 guard: sys2_protective_stop_pct clamps leverage to SYS2_MAX_LEVERAGE
|
||||
# when computing the stop distance. If the actual position is above that cap
|
||||
# the computed stop is WIDER than the real liquidation band — the user could
|
||||
# get HL-liquidated before our stop fires. Reject up front with a clear
|
||||
# error so the user knows to reduce leverage on HL before adopting.
|
||||
if leverage > SYS2_MAX_LEVERAGE:
|
||||
raise AdoptionError(
|
||||
"leverage_too_high",
|
||||
f"{asset_u} position is at {leverage}× leverage. "
|
||||
f"The bot's System-2 strategy supports up to {SYS2_MAX_LEVERAGE}×. "
|
||||
f"Reduce leverage on Hyperliquid to ≤{SYS2_MAX_LEVERAGE}× first, "
|
||||
"then try /adopt again.",
|
||||
)
|
||||
|
||||
# Build the System-2 exit profile against the ACTUAL HL leverage so the
|
||||
# protective stop is always inside the real liquidation line. Identical
|
||||
# math to bot_engine's old sys2 open path; reused so behaviour stays
|
||||
|
||||
Reference in New Issue
Block a user