Hypotheses
AFAOSMD (geraked, MIT) on ETHUSDT.OKX 30m: Average Force zero-cross + Andean Oscillator + MACD(100,200) signal, REVERSED (contrarian), swing-distance 50% trailing stop, 1.1x averaging grid up to 20 levels
A faithful statement of geraked's MT5 expert 'AFAOSMD' v1.5 (https://github.com/geraked/metatrader5, Experts/AFAOSMD.mq5 + Include/EAUtils.mqh + Indicators/AverageForce.mq5 + Indicators/AndeanOscillator.mq5, MIT…
Strategies
- AfaosmdEthOkxReverseGrid Abandoned
Hypothesis
A faithful statement of geraked's MT5 expert 'AFAOSMD' v1.5 (https://github.com/geraked/metatrader5, Experts/AFAOSMD.mq5 + Include/EAUtils.mqh + Indicators/AverageForce.mq5 + Indicators/AndeanOscillator.mq5, MIT licence; credit: geraked). The original trades NZDCAD 30M FX, which our platform does not carry, so it is mapped to ETHUSDT.OKX (OKX USDT perpetual swap, 30-MINUTE bars, long+short, taker 0.05%, ~0.10% RT). OKX is chosen because it is 0.3% of the corpus while BINANCE is 67%. The mechanism is pure OHLCV,……Show moreShow less
A faithful statement of geraked's MT5 expert 'AFAOSMD' v1.5 (https://github.com/geraked/metatrader5, Experts/AFAOSMD.mq5 + Include/EAUtils.mqh + Indicators/AverageForce.mq5 + Indicators/AndeanOscillator.mq5, MIT licence; credit: geraked). The original trades NZDCAD 30M FX, which our platform does not carry, so it is mapped to ETHUSDT.OKX (OKX USDT perpetual swap, 30-MINUTE bars, long+short, taker 0.05%, ~0.10% RT). OKX is chosen because it is 0.3% of the corpus while BINANCE is 67%. The mechanism is pure OHLCV, so it needs no supplementary feed (lesson 160). All performance the author claims is unverified; our fee-inclusive backtest decides. INDICATORS (all on closed 30m bars; index 1 = last closed bar, index 2 = the bar before): (1) Average Force AF(period P=20, smooth S=9): C1[i] = (close[i] - lowest_low(P bars ending at i)) / (highest_high(P) - lowest_low(P)) - 0.5 (0 if the range is 0); AF[i] = simple mean of C1 over the last S=9 bars. Buffer 0. (2) Andean Oscillator (Length=50, SignalLength=9): alpha = 2/(Length+1). Recursively: up1 = max(max(close,open), up1_prev - (up1_prev - close)*alpha); up2 = max(max(close^2,open^2), up2_prev - (up2_prev - close^2)*alpha); dn1 = min(min(close,open), dn1_prev + (close - dn1_prev)*alpha); dn2 = min(min(close^2,open^2), dn2_prev + (close^2 - dn2_prev)*alpha). Each state is seeded with close (or close^2) when it is 0. Bull = sqrt(dn2 - dn1^2); Bear = sqrt(up2 - up1^2); Signal = EMA9(max(Bull,Bear)), which the rules do not use. Compute on raw prices (squared ETH prices fit in float64) and guard sqrt of tiny negatives with max(0,.). (3) MACD main line MD = EMA(close,100) - EMA(close,200) (iMACD with signal period 1; only the main line is read). RAW SIGNALS (evaluated once per new bar, at each 30m bar close): BuySignal: Bull[1] > Bear[1] AND AF[2] < 0 AND AF[1] > 0 AND MD[2] > 0 AND MD[1] > 0 AND MD[2] < MD[1]. SellSignal: Bull[1] < Bear[1] AND AF[2] > 0 AND AF[1] < 0 AND MD[2] < 0 AND MD[1] < 0 AND MD[2] > MD[1]. BuySignal is checked first; SellSignal is checked only if BuySignal did not fire. REVERSE = true (default): the EA trades the OPPOSITE side. A BuySignal opens a SHORT and a SellSignal opens a LONG. The strategy therefore fades a fresh AF zero-cross that agrees with the Andean regime and a rising or falling MACD trend. GATES before signals are evaluated (OnTick, new bar only): OpenNewPos=true; SpreadLimit=-1 (off); MarginLimit=300%, meaning skip new entries when positions are open and the margin level is below 300% (translate as: skip new entries when margin used > equity/3). Because Grid=true, there is NO new signal entry while any position (any grid level) is open. News=false; EquityDrawdownLimit=0 (off). SWING DISTANCE pd (stored per basket; the EA writes it into the order comment): for a BuySignal, swing = lowest low of bars 1..7 minus SLDev; for a SellSignal, swing = highest high of bars 1..7 plus SLDev. SLDev=60 points on a 5-digit FX quote is about 0.07% of price, so use 0.07% of entry price. pd = |entry - swing|. TPCoef=1.0, so the original TP distance is also pd. STOPS AND TARGETS ON THE FIRST ORDER: with Reverse=true the EA swaps SL and TP and also swaps the IgnoreSL and IgnoreTP flags. With Grid=true it forces isl=true before the swap. With the defaults (IgnoreSL=false, IgnoreTP=true, Grid=true), the first order therefore has NO stop-loss and NO take-profit. Exits come only from the trailing logic and the grid basket TP below. POSITION SIZE (RISK_DEFAULT, Risk=1%): volume = 1% of min(balance, free margin) / |entry - SLparam|. After the reverse swap SLparam is the original TP price, so the distance is TPCoef*pd = pd. Level-1 notional = 0.01*equity*entry/pd (e.g. pd = 1.2% gives notional of about 0.83x equity). TRAILING (Trail=true, TrailingStopLevel=50%): MT5 checks this every 30s; we check at each 30m bar close and hold the stop as a resting stop order, so it can trigger intrabar. It applies while the basket has exactly one position. For a long: once price is above entry by d, candidate stop = max(entry, breakeven including costs) + d - 0.5*pd. The stop is only set if it is >= entry and tighter than the existing stop, so it activates after a favourable move of 0.5*pd and then trails 0.5*pd behind the best price. If price is within 30 points (~0.035%) of the candidate stop and the trade is net profitable, close at market. Shorts mirror this. GridTrailingStopLevel=0, so there is no trailing once the grid has 2+ levels. GRID (Grid=true, GridVolMult=1.1, GridMaxLvl=20): while n (open levels) < 20, check whether price has moved ADVERSELY to level lvl = first_entry -/+ n*pd (long: price <= first_entry - n*pd; short: price >= first_entry + n*pd). If |last_level_price -/+ pd - lvl| > 0.5*pd, use last_level_price -/+ pd as the level instead. If the level is reached and price is at least 30 points from the last level price, add a position in the same direction with volume = largest existing volume * 1.1. Then set ONE basket take-profit on all levels at the price where total basket PnL = level-1 volume * pd + accumulated costs, at least 30 points from price. The whole basket closes when that TP is hit. The source has no basket stop. PLATFORM ADAPTATION (only where the source cannot run as written): NautilusTrader holds one net position per instrument, so grid levels are tracked internally as a list of (price, qty), and the net position is increased by market order. Basket breakeven and TP are computed from that list. Leverage config = 10x (the engine clamps at 20x). An add-on that would take gross notional above 10x equity is skipped, which mirrors MT5's 'no money' rejection. Flat state: flat between baskets, expected ~55-65% of the time. PRE-REGISTERED SECOND VARIANT (scored separately; Grid=false, all else default): no averaging. With Reverse and IgnoreTP=true/IgnoreSL=false, the first order gets NO stop and a TAKE-PROFIT at the original swing level (distance pd in the trade's favour), plus the same 50% trail. Report both; the primary claim is the faithful default.
Analysis
AFAOSMD
Backtest and paper results are hypothetical. Trading involves risk of loss.