Summary: 黄金层进EA是一款专为XAUUSD设计的MQL4智能交易系统。仅在趋势方向执行受控的多层网格加仓,使用EMA趋势过滤、ADX强度验证、动态手数进阶和整体止盈机制,适合H1周期稳定运行。




黄金层进EA采用纪律严明的“趋势网格”方法,专为黄金稳定交易而设计。与盲目双向开仓的传统网格系统不同,本EA仅在主趋势方向(H1 EMA50)上进行网格加仓。它使用多层仓位结构(最多5层),配合受控的动态手数进阶(非马丁格尔)。EA包含ADX(14)趋势强度过滤(>25)以规避震荡市场、ATR波动率保护、点差控制、每日亏损限制和周五平仓保护。整体止盈机制在总浮动盈利达到可配置目标时平掉所有仓位,锁定累积收益。

推荐加载周期: H1
策略核心逻辑:
1. 趋势方向:H1 EMA(50)决定网格方向(价格高于EMA只做多网格;低于EMA只做空网格)。
2. 趋势强度:ADX(14)必须大于25,确认市场处于趋势状态。
3. 首单入场:当价格回撤至EMA(50)附近并出现确认性K线形态时开第一单。
4. 网格层进:每隔`GridStepPoints`点(默认200点)沿趋势方向加仓,手数按`LotIncrement`递增(默认每级增加0.01手)。
5. 整体止盈:当所有网格仓位的总浮动盈利达到`BasketTargetProfit`(起始手数0.01对应默认15美元)时,全部平仓。

```mql4
//+------------------------------------------------------------------+
//| GoldCascadeEA.mq4 |
//+------------------------------------------------------------------+
#property copyright ""
#property link ""
#property version "1.00"
#property strict

//--- 输入参数及注释
input double StartLot = 0.01; // 起始手数(黄金0.01手)
input double LotIncrement = 0.01; // 每级手数增量(每层增加0.01手)
input int MaxGridLevels = 5; // 最大网格层数(持仓数量)
input int GridStepPoints = 200; // 网格步长点数(层间距离200点)
input int TrendMAPeriod = 50; // EMA周期(趋势方向过滤)
input int ADXPeriod = 14; // ADX周期(趋势强度)
input int ADXThreshold = 25; // 最小ADX阈值(趋势市场要求)
input double ATRStopMultiplier = 1.5; // 止损倍数(ATR倍数)
input double BasketTargetProfit = 15.0; // 整体止盈金额(美元,起始手数0.01参考)
input double DailyLossLimit = 5.0; // 每日亏损限额(账户余额百分比)
input int MaxSpread = 35; // 最大允许点差(黄金单位:点)
input bool UseFridayClose = true; // 周五21:00 GMT前平仓
input int MagicNumber = 202502; // EA魔术号

//--- 全局变量
double dailyStartBalance = 0;
datetime lastBarTime = 0;
bool fridayCloseExecuted = false;
double avgATR = 0;
int consecutiveLosses = 0;

//+------------------------------------------------------------------+
//| EA初始化函数 |
//+------------------------------------------------------------------+
int OnInit()
{
dailyStartBalance = AccountBalance();
lastBarTime = 0;
fridayCloseExecuted = false;
avgATR = iATR(Symbol(), PERIOD_H1, 14, 1);
if(avgATR <= 0) avgATR = 250 * Point;
return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| EA退出函数 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}

//+------------------------------------------------------------------+
//| 获取EMA趋势方向 |
//+------------------------------------------------------------------+
int GetTrendDirection()
{
double close1 = iClose(Symbol(), PERIOD_H1, 1);
double ema = iMA(Symbol(), PERIOD_H1, TrendMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
if(close1 > ema) return 1; // 上涨趋势
if(close1 < ema) return -1; // 下跌趋势
return 0;
}

//+------------------------------------------------------------------+
//| 检查ADX趋势强度 |
//+------------------------------------------------------------------+
bool IsTrendStrong()
{
double adx = iADX(Symbol(), PERIOD_H1, ADXPeriod, PRICE_CLOSE, MODE_MAIN, 1);
return (adx >= ADXThreshold);
}

//+------------------------------------------------------------------+
//| 统计指定方向的网格持仓数量 |
//+------------------------------------------------------------------+
int CountGridPositions(int direction)
{
int count = 0;
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
if((direction == 1 && OrderType() == OP_BUY) ||
(direction == -1 && OrderType() == OP_SELL))
count++;
}
}
}
return count;
}

//+------------------------------------------------------------------+
//| 获取指定方向的最后一单开仓价格 |
//+------------------------------------------------------------------+
double GetLastOrderPrice(int direction)
{
double lastPrice = 0;
datetime lastTime = 0;
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
if((direction == 1 && OrderType() == OP_BUY) ||
(direction == -1 && OrderType() == OP_SELL))
{
if(OrderOpenTime() > lastTime)
{
lastTime = OrderOpenTime();
lastPrice = OrderOpenPrice();
}
}
}
}
}
return lastPrice;
}

//+------------------------------------------------------------------+
//| 计算所有网格仓位的总浮动盈亏 |
//+------------------------------------------------------------------+
double CalculateBasketProfit()
{
double totalProfit = 0;
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
totalProfit += OrderProfit() + OrderSwap() + OrderCommission();
}
}
}
return totalProfit;
}

//+------------------------------------------------------------------+
//| 平仓所有网格订单(整体平仓) |
//+------------------------------------------------------------------+
void CloseAllGridOrders()
{
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
if(OrderType() == OP_BUY)
OrderClose(OrderTicket(), OrderLots(), Bid, 5, clrNONE);
else if(OrderType() == OP_SELL)
OrderClose(OrderTicket(), OrderLots(), Ask, 5, clrNONE);
}
}
}
}

//+------------------------------------------------------------------+
//| 计算下一层的手数 |
//+------------------------------------------------------------------+
double GetNextLotSize(int currentLevel)
{
// 手数 = 起始手数 + (当前层数 × 手数增量)
// 第0层(首单):起始手数
// 第1层:起始手数 + 手数增量
// 第2层:起始手数 + 2 × 手数增量
double lot = StartLot + (currentLevel * LotIncrement);
if(lot < 0.01) lot = 0.01;
if(lot > 1.0) lot = 1.0;
return NormalizeDouble(lot, 2);
}

//+------------------------------------------------------------------+
//| 判断是否需要添加网格层 |
//+------------------------------------------------------------------+
bool ShouldAddGridLayer(int direction, int currentLevel, double lastPrice)
{
if(currentLevel >= MaxGridLevels) return false;

double currentPrice = (direction == 1) ? Bid : Ask;
double step = GridStepPoints * Point;
double distance = MathAbs(currentPrice - lastPrice);

return (distance >= step);
}

//+------------------------------------------------------------------+
//| 开立首单(趋势入场) |
//+------------------------------------------------------------------+
bool OpenFirstPosition(int direction, double atr)
{
double entryPrice = 0, sl = 0, tp = 0;
int cmd = (direction == 1) ? OP_BUY : OP_SELL;

if(direction == 1)
{
entryPrice = Ask;
sl = entryPrice - (atr * ATRStopMultiplier);
tp = 0; // 无单独止盈,由整体止盈管理
}
else
{
entryPrice = Bid;
sl = entryPrice + (atr * ATRStopMultiplier);
tp = 0;
}

double lot = StartLot;
int ticket = OrderSend(Symbol(), cmd, lot, entryPrice, 5, sl, tp, "Cascade L1", MagicNumber, 0, clrNONE);
if(ticket > 0)
{
Print("首单开仓成功,方向:", direction==1?"买入":"卖出");
return true;
}
else
{
Print("首单开仓失败,错误码:", GetLastError());
return false;
}
}

//+------------------------------------------------------------------+
//| 添加网格层 |
//+------------------------------------------------------------------+
bool AddGridLayer(int direction, int currentLevel)
{
double entryPrice = 0, sl = 0;
int cmd = (direction == 1) ? OP_BUY : OP_SELL;
double atr = iATR(Symbol(), PERIOD_H1, 14, 1);
if(atr <= 0) atr = avgATR;

if(direction == 1)
{
entryPrice = Ask;
sl = entryPrice - (atr * ATRStopMultiplier);
}
else
{
entryPrice = Bid;
sl = entryPrice + (atr * ATRStopMultiplier);
}

double lot = GetNextLotSize(currentLevel);
int ticket = OrderSend(Symbol(), cmd, lot, entryPrice, 5, sl, 0, "Cascade L" + string(currentLevel+1), MagicNumber, 0, clrNONE);
if(ticket > 0)
{
Print("第 ", currentLevel+1, " 层加仓成功,手数:", lot);
return true;
}
else
{
Print("加仓失败,错误码:", GetLastError());
return false;
}
}

//+------------------------------------------------------------------+
//| 检查回撤至EMA的入场条件 |
//+------------------------------------------------------------------+
bool IsPullbackEntry(int direction)
{
double close1 = iClose(Symbol(), PERIOD_H1, 1);
double low1 = iLow(Symbol(), PERIOD_H1, 1);
double high1 = iHigh(Symbol(), PERIOD_H1, 1);
double ema = iMA(Symbol(), PERIOD_H1, TrendMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
double open1 = iOpen(Symbol(), PERIOD_H1, 1);

if(direction == 1) // 做多:价格回撤至EMA下方(或触及),收盘于EMA上方
{
bool touchedEMA = (low1 <= ema);
bool closedAbove = (close1 > ema);
bool bullishCandle = (close1 > open1);
return (touchedEMA && closedAbove && bullishCandle);
}
else if(direction == -1) // 做空:价格反弹至EMA上方(或触及),收盘于EMA下方
{
bool touchedEMA = (high1 >= ema);
bool closedBelow = (close1 < ema);
bool bearishCandle = (close1 < open1);
return (touchedEMA && closedBelow && bearishCandle);
}
return false;
}

//+------------------------------------------------------------------+
//| 检查每日亏损限额 |
//+------------------------------------------------------------------+
bool IsDailyLossExceeded()
{
double currentEquity = AccountEquity();
double lossPercent = (dailyStartBalance - currentEquity) / dailyStartBalance * 100;
return (lossPercent >= DailyLossLimit);
}

//+------------------------------------------------------------------+
//| 检查整体止盈 |
//+------------------------------------------------------------------+
bool CheckBasketTakeProfit()
{
double basketProfit = CalculateBasketProfit();
if(basketProfit >= BasketTargetProfit)
{
CloseAllGridOrders();
Print("整体止盈触发,盈利:$", basketProfit);
return true;
}
return false;
}

//+------------------------------------------------------------------+
//| EA主循环函数(每Tick执行) |
//+------------------------------------------------------------------+
void OnTick()
{
// 每日亏损保护
if(IsDailyLossExceeded())
{
Comment("已达每日亏损上限,停止开新仓");
return;
}

// 周五收盘前平仓(规避周末跳空)
if(UseFridayClose && !fridayCloseExecuted)
{
datetime currentTime = TimeCurrent();
if(TimeDayOfWeek(currentTime) == 5 && TimeHour(currentTime) >= 21)
{
CloseAllGridOrders();
fridayCloseExecuted = true;
return;
}
if(TimeDayOfWeek(currentTime) != 5)
fridayCloseExecuted = false;
}

// 点差过滤
if(MarketInfo(Symbol(), MODE_SPREAD) > MaxSpread)
{
Comment("当前点差过大:", MarketInfo(Symbol(), MODE_SPREAD));
return;
}

// 仅在新K线开始时检测入场(H1)
if(Time[0] == lastBarTime)
return;
lastBarTime = Time[0];

// 更新平均ATR
double atr = iATR(Symbol(), PERIOD_H1, 14, 1);
if(atr > 0) avgATR = (avgATR * 0.95) + (atr * 0.05);

// 检查现有持仓
int posCount = CountGridPositions(1) + CountGridPositions(-1);

if(posCount > 0)
{
// 优先检查整体止盈
if(CheckBasketTakeProfit())
return;

// 确定持仓方向
int direction = 0;
if(CountGridPositions(1) > 0) direction = 1;
else if(CountGridPositions(-1) > 0) direction = -1;

if(direction != 0)
{
int currentLevel = CountGridPositions(direction);
double lastPrice = GetLastOrderPrice(direction);

if(ShouldAddGridLayer(direction, currentLevel, lastPrice))
{
AddGridLayer(direction, currentLevel);
}
}
return;
}

// 无持仓 - 检查新入场信号
int trendDir = GetTrendDirection();
if(trendDir == 0)
{
Comment("无明确趋势方向");
return;
}

if(!IsTrendStrong())
{
Comment("ADX低于阈值,无明确趋势");
return;
}

// 检查回撤入场
if(IsPullbackEntry(trendDir))
{
OpenFirstPosition(trendDir, atr);
}
}

//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
```
参考来源: 原创MQL4代码,策略架构参考了2026年初商业黄金EA的趋势网格原理(如Quant King EA的结构化网格思路)。
免责声明: 黄金交易因高波动性具有重大风险。网格策略在强单边行情中可能放大亏损。本EA按“原样”提供,不保证盈利。实盘部署前请在模拟账户充分测试。历史表现不代表未来结果。
```