Bots

The six bots a market maker is created with, what each personality changes about the tape, every configuration field and the range it accepts, and the statuses that decide whether a market can quote at all.

5 min readUpdated 3 August 2026bots, personalities, order-flow, cooldown

Bots are the roster that produces the tape. They do not decide the price — that belongs to the price engine alone, and nothing else is allowed to touch it. What the bot layer decides is when a trade prints, how large it is, and which bot takes each side.

Six are created with every market maker, and the Bots tab on the market detail screen is where you manage them. There is no create-a-bot screen: the roster is fixed at six and you configure the ones you have.

Name Personality Default spread
Scalper Alpha SCALPER 0.10%
Scalper Beta SCALPER 0.15%
Swing Trader SWING 0.30%
Accumulator ACCUMULATOR 0.20%
Distributor DISTRIBUTOR 0.20%
Market Maker MARKET_MAKER 0.10%

The two-bot gate

A print needs two sides. The engine checks the count of ACTIVE bots before it consults the bot layer at all, and a market below two prints nothing — while keeping its ACTIVE status and its green badge. This is the single most common reason a market goes silent, and the dashboard names it as the closed gate.

Bots are created PAUSED. Starting a market maker activates all of them; stopping or pausing it pauses all of them. You can pause individual bots afterwards — just not below two if you want the market to keep quoting.

What each personality changes

A personality is a small table of numbers, not a strategy. Three things differ:

Personality Buy affinity Size multiplier Minimum gap between its own trades
SCALPER 0.5 — neutral 0.6x 1s
SWING 0.45 — mild sell lean 1.4x 12s
ACCUMULATOR 0.7 — buys more often 1.0x 6s
DISTRIBUTOR 0.3 — sells more often 1.0x 6s
MARKET_MAKER 0.5 — neutral 0.8x 2s

Buy affinity biases which bot is picked as the buyer when a trade happens. It does not bias the market's direction — direction is settled by the price process before any bot is selected. An accumulator is simply more often found on the bid than the ask, which is what the word means.

The minimum gap is a floor against rapid-fire, not the rate limiter. Trade cadence comes from a 24-hour activity curve applied to each bot's daily budget.

The personality column is set when the six bots are seeded and there is no endpoint to change it. What you tune is the numbers below.

Configuration

Every field is on the Bots tab, and every change applies to the running market immediately and is recorded in the audit trail.

Scales trade size across a 0.5x to 1.5x multiplier
Relative trade cadence
The centre of this bot's order size distribution
How far order sizes spread around the average
How far from mid this bot quotes real liquidity
This bot's daily trade budget
Field Accepted range Refusal
riskTolerance 0.1 – 1.0 "Risk tolerance must be between 0.1 and 1"
tradeFrequency HIGH, MEDIUM, LOW "Trade frequency must be HIGH, MEDIUM or LOW"
avgOrderSize greater than 0 "Average order size must be greater than 0"
orderSizeVariance 0.1 – 0.5 "Order size variance must be between 0.1 and 0.5 (50%)"
preferredSpread 0.0001 – 0.1 "Preferred spread must be greater than 0"
maxDailyTrades 1 or more "Max daily trades must be greater than 0"

Seeded values follow the market's aggression level: risk tolerance 0.3 / 0.5 / 0.8, average order size 50 / 100 / 200 and a daily budget of 1,200 / 3,500 / 9,000 for CONSERVATIVE, MODERATE and AGGRESSIVE respectively.

Before v6.1.5 the Bot Management form posted field names the server does not read, so trade frequency, order size and risk tolerance were silently thrown away. Risk tolerance was worse: the slider ran 1 to 10 in whole steps against a server that accepts 0.1 to 1, so nine of the ten positions were refused outright — and because the request fails as a whole, they took Max Daily Trades down with them, the one field that did work. If you are on an older build, none of your bot edits have applied.

How the daily budget behaves

maxDailyTrades is a budget paced across the whole UTC day, not a fuse. The order-flow layer spends it along a 24-hour activity curve — roughly one trade every 10 seconds across the US/EU overlap and every 35 seconds overnight — so it lasts until midnight.

A market does not spend its full budget. Two bots are needed per print but only one initiates, and simultaneous initiators on the same tick collapse into a single trade, so realised use lands near a third of the cap. In the 1,000–5,000 range the observed result is close to one trade per day per unit of cap.

Both the per-bot counter and the market's currentDailyVolume are zeroed by the daily reset job at the UTC boundary. That job checks whether the day has already been reset before handing out a fresh allowance — two separate resets that disagreed about when a day starts could otherwise hand a market a second full allowance mid-session.

Order sizes and spreads

Order sizes follow a realistic distribution — mostly small, occasionally large, snapped to round lots — rather than a uniform band around the average, which is the most obvious synthetic-tape tell an addon can have. orderSizeVariance shapes that spread and riskTolerance scales it.

preferredSpread sets how far from mid a bot quotes real liquidity, so the five personalities sit at visibly different distances from the touch rather than stacking onto the same two levels of the book. It has no effect on a market running at 0% real liquidity.

Statuses

Status Meaning
ACTIVE Counts toward the two-bot gate and can be selected for a trade
PAUSED Present but not trading
COOLDOWN Temporarily out, with an expiry, and returns to ACTIVE on its own

A bot can only be activated while its market maker is ACTIVE. Activating one on a stopped market is refused with "Cannot activate bot when market maker is not active".

Cooldown takes a duration. The dialog asks for minutes and defaults to 15. Setting any other status clears the cooldown. Before v6.1.5 nothing recorded a duration and nothing brought a bot back, so cooldown was a one-way door: the bot stayed out until an operator noticed and reactivated it by hand.

Pausing and activating individual bots reaches the running market immediately. The engine loads every bot on a market, not just the active ones, precisely so that a paused bot has a row to flip — otherwise activating it did nothing until the next daily reset or a full stop/start cycle.

Reading bot performance

The bot list and the individual bot screen report what was actually measured:

Figure What it counts
Total trades Every trade, AI-to-AI and real
Real trades Fills against real user orders — the only trades with P&L
Profitable trades Profitable real fills
Realised P&L The bot's lifetime accumulator, written by the matcher on each real fill
Position and average entry The bot's current inventory
Trades remaining today Daily budget less trades made

A trade between two of the platform's own bots has no profit or loss at all, so on a market at 0% real liquidity most bots have never had a trade capable of winning or losing. Those screens show blanks, not zeros and not an assumed rate.

An older build reported every bot's success rate as 50% and its profitable trades as exactly half its total on the list, and a flat 65% win rate on the detail screen with the counts derived from it. None of it was measured.

Two tiles that could only ever read N/A — the bot's next scheduled trade and its behaviour seed — were removed rather than left on the page.