Architecture, strategy logic, version governance, and MQL5 patterns behind GoldBreak — running live on XAUUSD. Built with the same rigour as production software.
GoldBreak is a session-aware Donchian channel breakout Expert Advisor targeting XAUUSD on M1. Entry signals trigger when price breaks the Donchian high or low within defined session windows — session timing is the primary filter, not a secondary one.
On a valid breakout, the EA opens an initial position sized by risk percentage. Subsequent positions scale in at fixed ATR multiples — a pyramid scaling architecture that compounds winning moves while keeping total position risk bounded. Each pyramid level carries an independent take-profit; a shared trailing stop manages the composite position.
Development is strictly version-controlled. Every parameter change requires a full backtest comparison against the benchmark version before deployment. The benchmark — v11.7 — achieved 87% win rate with 7.61% max drawdown across 2022–2025. Version 12.0 regressed severely when three features simultaneously suppressed the pyramid; the lesson is now a governance rule.
g_ordersActive flag now correctly clears on London expiry.| Version | Net Profit | Win Rate | Max DD | Key Change | Status |
|---|---|---|---|---|---|
| v11.7 | $1,260,000+ | 87% | 7.61% | Benchmark — strongest live performer | Live |
| v11.8 | — | — | — | 5 bug fixes: Asia expiry, NY cancel, Friday cutoff, VPS migration | In Dev |
| v12.0 | Regressed | ↓ | ↑ | H4 EMA gate + Adaptive ADT + VAS floored — all three suppressed pyramid | Reverted |
| v13 (best) | $2,016,226 | — | — | BATRP=8, Risk=25, MaxLot=150 · AccelLo/Hi hardcoded constants | Research |
// Donchian breakout entry check
double hi = iHigh(Symbol(), PERIOD_M1,
iHighest(Symbol(), PERIOD_M1,
MODE_HIGH, DonchianPeriod, 1));
double lo = iLow(Symbol(), PERIOD_M1,
iLowest(Symbol(), PERIOD_M1,
MODE_LOW, DonchianPeriod, 1));
if (InSession(LONDON) && !g_londonFired) {
if (Ask > hi) {
OpenBuy(LotSize);
g_londonFired = true;
} else if (Bid < lo) {
OpenSell(LotSize);
g_londonFired = true;
}
}
// Pyramid entry at ATR multiples
double atr = GetATR(ATRPeriod);
for (int i=1; i<=MaxPyramidLevels; i++) {
double target =
g_initialEntry + (i * atr * PyramidStep);
if (Ask >= target && !g_levelOpen[i]) {
double lot = PyramidLot(i, LotSize);
OpenBuy(lot);
SetTP(target + atr * TPMultiplier);
g_levelOpen[i] = true;
}
}
g_ordersActive flag resets on London expiry so NY can place fresh orders without immediately cancelling.
// OnTimer — session expiry handler
void OnTimer() {
if (IsLondonExpiry()) {
CancelPendingOrders(LONDON);
// v11.8 fix: reset flag so NY fires
g_ordersActive = false;
g_londonFired = false;
}
if (InSession(NEW_YORK) &&
!g_ordersActive &&
!g_nyFired) {
PlaceBreakoutOrders(NEW_YORK);
g_ordersActive = true;
g_nyFired = true;
}
}
// Friday-aware expiry calculation
datetime GetExpiryTime() {
MqlDateTime dt;
TimeToStruct(TimeCurrent(), dt);
// Friday = day_of_week 5
if (dt.day_of_week == 5) {
// Use early close to avoid weekend gap
return BuildTime(dt,
FridayExpiryHour, 0);
}
// Standard expiry for other days
return BuildTime(dt, ExpiryHour, 0);
}