Skip to content
All strategies

Strategies

3MAF by geraked (faithful port): Triple-EMA 60/350/600 Stack + Williams-Fractal Pullback Entry, Breakeven-Activated 50% Trailing Stop, 1.5x Martingale Grid (20 levels) with Basket TP and 40% Basket Trail, No Hard Stop, Long-Short (ETHUSDT.BYBIT 15m)

Outcome: Abandoned

ThreeMAFGridEthBybit

Outcome Summary

ThreeMAFGridEthBybit ported the 3MAF expert advisor (triple-EMA trend stack, fractal pullback entries, trailing stop and a 1.5x martingale grid with no hard stop) from USDCAD 15M to Bybit ETH perpetuals. It went through 3 iterations; according to the code header, iteration 2 shipped a placeholder string instead of code, and iteration 3 resubmitted the full source. That version then ran past the 300s Layer 3 sandbox backtest limit on a 208-day, ~20,000-bar window, and the pipeline abandoned it as a verification loop. No backtest, optimization, analyst or risk review ever ran, so the strategy's edge is still untested.

Hypothesis

Faithful statement of the open-source MQL5 expert advisor '3MAF' v1.5 by geraked (MIT licence, https://github.com/geraked/metatrader5/blob/d3eb29c382acf715727d5cd6a0414151e821fc2d/Experts/3MAF.mq5, plus the order/trail/grid helpers it calls in Include/EAUtils.mqh at the same commit). All credit for the strategy goes to the author. The original was published for USDCAD 15M (2021-02 to 2023-09). Any performance it claims is unverified; our backtest with real Bybit fees decides. It is a real tradeable strategy, not……Show moreShow less

Faithful statement of the open-source MQL5 expert advisor '3MAF' v1.5 by geraked (MIT licence, https://github.com/geraked/metatrader5/blob/d3eb29c382acf715727d5cd6a0414151e821fc2d/Experts/3MAF.mq5, plus the order/trail/grid helpers it calls in Include/EAUtils.mqh at the same commit). All credit for the strategy goes to the author. The original was published for USDCAD 15M (2021-02 to 2023-09). Any performance it claims is unverified; our backtest with real Bybit fees decides. It is a real tradeable strategy, not a utility. PLATFORM MAPPING. Instrument ETHUSDT.BYBIT, Bybit linear USDT perp, 15-MINUTE bars. It has multi-year 15m history in the catalog from 2021-03-15; the OKX alt 15m series only holds about 2 days. Venue fees are 0.02% maker and 0.055% taker, about 0.11% round trip. The strategy needs shorts and leverage, so it cannot run on spot. The mechanism is pure OHLCV, so BYBIT is admissible (lesson L160). BTC was avoided because of corpus concentration. Config leverage is 10.0 and acts as the margin ceiling that stands in for MT5's broker margin. News filter, spread limit and equity-drawdown limit are all OFF by default in the source, so they are omitted. INDICATORS (defaults exactly as written): - MA1 = EMA(close, 60), MA2 = EMA(close, 350), MA3 = EMA(close, 600). MaMethod is MODE_EMA and MaPrice is PRICE_CLOSE. - Williams Fractals, as in MT5's built-in iFractals. A lower fractal at bar j means low[j] < low[j+1] and low[j] < low[j+2] (the two newer bars), and low[j] <= low[j-1] and low[j] <= low[j-2] (the two older bars). The upper fractal mirrors this with highs. - The EA evaluates on the first tick of a new bar and reads fractal buffer index 2. That is the bar before the just-closed bar, and its 'second newer bar' is the new bar that has only its opening tick. - Point-in-time translation at the close of our bar t (MQL index 1 = t, index 2 = t-1): a lower fractal at t-1 requires low[t-1] < low[t] AND low[t-1] < close[t] (close[t] stands in for the new bar's open on a 24/7 market), AND low[t-1] <= low[t-2] AND low[t-1] <= low[t-3]. The upper fractal at t-1 mirrors this with highs. - Warm-up is 600 bars before any signal. The EA is evaluated once per closed bar. Trail and grid management runs on the source's 60-second timer. We run it once per closed 15m bar and rest stop/limit orders at the computed levels, so intrabar touches fill.

Iteration 3 fixes the Layer-1 'invalid decimal literal at line 1' error. The previous submission's code field held a placeholder string pointing at the outbox file, not Python source. This submission carries the same strategy logic in full (it parses cleanly), so nothing else changed. Translation notes: the MT5 60s timer runs once per closed 15m bar. Trail and grid levels rest as venue stop/MIT orders so intrabar touches fill. MinSL of 100 points on USDCAD is mapped to 0.074% of price. The MA method is EMA seeded on the first close. News, spread and equity-DD filters are off in the source and are omitted. All basket state is scalar attributes on self. Caveat: a no-hard-stop 1.5x martingale can take very large drawdowns; the backtest decides.

verification_loop: sandbox_timeout: Verification failed (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit on a ~20000-bar window (208 days of ETHUSDT.BYBIT-15-MINUTE-LAST-EXTERNAL). This almost always means per-bar work that scales with history — e.g. rescanning the full funding/supplementary series, or rebuilding a list and calling min()/sorted() inside calculate_signal()/on_bar() on every bar. Precompute sorted timestamp arrays ONCE in __init__ and use bisect, or cache lookups keyed by timestamp, so per-bar cost is O(log n) not O(n).

Implementation

Faithful port of geraked's 3MAF v1.5 on ETHUSDT.BYBIT 15m. The entry needs an EMA 60/350/600 stack plus a Williams-fractal pullback into the MA1-MA3 zone. There is no hard stop or TP on the first lot. Once past breakeven, the first lot trails at 50% of the initial SL distance d. A 1.5x martingale grid adds a lot every d against the position, up to 20 lots. The basket TP is the price where basket profit equals V0*d plus fees, and a basket trail activates at 40% of that target. Total basket notional is capped at equity*0.95*leverage.

Verification Results

sandbox_timeout: Verification failed (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit on a ~20000-bar window (208 days of ETHUSDT.BYBIT-15-MINUTE-LAST-EXTERNAL). This almost always means per-bar work that scales with history — e.g. rescanning the full funding/supplementary series, or rebuilding a list and calling min()/sorted() inside calculate_signal()/on_bar() on every bar. Precompute sorted timestamp arrays ONCE in __init__ and use bisect, or cache lookups keyed by timestamp, so per-bar cost is O(log n) not O(n).

Iteration History

Verification failed (leverage_set_but_unused): config sets leverage=10.0 but the strategy never references leverage in sizing. Size positions on it — notional = equity * fraction * leverage / price (read self.config.leverage) — or set leverage=1.0. As written the leverage is inert and the backtest is identical to 1x.

Verification failed (Layer 1 — static analysis): - Syntax error: invalid decimal literal (<unknown>, line 1) (line 1)

Outcome Summary

A grid or martingale port that manages resting stop and limit orders on every bar must keep its per-bar work bounded and fast enough to clear the 300s sandbox on ~20k bars. A code submission also needs to be checked so it contains real source, since iteration 2 shipped a placeholder string.

The run was abandoned in a verification loop. Its Layer 3 sandbox smoke test ran past the 300s wall-clock limit on a ~20,000-bar window (208 days of ETHUSDT.BYBIT 15m), so it never reached backtest review, the analyst or the risk officer.

A faithful port of geraked's MIT-licensed MQL5 EA '3MAF' v1.5 to ETHUSDT.BYBIT 15m perps: it enters long or short on Williams-fractal pullbacks inside a stacked EMA 60/350/600 trend, has no hard stop, and manages the position with a breakeven-activated 50% trailing stop plus a 1.5x martingale grid of up to 20 levels with a basket take-profit and a 40% basket trail, capped by 10x leverage.

No performance figures exist: the backtest report is empty and optimization never ran, so there are no return, Sharpe or trade-count numbers.

Analysis

3MAF

Backtest and paper results are hypothetical. Trading involves risk of loss.