Binary order types, durations and payout percentages

The five binary order types, the sides each accepts, the duration ladder and its cascading profit adjustments, and exactly how the payout on a customer's ticket is computed.

10 min readUpdated 6 August 2026binary, payouts, durations, order-types, house-edge

This is where you decide what your customers can bet on and what the house pays out. Nothing else in the product moves the margin as directly, and nothing else is as easy to get wrong by changing one number in isolation — the payout on a ticket is assembled from up to four separate places on this screen.

Everything here lives on Admin → Finance → Binary Options → Binary Settings (/admin/finance/binary/settings), under the Order Types, Barrier Levels and Durations tabs. Turning the product on, the per-user limits and the markets are on Binary options: switching it on.

The five order types

Each type is a block under orderTypes in the settings document, and each carries at minimum enabled, profitPercentage and tradingModes: { demo, live }.

Type What the customer predicts Sides stored on the order Extra configuration
RISE_FALL Price rises or falls from the entry price RISE · FALL none
HIGHER_LOWER Price ends above or below a barrier HIGHER · LOWER barrierLevels
TOUCH_NO_TOUCH Price does or does not touch a barrier TOUCH · NO_TOUCH barrierLevels, touchProfitMultiplier, noTouchProfitMultiplier
CALL_PUT Traditional option shape against a strike CALL · PUT strikeLevels, requires payoutPerPoint
TURBO Short, high-volatility contract with a knockout barrier UP · DOWN barrierLevels, payoutPerPointRange, maxDuration, allowTicksBased

Those side values are what land in the side column on the binaryOrder row, so they are what you will see in the admin orders list and in any export. The server refuses any other side for that type with a 400.

Only RISE_FALL is enabled in the shipped defaults. The other four ship enabled: false and must be switched on deliberately — each one needs its barrier or strike ladder reviewed before it earns anything.

tradingModes.demo and tradingModes.live

Every type carries both, both default to true, and they are checked at order placement: an order for a type whose mode is off is refused with Order type <TYPE> is not available in <demo|live> mode. This is how you trial a new type on practice accounts before exposing it to real money — turn live off, leave demo on, watch the numbers, then flip it.

durationType: TIME versus TICKS

The binaryOrder row carries durationType, an enum of exactly TIME or TICKS.

TIME is the normal case and the default. TICKS is valid for TURBO only — the server rejects TICKS on any other type with durationType "TICKS" is not valid for <TYPE> orders. Only TURBO orders support TICKS duration type., and TURBO is the one type where durationType must be supplied explicitly.

Two Turbo-only fields go with it:

  • allowTicksBased — a switch on the Turbo card. It is published to the trading page through the public binary settings endpoint, which is what decides whether the ticks option is offered to the customer at all.
  • maxDuration — Turbo's own ceiling in minutes, default 5. An order whose chosen duration exceeds it is refused with TURBO orders cannot exceed <n> minute duration, regardless of what the duration ladder allows for every other type. The settings validator raises a warning when you set it above 5.

A Turbo contract on a TICKS duration also cannot be closed early: the cancel route refuses it outright.

How a payout is actually computed

The number a customer wins is assembled at order placement, frozen onto the order row as profitPercentage, and used unchanged at settlement. It is built in this order:

  1. Start with the type's base. orderTypes[TYPE].profitPercentage.

  2. Replace it with the selected level's own figure, for every type that has levels. Choosing a barrier level is mandatory on HIGHER_LOWER, TOUCH_NO_TOUCH and TURBO; choosing a strike level is mandatory on CALL_PUT. The level's profitPercent overwrites the base outright.

  3. Apply the Touch multipliers, on TOUCH_NO_TOUCH only. A TOUCH side is multiplied by touchProfitMultiplier (default 1.2); a NO_TOUCH side by noTouchProfitMultiplier (default 0.7).

  4. Apply the cumulative duration adjustment — see the next section. It is relative: payout = payout + payout × adjustment ÷ 100.

  5. Check the result is between 0% and 1000%. Outside that, the order is refused with a 400. The ceiling is 1000 because a Touch contract legitimately pays multiples of the stake.

For HIGHER_LOWER, TOUCH_NO_TOUCH, CALL_PUT and TURBO, a level must always be selected, and the level's own profitPercent replaces the type-level figure before anything else happens. That base number is only a fallback and an input to the console's own warnings — it never reaches a customer's ticket.

RISE_FALL is the exception: it has no levels, so its profitPercentage really is the payout (before the duration adjustment). Shipped default: 72%.

An order placed by copy trading is not recomputed. A follower's copy carries the leader's frozen profitPercentage verbatim, and steps 2 through 4 are skipped — so a change you make here reaches new leader orders and their copies, not positions already open.

Rows that predate the current validation and carry no payout rate at all settle on a per-type fallback (RISE_FALL 72, HIGHER_LOWER 68, TOUCH_NO_TOUCH 95, CALL_PUT 72), with a warning in the log naming the order. New orders can no longer be created without a rate.

The Durations tab

A duration is a DurationConfig:

Field Meaning
id The identifier the trading page sends back when placing an order — d_5m for the shipped rungs, duration_<timestamp>_<random> for one you add.
minutes Length of the contract.
enabled Whether it is offered at all.
orderTypeOverrides Per-order-type { enabled?, profitAdjustment? }.

orderTypeOverrides[TYPE].enabled: false removes that duration from that type only — this is how Turbo is kept off the long rungs while Rise/Fall keeps them. An order for a disabled combination is refused with Duration <n>m is not available for <TYPE> orders.

orderTypeOverrides[TYPE].profitAdjustment is a percentage adjustment to the base payout, not a payout. -5 on a 72% base produces 68.4%, not 5%.

The engine sorts the ladder by length and adds up every rung's adjustment from the shortest one up to and including the one the customer chose. A -5 on the 3-minute rung therefore also applies to 5 minutes, 10 minutes and everything above it, on top of whatever those rungs carry themselves.

That is deliberate and it is what the shipped numbers assume — but it means the figure in the box is not the figure applied. Work out the running total before you change one.

Deleting a rung and adding it back creates a new id. A trading page still holding the old catalogue will send the old id and get Invalid or inactive duration selected. Prefer switching a rung off to deleting it, and expect customers to need a page reload after a ladder change either way.

The shipped ladder

An install that has never saved binary settings serves this ladder, with these per-type adjustments:

Rung Minutes RISE_FALL HIGHER_LOWER TOUCH_NO_TOUCH CALL_PUT TURBO
d_1m 1 +5 +3 +5 +3 0
d_2m 2 +3 +2 +3 +2 −2
d_3m 3 0 0 0 0 −5
d_5m 5 0 −2 0 −2 −8
d_10m 10 −3 −5 −3 −5 off
d_15m 15 −5 −7 −5 −7 off
d_30m 30 −8 −10 −8 −10 off
d_1h 60 −12 −15 −12 −15 off

Because the adjustments cascade, the effective RISE_FALL payout on a default install is not the 72% on the Order Types tab at any duration except 15 minutes:

Duration Running total Effective payout
1 min +5 75.6%
2 min +8 77.8%
3 min +8 77.8%
5 min +8 77.8%
10 min +5 75.6%
15 min 0 72.0%
30 min −8 66.2%
1 hour −20 57.6%

If you take one thing from this page, take that table: an operator reading "72%" off the Order Types tab and quoting it to a customer is wrong at seven of the eight shipped durations.

If the settings screen fails to load its data it falls back to a client-side copy with only six rungs — d_1m, d_3m, d_5m, d_15m, d_30m, d_1h — and no per-type adjustments at all. Saving through a screen that showed "Failed to load settings" therefore writes a materially different ladder from the one your install was running. Reload instead.

Adding and removing rungs

The Durations tab has a row of quick-add buttons and a custom field. The preset set is 1, 2, 3, 5, 10, 15, 30, 60, 120, 240 and 1440 minutes; a preset already on the ladder is not offered, and only the first eight of the remaining ones get a button, so the longer options appear only as you remove shorter rungs. Anything else goes in the custom minutes field, which accepts any positive whole number.

Per-duration profitAdjustment is chosen from a fixed list running from −25 to +25 (every whole number between −15 and +15, plus −20, −25, +20 and +25).

Two things the platform enforces around the ladder regardless of what you put in it: an order's expiry must land on a boundary of its own duration (a 5-minute contract must expire at :00, :05, :10 … within 5 seconds of the minute), and no order may run longer than the longest enabled rung.

Shipped barrier and strike ladders

Defaults for an install that has never saved. Each level's profitPercent is the payout that reaches the ticket for that level, before the duration adjustment.

Higher/Lower (orderTypes.HIGHER_LOWER.barrierLevels)

Level Distance Payout Enabled
hl_close 0.1% 68% yes
hl_near 0.2% 54% yes
hl_medium 0.3% 45% yes
hl_far 0.5% 35% no — high abuse potential

Touch/No Touch (orderTypes.TOUCH_NO_TOUCH.barrierLevels), before the ×1.2 / ×0.7 side multipliers

Level Distance Payout Enabled
tn_close 0.1% 95% yes
tn_near 0.2% 120% yes
tn_medium 0.3% 150% yes

Call/Put (orderTypes.CALL_PUT.strikeLevels)

Level Distance Payout Enabled
cp_atm 0.1% 72% yes
cp_near 0.2% 62% yes
cp_otm 0.5% 48% yes

Turbo (orderTypes.TURBO.barrierLevels), plus a payoutPerPointRange of 0.1 to 10

Level Distance Payout Enabled
turbo_tight 0.03% 75% yes
turbo_normal 0.05% 65% yes
turbo_wide 0.1% 52% yes

A wider barrier is easier for the customer to win, which is why every ladder pays less as the distance grows. Inverting that relationship is the single most expensive mistake available on this screen, and the settings validator warns about the Higher/Lower version of it specifically: danger above 2% distance, warning above 1%.

Two things that are not payout settings

NEXT_PUBLIC_BINARY_PROFIT sets nothing

Despite the name, this variable does not set any payout — and it is not shipped in .env or .env.example either. Its only occurrence anywhere in the codebase is one module-level constant in the cancel-order route, parseFloat(process.env.NEXT_PUBLIC_BINARY_PROFIT || "87"), and nothing in that route ever reads the constant. The 87 is a code fallback, not a configured default. Early closes are priced entirely from the Cancellation tab's per-type penalty rules, which the route computes server-side and deliberately ignores any client-supplied percentage for.

Treat it as inert. Adding it to .env changes nothing, and if an older deployment's .env still carries it, that number will disagree with every figure on this page — and the disagreement means nothing.

The AI engine only steers Rise/Fall

If you run the Binary Trading AI Engine addon, be clear about its scope: the settlement hook it installs returns the real close price unchanged for every order type except RISE_FALL. On the other four the house edge is entirely whatever you configure here — there is nothing steering the outcome toward the platform, and a barrier ladder that pays too much simply loses money.

Even on RISE_FALL the hook falls back to fair settlement in many ordinary situations: no engine loaded for the symbol, the engine paused, the engine not ACTIVE, simulation or shadow mode, a demo order with practice steering disabled, no decision recorded for that order, or a steering band of zero. It never throws — any error settles fairly.

So the payouts on this page are the product's real margin. Configure them as if the engine did not exist, and treat anything it adds as upside.

A sane review order

  1. Decide the types you will offer. Start with RISE_FALL only, which is what ships enabled.

  2. Set the base payout for RISE_FALL on the Order Types tab, remembering that the duration ladder will move it by up to ±20% relative.

  3. For every other type you enable, set its ladder first, on the Barrier Levels tab. The type-level Profit % is not what those types pay.

  4. Walk the duration ladder and total the adjustments for each type, rung by rung, and confirm the effective payout at the longest enabled duration is one you are happy to pay.

  5. Read the warnings in the console's validation panel before you save — the barrier-distance and average-payout ones are commercial advice, not noise.

  6. Save, then place one real order of each enabled type on a test account and check the profitPercentage frozen on the row in Order Management → Binary Orders. That column is the only proof the arithmetic came out where you intended.

pnpm --filter backend verify:binary audits already-settled orders and admin-profit rows against your live data, read-only and safe on production. See Repair scripts.