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




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

推荐加载周期: H1
策略核心逻辑:
  • 趋势方向:H1 EMA(50)决定网格方向(价格高于EMA只做多网格;低于EMA只做空网格)。

  • 趋势强度:ADX(14)必须大于25,确认市场处于趋势状态。

  • 首单入场:当价格回撤至EMA(50)附近并出现确认性K线形态时开第一单。

  • 网格层进:每隔GridStepPoints点(默认200点)沿趋势方向加仓,手数按LotIncrement递增(默认每级增加0.01手)。

  • 整体止盈:当所有网格仓位的总浮动盈利达到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按“原样”提供,不保证盈利。实盘部署前请在模拟账户充分测试。历史表现不代表未来结果。
    ``