Strategy reference

Every parameter of all five strategy families — Grid, DCA, Indicator, Trailing Stop and Custom — what the engine does with each one, and the behaviours that surprise people.

4 min readUpdated 3 August 2026strategies, grid, dca, indicators, trailing-stop

Five strategy families ship. Each one is a class the engine constructs from the bot's strategyConfig and asks for a signal on every tick. This page is the parameter reference; the schema below is exactly what GET /api/trading-bot/strategy-schema returns and exactly what the create endpoint validates against.

Configuration is validated when a bot is created and again when its config is edited. Fields marked required below are refused if absent, with the message Missing required field: <name>.

Grid — GRID

Places a ladder of rungs across a price band. Buy rungs below the market, sell rungs above it, and the spread between adjacent rungs is the profit per fill.

Field Type Required What it does
upperPrice number yes Top of the band
lowerPrice number yes Bottom of the band. Must be below upperPrice
gridCount number (2–100) yes Number of levels
amountPerGrid number (≥1) yes Order size at each level
gridType arithmetic | geometric yes Even price steps, or even percentage steps
initialBuy boolean no Buy once at start so the bot holds inventory to sell into
sellAllOnStop boolean no Liquidate the ladder's inventory when the bot stops
restingOrders boolean no false makes the bot take with marketable limits instead of resting on the book

Two behaviours are worth knowing before someone reports them as bugs.

The ladder builds one rung per tick. A 25-level grid takes about 25 ticks — a little under two minutes at the default 5-second interval — to be fully placed. Rung state is read back from the bot's own order and trade rows on every tick rather than held in memory, so a rung whose order was refused is retried rather than silently lost, and a rung that filled can never be placed twice.

A grid can look like it only buys. A sell rung is only considered when the bot actually holds inventory to sell. A new grid starting in the upper half of its band works downwards to the buy rungs first; enable initialBuy if you want it to hold inventory from the outset. If price has left the band downward, the bot is fully invested and there is nothing above the market to sell into.

gridCount × amountPerGrid must fit inside the allocation, and each rung's notional must clear Minimum Trade Amount. A grid with many small rungs on a small allocation is the single most common cause of "my bot never trades".

DCA — DCA

Buys on a schedule, optionally gated by a price filter.

Field Type Required What it does
interval hourly | daily | weekly | biweekly | monthly yes The cadence
intervalHours number no Custom hour count, used with hourly
amount number (≥1) yes Size of each buy
amountType fixed | percentage yes A flat figure, or a share of the allocation
maxBuys number no Stop after this many buys
priceCondition.enabled boolean no Turn the filter on
priceCondition.type below_ma | rsi_oversold | below_price no Which filter
priceCondition.value number no The filter's threshold

The schedule is reconstructed from the bot's own trade history at startup — the last buy and the total buy count both come from the rows — so a restart does not reset a DCA bot's cadence.

The schedule only advances when a trade actually executes. A buy that the price filter held, or that the risk manager refused, does not consume the interval and does not consume a maxBuys slot. All three filters hold rather than pass when candle data cannot be read, which is the safe direction.

Indicator — INDICATOR

Enters and exits on technical indicators computed over closed candles.

Field Type Required What it does
timeframe 1m | 5m | 15m | 1h | 4h | 1d yes Candle size every indicator is computed on
indicators object yes The indicator set — at least one must be enabled
signalMode any | all yes Fire when any indicator agrees, or only when all do
entryAmount number (≥1) yes Position size on entry
exitMode indicator | take_profit | both no What closes the position

The indicator set:

Indicator Parameters
rsi enabled, period, overbought, oversold
macd enabled, fastPeriod, slowPeriod, signalPeriod
bollingerBands enabled, period, stdDev
ma enabled, type (SMA/EMA), period, crossType (price_cross/ma_cross), secondPeriod

The in-progress candle is dropped before any indicator is computed, and every comparison is made against the previous closed bar. That is what makes a crossing signal mean anything — an implementation that compared live values would fire on every tick while one line sat above another.

The practical consequence: on a 1-hour timeframe an indicator bot produces at most one signal per hour regardless of the 5-second tick. Use a shorter timeframe if you want faster reaction, and expect more noise.

Trailing Stop — TRAILING_STOP

Enters once, then follows the price up with a stop that never moves down.

Field Type Required What it does
trailPercent number (0.1–50) yes How far behind the peak the stop sits
activationPercent number (≥0) no Profit the position must reach before the trail arms
entryMode market | limit yes Entry order type
entryAmount number (≥1) yes Position size
entryCondition.type immediate | indicator | price_level no When to enter
entryCondition.value number no The condition's threshold

Until the position is up by activationPercent, the trail is not armed and the ordinary stop-loss is what protects it. The peak only ever ratchets upward, so the stop can never drift down — a position that falls straight from entry is closed by the stop-loss, never by an un-armed trail.

The terminal draws the entry, the peak and the chasing stop, which is the fastest way to see where the stop actually sits.

Custom — CUSTOM

Runs the IF/THEN rules produced by the Strategy Builder.

Field Type What it does
rules array The builder's rule list — the format the product actually writes
symbol string The market the strategy was designed against
timeframe string The candle size conditions are evaluated on
riskManagement object stopLoss, takeProfit, maxPositionSize carried with the strategy
nodes / connections / entryAmount array / array / number The legacy node-graph format, still accepted

CUSTOM has no fixed required list because it accepts either format; the validator checks whichever one was supplied. See the Strategy Builder for the rule shape and every message the validator can produce.

Order types

A strategy declares each signal as MARKET or LIMIT. Both can be disabled platform-wide on the settings screen, and a disabled type is refused before any other risk check runs — it needs no database round trip and could never become allowable further down.

A LIMIT signal with a usable price rests on the book by default. Setting restingOrders: false in the strategy config forces marketable limits instead, which is a legitimate order type — it just is not what a grid wants, since a grid's sell rung is the half of the strategy that books the spread.

Validating before you save

List the strategy types the engine supports
The full configuration schema for every type
Pre-configured templates for quick creation
Validate a configuration without creating anything

The Algo panel mirrors these schemas client-side so a user sees the error before the request is made, but the backend check is the one that counts.