Creating and configuring a market
The four-step create wizard, every field it writes and the validation that rejects it, plus the price controls that only appear afterwards — price mode, bias, forced phase, volatility and the target price.
A market maker attaches one-to-one to an ecosystem market. The marketId column
carries a unique index, so the second attempt on the same pair is refused with
"AI Market Maker already exists for this market".
Creation happens in a four-step wizard at /admin/ai/market-maker/market/create. Everything else — price mode, bias, phase, volatility, the running-state controls — lives on the market's own Configuration tab afterwards.
What creation actually produces
One request writes four things in a single transaction:
- the market maker row, status STOPPED;
- a pool with zero balances on both sides;
- six bots, all PAUSED — Scalper Alpha, Scalper Beta, Swing Trader, Accumulator, Distributor and Market Maker;
- a
CONFIG_CHANGEhistory entry recording the parameters it was created with.
Nothing trades. The market is created stopped on purpose: it has to be funded and started deliberately.
Step 1 — Select market
The list offers ecosystem markets that do not already have a market maker. The target price field is pre-filled from the market's own metadata price where one exists.
Step 2 — Price settings
Two inputs: a target price and a range, expressed as a percentage either side of it. The wizard converts that percentage into the two absolute bounds the API stores.
priceRangeLow = targetPrice x (1 - percent/100)
priceRangeHigh = targetPrice x (1 + percent/100)The API validates the result, and every one of these is a hard refusal:
| Rule | Message |
|---|---|
| All three prices above zero | "Target price must be greater than 0" |
priceRangeLow < priceRangeHigh |
"Price range low must be less than price range high" |
| Target inside the range | "Target price must be within the price range" |
| Deviation from target at most 50% on each side | "Price range deviation from target must be within 50%" |
No value below 0.00000001 |
"Price values must be at least 0.00000001 (8 decimal places)" |
The price process is contained inside the band you configure — but the restoring force only engages in the outer 20% of it. Once it is pulling, the direction of the next move becomes progressively predictable, which on a synthetic market is an exploitable edge and on one that settles binary options is a free bet.
That is why the dashboard reports at range edge as its own state rather than lumping it in with "inside the band": you can still fix it by widening the range, before the price actually leaves. A range too tight for the configured volatility also produces a startup warning in the server log naming the edge an observer would hold.
The band is measured geometrically, not linearly. On a range of 1 to 100 the centre is 10, not 50.5 — so a market sitting exactly on its anchor reads as centred rather than as 90% of the way to the floor.
Step 3 — Trading configuration
Aggression is a 1–10 slider that maps onto the three levels the API stores:
| Slider | Level | Bot risk tolerance | Bot average order size | Bot daily trade budget |
|---|---|---|---|---|
| 1–3 | CONSERVATIVE |
0.3 | 50 | 1,200 |
| 4–7 | MODERATE |
0.5 | 100 | 3,500 |
| 8–10 | AGGRESSIVE |
0.8 | 200 | 9,000 |
Those figures seed the six bots at creation and are editable per bot afterwards. They are sized from measured density, not from nominal arithmetic: a MODERATE market prints roughly 3,500 trades a day, one every 25 seconds on average, about every 10 seconds across the US/EU overlap and every 35 seconds overnight.
Older builds seeded 50/100/200 daily trades, which a market spent inside the
first hour of each UTC day and then printed nothing at all until midnight. The
allowance is now paced across the whole day along an activity curve, so an old
market with an old number is strictly better off — the same allowance simply
lasts until midnight. If it reads as abandoned rather than conservative, raise
maxDailyTrades on its bots.
Real Liquidity (0–100) is the share of each trade's size that is placed as a genuine resting order in the Ecosystem book, backed by the pool. Zero means bot-to-bot only — a price series and a tape with no user-fillable orders and no money at risk. Start there.
Max daily volume is a hard trade gate, not a target. A market that reaches it
stops quoting until the daily UTC reset. Its counter is currentDailyVolume, and
it is zeroed by the daily reset job — so it is volume today, never a rolling 24
hours.
Step 4 — Review
The review step restates what will be created. Creating writes the transaction described above and lands you on the market's detail screen.
After creation: the Configuration tab
These controls do not exist in the wizard. Each is its own endpoint, each writes a history entry, and — since v6.1.5 — each applies to the running market immediately rather than at the next full reload.
Price mode
- AUTONOMOUS — the price process alone. No external reference.
- FOLLOW_EXTERNAL — tethered to an external symbol at
correlationStrength(0–100). - HYBRID — the same tether at half that strength. It is a blend, not a peg.
externalSymbol is required for both non-autonomous modes; the request is
refused without it. The external price is fetched on a slow cached cadence, off
the price step, so a slow exchange can never stall a tick.
The first time a tether engages, the server log states the estimated directional edge a client watching both feeds would hold over the next hour. That is a legitimate configuration for an ordinary market and a poor one for a market that also settles binary options. Use AUTONOMOUS there.
Market bias
BULLISH, BEARISH or NEUTRAL, with a strength of 0–100. Bias influences how
the market moves between phases; it is not a guaranteed direction.
Volatility
Accepted ranges are 0.1–20 for base volatility, 0.5–2.0 for the
multiplier and 0.8–0.999 for momentum decay. At least one of the three must
be present or the request is refused.
Volatility is integrated against wall-clock time, not against tick count, so a market's realised volatility matches what you configured regardless of how often the engine happens to tick, and a restart resumes on the correct distribution.
Market phase
Four Wyckoff-style phases — ACCUMULATION, MARKUP, DISTRIBUTION,
MARKDOWN. The market transitions between them on its own; Market Phase
Control forces one, bypassing the normal transition rules, and the response
says so.
A forced phase now reaches the live market and expires when told to. Its volatility multiplier is applied by the engine only — an older build applied it twice, once in the engine and once written back onto the market's own volatility setting, so a forced phase ran at roughly 2.25x the volatility intended.
Target price
Must sit inside the configured range or the request is refused with the range quoted back. A move of more than 5% is flagged as a large change but still allowed.
The price sync job warns when a target price has drifted more than 10% from its external reference, at most once per market per hour.
Reset daily counters
Zeroes currentDailyVolume and the bots' dailyTradeCount immediately rather
than waiting for the UTC reset. Use it to bring a market that has spent its
budget back to quoting inside the same day — but understand that you are handing
out a second full allowance, and the budget existed for a reason.
Editing the core fields later
The same fields the wizard writes are editable from the Configuration tab:
target price, both range bounds, aggression, max daily volume, volatility
threshold, pauseOnHighVolatility and real liquidity percent. Validation is
identical to creation.
Only fields that actually changed are recorded in history. An earlier build
compared a DECIMAL column (which arrives from the database as a string)
against a number, so every save wrote a CONFIG_CHANGE for fields nobody had
touched — and a market with a 9–10 range could not be edited at all, because
"9" > "10" is true as text.
Deleting a market maker
Deleting stops the market through the engine first, waits up to ten seconds for the engine to confirm, cancels the bots' open ecosystem orders so locked funds return, and only then removes the row. The pool, the bots and the entire history cascade with it.
Withdraw the pool before you delete. Nothing warns you that you are deleting money.