Summary: 黄金突破引擎EA是一款专为XAUUSD设计的MQL4智能交易系统。识别波动率压缩突破,配合Order Block趋势确认和ATR动态网格管理,适合M15周期。




黄金突破引擎EA专为XAUUSD设计,融合三大核心模块:波动率压缩突破检测、Order Block趋势过滤、以及ATR自适应网格回血。EA首先识别波动率压缩形态(区间收窄),然后通过简化的Order Block概念(近期摆动高低点结构)确认突破方向,最后用ATR自适应网格管理交易序列,在达到盈利目标时平仓所有订单。这种多层过滤机制减少了假突破,而受控的网格结构有助于挽回回撤且不产生无限风险。

推荐加载周期: M15
策略核心逻辑:
  • 波动率压缩:检测当前ATR(14)是否低于过去20根K线平均ATR的0.65倍。

  • 突破方向:当价格收盘高于压缩期间最高点→潜在买入;低于压缩期间最低点→潜在卖出。

  • Order Block过滤:确认近期摆动结构支持突破方向(价格已突破前期关键水平位)。

  • 网格执行:首单设固定止损(ATR×1.2),后续按ATR距离间隔加仓,手数1.5倍递增(最多3层)。

  • 止盈退出:当总浮动盈利达到账户余额的1%时,或单笔止盈触发时,平仓全部订单。


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

    //--- 输入参数及注释
    input double BaseLotSize = 0.01; // 首单基础手数
    input int ATRPeriod = 14; // ATR周期(波动率检测)
    input double CompressionRatio = 0.65; // 波动率压缩比率(当前ATR/平均ATR)
    input int LookbackBars = 20; // 压缩检测回溯K线数
    input int OBLookback = 10; // Order Block回溯(摆动检测)
    input double GridDistanceATR = 1.2; // 网格距离(ATR倍数)
    input double GridLotMultiplier = 1.5; // 网格手数倍数
    input int MaxGridLevels = 3; // 最大网格层数(0=禁用网格)
    input double TPPercent = 1.0; // 止盈百分比(账户余额的百分比)
    input double StopLossATR = 1.2; // 止损倍数(ATR倍数)
    input int MagicNumber = 202601; // EA魔术号
    input int MaxSpread = 35; // 最大允许点差(单位:点)
    input double DailyLossLimit = 5.0; // 每日亏损限额(账户余额百分比)
    input bool UseFridayClose = true; // 周五20:00 GMT前平仓

    //--- 全局变量
    double dailyStartBalance = 0;
    datetime lastBarTime = 0;
    bool fridayCloseExecuted = false;
    double compressionHigh = 0;
    double compressionLow = 0;
    bool compressionActive = false;
    datetime compressionStartTime = 0;

    //+------------------------------------------------------------------+
    //| EA初始化函数 |
    //+------------------------------------------------------------------+
    int OnInit()
    {
    dailyStartBalance = AccountBalance();
    lastBarTime = 0;
    fridayCloseExecuted = false;
    compressionHigh = 0;
    compressionLow = 0;
    compressionActive = false;
    return(INIT_SUCCEEDED);
    }

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

    //+------------------------------------------------------------------+
    //| 计算回溯周期内的平均ATR |
    //+------------------------------------------------------------------+
    double GetAvgATR()
    {
    double sum = 0;
    for(int i = 1; i <= LookbackBars; i++)
    sum += iATR(Symbol(), PERIOD_M15, ATRPeriod, i);
    return sum / LookbackBars;
    }

    //+------------------------------------------------------------------+
    //| 检测波动率压缩形态 |
    //+------------------------------------------------------------------+
    bool DetectCompression()
    {
    double currentATR = iATR(Symbol(), PERIOD_M15, ATRPeriod, 1);
    double avgATR = GetAvgATR();

    if(avgATR <= 0) return false;

    bool isCompressed = (currentATR < avgATR CompressionRatio);

    if(isCompressed && !compressionActive)
    {
    // 开始跟踪压缩区间
    compressionActive = true;
    compressionStartTime = Time[0];

    // 记录压缩期间的最高点和最低点
    compressionHigh = iHigh(Symbol(), PERIOD_M15, iHighest(Symbol(), PERIOD_M15, MODE_HIGH, 5, 1));
    compressionLow = iLow(Symbol(), PERIOD_M15, iLowest(Symbol(), PERIOD_M15, MODE_LOW, 5, 1));
    }
    else if(!isCompressed && compressionActive)
    {
    // 压缩结束,检测突破
    compressionActive = false;

    double close1 = iClose(Symbol(), PERIOD_M15, 1);
    double high1 = iHigh(Symbol(), PERIOD_M15, 1);
    double low1 = iLow(Symbol(), PERIOD_M15, 1);

    // 向上突破:收盘价高于压缩高点
    if(close1 > compressionHigh)
    return true;
    // 向下突破:收盘价低于压缩低点
    else if(close1 < compressionLow)
    return true;
    }

    return false;
    }

    //+------------------------------------------------------------------+
    //| 简化版Order Block趋势检测(摆动结构) |
    //+------------------------------------------------------------------+
    int CheckOrderBlockTrend()
    {
    double highs[];
    double lows[];
    ArrayResize(highs, OBLookback);
    ArrayResize(lows, OBLookback);

    for(int i = 0; i < OBLookback; i++)
    {
    highs[i] = iHigh(Symbol(), PERIOD_M15, i);
    lows[i] = iLow(Symbol(), PERIOD_M15, i);
    }

    // 找出近期摆动高点和低点
    double recentHigh = highs[ArrayMaximum(highs, 0, OBLookback/2)];
    double recentLow = lows[ArrayMinimum(lows, 0, OBLookback/2)];
    double currentPrice = iClose(Symbol(), PERIOD_M15, 1);

    // 看涨:价格突破近期摆动高点
    if(currentPrice > recentHigh)
    return 1;
    // 看跌:价格跌破近期摆动低点
    else if(currentPrice < recentLow)
    return -1;

    return 0;
    }

    //+------------------------------------------------------------------+
    //| 检查是否存在当前持仓序列 |
    //+------------------------------------------------------------------+
    bool HasActiveSeries()
    {
    for(int i = OrdersTotal()-1; i >= 0; i--)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
    if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
    return true;
    }
    }
    return false;
    }

    //+------------------------------------------------------------------+
    //| 统计当前网格层数(序列中的订单数) |
    //+------------------------------------------------------------------+
    int CountGridLevels()
    {
    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;
    }

    //+------------------------------------------------------------------+
    //| 获取当前序列的方向(1=买入,-1=卖出) |
    //+------------------------------------------------------------------+
    int GetSeriesDirection()
    {
    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) return 1;
    if(OrderType() == OP_SELL) return -1;
    }
    }
    }
    return 0;
    }

    //+------------------------------------------------------------------+
    //| 获取序列中最后一张订单的开仓价 |
    //+------------------------------------------------------------------+
    double GetLastOrderPrice()
    {
    datetime latestTime = 0;
    double latestPrice = 0;
    for(int i = OrdersTotal()-1; i >= 0; i--)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
    if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
    {
    if(OrderOpenTime() > latestTime)
    {
    latestTime = OrderOpenTime();
    latestPrice = OrderOpenPrice();
    }
    }
    }
    }
    return latestPrice;
    }

    //+------------------------------------------------------------------+
    //| 计算总浮动盈亏(美元) |
    //+------------------------------------------------------------------+
    double GetTotalFloatingProfit()
    {
    double total = 0;
    for(int i = OrdersTotal()-1; i >= 0; i--)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
    if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
    total += OrderProfit() + OrderSwap() + OrderCommission();
    }
    }
    return total;
    }

    //+------------------------------------------------------------------+
    //| 平仓序列中的所有订单 |
    //+------------------------------------------------------------------+
    void CloseAllSeriesOrders()
    {
    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);
    }
    }
    }
    }

    //+------------------------------------------------------------------+
    //| 添加下一层网格订单 |
    //+------------------------------------------------------------------+
    void AddGridLevel(int direction, double distance)
    {
    int currentLevels = CountGridLevels();
    if(currentLevels >= MaxGridLevels) return;

    double lot = BaseLotSize
    MathPow(GridLotMultiplier, currentLevels);
    if(lot > 1.0) lot = 1.0;

    double atr = iATR(Symbol(), PERIOD_M15, ATRPeriod, 1);
    double slDistance = atr StopLossATR;

    int cmd = -1;
    double price = 0, sl = 0, tp = 0;

    if(direction == 1) // 做多序列
    {
    cmd = OP_BUY;
    price = Ask;
    sl = price - slDistance;
    }
    else if(direction == -1) // 做空序列
    {
    cmd = OP_SELL;
    price = Bid;
    sl = price + slDistance;
    }

    if(cmd != -1)
    {
    int ticket = OrderSend(Symbol(), cmd, lot, price, 5, sl, 0, "Grid Level", MagicNumber, 0, clrNONE);
    if(ticket < 0)
    Print("添加网格层失败:", GetLastError());
    }
    }

    //+------------------------------------------------------------------+
    //| EA主循环函数(每Tick执行) |
    //+------------------------------------------------------------------+
    void OnTick()
    {
    // 每日净值保护
    double currentEquity = AccountEquity();
    double lossPercent = (dailyStartBalance - currentEquity) / dailyStartBalance
    100;
    if(lossPercent >= DailyLossLimit)
    {
    Comment("已达每日亏损上限,停止开新仓");
    return;
    }

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

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

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

    // 检查是否存在当前持仓序列
    bool hasSeries = HasActiveSeries();

    if(hasSeries)
    {
    // 管理现有序列:检查止盈目标
    double totalProfit = GetTotalFloatingProfit();
    double targetProfit = AccountBalance() TPPercent / 100;

    if(totalProfit >= targetProfit)
    {
    CloseAllSeriesOrders();
    Print("达成止盈目标:", totalProfit);
    return;
    }

    // 检查是否需要添加下一层网格
    int currentLevels = CountGridLevels();
    if(currentLevels > 0 && currentLevels < MaxGridLevels)
    {
    int direction = GetSeriesDirection();
    double lastPrice = GetLastOrderPrice();
    double atr = iATR(Symbol(), PERIOD_M15, ATRPeriod, 1);
    double gridDistance = atr
    GridDistanceATR;
    double currentPrice = (direction == 1) ? Bid : Ask;
    double priceDiff = MathAbs(currentPrice - lastPrice);

    if(priceDiff >= gridDistance)
    {
    AddGridLevel(direction, gridDistance);
    }
    }
    }
    else
    {
    // 无持仓序列:寻找新信号

    // 步骤1:检测波动率压缩突破
    bool breakoutDetected = DetectCompression();
    if(!breakoutDetected)
    {
    Comment("未检测到突破信号");
    return;
    }

    // 步骤2:确认Order Block趋势方向
    int obTrend = CheckOrderBlockTrend();
    if(obTrend == 0)
    {
    Comment("无明确Order Block方向");
    return;
    }

    // 步骤3:确定压缩突破的方向
    double close1 = iClose(Symbol(), PERIOD_M15, 1);
    int breakoutDir = 0;
    if(close1 > compressionHigh) breakoutDir = 1;
    else if(close1 < compressionLow) breakoutDir = -1;

    // 步骤4:突破方向与OB趋势对齐
    if(breakoutDir != obTrend)
    {
    Comment("突破方向与OB趋势不一致");
    return;
    }

    // 步骤5:开首单
    double atr = iATR(Symbol(), PERIOD_M15, ATRPeriod, 1);
    double slDistance = atr * StopLossATR;
    double lot = BaseLotSize;

    int cmd = -1;
    double price = 0, sl = 0;

    if(breakoutDir == 1) // 做多
    {
    cmd = OP_BUY;
    price = Ask;
    sl = price - slDistance;
    }
    else if(breakoutDir == -1) // 做空
    {
    cmd = OP_SELL;
    price = Bid;
    sl = price + slDistance;
    }

    if(cmd != -1)
    {
    int ticket = OrderSend(Symbol(), cmd, lot, price, 5, sl, 0, "Breakout Entry", MagicNumber, 0, clrNONE);
    if(ticket < 0)
    Print("首单开仓失败:", GetLastError());
    else
    Print("突破开仓成功,方向:", cmd==OP_BUY?"买入":"卖出");
    }
    }
    }
    //+------------------------------------------------------------------+
    `
    参考来源: 原创MQL4代码,策略架构参考了波动率突破与机构订单流(SMC)概念。
    免责声明: 黄金交易因高波动性具有重大风险。本EA按“原样”提供,不保证盈利。实盘部署前请在模拟账户测试至少2个月。历史表现不代表未来结果。
    ``