The Strategy Studio
The admin screen at /admin/hb/strategies — what a preset row stores, its endpoints and permissions, draft versus published, the six seeded profiles and why editing one silently changes a running bot.
Admin → Hummingbot → Strategy Studio at /admin/hb/strategies is where
controller presets are authored, versioned and published. It is the fourth of
the five Hummingbot admin screens, and it is the one with two very different
audiences: a published preset is what your customers download for their own
Hummingbot, and it is also what your own server-run bots are launched with.
That second half is what makes this screen an operator surface rather than a content editor. Editing a preset is a deployment.
A server-run instance regenerates its controller YAML from the linked preset on every start, and Restart is a start. So changing a spread ladder here does not touch the live process — but the next restart, the next crash auto-restart, and the next server reboot all pick up your edit.
Change a preset an instance is linked to only when you are willing for that bot to run the new parameters, and prefer creating a new preset for anything experimental.
The list
| Column | Holds |
|---|---|
| Preset | name, up to 120 characters |
| Family | pmm or xemm — which controller this becomes |
| Market | The pair in BASE-QUOTE form, with a second line: spot or perp for PMM, or maker <connector> → taker <connector> for XEMM |
| Status | draft or published |
| Version | version, bumped on every update |
| Updated | updatedAt |
| Author | The admin who last saved it, from createdBy. Expanded only |
| Created | createdAt. Expanded only |
| Description | The guidance paragraph. Expanded only — in a row it pushed every other column off the right edge |
The row actions are Preview / download YAML, Publish or Unpublish, Edit preset and Delete; New preset is in the toolbar. Multi-select delete posts to the collection endpoint.
The nine columns tell you which preset a row is; none of them shows what it
would do. The parameters live in the config JSON, and Preview YAML is how
you read them.
What a row actually stores
Table hb_strategy_preset. One row is a complete strategy minus its market.
| Column | Type | Notes |
|---|---|---|
id |
UUID | Primary key, and what hb_instance.presetId points at. Not the controller id — a downloaded YAML derives that from its filename stem, and a server-run bot uses instance-<instance id> |
name |
varchar(120) | Unique only by convention. The seeder matches on it |
description |
text | Up to 2000 characters, collapsed to one line in the YAML header |
family |
enum pmm | xemm |
Drives the form, the validator and the generator |
pair |
varchar(40) | BASE-QUOTE, uppercased, / rewritten to - |
makerConnector |
varchar(60) | Defaults to bicrypto |
takerConnector |
varchar(60), nullable | Required for XEMM, null for PMM |
config |
JSON | The family-specific parameters — the substance of the preset |
status |
enum draft | published |
Defaults to draft |
version |
int | Starts at 1, +1 on every successful update |
createdBy |
UUID, nullable | SET NULL if the admin is deleted, so the preset survives |
pair is only the default a self-hosting user downloads. Every server-run
instance selects its own market and overrides it, which is why the seeded
presets are named for market conditions — Tight, Balanced, Wide — and not for
assets. Full parameter reference: Strategies and presets.
For PMM the generator picks the connector from config.market
(perp → bicrypto_perpetual, otherwise bicrypto), not from makerConnector
— so a PMM preset's stored maker connector is informational. For XEMM both
connectors are used as stored.
The endpoints
A few behaviours worth knowing:
- The list returns up to 500 rows when no
perPageis given, so the instance form's preset picker sees everything rather than the first ten. It runs non-paranoid, because this table has nodeletedAtcolumn — there is no soft delete and no restore. - PUT is a full replace, not a patch. The whole body is re-validated and
re-normalised through the same path as create. That includes the
publish/unpublish action, which is why toggling status also increments
version. - Validation runs twice on write — once on the body, once by rendering the
YAML — and again on export. A config that cannot render is refused with
422 before it is persisted, so a stored preset can never emit malformed
YAML. Common refusals:
buySpreads and buyAmountsPct must have the same length (one per level),maxProfitability must be greater than minProfitability, a connector name outside[a-z0-9_], and a pair that is notBASE-QUOTE. - Deleting is immediate and permanent. Users who already downloaded a
preset keep their copy — their bot runs on their machine — so a delete only
delists it here. What it does affect is your own instances:
presetIdisSET NULL, and an instance with no preset refuses to start with "this instance has no strategy preset, so there would be nothing for Hummingbot to run."
Permissions
| Key | Grants |
|---|---|
access.hb.strategy |
The screen itself |
view.hb.strategy |
Listing presets and rendering one to YAML |
create.hb.strategy |
New preset — including creating one already published |
edit.hb.strategy |
Edit preset, and Publish / Unpublish on an existing row |
delete.hb.strategy |
Delete, single and bulk |
/admin/hb/strategies is gated on view.hb.strategy in the route middleware,
and the section root needs access.hb.
Publishing is not an edit-only act. The Publish / Unpublish row
action is an ordinary PUT, so it needs edit.hb.strategy — but the create
endpoint accepts status in its body, and the New preset dialog carries the
same Draft/Published toggle. A role with view and create but no edit can
therefore release a preset outright, at the moment it authors it; what it cannot
do is change the status of a preset that already exists. If you are handing out
create.hb.strategy to staff who should not be publishing to your customers,
there is no permission that stops them — review the catalogue instead.
Super Admin bypasses permission checks entirely, so a Studio that works for the owner tells you nothing about your staff. Grant the keys in Admin → Roles and open the screen with a configured role.
Draft versus published
status is the only thing standing between a preset and your customers.
draft |
published |
|
|---|---|---|
| Visible in the Studio | Yes | Yes |
Listed at /hb/strategies for users |
No | Yes |
| Downloadable by a user | No — GET /api/hb/strategy/{id}/yaml returns 404 |
Yes |
| Usable by a server-run instance | Yes | Yes |
The user-facing list returns published presets only, newest-updated first,
capped at 200, and is gated by the view_hb KYC feature — the same gate that
guards the connector kit, the setup page and the bot console. It is configured
per level under Admin → CRM → KYC, not on this screen.
Note the asymmetry in the last row: your own instances can run a draft. The supervisor looks up the preset by id and never checks its status, so unpublishing a preset removes it from the customer catalogue without stopping the bots that use it. That is the safe way to retire a profile.
The six seeded presets
backend/seeders/20260729000001-hbStrategyPresets.js seeds six presets, all
with status: "published" and version: 1, so the Studio is not empty on a
fresh install.
| Name | Family | Ladder / targets | Refresh |
|---|---|---|---|
| PMM — Tight (deep, liquid markets) | pmm, spot |
0.0005 / 0.0015 / 0.003 at 15/30/55% | 8s |
| PMM — Balanced (start here) | pmm, spot |
0.002 / 0.005 / 0.01 at 20/30/50% | 12s |
| PMM — Wide (thin or volatile markets) | pmm, spot |
0.005 / 0.015 / 0.03 at 20/30/50% | 25s |
| PMM — Perpetual, conservative (3x) | pmm, perp |
The Balanced ladder at 3× leverage | 12s |
| XEMM — Hedged on Binance | xemm |
Targets 0.001 and 0.002, band 0.0008–0.003 | — |
| XEMM — Hedged on MEXC | xemm |
The same, hedging on MEXC | — |
All six default to BTC-USDT and to modest sizes, but the two families are
sized in different places. The four PMM presets carry totalAmountQuote — 1000
quote, 500 for Wide. The two XEMM presets have no totalAmountQuote at all;
their size is per level, amountQuote 200 then 300, so 500 a side.
They are starting points, not tuned strategies: raise totalAmountQuote on a
PMM preset, or the per-level amountQuote on an XEMM one, to your own size, and
recompute the XEMM targets against your own fee schedule before running any of
them.
What re-running the seeder does
pnpm seed runs every seeder unconditionally — seeder state is not tracked — and
pnpm updator runs pnpm seed, so this happens on every platform update
whether you asked for it or not.
| Your change | What the next seed run does |
|---|---|
| Edited a seeded preset, kept the name | Nothing. The name is present, so it is skipped and your parameters survive |
| Renamed a seeded preset | Re-inserts a fresh copy under the original name, beside your renamed one |
| Deleted a seeded preset | Re-inserts it. "Insert what is missing by name" cannot tell a deletion from a fresh install |
| Created your own presets | Never touched. The seeder only ever inserts its own six names |
It also deletes six legacy names by exact match — the pair-named presets that
shipped before markets moved onto the instance (PMM — BTC/USDT (spot) and its
five siblings). If an instance is still linked to one of those, its presetId
goes to NULL and it must be pointed at a new profile before it will start.
If you do not want one of the six in your catalogue, unpublish it rather than deleting it. Unpublishing survives a seed run; deleting does not. Renaming is the worst of the three — you end up with two.
Authoring a preset
The editor is a purpose-built dialog rather than the generic table form, because which fields exist depends on the family, and within PMM again on spot versus perpetual.
-
Name it for a market condition, not a pair. The market is chosen per deployment and overrides
pair, so a preset called "PMM — BTC/USDT" can and will be run on something else. -
Pick the family. PMM shows the ladder and the risk envelope; XEMM shows the taker venue, the hedge levels and the profitability band.
-
Enter the parameters. Spreads and amounts are comma-separated lists, one entry per level, and the two lists for a side must be the same length. XEMM levels are
targetProfitability:amountQuotepairs. Every field is documented in Strategies and presets. -
Leave the status on
draftuntil it has been validated. -
Save. A 422 names the exact field — the message is written for the person who typed it, so read it rather than guessing.
Validating a preset before you publish
A preset that renders is not a preset that trades. Three checks, in increasing cost:
-
Render the YAML. Row menu → Preview / download YAML. Confirm the
controller_nameis what you expect (bicrypto_pmmorxemm_multiple_levels), the connector matches spot versus perp, and every level you entered is present with the value you meant. The dialog also shows the two filenames a user has to save it under. -
Run one instance against it. Size the preset small first — sizing lives on the preset, not on the instance, so that is a low
totalAmountQuotefor PMM and low per-levelamountQuotefor XEMM. Then register a bot in Bot Instances, pick a real market, press Diagnose, then Start. The instance's YAML is generated from this preset, so this is the preset running for real. -
Read the run log. The instance log tells you the difference between "started" and "working". A market maker can start, stay alive and report RUNNING while never placing an order. Watch for quotes appearing on the instance terminal at
/admin/hb/instances/<id>, and cross-check the account in the Command Center.
Only then set the status to published. Remember that publishing is a PUT and
bumps the version, which is exactly what you want — the version is how you tell
which revision a customer downloaded.
Where to go next
- Strategies and presets — every PMM and XEMM parameter, what it does to a running bot, and how to tune a ladder.
- Bot Instances — running a preset on your own server.
- Reboots, backups and recovery — what to back up, and what the seeder does after an update.
- The admin console — the other four Hummingbot screens.