Skip to content

Fix/hyperliquid price and config sync - #187

Open
SpicySOB wants to merge 13 commits into
hummingbot:mainfrom
SpicySOB:fix/hyperliquid-price-and-config-sync
Open

Fix/hyperliquid price and config sync#187
SpicySOB wants to merge 13 commits into
hummingbot:mainfrom
SpicySOB:fix/hyperliquid-price-and-config-sync

Conversation

@SpicySOB

Copy link
Copy Markdown

No description provided.

SpicySOB and others added 13 commits July 28, 2026 23:15
- Default hummingbot deploys to a custom image (condor/hummingbot:hyperliquid-price-fix)
  that patches hyperliquid_perpetual_derivative.quantize_order_price: the stock
  implementation constructs a Decimal directly from a rounded float, reintroducing
  binary floating-point noise, and always rounds to a flat 6 decimals regardless of a
  pair's real tick size -- both cause "Order has invalid price" rejections on
  lower-priced pairs. Wired as the default everywhere a bot can be deployed from
  Condor (Telegram wizard, web dashboard, MCP tools).
- Always pass headless=true when deploying v2-controller bots (deploy_v2_controllers_headless
  in handlers/bots/_shared.py), since hummingbot_api_client's wrapper doesn't expose that
  param and without it a bot trades normally but is invisible to Condor's MQTT-based
  status/discovery layer.
- Fix BotDetail.tsx's config editor: saving from a running bot's own page only updated
  the design-time config store, never the live bot (there's no redeploy button on that
  page, so Save was the only way to change a running bot). Now pushes to the live bot's
  controller config first (for is_updatable fields), then syncs the design-time store.
- Add schema validation (with closest-field-name suggestions) to the web dashboard's
  raw-paste config save routes, which previously accepted any field names and only
  failed later, opaquely, at strategy startup.
… coupling

- Point the Hyperliquid builder-code approval at the operator's own address at 0 fee
  (attribution only), replacing the Hummingbot Foundation builder wallet/fee.
- Decouple WEB_PORT (local uvicorn bind port) from WEB_URL (public-facing URL used
  for generated links and CORS) -- behind a reverse proxy these are different ports,
  and an https:// WEB_URL used to silently mean "bind to 443", which fails without root.
- Always include a copyable raw link in the Telegram /web command's message text, not
  just an inline button URL, since some Telegram clients (e.g. a mobile wallet's
  in-app browser) don't expose a way to copy a button's URL.

Removes agents/market_making_expert/strategies/pmm_mister_operator/strategy.md, already
absent from the working tree prior to this commit.
Rolls the new cumulative image forward everywhere a Hyperliquid bot can
be deployed from Condor (Telegram wizard, web dashboard, MCP tools).
The image now bundles the price-quantize fix, WS order/cancel
submission, retry backoff, and a fix for _place_cancel crashing on
Hyperliquid's flat {"status":"err"} response shape (see the connector
fork commit fe5a3d63d on condor-main).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
hummingbot's v2 controllers don't sync positions_held against the real
wallet on their own -- it's seeded once from initial_positions at
startup and otherwise built up only from that controller instance's own
executor fills. Every fresh deploy, including a redeploy of an existing
bot (e.g. to pick up a new image or config), resets that tracking to
empty, so a controller can silently fall behind the real exchange
position -- including the max_base_pct safety cap, which stops
protecting once the real position runs ahead of what the controller
thinks it holds.

Seeds initial_positions from live exchange state (via
client.trading.get_positions) immediately before every deploy, wired
into both deploy_v2_controllers_headless and the MCP deploy_bot tool.
Best-effort: a reconciliation failure is logged and swallowed rather
than blocking the deploy, since the fallback (start from zero) is the
pre-existing, already-safe behavior.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Per-controller volume_traded/global_pnl_quote from hummingbot-api resets on
every redeploy, making cumulative daily/weekly PnL tracking unreliable
across restarts (confirmed live 2026-07-29). This adds a panel sourced
directly from Hyperliquid's own fill history (closedPnl per fill), scoped
to (account, coin, time window) instead of any specific bot process, so it
survives redeploys.

Backend: handlers/bots/hyperliquid_pnl.py fetches+paginates userFillsByTime
and sums by coin; new GET /servers/{name}/pnl-summary endpoint in
condor/web/routes/bots.py; HYPERLIQUID_ADDRESS env var in utils/config.py.

Frontend: PnlRangeSummary.tsx component wired into ActiveBotsTab, period
selector (Today/7D/30D), api.ts client method.

Note: activeCoins passed into the panel is currently derived from
currently-running controllers only, so a stopped bot's realized PnL drops
out of the total -- tracked as a known follow-up, not fixed in this commit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…aths

hummingbot_api_client's stop_and_archive_bot() defaults
skip_order_cancellation=True (the opposite of its own stop_bot()'s
default=False), so both the dashboard's stop-bot flow
(mcp_servers/hummingbot_api/tools/bot_management.py::manage_bot_execution)
and the Telegram "Stop Bot" confirm flow (handlers/bots/menu.py::
handle_confirm_stop_bot, which additionally passed the unsafe value
explicitly) could leave resting orders orphaned on the exchange when a bot
is stopped. Both now pass skip_order_cancellation=False explicitly.

Also removed a stray `await client.bot_orchestration.deploy_v2_controllers()`
call in controllers.py::modify_controllers' config-delete branch: it was
called with zero arguments against a method that requires instance_name/
credentials_profile/controllers_config, so it would always raise TypeError,
and it contradicted the function's own documented "does NOT affect running
bots" contract for this design-time-only operation.

Audited every other client.bot_orchestration/.controllers/.trading call
site in mcp_servers/hummingbot_api/tools/ and handlers/bots/ for similarly
risky unreviewed defaults (archive_locally, deploy image defaults,
deploy_v2_controllers/_headless call sites, set_leverage/set_position_mode,
delete_* calls) -- no other unsafe defaults found.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…coped

The panel's coin filter was derived from activeCoins, built only from
currently-running controllers (ActiveBotsTab.tsx). Effect: the instant a
bot is stopped, its already-realized PnL from earlier in the window
silently drops out of "Today/7D/30D" totals -- the exact bug this panel
was built to avoid (see handlers/bots/hyperliquid_pnl.py docstring).

Now passes coins=[] (no filter) so the summary is truly account-wide and
matches its own "survives restarts/redeploys" framing -- a stopped bot's
fills stay counted for the rest of the window regardless of controller
status. PnlRangeSummary's query `enabled` condition updated accordingly
(was gated on coins.length > 0, which would always be false now).

Frontend rebuilt (dist/ is gitignored, not part of this commit) so the
change is live without a backend restart.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Codifies the rules learned from tonight's incident: never bypass Condor's
own deploy/stop wrappers with raw hummingbot-api calls, the image and
controller-code sync mechanism (build_condor_image.sh), the trust
hierarchy for PnL/position data (Hyperliquid fills first, positions_summary
never for pmm_mister), order-cancellation safety, rate-limit sharing, and
pmm_mister's dangerous silent defaults. Read at the start of every session
touching this infra, per the same pattern already used in POLY-ETH15.
…r scratch clones

More dangerous than the same mistake in /home/nate/condor: that checkout is
durable and persists on the VPS even if left uncommitted. Hummingbot-Condor
has no durable local checkout at all -- it only exists in a session's
ephemeral scratchpad, so an uncommitted change there is on a countdown to
actually vanishing, not just bad practice. This is exactly how the original
image's working copy was lost, requiring a from-scratch re-discovery
2026-07-31. Rule going forward: commit + push immediately after editing
anything in that clone, not batched.
Restarting several bots at once stacks each one's independent
leverage/order-placement/cancellation burst on top of the others, and can
blow through the rate limit even when each bot's rate_limits_share_pct is
correctly sized for steady-state. Seen directly restarting kPEPE and AVAX
pmm_dynamic validation bots together on 2026-07-31.
grok agent stdio speaks ACP natively (no npm bridge needed, unlike
codex). Auth rides on the grok CLI's own cached login (SuperGrok/
grok.com OAuth via `grok login --device-auth`), not xAI's metered
api.x.ai surface -- confirmed via a live ACP initialize handshake.

Also required (done separately, not part of this commit): the grok
binary installed to ~/.local/bin and added to condor.service's PATH,
since asyncio.create_subprocess_shell only sees the unit's own
environment, not the interactive shell's.
Creates market_making_expert.avax_strategy with deploy-time params
(TP 12bps, mild min_skew 0.35, $400 budget) and monitoring runbook.
Also points the MM expert agent at grok-build/local for this host.
Reflect the intentional controller swap: stop/archive the mister bot,
deploy mm_avax_dynamic_v2, and document NATR/MACD baseline params.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant