Hummingbot Connector 6.0.7

11 August 2026

This release has upgrade notes. Read them before updating — they describe behaviour changes that need your attention.

CRITICAL FIXESORDER PLACEMENTSTRATEGY PRESETSMARKET MAKINGCONNECTORPERPETUALSCONNECTOR KITBOT INSTANCESMARKET DATASUPERVISORAPI KEYSIP ALLOWLIST

Hummingbot Connector v6.0.7

Release Date: August 11, 2026 Tags: CRITICAL FIXES, ORDER PLACEMENT, STRATEGY PRESETS, MARKET MAKING, CONNECTOR, PERPETUALS, CONNECTOR KIT, BOT INSTANCES, MARKET DATA, SUPERVISOR, API KEYS, IP ALLOWLIST

Overview

If you run a PMM strategy on this connector, it has never placed an order.

The bundled PMM controller was missing the one piece that turns a strategy into resting orders, so it failed on every tick, for the life of the process — while the panel showed Running. This affects every PMM preset the Strategy Studio generates. XEMM presets are unaffected and have been quoting normally.

Two more things need a decision first. On a standard install with Apache or nginx in front, and this addon's proxy flag at its default, every signed request looked like it came from the proxy rather than from the bot — so an API key with IP restriction switched on was either refusing its own bot or admitting anyone who held the key. And where two backend processes ran on one host, both could launch a bot for the same instance — two market makers on one account, only one of which the panel could see and stop.

Read Upgrade Notes before restarting. Idle presets will begin quoting the moment they restart, at a size never once tested against a live book, and IP allowlists may need editing first.

Requires Core v6.6.3.

Update Instructions

pnpm updator

This release also requires a connector reinstall. pnpm updator delivers everything on the platform side — the address a signed request resolves to, the duplicate-launch guard, the cleanup of a stopped bot's resting orders — and those take effect as soon as the backend restarts. But the PMM controller and both connectors are Python that runs inside your Hummingbot checkout, and until you reinstall them there a PMM bot still places nothing. Reinstall into every checkout you run a bot from, from your platform root (public_html), in the Hummingbot conda environment:

conda activate hummingbot
python hummingbot/install_connectors.py /path/to/hummingbot

The conda environment matters: run it against the wrong interpreter and it installs files the Hummingbot that actually runs your bot will never import. The installer checks this for you and says so.

Then restart your instances — and restart the backend too, so the supervisor picks up the new build. The installer overwrites the controller and both connectors, adds any example preset you do not already have, and never overwrites a preset file you have edited, so any tuning you have done survives and is named back to you as it runs. There is no ./compile step — every changed file is pure Python — and no database migration.


Highlights

Why a bot that looked healthy placed nothing

Nothing about the failure was visible from outside the process. The bot logged "Strategy started successfully", the connector reached ready, memory sat at a normal footprint, and the panel reported Running. It simply never quoted — one failure per tick, once a second, for as long as the process stayed up, and not a single order in between.

The cause was inheritance. The bundled controller took everything from Hummingbot's market-making base class, including the one method that base deliberately leaves for its subclasses to implement. Left unwritten, every tick asked the strategy what orders to place and got an error instead. Bots started by hand were affected exactly as much as bots started from the panel, because both run the same controller.


Upgrade Notes

Your PMM presets will start quoting for the first time — check their sizing first

A PMM instance that has been showing Running was not trading. After this update it will be. Everything it was configured with has therefore never been exercised against a live book: the ladder, the per-level allocations, and above all the total quote notional the preset puts at risk across all its levels.

  • Before restarting, open each PMM preset and confirm total notional, level allocations and spreads are what you would choose today. A figure typed in weeks ago while trying to work out why nothing was happening is not a figure anyone signed off.
  • Restart one instance first and watch the book, rather than restarting a fleet.

An IP-restricted API key will see a different address after this update — check your allowlists first

On an install with a reverse proxy in front — the deployment this product documents, and almost certainly yours — a signed request used to present the proxy's own address rather than the bot's, unless you had set HB_TRUST_PROXY=true. After this update it presents the caller's. Any allowlist entry you added to work around the old behaviour will now refuse that bot, and any entry naming the machine your bot actually runs on, which until now silently rejected every request, will start working.

  • Open every API key that has IP restriction switched on and confirm each entry names a machine you run a bot from. An entry of 127.0.0.1, or your proxy's address, refuses that bot from the moment you update.
  • If one of your keys had the proxy's address on its allowlist, that restriction was admitting anyone in the world who held the key and secret, for as long as it was set that way. Review that key's recent use before you carry on with it, and rotate the secret if you cannot account for it.
  • HB_TRUST_PROXY=true still works and needs no edit. The address it resolves is now validated and canonicalised the way the rest of the platform does it, and hops belonging to your own proxies are stepped over, so a chain with two proxies in it no longer stops at the inner one.
  • If the platform's own TRUST_PROXY is also set, the platform's setting governs and this one is ignored, so the addon and the rest of the install can no longer disagree about who is calling.
  • Keys with IP restriction off are unaffected, and nothing here changes whether a signature verifies.

If you ever saw two bots for one instance, you have a second backend running

The duplicate launch needs two backend processes on the same host — normally an orphan that outlived a restart. The platform now refuses to launch the second bot and writes a line to that instance's log naming the condition, but it does not clean up the process that caused it, and two backends will still contend over scheduled jobs and live updates.

  • If you see that line, find and stop the extra backend process.

Changed

The market-data feed your bots read

Every connected bot reads the same public feed: order books and depth five times a second per market by default, alongside trades, tickers, mark prices and funding rates on their own cadences. The platform used to assemble each update separately for every listener, so ten bots watching one market meant the same order-book message built ten times over — fifty times a second for that one market, of which nine in every ten were redundant duplicates of work already done for the bot next door.

  • Changed the public feed to assemble each update once per broadcast rather than once per listener, so the cost of a busy market no longer climbs with every bot that connects to it.
  • Changed only how the message is built, not who gets it or what it contains. A bot whose connection has fallen behind is still skipped for that update exactly as before, and the private per-account streams are untouched.

What you were told about running two backends was wrong

  • Changed the guarantee published in the 6.0.3 note, which stated that exactly one supervisor is active "even when the backend runs across several processes". It held across worker threads inside one process — the case that arises in normal operation — but nothing enforced it across separate processes, which is the case that actually produced two market makers on one account. Something enforces it now; see Fixed below.

The guidance for writing your own controller pointed the wrong way

  • Changed the description the bundled PMM controller carries of itself, which called it the stock market maker with tuned defaults and nothing overridden. Anyone who took that as the model for their own controller would have inherited the same silent fault. It now states plainly that a market-making controller which implements nothing places no orders, and names the method that has to be written.

The setup guide described an installer that installs no strategies

Setup told you to expect a warning that no presets had been installed, and that strategy files only ever come from the exchange. That has not been true for some time: the installer places the PMM controller in the folder Hummingbot resolves a market-making controller by name in, and copies the example presets alongside it. A reader had no reason to look for either, or to know their own edits were safe.

  • Changed the setup guide to describe what the installer actually does, including that a preset file you have already tuned is kept rather than overwritten and is named back to you as the install runs.
  • Changed the guide to explain why the create wizard never offers the bundled controller and why reinstalling will not change that — it is the older strategy system, and a controller is started from a script config that names it. Its absence from that list reads like a failed install and is not one.

Fixed

A PMM bot started cleanly, reported healthy, and placed nothing

Hummingbot's market-making base class builds the ladder — levels, spreads, sizes — and decides when to refresh, but it cannot know what one level should become, so it leaves that decision to the controller and refuses to guess. The bundled controller never made it, on the stated reasoning that the base class already did everything needed. Nothing surfaced that: every indicator an operator has said the bot was fine, and the only symptom was NotImplementedError repeating in the bot log, which reads like noise next to the connector's normal startup chatter. That is still the shape a failure like this takes — this release removes the fault rather than making it easier to spot.

  • Fixed the bundled PMM controller failing on every refresh of every level, in both spot and perpetual presets. It now builds a position executor per level, carrying that level's price and size along with the preset's stop loss, take profit, time limit and leverage — the risk settings the Strategy Studio has always written into the file and which, until now, no order ever reached.

The connectors could not report a last traded price

Both the spot and perpetual connectors were missing the method Hummingbot calls for a market's most recent traded price, so every attempt failed and logged Error getting last traded price in connector ... against each pair, on every refresh, for the life of the process.

  • Fixed the spot connector, which now answers from the same ticker endpoint the order book already uses.
  • Fixed the perpetual connector, which answers with the contract's mark price, falling back to the order book mid when no mark has been published yet.
  • This was never fatal — the error was caught and the bot continued — but it left the platform with no last price for your venue, which quietly degraded currency conversion in reporting and gave nothing at all to any strategy that quotes from the last traded price rather than the mid.
  • Fixed the same message when it names no cause. Hummingbot builds unconfigured connector instances for its own internal price lookups, and those have no exchange address and never could fetch anything. Each attempt now says exactly that, in one line, instead of a stack trace followed by an unexplained error. It still says it on every lookup, and a connector that is actually trading is unaffected either way.

A stopped bot left its orders resting on the book

Hummingbot cancels its own orders when it shuts down, and it does exactly that when you stop it from inside its own console. Stop in the panel is a different path: it signals the process, and Python ends an unhandled signal by terminating the interpreter outright — no cleanup, nothing awaited. Measured on a real stop, the bot was gone 35 milliseconds after the signal. A 90-second run placed 38 orders, cancelled 31 of them as it re-quoted, filled none, and left the remaining 7 resting on the book at prices nothing was managing any more.

It is fixed in two places, because neither one alone covers every way a bot stops.

  • Added a shutdown handler to the bot process itself, so a panel stop now behaves like Hummingbot's own: the bot cancels its own orders — and only its own — then exits. This is the one that matters day to day, because it distinguishes the bot's orders from everything else on your account, which nothing outside the process can do.
  • Fixed the orders outliving the process in the cases no in-process handler can ever cover: a crash, the memory ceiling, an out-of-memory kill, a host reboot. Once the process is confirmed gone the platform clears up on the bot's behalf.
  • Added a line in the instance log from both, saying how many orders were pulled, so a stop that cleaned up after itself says so rather than leaving you to go and check the book.
  • Your Hummingbot checkout is not modified to get this. There is nothing extra to install and nothing for a git pull to quietly revert.
  • The handler is bounded at 15 seconds and cannot hold a stop open: a second stop goes through immediately, a stuck exchange is abandoned after 8, and the forced kill still lands regardless. The grace period before that forced kill was never the protection it appeared to be — it only ever helps a process that survives the first signal, and until now this one did not.

When the platform clears up on a dead bot's behalf, it has to answer a question the order itself cannot: which of these were the bot's? The matching engine records an order against an account and keeps no trace of the API key behind it. What the signed bot endpoints do keep, and a manual placement never gets, is a client-order-id mapping written for every order a connector places on both spot and perpetual. That is used as the test.

  • Orders you placed by hand are not touched — on the same pair as a running bot or anywhere else. You do not have to keep bots off markets you also trade by hand.
  • If that mapping cannot be read — Redis unreachable — the cleanup widens to every open order on the bot's market rather than cancelling nothing, and says so in the instance log. Cancelling too much beats leaving a dead market maker quoting.
  • An order resting longer than seven days outlives the mapping and reads as hand-placed. Market makers re-quote on a timer measured in seconds, so this does not arise for them.
  • Positions and balances are never touched — resting orders only, and only on the Bicrypto side. An XEMM strategy's hedge venue is your own account on Binance or MEXC and is not ours to reach into.

A rejected order blamed the server when the account was simply short

An order whose funds were held between the balance check and the hold was rejected with "Failed to update wallet balance. Order rolled back." as a 500, the code that means the platform broke. The rollback was correct — no order was ever left unfunded — but the message told operators nothing and the status code sent them looking for an outage. It happens under ordinary concurrency: several orders placed at once, or a fill landing in between.

  • Fixed the reported reason. A shortfall now says which currency was short, how much was available and how much was needed, and returns a client-side 4xx instead of a server error. Genuinely unexpected failures keep the 500 and the old wording.

An underfunded bot said nothing at start and then failed on every order

A market maker with nothing to trade does not fail: it starts, reports Running, and has every order refused. One real run logged 921 rejections in 90 seconds — 461 for the quote currency and 460 for the base — which reads as a wall of noise rather than "the account is empty".

  • Added a funding check when an instance starts. It states plainly which side cannot be quoted and why, next to the amount the preset is configured to deploy.
  • It warns rather than refuses. A two-sided maker legitimately starts holding only quote and builds inventory by buying first, and blocking that would be wrong. If the log fills with "Insufficient balance", the reason is now the first thing above it.

Every bot behind your reverse proxy looked like the same caller

A signed request carries a source address, and the connector uses it for two things: the IP allowlist on the API key, and the throttle in front of the unsigned market-data endpoints. It took that address from the network connection itself, which on an install with Apache or nginx in front — the deployment this product documents, with the proxy on the same host — is the proxy, not the machine running the bot. The forwarded address was consulted only if you had set HB_TRUST_PROXY=true, and even then it was taken as written, so a hop recorded with a port on the end, or in the IPv6 form a dual-stack socket produces, could never match an allowlist entry an operator had typed as a plain address.

  • Fixed an IP-restricted key refusing its own bot. The address compared against your allowlist was the proxy's, so a key restricted to the address your bot actually runs from rejected every signed request with IP not allowed for this key — and a key restricted to the proxy's address instead admitted any caller anywhere who held that key and secret. Requests now resolve to the caller's real address, following the platform's TRUST_PROXY and TRUST_PROXY_CIDRS settings rather than a second copy of that policy kept here. See Upgrade Notes before you restart a bot on a restricted key.
  • Fixed the per-address throttle on the public market-data endpoints metering every bot on the install into one bucket, because every one of them presented the proxy's address. A single busy client could exhaust the market-data budget for everybody else; the same requests are now counted per caller.
  • Fixed the last used from address recorded against a key, which showed the proxy for every key on every install and so told you nothing about who had been using it.
  • A forwarded address is believed only when the connection arrives from a proxy you actually have — loopback by default, or whatever you declare — and the chain is read from the end a proxy appends to, so a caller cannot choose their own address by sending a header. A hop that cannot be read as an address stops the search rather than being trusted.

Two backend processes could each launch a bot for the same instance

Starting an instance runs a sequence of checks and provisioning steps before the new process id is recorded. Throughout that window the instance still reads as nothing is running here, and a second backend reading it at that moment would start a bot of its own. Both then provisioned the same credentials and traded the same account.

  • Fixed the launch being unguarded across processes. It is now claimed in a single atomic step, so a second process finds the instance already taken and starts nothing.
  • Fixed the panel losing track of one of the two bots. Only the second launch's process id survived on the record, so Stop reached one bot and left the other quoting.
  • Added a line in the losing process's instance log naming the condition, so it appears where you are already looking rather than being silently absorbed.
  • A claim left behind by a backend killed mid-launch — a crash, an out-of-memory kill, a host reboot — expires on its own after two minutes rather than leaving the instance unable to start.