Connecting a bot to your exchange
The customer-side flow end to end — download the connector kit, install it into a Hummingbot checkout, mint a signed API key, run connect bicrypto, add a controller preset and start it with the V2 flag.
This is what a user does on their own machine, and what you do on yours if you
run a bot outside the Bot Instances panel. The page at
/hb/setup walks the same first four steps with live status derived from the
account's real keys, and adds an optional fifth for the
local agent — so send people there rather than to a copy of
the commands.
What has to be true first
A bot needs four things from the exchange and one of them cannot be put in a file:
| Thing | Where it comes from |
|---|---|
| The connector package | The kit download at /hb/setup — identical for every user |
| An API key and signing secret | /hb/keys. The secret is shown once |
| The exchange's base URL | Shown on /hb/setup, derived from the incoming request |
| A controller preset | /hb/strategies, or authored in the Strategy Studio |
The kit deliberately contains nothing account-specific — no key, no secret,
no base URL. Those belong in connect, not in a zip thousands of people
download, which is also what makes it safe for any authenticated user to fetch.
Step 1 — install the connector
Hummingbot has no idea your exchange exists until a package named bicrypto is
inside its own checkout. Until then connect bicrypto answers "not a valid
connector" and nothing is logged, because Hummingbot's discovery imports each
connector inside a bare except ModuleNotFoundError: continue — an absent or
unimportable connector is silently skipped rather than reported.
Download the kit from Connect your bot, unzip it next to the checkout, and run the installer inside the Hummingbot conda environment:
conda activate hummingbot
python install_connectors.py /path/to/your/hummingbotpython install_connectors.py /path/to/your/hummingbot --doctorpython install_connectors.py /path/to/your/hummingbot --clean| Flag | What it does |
|---|---|
--doctor |
Read-only. Checks the interpreter, the target directories, compares against the shipped kit, and verifies the import the way Hummingbot's own discovery does |
--clean |
Wipes the target directories before copying. This is the fix for a nested or half-copied install |
--force |
Copies over an existing install the audit flagged as broken, instead of refusing |
The installer places both packages (spot and perpetual) and the controller
module, patches setup.py, and then imports everything to prove it worked. If
it reports that setup.py changed, rebuild before starting Hummingbot:
./install && ./compileThe kit carries the connector and the controller module, but no strategy
files, so the installer prints that line and installs no presets. It is a
warning, not a failure — strategies come from /hb/strategies in step 3, where
the operator versions and republishes them, rather than being frozen into a zip
thousands of people already downloaded.
cp -r SRC DST where DST already exists produces DST/bicrypto/bicrypto/ — a
nested package Hummingbot never discovers, with no error anywhere. Use the
installer, or cp -a SRC/. DST/ with the trailing dot.
Run the installer with the same interpreter the bot runs. A verification that passes under a different Python can pass while Hummingbot still fails to import.
Step 2 — mint a key and connect it
Create the key at /hb/keys. Pick the narrowest preset that does the job:
| Preset | Scopes |
|---|---|
| Read-only | hb:read:account, hb:read:market |
| Spot trading | the two reads, plus hb:trade:spot and hb:cancel:spot |
| Perp trading | the two reads, plus hb:trade:perp, hb:cancel:perp, hb:perp:positions |
| Bot control | hb:read:account and hb:control:bot — for the local agent only |
| Full access | everything |
Optional but worth doing: restrict the key by IP, so a leaked secret is unusable from anywhere else, and set an expiry to force rotation. An IP-restricted key with an empty allowlist denies everything — that is deliberate, because an empty list previously meant allow-all and silently defeated the restriction the user had just switched on.
It is never displayed again, it is excluded from every API response, and no administrator can read it. If it is lost, rotate the key to mint a new one. Rotation invalidates the old secret immediately.
Then, inside Hummingbot:
connect bicryptoThree prompts:
| Prompt | Value |
|---|---|
| API key | The key string from /hb/keys |
| API secret | The signing secret shown once at creation or rotation |
| REST base URL | Your exchange URL, e.g. https://your-domain.com |
For perpetuals the connector is bicrypto_perpetual and connects the same way.
The connector refuses to guess a base URL and fails with "Bicrypto base URL is not configured. Run 'connect bicrypto'…" instead of falling back. An earlier build shipped a third-party demo hostname as its default, which meant a correctly configured install was still quietly dialling someone else's server on every launch. If you are upgrading from before that fix, reinstall the kit.
Verify with balance. You should see the assets in the Funding (ECO) wallet
for the spot connector, and the Futures wallet for the perpetual one.
Answering No aborts the whole prompt sequence, including the base URL — which is one of the two ways a bot ends up with no address saved at all.
Step 3 — add a strategy
Download a preset from /hb/strategies. What you get is a V2 controller
config, and Hummingbot never starts one of those directly: a script config
names the controller, and you start the script.
id: my-strategy
controller_name: bicrypto_pmm
controller_type: market_making
connector_name: bicrypto
trading_pair: BTC-USDTscript_file_name: v2_with_controllers.py
controllers_config:
- my-strategy.ymlEvery downloaded preset prints this two-file layout in its own header comment, naming the exact filenames to save it under.
create is the Strategy V1 wizard and only ever offers V1 strategies —
pure_market_making, amm_arb and so on. That is Hummingbot's design;
reinstalling the kit does not change it. bicrypto_pmm is a V2 controller, a
separate system.
Step 4 — start it
conda activate hummingbot
python bin/hummingbot_quickstart.py --headless --v2 my-strategy.ymlOr start --v2 my-strategy.yml from inside an interactive session. The flag
takes the script config's name, resolved against conf/scripts/. Passing the
controller's filename is the usual mistake and fails with "V2 config file not
found". If your build rejects the flag, run start --help — the option name has
moved between Hummingbot releases, and the config files are valid either way.
An MQTT bridge warning every five seconds is expected and unavoidable in headless
mode: Hummingbot forces mqtt_autostart on whenever --headless is passed and
raises if it is off, so there is no configuration that both keeps headless
working and silences the bridge. Nothing in the connector depends on it.
Step 5 — confirm it is actually talking to the exchange
Open /hb/console. The setup page and the console both compute one honest
verdict from the account's real records, because a customer cannot "connect" a
bot from a web page — detecting the link is the only truthful thing either
surface can do:
| Verdict | Means |
|---|---|
| Never connected | No key on the account has ever authenticated |
| Connected | Signed requests are arriving and being accepted |
| Being refused | Requests are arriving and failing — a disabled key, a bad signature, a blocked IP |
| Silent | It authenticated once but nothing has arrived recently; the process has probably exited |
A tie between a success and a rejection in the same second resolves to the rejection. Both are recorded to the nearest second and a bot polls several times a second, so the exact situation this status exists to describe — last success moments before a block, everything since refused — otherwise landed in one second and reported "your bot is connected" during an emergency stop.
Clock drift is the failure nobody expects
Signed requests carry a timestamp and are refused more than 10 seconds away from the exchange's clock. The rejection is recorded against the key and names the direction and size of the drift:
Request outside recvWindow: this machine's clock is 12400ms ahead of the
exchange, limit 10000ms. Sync the clock on the machine running the bot.Being ahead is the case people do not expect a receive window to reject, which is why the direction is stated rather than an absolute difference. Enable NTP on the bot's host. Anything drifting more than five minutes is refused before the key is even looked up, so probe traffic never reaches your account records.
Where to go next
- Strategies and presets — every PMM and XEMM parameter, and how to tune them.
- Monitoring and stopping bots — the console, the emergency stop and the optional local agent.
- Troubleshooting —
connectnot listing the connector, empty balances, empty books.