adxTrendMM — 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 | 4 tagged calls, 1 off-format |
| Side panel | 34 rows, padded to the 3-column grid |
| Chart marks | reference-levels |
| Palette | 8 / 8 canonical |
| GUI settings | 52 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 6 months on 7 markets it returns a median -56.8% against buy-and-hold's 8.1% — an edge of -64.9% — 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 1-minute trend scalper. It has no shared engine behind it — this file is the whole strategy — and it is one of the 33 in the pack that declare a sub-hourly timeframe, so it is measured on 1-minute bars over six months rather than on hours over three years.
The signal is Wilder's directional movement system, computed by the indicator library with a manual Wilder-smoothing fallback:
- ADX measures trend strength on a 0–100 scale, without regard to direction.
- +DI and −DI measure directional pressure up and down.
Entry needs four things at once: ADX above ADX_MIN_STRENGTH (25), +DI above −DI, price no more than 0.3% above its 20-bar moving average — a cap against chasing — and the averaging-down ladder not already full. The entry is placed as a post-only limit at the bid, so it is a maker order and rests rather than crossing.
Averaging down adds a layer whenever price falls ADX_DCA_STEP (0.3%) below the previous entry while ADX and the DI ordering still hold, up to ADX_MAX_DCA (3) layers, each sized ADX_DCA_DECAY (0.75) times the last.
Exits are checked in a fixed priority order, and which one fires matters more than any of the entry logic: a hard stop at ADX_MAX_DD (8%), a time-to-live at ADX_MAX_HOLD (200 cycles), a bearish −DI/+DI cross, ADX falling below ADX_EXIT (20), a trailing stop that arms at ADX_TRAIL_ARM (0.4%) and gives back ADX_TRAIL_PCT (0.5%) from the peak, and last a fixed profit target at ADX_GAIN (0.15%) that is off by default — the header says so: "OFF by default — let winners run".
That reads as a considered design — let the trend run, take profit on a trailing give-back rather than a fixed target. It is not what happens. Measured over six months on seven markets, the trailing stop, the fixed target and the time-to-live fired zero times between them; 97.9% of exits were one of the two trend tests. The order the branches are checked in decides this strategy's behaviour far more than any of its thresholds do. See the fixes report.
Sizing is fixed quote per order — ADX_TL 100, falling back to TRADING_LIMIT — against a per-pair cap of ADX_CAPITAL_ALLOC 500 and a ADX_MAX_EXP 80% exposure ceiling.
Read from the shipped strategy source, not from its documentation.
The measured constraint
Time in market is 3.2%, over 3766 round trips across all 7 markets and 6 months. Everything in the performance report rests on that fraction of the bars. A strategy out of the market 97% of the time is not therefore a low-risk one: the 56.8% drawdown happens entirely inside the time it is committed.
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. The result was not a measurement of this strategy — it was the account hitting the floor and stopping
Highest priority
This is the single most important fact on the page, and nothing else here can be read without it.
The pre-fix run reported a median −56.8% across seven markets. Six of the seven ended holding within 0.25% of exactly one trading limit — 99.77, 99.83, 99.84, 99.87, 99.89, 99.96, against an order size of 100 and a starting capital of 231.
Six markets landing within a quarter of a percent of each other is not a market outcome. It is arithmetic: 231 → 100 is −56.7%. The strategy ran until it could no longer afford a whole order, and then stopped, because its two capital tests contradict each other — one allows a cycle at half an order, the other refuses to place one below a full order, and nothing sizes down in between.
The seventh market, LINK, is the control. It is the only one that never reached the floor (117.08), and it is also the only one whose order count barely changes when the fees are removed — 0.98 against 0.46–0.73 everywhere else. A strategy that is not locked out does not care how fast it would have got there.
What to do with the pre-fix number: discard it. It is not a pessimistic estimate of this strategy's edge, it is a measurement of when it ran out of money. The post-fix run is the first number on this page that measures the strategy.
2. Four of its six exit paths have never executed, and the two that carry the strategy are the ones nobody tuned
Highest priority
Every exit over six months across seven markets, attributed to the branch that produced it:
| exit path | count | share | checked |
|---|---|---|---|
DI_CROSS_BEARISH — −DI crosses above +DI |
3,298 | 87.6% | 3rd |
ADX_WEAK — ADX falls below ADX_EXIT |
388 | 10.3% | 4th |
STOP_LOSS — hard stop at ADX_MAX_DD |
80 | 2.1% | 1st |
TRAIL_STOP — trailing stop |
0 | 0% | 5th |
GAIN_EXIT — fixed profit target |
0 | 0% | 6th |
TTL — time-to-live |
0 | 0% | 2nd |
This strategy does not take profit the way the file says it does. The header presents the design plainly: the fixed target is off by default — "OFF by default — let winners run" — and winners are meant to run into the trailing stop. Neither has ever fired. What actually closes a position, in 97.9% of cases, is one of two trend tests.
And the trailing stop is arranged to lose if it is ever reached. It arms at ADX_TRAIL_ARM
0.4% and gives back ADX_TRAIL_PCT 0.5% from the peak. The give-back is wider than the gain that
arms it, so a position that arms and immediately turns is sold at 0.4% up then 0.5% down:
| entry | 1.000000 |
| peak, arming the trail at +0.4% | 1.004000 |
| exit, −0.5% from that peak | 0.998980 |
| net before any cost | −0.102% |
| net after 0.10% fee + 2 bps slippage per side | −0.342% |
It loses at zero fees. The break-even pair is not far away — a 0.398% trail at the shipped 0.4% arm, or a 0.744% arm at the shipped 0.5% trail — which is exactly why the shipped values look plausible and are not.
The consequence for an operator is worse than either fact alone. ADX_TRAIL_ARM and
ADX_TRAIL_PCT are exposed in the settings panel as live controls. They are inert at the shipped
exit ordering, so anyone tuning them is tuning nothing — and if the ordering were ever corrected,
the values they were left at would start selling below cost.
The experiment, in order. First re-order so the trailing stop is reachable, or accept that it is decoration and say so in the file. Only then sweep the pair, bounded by the break-even surface above: arm over 0.4–1.2%, trail over 0.15–0.5%, with half that grid ruled out before a single bar is replayed. Run it after the lockout repair, never before — on the pre-fix build every cell returns the same −56.8%, because every cell ends at the floor.
A note on how this was found, because it nearly was not. The first pass of the exit ladder reported 3,686 of 3,766 exits as unexplained, which would have been published as a 97.9% silent-exit defect. It does not exist: the strategy announced every one of them, and the measurement tool simply had no pattern for this notification format. The table above is the corrected reading. A tool that cannot parse a message reports silence, and silence reads as a finding.
3. Fees alone consume 41–50% of the account over six months
High priority
Fee drag, as a share of starting capital, by market: ADA 43.7%, BTC 48.1%, DOGE 44.8%, ETH 49.2%, LINK 41.0%, SOL 50.5%, XRP 50.5%.
That is the engine of the lockout. Roughly 540 round trips per market over six months, each a 100-quote order paying about 0.2% round-trip, is about 108 quote of cost against a 231-quote account. The trailing stop supplies a small negative edge per trade; the fee schedule supplies a large one; together they walk the account down to the floor, where the buy gate stops it.
One mitigation is already in the file and is worth measuring rather than assuming. The entry is placed as a postOnly limit at the bid — a maker order. The backtest charges a single taker rate on every fill, so the measured drag is an upper bound on the entry side. What the maker rebate is actually worth here is a question the current engine cannot answer, because it carries no order book and cannot model whether a resting bid gets filled at all.
That cuts both ways, and the report should not claim the rebate as a saving: an entry that rests at the bid in a rising market is an entry that does not happen. Measuring it needs a fill model this engine does not have.
4. It is in the market 2–3% of the time, and all-in whenever it is
Worth testing
| market | time in market | mean weight | peak deployment |
|---|---|---|---|
| ADA | 2.14% | 1.36% | 99.6% |
| BTC | 3.22% | 2.12% | 99.9% |
| DOGE | 2.80% | 1.80% | 99.8% |
| ETH | 3.40% | 2.18% | 99.7% |
| LINK | 2.55% | 1.62% | 93.9% |
| SOL | 3.18% | 2.05% | 99.9% |
| XRP | 3.16% | 2.06% | 99.7% |
Two things follow, and they pull in opposite directions.
It is out of the market 97% of the time, so everything the performance report says rests on 2–3% of the bars. That is a small sample in wall-clock terms even though the trade count is large.
And when it is in, it is effectively all-in — peak deployment is 99.6–99.9% on six markets. The ADX_MAX_EXP ceiling of 80% is measured against total equity including the position, so it does not bind the way the name suggests. The pack-wide slicing policy applied to the directional engine — enter in quarters, cap exposure at 85% — has no equivalent here, because this file predates it and has no shared engine to inherit it from.
That combination is worth stating plainly to an operator: rarely in, all-in when it is. It is the opposite of the risk profile the 2–3% time-in-market figure suggests on its own.
5. Two reporting defects repaired, and one of them was the worst case in the pack
Worth testing
Neither changes what the strategy does; both change what an operator sees it doing.
The side panel counted only its winners. Round trips incremented only in the winning branch of each exit, and the hard stop — which has no winning branch, because a stop is always a loss — never incremented it at all. The engine counted 3,766 closed round trips; the panel would have shown 403. At a 9–13% win rate, 89.3% of this strategy's completed trades left no trace in its own reporting — the widest gap of the 22 strategies that carried the defect, and widest precisely because it loses most often.
It silenced its own logger. One unconditional line per cycle replaced the INFO logger with no-ops, so setting LOG_LEVEL to DEBUG in the GUI did nothing and no exit message the file contains could ever print. Now gated on the operator's own setting; the shipped default is still silent, so nothing changes for anyone who has not asked for logs.
The second one is a repeat: the fixer for it had reported “0 files to change” because a third spelling of the line existed that it did not match. Six files had never been repaired. That is the third time in this pack a fixer matching literals rather than structure has reported success over work it had not done — and it is why the buy-gate lockout at the top of this page went unfound for months.
6. What to build next, in order
Read before acting on the others
Re-measure at several capitals. The lockout is repaired, but the repair is worth proving across the range an operator would actually use — 231 (the calibration), and a deliberate 150 and 120 where the pre-fix build locked out fastest. Cost-independence should now hold at all three.
Decide what the exit rules are. Four of six paths have never executed. Either the ordering is wrong and the trailing stop should be reachable, or the file carries four settings and two exit branches that exist only on paper and should say so. This is a decision, not a sweep, and it comes before any tuning: sweeping thresholds on a branch that cannot run measures nothing.
Then sweep whichever exit actually carries the strategy. Today that is the DI cross, and nothing in the settings panel tunes it — there is no minimum separation, no confirmation bar, no cooldown. At 1-minute cadence the DI lines cross constantly, which is the likeliest explanation for a 9–13% win rate across all seven markets. A single
SIG_diCrossConfirm-style bar count would be the cheapest thing in this list to test.Then, and only then, ask whether the entry adds anything. The honest null hypothesis for a 1-minute scalper with a 9–13% win rate is that the ADX/DI entry gates are noise and the result is entirely the exit rule. Testing it is a one-line change: enter at random with the same frequency, keep the exits, compare. If the measured edge does not move, the signal is decoration.
Nothing above is applied. Each changes live behaviour and belongs in a measurement of its own.
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
- 4
- Raw and off-format
- 1
- Exempt (object and error dumps)
- 4
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
- 34
- 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
52 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.
PERIODTRADING_LIMITADX_TLADX_CAPITAL_ALLOCALLOC_PCTALLOC_CONFIRMEDALLOC_SPLIT_TOLALLOC_ENFORCE_SPLITALLOC_AUTO_REBALANCEALLOC_RESERVE_PCTADX_GRIDADX_GRID_LEVELSADX_GRID_SPAN_PCTADX_PERIODADX_MIN_STRENGTHADX_EXITADX_USE_FIXED_TPADX_GAINADX_TRAIL_ARMADX_TRAIL_PCTADX_MAX_HOLDADX_MAX_DCAADX_DCA_STEPADX_DCA_DECAYADX_MAX_EXPADX_MAX_DDADX_DAILY_LOSSADX_CONSEC_LOSS_MAXADX_FEEADX_SPLOG_LEVELWARMUP_CYCLESMIN_ORDER_QUOTEBE_GUARDBE_GUARD_BLOCK_MARKET_SELLSNO_POST_ONLYIS_MARGIN_STRATADX_TRACEVERBOSE_LOGSVERBOSE_INTERVAL_MINADX_TEST_MODEPORTFOLIO_INCLUDEPORTFOLIO_EXP_BUDGETPAIR_EXP_BUDGETNO_CLOSE_MARKETCONSEC_RESET_CYCLESDISABLE_BREAKER_WINDDOWNRESET_BREAKER_ONCERESET_STATS_ONCEQUANTRODUCTION_TRACETRACE_ALLSPREAD_PNL_JUMP_GUARD
Open presentation findings
- WARN · console — 1 raw console.* call(s) bypass the tagged emitter — output carries no tag and will not align: [AdxTrendMM] dashboard err: +String(_de))} }
- NOTE · inputs — GUI editor entry is linked by the marker `adxtrendmm` rather than the filename `adxTrendMM` (case-insensitive). It resolves, but a rename of either side breaks the link silently.