apexEngine — Status & roadmap
Where this strategy is today
BLOCKED — the code is correct, uniform and shippable. That is a statement about engineering, not about profitability; the performance verdict is separate and sits below it.
| Dimension | State |
|---|---|
| Correctness | failing |
| Console output | 22 tagged calls, 0 off-format |
| Side panel | 37 rows, padded to the 3-column grid |
| Chart marks | reference-levels |
| Palette | 8 / 8 canonical |
| GUI settings | 32 exposed · 0 read at runtime · 0 untunable · 0 inert |
| Deployed to a live install | Not yet — audited and staged, not yet shipped |
Performance verdict. Over three years on 7 markets it returns a median -39.6% against buy-and-hold's 49.6% — an edge of -94.8% — and is profitable on 0 of 7. On this window it is not a replacement for simply holding the asset, and nothing in these reports claims it is.
What it actually does
A hand-written Quantroduction strategy — no shared generator engine, one published model. Its header describes it as "if I could build exactly one strategy for crypto spot markets with zero constraints", and it is by some distance the most ambitious file in the pack.
It is a regime-switching state machine with four modes:
- GRID — range-bound, Hurst ≈ 0.5 and low ADX. An ATR-spaced buy/sell grid,
GRID_SPACING_ATRbetween rungs, selling partial at each step up. Its own header calls this "the bread and butter". - TREND — Hurst > 0.55 and high ADX. Buy pullbacks to the EMA in an uptrend; in a downtrend sit in cash, since spot cannot go short.
- ACCUMULATE — extreme negative z-score. Scale in at support with decreasing size.
- DISTRIBUTE — extreme positive z-score. Sell into strength in tranches.
Mode transitions require multiple agreeing signals, with hysteresis, to avoid whipsawing. Position size compounds: effectiveTL: max(TRADING_LIMIT, TRADING_LIMIT + totalRealisedPnL × COMPOUND_PCT/100), with profit split between a reinvested share and harvested cash.
Every cycle it also publishes ledger.customSellTarget at breakEven + atr × GRID_GAIN_ATR — a resting limit order, and in practice the dominant exit: 2,744 of 3,352 exits (81.9%) are that order being filled, against 608 that go through the strategy's own sell logic.
Read from the shipped strategy source, not from its documentation.
The measured constraint
Time in market is 96.9%, over 5398 round trips across all 7 markets and three years. Everything in the performance report rests on that fraction of the bars.
Settings, measured
This strategy does not use the engine config surface.
What to build next
Ordered by expected effect on the result, not by effort.
1. Everything previously published about this strategy described a strategy that was switched off
Highest priority
This strategy's earlier report showed +1.3% median return, profitable on 7 of 7 markets, a 0.7% maximum drawdown — the best risk-adjusted numbers of anything audited so far. Those numbers were real, and they meant nothing, because the strategy held a position 0.7% of the time and placed 29 buys per market in three years. Roughly one trade every 40 days, from a four-mode adaptive engine.
The cause is in the fixes report: it never noticed its own resting-order fills, so after each one it went on believing it still held the position. A grid engine that thinks its rungs are open does not open new ones. It was not being selective; it was paralysed.
With that repaired it trades as designed — and returns a median −20.2% with a 67.4% drawdown, in the market 92.4% of the time, against a buy-and-hold of +39.2%. It is profitable on 0 of 7 markets and now fails the cost-independence invariant.
Do not run this strategy at its shipped defaults. That is a stronger statement than the old report would have supported, and it is the first honest one. The pack's own rule — a good result on very low exposure usually means the strategy stopped trading — was written for exactly this case.
2. The grid's gain target is 0.50% and it pays 29% of the account in fees
Highest priority
Now that it trades, the shape of the loss is legible. The resting target takes 81.9% of exits at a mean realised +0.50%, and median fee drag is 29.1% of the account across 3,352 exits and 4,589 entries.
A 0.50% target against roughly 0.20% of round-trip cost keeps about 60% of each win — but only when the trade wins. The other 18.1% of exits go through the strategy's own sell logic, which includes the stop, and the net across seven markets is −20.2%.
So the first experiment is the same one the other high-turnover strategies in this pack point at: widen the grid. GRID_GAIN_ATR and GRID_SPACING_ATR set the target and the rung spacing in ATR units; raising both cuts the trade count and raises the per-trade edge against a fixed cost. If the edge survives at a fifth of the turnover, fee drag stops dominating. If it does not, the grid has no edge to find and the TREND and ACCUMULATE modes are carrying the strategy on their own — which is itself worth knowing, because the header claims the opposite.
A second measurement is cheap and would settle the header's central claim: record which mode each fill happened in, and report P&L per mode. The file already tracks mode; adding it to the fill log costs one field and would say whether the regime detection is doing anything, or whether GRID is simply running all the time.
3. It fails cost-independence, and here that is a symptom rather than the disease
High priority
The pack's cost-independence invariant fails a strategy that places less than half as many buys when fees are charged. apexEngine now fails it.
That is worth reading correctly. Nothing in the logic is gated on a fee-dependent quantity — the buy gate that was structured that way is repaired, and measured as a no-op at every capital tested. What fails now is simpler: at 29% fee drag and a −20% return, the fee-charged run has materially less money to trade with, so it places fewer orders.
The invariant is doing its job. A strategy that cannot afford to keep trading is one whose ability to act depends on fees. But the fix is not to the gate; it is to the turnover, per the previous item.
Until that is resolved the strategy is correctly marked BLOCKED, and should stay marked so.
4. The compounding rule was reading a seventh of the profit it had made
Worth testing
effectiveTL: max(TRADING_LIMIT, TRADING_LIMIT + totalRealisedPnL × COMPOUND_PCT/100) grows the order size out of realised profit. Before the repair, totalRealisedPnL had only ever seen the 13.9% of exits that went through the strategy's own sell code — so the position size the engine was supposed to grow into was being computed from a seventh of the actual result.
Measured in isolation, fixing only that changed almost nothing (209 → 228 buys, +1.27% → +1.34%) because the strategy was paralysed for the other reason. It matters now that it trades: the compounding is live, and COMPOUND_PCT has never been exercised on real numbers on any of the seven markets.
So treat COMPOUND_PCT and HARVEST as untested knobs, not tuned ones. The sensible next measurement is a sweep of COMPOUND_PCT from 0 (fixed size) upward, because compounding into a losing strategy enlarges the loss, and the current setting has never been measured against anything but a dormant engine.
The same applies to the circuit breaker: wins, losses and consecutiveLosses were also blind to 86% of trades, so the breaker never had a chance to fire. It can now.
5. The settings surface on this strategy has never been measured
Worth testing
The audit measures which GUI settings a strategy actually reads by watching it run behind a recorder. This file, like all 79 hand-written Quantroduction strategies, builds its settings object directly instead, so there is nothing for the recorder to watch.
That matters more here than on most files because this strategy has an unusually large settings surface — four modes, each with its own thresholds — and because every dead setting found in this lineage so far was found by hand. kalmanGrid had three Kalman parameters exposed in the GUI under names the filter did not read, with three different defaults across three sources, and nothing detected it automatically.
Wrapping the settings object the same way the shared settings accessor is wrapped is the highest-value tooling work outstanding on the whole audit, and it would cover 79 strategies at once. Until it exists, treat the GUI settings on this file as unverified.
6. What this audit repaired, and what it deliberately did not
Read before acting on the others
Two defects repaired, one of which changed everything:
- Stale position state after a resting fill — the strategy went on believing it held a position it had already sold, which switched it off for three years. Repaired with a reconcile block that books the fill and clears the state. This is why the numbers on this page bear no resemblance to the ones previously published.
- The self-contradicting buy gate — allowed a cycle holding half an order's worth of cash, then demanded a whole one. Repaired, and honestly reported as a no-op on this strategy at every capital tested: it was recorded here from the
btcRegimeScaleraudit, where it did bite, and the measurement does not support claiming it bites here.
Not repaired: the settings surface remains unmeasurable for this lineage, and no attempt was made to tune the strategy into profitability. Tuning belongs after the measurements in this roadmap, not before them.
One earlier claim is corrected outright. This strategy's previous report described it as profitable on 7 of 7 markets. It is profitable on 0 of 7. The strategy did not change between those two reports in any way that made it worse — the first report measured an engine that was not running.
Operator output, measured
Everything below was read out of the strategy file by the presentation audit, not taken from its documentation. These are the surfaces an operator actually watches: the terminal log, the side panel, the chart, and the settings the GUI offers.
- Tagged, aligned, coloured
- 22
- Raw and off-format
- 0
- Exempt (object and error dumps)
- 20
Every non-exempt line carries the strategy name, an event tag and the palette colour for that tag, so one terminal running many pairs stays readable.
- Data rows
- 37
- Section headers
- 7
- Rows with no tooltip
- 0
- Padded to the 3-column grid
- yes
- Model
- reference-levels
draws price levels into customChartTargets and no per-trade marks, so there is no intent-vs-fill distinction to get wrong
- Non-canonical colours
- 0
One colour per meaning, identical in the log, the panel and the chart — the eight canonical roles.
Settings the GUI exposes
32 settings appear in the Gunbot strategy editor for this strategy. Which of them the code reads has not yet been measured for this lineage: it does not use the shared config surface, so there is nothing to wrap with a recording proxy.
LOG_LEVELWARMUP_CYCLESAX_COMPOUNDAX_RESERVEAX_MAX_EXPAX_H_MRAX_H_TRAX_ADX_TRAX_CONFIRMAX_Z_ACCUMAX_Z_DISTAX_GRID_ATRAX_GRID_DCAAX_GRID_DECAYAX_TREND_PBAX_ACCUM_LVLAX_ACCUM_ATRAX_ACCUM_DECAYAX_DIST_TRAX_DIST_STEPAX_EMA_FAX_EMA_SAX_Z_LBAX_H_LBAX_VOL_LBAX_SPMIN_ORDER_QUOTEAX_TLAX_CAPITAL_ALLOCAX_GRID_GAINAX_TREND_TRAILAX_FEE