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.
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 withTURBO 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:
-
Start with the type's base.
orderTypes[TYPE].profitPercentage. -
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_TOUCHandTURBO; choosing a strike level is mandatory onCALL_PUT. The level'sprofitPercentoverwrites the base outright. -
Apply the Touch multipliers, on
TOUCH_NO_TOUCHonly. ATOUCHside is multiplied bytouchProfitMultiplier(default 1.2); aNO_TOUCHside bynoTouchProfitMultiplier(default 0.7). -
Apply the cumulative duration adjustment — see the next section. It is relative:
payout = payout + payout × adjustment ÷ 100. -
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
-
Decide the types you will offer. Start with
RISE_FALLonly, which is what ships enabled. -
Set the base payout for
RISE_FALLon the Order Types tab, remembering that the duration ladder will move it by up to ±20% relative. -
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.
-
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.
-
Read the warnings in the console's validation panel before you save — the barrier-distance and average-payout ones are commercial advice, not noise.
-
Save, then place one real order of each enabled type on a test account and check the
profitPercentagefrozen 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.