Summary: 黄金结构边缘EA是一款专为XAUUSD设计的MQL4智能交易系统,识别H1枢轴区突破并由多EMA趋势过滤确认。包含硬性回撤限制、每日亏损上限和纯结构逻辑。




黄金结构边缘EA基于一个核心理念设计:成功的黄金交易需要结构清晰而非信号噪音。EA识别H1枢轴区——定义市场结构的波段高点和低点——并等待价格突破这些水平,同时接受多EMA趋势过滤器(维加斯隧道:144、288、576 EMA)的确认。不使用马丁格尔、网格或对冲。每笔交易都带有设在枢轴区之外的硬止损,以及基于ATR风险回报比的止盈。EA包含真正生效的硬编码风控限制:每日亏损上限停止交易、总回撤保护阻止新开仓、紧急制动在波动率超过2.5倍ATR时平仓所有头寸。这些限制并非装饰——它们是策略在整个市场周期中保持可控回撤的原因。

推荐加载周期: H1
策略核心逻辑:
  • 枢轴区检测:识别最近20根H1 K线的最高高点和最低低点作为结构枢轴水平。

  • 趋势过滤:维加斯隧道(EMA 144、288、576)在H1上必须全部同向排列。

  • 突破确认:价格收盘高于枢轴高点(做多)或低于枢轴低点(做空),且为动量K线(实体 > 0.7倍区间)。

  • 入场:确认后下一根K线开盘价入场。

  • 风险管理:硬止损为枢轴区外1.5倍ATR;止盈为2.2倍ATR;盈利达到0.8倍ATR后启动追踪止损。


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

    //--- 输入参数及注释
    input double LotSize = 0.01; // 固定交易手数(黄金0.01手)
    input int PivotLookback = 20; // 枢轴区检测回溯K线数
    input int VegasFastEMA = 144; // 维加斯隧道快EMA
    input int VegasMidEMA = 288; // 维加斯隧道中EMA
    input int VegasSlowEMA = 576; // 维加斯隧道慢EMA
    input double MinBodyRangeRatio = 0.7; // 最小实体/区间比例(动量确认)
    input int ATRPeriod = 14; // ATR周期(止损/止盈计算)
    input double ATRStopMultiplier = 1.5; // 止损倍数(ATR倍数)
    input double ATRTakeMultiplier = 2.2; // 止盈倍数(ATR倍数)
    input double TrailingStartATR = 0.8; // 追踪止损启动(盈利达到x倍ATR)
    input double TrailingStepATR = 0.4; // 追踪步长(ATR倍数)
    input double MaxDailyLossPercent = 3.0; // 硬性每日亏损上限(停止交易)
    input double MaxDrawdownPercent = 8.0; // 硬性总回撤上限
    input int MaxConsecutiveLosses = 5; // 最大连续亏损次数(超限后暂停)
    input double EmergencyATRMultiplier = 2.5; // 紧急制动:ATR超过avgATR倍数时平仓
    input int MagicNumber = 202502; // EA魔术号
    input int MaxSpread = 35; // 最大允许点差(黄金单位:点)

    //--- 全局变量
    double dailyStartBalance = 0;
    double peakEquity = 0;
    datetime lastBarTime = 0;
    int consecutiveLosses = 0;
    datetime lastLossTime = 0;
    double avgATR = 0;
    bool drawdownStop = false;
    bool dailyStop = false;
    double pivotHigh = 0;
    double pivotLow = 0;

    //+------------------------------------------------------------------+
    //| EA初始化函数 |
    //+------------------------------------------------------------------+
    int OnInit()
    {
    dailyStartBalance = AccountBalance();
    peakEquity = AccountEquity();
    lastBarTime = 0;
    consecutiveLosses = 0;
    drawdownStop = false;
    dailyStop = false;
    avgATR = iATR(Symbol(), PERIOD_H1, ATRPeriod, 1);
    if(avgATR <= 0) avgATR = 250 Point;
    return(INIT_SUCCEEDED);
    }

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

    //+------------------------------------------------------------------+
    //| 获取维加斯隧道趋势方向(所有EMA同向排列) |
    //+------------------------------------------------------------------+
    int GetVegasTrend()
    {
    double emaFast = iMA(Symbol(), PERIOD_H1, VegasFastEMA, 0, MODE_EMA, PRICE_CLOSE, 1);
    double emaMid = iMA(Symbol(), PERIOD_H1, VegasMidEMA, 0, MODE_EMA, PRICE_CLOSE, 1);
    double emaSlow = iMA(Symbol(), PERIOD_H1, VegasSlowEMA, 0, MODE_EMA, PRICE_CLOSE, 1);
    double emaFastPrev = iMA(Symbol(), PERIOD_H1, VegasFastEMA, 0, MODE_EMA, PRICE_CLOSE, 2);
    double emaMidPrev = iMA(Symbol(), PERIOD_H1, VegasMidEMA, 0, MODE_EMA, PRICE_CLOSE, 2);
    double emaSlowPrev = iMA(Symbol(), PERIOD_H1, VegasSlowEMA, 0, MODE_EMA, PRICE_CLOSE, 2);

    bool bullishAlign = (emaFast > emaMid && emaMid > emaSlow);
    bool bearishAlign = (emaFast < emaMid && emaMid < emaSlow);
    bool bullishSlope = (emaFast > emaFastPrev && emaMid > emaMidPrev && emaSlow > emaSlowPrev);
    bool bearishSlope = (emaFast < emaFastPrev && emaMid < emaMidPrev && emaSlow < emaSlowPrev);

    if(bullishAlign && bullishSlope) return 1;
    if(bearishAlign && bearishSlope) return -1;
    return 0;
    }

    //+------------------------------------------------------------------+
    //| 检测枢轴区水平(波段高低点) |
    //+------------------------------------------------------------------+
    void DetectPivotZone()
    {
    int highestIdx = iHighest(Symbol(), PERIOD_H1, MODE_HIGH, PivotLookback, 1);
    int lowestIdx = iLowest(Symbol(), PERIOD_H1, MODE_LOW, PivotLookback, 1);

    if(highestIdx > 0)
    pivotHigh = iHigh(Symbol(), PERIOD_H1, highestIdx);
    if(lowestIdx > 0)
    pivotLow = iLow(Symbol(), PERIOD_H1, lowestIdx);
    }

    //+------------------------------------------------------------------+
    //| 检查动量K线质量 |
    //+------------------------------------------------------------------+
    bool IsMomentumCandle(int direction)
    {
    double open = iOpen(Symbol(), PERIOD_H1, 1);
    double close = iClose(Symbol(), PERIOD_H1, 1);
    double high = iHigh(Symbol(), PERIOD_H1, 1);
    double low = iLow(Symbol(), PERIOD_H1, 1);
    double range = high - low;
    double body = MathAbs(close - open);

    if(range <= 0) return false;
    if(body / range < MinBodyRangeRatio) return false;

    if(direction == 1) // 看涨动量
    return (close > open && close > pivotHigh);
    else if(direction == -1) // 看跌动量
    return (close < open && close < pivotLow);

    return false;
    }

    //+------------------------------------------------------------------+
    //| 检查突破入场条件 |
    //+------------------------------------------------------------------+
    bool CheckBreakoutEntry(int trendDir, double &entryPrice, double &sl, double &tp, double atr)
    {
    if(trendDir == 0) return false;
    if(pivotHigh <= 0 || pivotLow <= 0) return false;

    double close1 = iClose(Symbol(), PERIOD_H1, 1);

    if(trendDir == 1 && close1 > pivotHigh && IsMomentumCandle(1))
    {
    entryPrice = Ask;
    sl = entryPrice - (atr
    ATRStopMultiplier);
    tp = entryPrice + (atr ATRTakeMultiplier);
    return true;
    }
    else if(trendDir == -1 && close1 < pivotLow && IsMomentumCandle(-1))
    {
    entryPrice = Bid;
    sl = entryPrice + (atr
    ATRStopMultiplier);
    tp = entryPrice - (atr ATRTakeMultiplier);
    return true;
    }
    return false;
    }

    //+------------------------------------------------------------------+
    //| 更新连续亏损计数器(市场记忆) |
    //+------------------------------------------------------------------+
    void UpdateLossCounter()
    {
    static int prevOrders = 0;
    static double prevEquity = 0;

    int currentOrders = CountPositions();
    double currentEquity = AccountEquity();

    if(prevOrders > 0 && currentOrders == 0)
    {
    double equityChange = currentEquity - prevEquity;
    if(equityChange < 0)
    {
    consecutiveLosses++;
    lastLossTime = TimeCurrent();
    }
    else if(equityChange > 0)
    {
    consecutiveLosses = 0;
    }
    }

    if(currentOrders > 0)
    prevEquity = currentEquity;

    prevOrders = currentOrders;
    }

    //+------------------------------------------------------------------+
    //| 检查并执行硬性风控限制 |
    //+------------------------------------------------------------------+
    bool CheckHardRiskLimits()
    {
    double currentEquity = AccountEquity();
    double dailyLossPercent = (dailyStartBalance - currentEquity) / dailyStartBalance
    100;
    double totalDrawdownPercent = (peakEquity - currentEquity) / peakEquity 100;

    // 更新峰值权益
    if(currentEquity > peakEquity)
    peakEquity = currentEquity;

    // 每日亏损限制
    if(dailyLossPercent >= MaxDailyLossPercent)
    {
    if(!dailyStop)
    {
    CloseAllOrders();
    dailyStop = true;
    Comment("每日亏损上限触发,今日停止交易");
    }
    return false;
    }

    // 总回撤限制
    if(totalDrawdownPercent >= MaxDrawdownPercent)
    {
    if(!drawdownStop)
    {
    CloseAllOrders();
    drawdownStop = true;
    Comment("最大回撤上限触发,EA暂停");
    }
    return false;
    }

    // 连续亏损冷却
    if(consecutiveLosses >= MaxConsecutiveLosses)
    {
    if(TimeCurrent() - lastLossTime < 3600) // 冷却1小时
    {
    Comment("连续亏损冷却中,已亏损", consecutiveLosses, "次");
    return false;
    }
    else
    {
    consecutiveLosses = 0;
    }
    }

    return true;
    }

    //+------------------------------------------------------------------+
    //| 紧急制动:波动率爆炸时平仓 |
    //+------------------------------------------------------------------+
    void CheckEmergencyBrake()
    {
    double atr = iATR(Symbol(), PERIOD_H1, ATRPeriod, 1);
    if(atr > avgATR
    EmergencyATRMultiplier && avgATR > 0)
    {
    CloseAllOrders();
    Comment("紧急制动触发:波动率过高 ATR ", atr);
    }
    if(atr > 0) avgATR = (avgATR 0.95) + (atr 0.05);
    }

    //+------------------------------------------------------------------+
    //| 管理持仓的追踪止损 |
    //+------------------------------------------------------------------+
    void ManageTrailingStop(double atr)
    {
    for(int i = OrdersTotal()-1; i >= 0; i--)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
    if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
    {
    double activate = atr TrailingStartATR;
    double step = atr
    TrailingStepATR;
    double newSL = 0;

    if(OrderType() == OP_BUY)
    {
    double profit = Bid - OrderOpenPrice();
    if(profit >= activate)
    {
    newSL = Bid - step;
    if(newSL > OrderStopLoss())
    OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE);
    }
    }
    else if(OrderType() == OP_SELL)
    {
    double profit = OrderOpenPrice() - Ask;
    if(profit >= activate)
    {
    newSL = Ask + step;
    if(newSL < OrderStopLoss() || OrderStopLoss() == 0)
    OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE);
    }
    }
    break;
    }
    }
    }
    }

    //+------------------------------------------------------------------+
    //| EA主循环函数(每Tick执行) |
    //+------------------------------------------------------------------+
    void OnTick()
    {
    // 更新亏损计数器(市场记忆)
    UpdateLossCounter();

    // 优先检查紧急制动
    CheckEmergencyBrake();

    // 检查硬性风控限制
    if(!CheckHardRiskLimits())
    return;

    // 每日重置
    datetime currentTime = TimeCurrent();
    static datetime lastDay = 0;
    if(TimeDayOfYear(currentTime) != TimeDayOfYear(lastDay))
    {
    dailyStartBalance = AccountBalance();
    dailyStop = false;
    lastDay = currentTime;
    }

    // 周五收盘保护
    if(TimeDayOfWeek(currentTime) == 5 && TimeHour(currentTime) >= 21)
    {
    if(CountPositions() > 0)
    CloseAllOrders();
    return;
    }

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

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

    // 管理现有持仓
    int posCount = CountPositions();
    if(posCount > 0)
    {
    double atr = iATR(Symbol(), PERIOD_H1, ATRPeriod, 1);
    if(atr > 0) ManageTrailingStop(atr);
    return;
    }

    // 获取ATR
    double atr = iATR(Symbol(), PERIOD_H1, ATRPeriod, 1);
    if(atr <= 0) atr = avgATR;

    // 检测枢轴区水平
    DetectPivotZone();

    // 获取维加斯隧道趋势方向
    int trendDir = GetVegasTrend();
    if(trendDir == 0)
    {
    Comment("维加斯隧道无明确同向排列");
    return;
    }

    // 检查突破入场
    double entryPrice = 0, sl = 0, tp = 0;
    if(CheckBreakoutEntry(trendDir, entryPrice, sl, tp, atr))
    {
    int cmd = (trendDir == 1) ? OP_BUY : OP_SELL;
    int ticket = OrderSend(Symbol(), cmd, LotSize, entryPrice, 5, sl, tp, "Structural Edge", MagicNumber, 0, clrNONE);
    if(ticket < 0)
    Print("开仓失败,错误码:", GetLastError());
    else
    Print("枢轴突破开仓成功,方向:", cmd==OP_BUY?"买入":"卖出");
    }
    }

    //+------------------------------------------------------------------+
    //| 统计当前魔术号的持仓数量 |
    //+------------------------------------------------------------------+
    int CountPositions()
    {
    int count = 0;
    for(int i = OrdersTotal()-1; i >= 0; i--)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
    if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
    count++;
    }
    }
    return count;
    }

    //+------------------------------------------------------------------+
    //| 平仓当前品种下所有属于该EA的订单 |
    //+------------------------------------------------------------------+
    void CloseAllOrders()
    {
    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);
    }
    }
    }
    }
    //+------------------------------------------------------------------+
    ``
    参考来源: 原创MQL4代码,策略架构参考了2025-2026年MQL5市场上黄金EA的结构化交易原理,包括Gold BullBear Structure Trader的枢轴区检测方法和