Analytics and optimisation

The Binary AI Engine analytics suite — machine-learning win-rate recommendations, cohort analysis, A/B testing, time-of-day breakdowns and external price correlation monitoring.

6 min readUpdated 3 August 2026analytics, ml, ab-testing, cohorts, correlation

Everything on this page reads from the same source: binary_ai_engine_position, the row the engine writes for every order it tracks and completes at settlement. Every profit figure is the realised platformProfit on those rows, not a projection from an assumed payout — which matters, because payouts differ per order type and per duration and are stamped on the order at placement.

Live positions only. Demo positions are excluded from every report below.

The screens are at Optimization → Analytics (four tabs) and Optimization → Price Correlation.

ML optimisation

A small neural network — ten inputs, sixteen hidden units, one output — trained by gradient descent on the engine's own settled history, producing a recommended target win rate.

Training

Train Model on the ML tab trains on the last N days (30 by default). Training runs in a worker thread, so it never blocks the event loop no matter how much history there is. The main thread does all database work; the worker only does arithmetic on plain arrays.

Training fails cleanly when there is not enough history. That is the normal outcome on a new engine, and it is not an error to chase.

The trained weights are stored on the engine's mlModelWeights column together with the run's loss, accuracy and a trainedAt timestamp. Accuracy here is a genuine measured metric: the fraction of samples whose predicted win rate falls within 0.05 of the actual label. It is not 1 − RMSE dressed up.

Recommendations

Get Recommendation asks for a recommended win rate against one of three objectives:

Objective Optimises for
PROFIT Platform margin
RETENTION Users continuing to trade
BALANCED A compromise; the default

You get back a recommended rate, a confidence score, expected profit, expected retention, and the factors that drove the answer.

Automatic application

enableMlAutoApply on the engine — off by default — lets the cron train and apply the recommendation on its own. At most one engine per cron cycle, and no more than once every six hours per engine.

Three guards stand between a model and your live target:

  • Confidence must be at least 0.5.
  • The last training run's accuracy must be at least 0.5. A model that does not fit its own training set never steers real settlements.
  • The step is bounded by the global Win Rate Adjustment Speed, expressed in permille on the Settings page. At the default 10‰ the optimiser can move a target by at most 0.010 per adjustment. Changes below a minimum threshold are skipped as noise.

The result is then clamped to the platform min/max band like any other target, and the loaded engine configuration is hot-reloaded so the next tick uses it.

Leave it off until you have watched the manual recommendations for several periods and agree with them. Every application is audited and every one is reversible from a snapshot, but the trades that settled in between are not.

Cohort analysis

A cohort is a saved definition of a group of users, so you can compare how different groups behave under the same engine. Cohorts are per engine.

Types

Type Criteria
SIGNUP_DATE A signup date range
DEPOSIT_AMOUNT A total deposit range
TRADE_FREQUENCY A settled trade count range
CUSTOM Reserved

CUSTOM cohorts do not execute a free-form query. Only the vetted, typed criteria above are ever run against the database.

Templates

Templates offers eight ready-made definitions you can create with one click:

  • New users (last 30 days) and Established users (30–90 days ago)
  • Small depositors (0–500), Medium (500–5,000), Large (5,000+)
  • Casual traders (1–10 trades), Regular (11–50), Heavy (50+)

Metrics

Analysing a cohort returns user count, total positions, total volume, win rate, average position size, average positions per user, retention rate, realised platform profit and a tier breakdown.

Compare puts two or more cohorts side by side, flags significant differences per metric and produces recommendations. The natural use is to check whether a target win rate that works for casual traders is quietly driving heavy traders away — or the reverse.

A/B testing

An experiment that splits users between a CONTROL arm and a TREATMENT arm with different target win rates, and measures the difference.

Creating a test

You supply a name, description, the two arm configurations, a traffic split (0–1, the share going to treatment), a minimum sample size per arm, an optional maximum duration in days, and a primary metric.

primaryMetric is one of WIN_RATE, PROFIT, RETENTION or VOLUME. It is persisted on the test and read back when results are computed, so the significance test always evaluates the metric you chose.

Only one test may run per engine at a time. Creating a second returns "Another A/B test is already running. Stop it first."

Assignment

Arm assignment is a deterministic hash of the test ID and the user ID against the traffic split. The same user always lands in the same arm for the same test, whether the answer comes from a stored row or is recomputed — so a lost or rebuilt assignment table is harmless.

How arms actually differ

Because one close resolves an entire expiry bucket, two users in different arms who expire in the same minute cannot be given different outcomes.

Instead, each order in a bucket contributes its arm's target, count-weighted, and the bucket's effective target is the average. Orders outside the test contribute the engine's own target, so a partly-enrolled bucket drifts proportionally rather than jumping to an arm's number. Bucket composition varies minute to minute, so over many buckets the realised win rates of the two arms genuinely diverge and the measured difference is real.

Attribution is per position, not per user: the arm is stamped on each position row the engine analyses. A user's history from before the test is never credited to either arm. Once stamped, an arm is never cleared — a test ending mid-life cannot erase the attribution of positions it already governed.

Results and ending a test

Results returns both arms' metrics, statistical significance, a winner (CONTROL, TREATMENT, NO_DIFFERENCE or INCONCLUSIVE), the target sample size and a recommendation.

Three ways a test ends:

  1. Stop — halts it manually.
  2. Duration expiry — the cron closes any RUNNING test that has passed its durationDays. A test with no duration runs until you stop it, which is the documented open-ended case.
  3. Apply Winner — closes the test and applies the winning arm's configuration to the engine. This refuses on an INCONCLUSIVE result.

Only one test runs per engine. An open-ended test started in April is still RUNNING in July, still enrolling users, and still blocking anything else you want to try. Set a duration unless you specifically want it open-ended.

Time analysis

Hour-of-day and day-of-week breakdowns of position count, volume, win rate, realised platform profit, average position size and unique users, over a configurable window (30 days by default).

Hourly buckets are keyed on UTC hours, because position timestamps are stored in UTC. Using server-local hours would shift your "peak hour" by the machine's offset — worth remembering when you read the chart against your own timezone.

Optimizations turns those patterns into per-hour recommended win rates with reasoning and expected impact. They are advisory: nothing applies them automatically, and the engine has no per-hour target column. Use them to decide whether your single target is a poor compromise across very different hours.

Price correlation monitoring

Watches your published price against an external reference and raises an alert when they diverge. This is the addon's own honesty check: on an ecosystem market you publish the price, so nothing else would tell you it had drifted.

Configuration

Per engine, on Optimization → Price Correlation or the engine's Advanced tab:

Field Meaning
enableExternalCorrelation Master switch
externalPriceSource BINANCE, COINGECKO or CRYPTOCOMPARE
maxDeviationPercent Alert threshold, as a fraction (0.05 = 5%)
checkIntervalSeconds How often to compare; default 60, range 5–86400
alertOnConsecutiveDeviations Consecutive breaches before alerting

An unknown provider name is rejected with a 400, and enabling monitoring with no provider is rejected too — both because monitoring that reports "enabled" while permanently down is worse than monitoring that is off.

Continuous, not on-demand

The Run Check button performs a single comparison. Continuous monitoring is driven by a supervisor in the engine cron: every cycle it reconciles running monitors against the database, starting one for every ACTIVE engine with correlation enabled and stopping monitors for engines that were disabled, paused or stopped. Monitors are re-established after a deploy because the reconcile runs on every cycle.

Turning the engine off globally, or engaging the global pause, tears every monitor down.

Alerts

Severity is derived from the absolute deviation:

Deviation Severity
Over 10% CRITICAL
Over 5% HIGH
Over 2% MEDIUM
Otherwise LOW

Alerts can be acknowledged (seen, being handled) or resolved (dealt with), and the history is queryable per symbol. Correlation alerts also surface in the dashboard's recent-events list.

A sustained HIGH or CRITICAL deviation on a market you steer is the signal to pause the engine and work out why your published series has left the rest of the market behind.