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.
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:
- Stop — halts it manually.
- 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. - Apply Winner — closes the test and applies the winning arm's configuration
to the engine. This refuses on an
INCONCLUSIVEresult.
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.