Early cancellation, risk limits and the three presets

The per-order-type cancellation rules and their penalties, which penalty tiers are actually reachable, why the two risk-management fields are inert, and what each preset really contains.

10 min readUpdated 6 August 2026binary, cancellation, refunds, risk, presets

Early cancellation lets a customer close a binary contract before it expires and get part of their stake back. It is a refund path with a configurable penalty, and the penalty is the whole product decision: leave it at zero and you have handed every trader a free option — enter, watch, exit for nothing when the price moves the wrong way, and keep the wins.

The other half of this page is the Risk Management tab, which contains two fields that look like safety nets and are not.

Both live on Admin → Finance → Binary Options → Binary Settings (/admin/finance/binary/settings), on the Cancellation, Risk Management and Presets tabs. Reading the console needs access.binary.settings; saving needs edit.binary.settings.

The two switches above every rule

cancellation.enabled is the global one. With it off, the cancel route refuses everything with 400 "Order cancellation is disabled", whatever the per-type rules say.

Under it, each of the five order types has its own CancellationRule, and each carries its own enabled. A type whose rule is off is refused with 400 "Cancellation is not available for <TYPE> orders".

Closes a binary contract early and refunds the stake less the penalty

What a rule contains

Field Meaning
enabled Whether this order type may be cancelled at all.
minTimeBeforeExpirySeconds The cutoff. Cancellation is refused once the contract is at or inside this many seconds of expiry, with a 400 naming the figure and the time remaining.
penaltyPercentage Percentage of the stake kept by the platform, 0–100. The customer receives stake − penalty.
penaltyByTimeRemaining Optional. Three tiers — above60Seconds, above30Seconds, below30Seconds — chosen by how long is left.

If penaltyByTimeRemaining exists on a rule, the server never reads penaltyPercentage for that type. It picks a tier by time remaining and uses it:

Time to expiry Tier used
more than 60 seconds above60Seconds
more than 30, up to 60 seconds above30Seconds
30 seconds or less below30Seconds

So the Penalty % box on a card that also shows three tier boxes is decorative. It is still saved, still validated, and still ignored.

You can edit the three tiers from the screen only if the rule already has them. The console renders that block conditionally, so a type shipped without tiers — Touch/No Touch and Turbo on the defaults, and every type under the conservative preset — offers no way to add them.

Some tiers can never fire

minTimeBeforeExpirySeconds is enforced before the tier is chosen, so a cutoff at or above a tier boundary makes the tiers below it unreachable. On the shipped defaults:

Type Cutoff Reachable penalties Unreachable
RISE_FALL 30s 5% over 60s, 10% between 30 and 60s below30Seconds 20%, and the flat 10%
HIGHER_LOWER 30s 10% over 60s, 15% between 30 and 60s below30Seconds 25%, and the flat 15%
CALL_PUT 60s 10% — the only tier that can ever apply both other tiers, and the flat 15%
TOUCH_NO_TOUCH 60s rule is disabled by default
TURBO 0s rule is disabled by default

Call/Put is the clearest case: a 60-second cutoff means every permitted cancel happens with more than 60 seconds left, so above60Seconds is the answer every time and the other three numbers on the card are noise.

If you want the graduated penalties to actually grade, the cutoff has to be below 30 seconds.

The shipped rules

Type Enabled Cutoff Flat penalty Graduated (60s / 30s / under)
RISE_FALL yes 30s 10% 5 / 10 / 20
HIGHER_LOWER yes 30s 15% 10 / 15 / 25
TOUCH_NO_TOUCH no 60s 20% none
CALL_PUT yes 60s 15% 10 / 15 / 25
TURBO no 0s 0% none

Touch/No Touch and Turbo ship disabled because both can be gamed: a Touch contract whose barrier has already been hit is a certain win the customer would otherwise cancel out of, and a Turbo contract is too short for an early exit to mean anything.

What the server checks, in order

  1. The order exists, belongs to the caller and is PENDING.

  2. cancellation.enabled, then the per-type enabled.

  3. minTimeBeforeExpirySeconds against the time left. Refused with a 400 naming both numbers.

  4. Barrier state, for TOUCH_NO_TOUCH and TURBO. A Touch contract whose barrier has already been touched, or a Turbo contract whose barrier has been breached, is refused. A Turbo contract on a TICKS duration cannot be cancelled at all.

  5. The penalty is computed server-side from the rule, and any percentage in the request body is deliberately ignored — otherwise a customer could post 0 and cancel for a full refund.

  6. A distributed lock is taken on the order — the same lock settlement uses — and the order is re-read FOR UPDATE inside the transaction and abandoned if it is no longer PENDING. That is what stops a cancel racing a payout.

  7. The refund is credited, the row is set to CANCELED with profit: 0 and the close price of the moment, and metadata records refundedAmount and cancelPenalty.

Both barrier checks read candle history from the centralised exchange provider. If that lookup throws, the code logs a warning and allows the cancellation — the customer gets the benefit of the doubt.

On a market whose source is ECOSYSTEM there is no exchange to ask, so the checks do not run at all: TOUCH_NO_TOUCH is skipped outright and TURBO treats the barrier as unbreached. If you enable early cancellation on those two types, do it on EXCHANGE-sourced markets. See Binary markets.

cancelExpirationBuffer does not do what its name suggests

global.cancelExpirationBuffer (default 60) is published to the trading page through the public binary settings endpoint. That is the entire extent of it:

  • Nothing on the server reads it. The only cutoff the cancel route enforces is the per-type minTimeBeforeExpirySeconds.
  • Nothing on the trading page reads it either. The customer's cancel button is enabled while more than 10 seconds remain, hard-coded; the cash-out button needs 30 seconds since entry and 10 to expiry, also hard-coded.

So on a default install a customer sees a live cancel button from 30 seconds down to 10 seconds before expiry and gets an error if they press it, because the RISE_FALL cutoff is 30 seconds. Two ways to make the screen and the server agree:

  • set minTimeBeforeExpirySeconds to 10 or less for every enabled type, so the button and the server refuse at the same moment; or
  • accept the error and keep the wider cutoff, which is the safer commercial choice — a contract cancelled 11 seconds before expiry is very close to a free look at the outcome.

Set cancelExpirationBuffer to match whichever you choose anyway. It costs nothing and a future release may start honouring it.

Demo contracts never move money

Every wallet operation in the binary order service sits behind if (!isDemo). A practice contract is cancelled, refunded and settled entirely on paper — no wallet is read, no transaction row is written, no penalty is taken. Cancellation rules still apply to demo orders in every other respect, so practice is a safe place to check that a rule behaves the way you expect.

Risk Management

Two fields, on their own tab.

Field Shipped default The screen says
riskManagement.dailyLossLimit 0 "Daily Loss Limit (trades)" — auto-pause trading after this many
riskManagement.winRateAlert 65 alert when a user's win rate exceeds this percentage

There is no code path anywhere in the platform that pauses trading when dailyLossLimit is exceeded, and none that raises an alert when a user's win rate passes winRateAlert. Both values are written into the binarySettings row, returned by the admin GET, rendered on this tab — and consumed by exactly one thing: the settings validator, which raises an info warning when dailyLossLimit is 0.

That warning is the source of the widespread belief that 0 means "disabled". It is accurate as far as it goes — 0 does mean nothing happens — but so does every other value.

Do not treat either field as a control. If you need a daily loss stop, it has to come from the limits that are enforced: global.maxDailyOrders, global.maxConcurrentOrders and global.cooldownSeconds, plus per-market minAmount / maxAmount on the binary market row. Those are on Binary options: switching it on and Binary markets.

For monitoring the exposure by hand, the analytics on the binary order desk carry live-only net house P&L, outstanding payout liability and user win rate — see The binary order desk.

The field label also disagrees with itself: it is titled "(trades)" and described as a loss limit. Since nothing reads it, the ambiguity has no consequence today, but it means you cannot infer the intended unit from the screen.

The three presets

The Presets tab offers three complete configurations. Each is returned by its own endpoint with a human-written description, a feature list, a risk level and its own validation result.

Returns the three presets with their validation

Conservative — riskLevel: low

Described as: only RISE_FALL enabled, tight barrier distances (0.1%–0.3%), lower max amounts ($10–$500), a 50–70% profit range, a 5-second cooldown, and a daily loss limit enabled.

What it actually sets, for this page's subjects:

Value
Cancellation on; no graduated tiers on any type; cutoffs 45s (Rise/Fall, Higher/Lower) and 90s (Touch, Call/Put); flat penalties 15 / 20 / 25 / 20 / 0
dailyLossLimit 1000
winRateAlert 60
Durations four rungs only — 1, 3, 5 and 15 minutes

Balanced — riskLevel: medium, and the shipped default

Described as: only RISE_FALL, moderate barriers (0.1%–0.5%), standard amounts ($1–$1,000), a 65–85% profit range, no cooldown, configurable risk limits.

Value
Cancellation on; the shipped rules table above
dailyLossLimit 0
winRateAlert 65
Durations eight rungs, 1 minute to 1 hour

Aggressive — riskLevel: high

Described as: RISE_FALL and HIGHER_LOWER enabled, wider barriers (0.1%–1%), higher max amounts ($1–$10,000), a 55–90% profit range, no cooldown, relaxed risk limits, extended durations.

Value
Cancellation on for all five types, including Touch and Turbo; cutoffs 15s / 15s / 30s / 30s / 10s; Turbo carries a flat 25% penalty
dailyLossLimit 0
winRateAlert 75
Durations nine rungs, including a 4-hour one

The bullet lists on the Presets tab are hand-written descriptions, not generated from the objects. Where they disagree, the object is what gets saved.

  • The amounts do not exist. There is no minimum or maximum stake anywhere in the binary settings document. Stake bounds are minAmount and maxAmount on each binary market row, and no preset touches them. "$10–$500" and "$1–$10,000" describe nothing that will change.
  • Balanced does have a cooldown. The list says "no cooldown between orders"; global.cooldownSeconds in the balanced preset is 3.
  • Aggressive does not reach 1% barriers. Its widest Higher/Lower barrier is 0.5%, at a 42% payout. Nothing in it goes to 1%.

Applying one replaces everything

The Presets tab does setSettings(preset.settings) — the whole settings document is swapped, including every payout, every barrier ladder, the duration rungs, the cancellation rules and the risk fields. It is not a merge and it does not preserve anything you had configured.

Like the optimizer, it stages the change: the floating unsaved-changes bar appears and nothing is written until you press Save. Discard restores what was loaded.

Two metadata fields ride along on the object:

  • _preset — the preset name, which is what the tab reads back to show which one is currently applied. An install that has never saved reports balanced, because the defaults are the balanced preset.
  • _lastModified — an ISO timestamp. The PUT overwrites it with the moment of the save, so on a saved row it is the last time anybody pressed Save, not when the preset was authored.

The validation object

Both the GET and the PUT return validation: { valid, errors, warnings }, and the presets endpoint returns one per preset — so you can see a preset's warnings before applying it.

Errors block the save. The PUT answers 400 and writes nothing. Warnings do not block anything; each is an object:

Field Is
level info, warning or danger
category Barrier Risk, Profitability, Configuration, Risk Management
message what is wrong, with the offending number in it
suggestion what to do about it
field the dotted path, e.g. orderTypes.HIGHER_LOWER.barrierLevels — absent on the two warnings that are about the configuration as a whole

The ones you will meet on this page's settings:

Level Warning
info "No daily loss limit is configured" — raised whenever dailyLossLimit is 0, which is the shipped default
info Touch profit under 150% is low for a difficult trade type
warning Turbo's maxDuration is over 5 minutes
danger no durations are enabled — trading will not work

The full list, including the barrier-distance and average-payout warnings, is on Binary options: switching it on.

Deciding a cancellation policy

  1. Start with cancellation off if you have no view on it. Nothing about the product needs it, and it is a strictly negative-margin feature until you have priced the penalty.

  2. Never set a penalty to 0 on an enabled type. A free cancel is a free option: the customer keeps every trade that is going their way and exits every one that is not.

  3. Set the cutoff before the penalty. If you want the graduated tiers to do anything, minTimeBeforeExpirySeconds must be under 30 — otherwise the nearest tier is the only one that fires.

  4. Leave Touch/No Touch and Turbo disabled unless every market you offer them on is EXCHANGE-sourced. The barrier checks that make cancellation safe on those types do not run on ecosystem markets, and fail open when the price feed errors.

  5. Do not rely on the Risk Management tab. Configure the enforced limits on the Global Settings tab instead, and watch the desk's analytics.

  6. Test on a practice account. Demo contracts follow the same rules and move no money, so you can confirm the penalty and the cutoff behave as configured before a customer meets them.

Related: Barriers, strikes and the payout optimizer, Order types, durations and payouts, and The binary order desk for reading a cancelled contract after the fact.