feat: DEX/LP dashboard candles + symbols, and uniform bot-mode agent attribution - #169
Open
fengtality wants to merge 5 commits into
Open
feat: DEX/LP dashboard candles + symbols, and uniform bot-mode agent attribution#169fengtality wants to merge 5 commits into
fengtality wants to merge 5 commits into
Conversation
LP/DEX executors (connector solana-mainnet-beta, trading_pair <mint>-SOL) had no candle feed — hummingbot's CandlesFactory is CEX-only, so charts showed "Failed to load candles" — and rendered raw base-mint addresses instead of tickers. This adds, all via GeckoTerminal (the same source the pools feature and Telegram LP report already use): - Pool candles: /market/candles now detects a DEX-network connector (or an explicit pool_address) and fetches OHLCV from GeckoTerminal instead of the CEX feed. It tries the executor's own pool_address, then falls back to the base token's top live pool resolved from the mint — so a live token always charts even when the passed pool is stale/absent. Reuses handlers.dex.pool_data.fetch_ohlcv and its cache. - /market/token-symbol: server-independent mint -> ticker resolver (GeckoTerminal token info, cached 24h). - PairLabel: renders a raw base-mint pair as <SYMBOL>-<QUOTE>, applied across the executor table + detail, agent session view (group header, chart title, positions), archived performance chart, and the agent market strip. Non-mint (CEX) pairs render unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T9Vygff6wPFpmZb5gahuW4
…ndow Adversarial-review follow-ups on the pool-candle path: 1. DEX candles ignored the requested window. fetch_ohlcv hardcoded limit=100 with no before_timestamp, so archived executors charted against the *latest* candles instead of the ones they traded in — overlays landed on an unrelated time axis. Thread limit + before_timestamp through fetch_ohlcv → _fetch_pool_candles_raw → _get_pool_candles, and pass the chart's window (bucketed_end) from the route. Verified against GeckoTerminal: before_timestamp walks history back to that window. limit is capped at GeckoTerminal's 1000. before_timestamp/limit are now part of fetch_ohlcv's cache key so a historical and a live window for the same pool don't collide. 2. Transient failures were cached as negative results. A single blip in _resolve_token_top_pool / get_token_symbol cached "" for 1h / 24h, blanking a resolvable pool/ticker long after the API recovered. Only cache on a successful API response (empty included — a genuinely unknown mint is worth remembering); an exception now returns uncached so the next render retries. 3. ArchivedPerformanceCharts now passes the executor's pool_address, so archived DEX charts use the exact pool the position traded in rather than the token's current top pool. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T9Vygff6wPFpmZb5gahuW4
…t_name
Bot-mode sessions whose bot name is derived at runtime (e.g. pmm_mister's
{base}-mm) never persisted it, so every consumer keyed on the session's
bot_name — CORE DATA totals, the dashboard session executors/PnL, the
metrics timeline, the strategy performance rollup — rendered an empty
session while the bot traded. Only strategies with a static name in
default_config (hip_3_delta_neutral_funding_mm) attributed correctly.
Root cause found on the way: the claude-agent-acp adapter sends tool
arguments as ACP wire field `rawInput`, while condor read `input` — so on
the claude-code path EVERY tool call arrived argument-less. That silently
disabled the risk engine's deploy-cap check, dry-run action blocking, and
controller_id validation, and left snapshots without Input blocks.
- condor/acp/client.py: normalize rawInput -> input at the boundary, for
both streamed tool_call/tool_call_update events and permission requests
(fold input from updates too). PydanticAI path already sent `input`.
- condor/agents/engine.py: _capture_bot_name — watch the tick's tool calls
for a successful manage_bots(action="deploy") and persist the deployed
bot_name into the session's config.yml (same place the delta-neutral
strategy keeps its static name), preserving the file's mtime, which
doubles as the session-start epoch for history window tiling. Works for
every strategy with zero strategy.md changes; executor-mode strategies
(lp_slot_operator) never deploy so nothing changes for them.
- condor/web/routes/agents.py: session-executors endpoint now resolves the
bot for non-operator (closed) sessions too, attributing that session's
time-window slice of the bot's history (same tiling as
_apply_bot_mode_pnl) instead of returning an empty page; response model
now carries bot_name + per-controller breakdown (previously computed and
dropped).
- frontend/src/lib/api.ts: AgentPerformance gains optional bot_name /
controllers.
Known residual gap: a bot instance that vanished from the
controller-performance tables AND whose archived sqlite the archived-bots
analyzer can't parse (upstream "cumsum is not supported for object dtype"
500) cannot be attributed; its sessions honestly show zero.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T9Vygff6wPFpmZb5gahuW4
…address params The OHLCV cache key now includes limit/before_timestamp, which rotates by the minute for live charts — with no eviction on the get/set path the web route's process-lifetime dict grew without bound (~0.3MB per entry). Sweep expired entries on every cache miss, same contract cached_call already has. Also reject a mint (base58) or pool_address (base58/0x-hex) that doesn't look like an address before interpolating it into a GeckoTerminal URL. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T9Vygff6wPFpmZb5gahuW4
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T9Vygff6wPFpmZb5gahuW4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
LP/DEX executors (connector
solana-mainnet-beta,trading_pair=<mint>-SOL) had two dashboard gaps:CandlesFactoryis CEX-only, so their charts showed "Failed to load candles" (502).DezXAZ8z7…263-SOLinstead ofBonk-SOL).Additionally, bot-mode agent sessions rendered empty (no executors, flat $0 PnL) whenever the strategy derives its bot name at runtime (e.g. pmm_mister's
{base}-mm) — the session never recorded which bot it operated, so nothing could attribute the bot's PnL back to it.Changes
DEX candles + symbols (all via GeckoTerminal — same source as the pools feature + Telegram LP report)
GET /market/candlesdetects a DEX-network connector (or explicitpool_address) and fetches OHLCV from GeckoTerminal instead of the CEX feed. Tries the executor's ownpool_address, then falls back to the base token's top live pool resolved from the mint. Reuseshandlers.dex.pool_data.fetch_ohlcv+ cache.fetch_ohlcvgainedlimit/before_timestamp(threaded from the chart's requested window), so archived executors chart against the candles they actually traded in, not the latest 100. Verified against GeckoTerminal's API.GET /market/token-symbol— server-independent mint→ticker resolver (24h cache).PairLabel— renders a raw base-mint pair as<SYMBOL>-<QUOTE>across executor table + detail, session view, archived charts, and the market strip. CEX pairs render unchanged.Bot-mode attribution (
6fbe36f)rawInputfix (latent, serious) — the claude-agent-acp adapter sends tool arguments as ACP wire fieldrawInput; condor readinput, so on the claude-code path every tool call arrived argument-less. This silently disabled the risk engine's deploy loss-cap check, dry-run action blocking, and controller_id validation, and left snapshots without Input blocks. Now normalized at the client boundary (streamed events + permission requests).bot_name—TickEnginewatches each tick's tool calls for a successfulmanage_bots(action="deploy")and persists the bot name into the session'sconfig.yml(the same place static-named strategies keep it), preserving the file's mtime (it doubles as the session-start epoch for PnL window tiling). Works for every strategy with zero strategy.md changes; executor-mode strategies are untouched.bot_name+ per-controller breakdown (previously computed then dropped).Review hardening (
421df77)limit/before_timestamp(rotates by the minute for live charts), which turned the web route's process-lifetime cache dict into unbounded growth.fetch_ohlcvnow sweeps expired entries on every cache miss (same contractcached_callalready has).mint(base58) andpool_address(base58/0x-hex) are rejected with 400 before being interpolated into GeckoTerminal URLs.Notes
before_timestampwindow confirmed). Bot attribution verified live: pmm_mister session 4 now reports its bot's total −$13.89 / $45.8k volume through the real endpoint.cumsum is not supported for object dtype) can't be attributed; affected sessions honestly show zero. Historical journal metrics lines are immutable — past flat-$0 timelines stay, new ticks record real values.🤖 Generated with Claude Code
https://claude.ai/code/session_01T9Vygff6wPFpmZb5gahuW4