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




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

推荐加载周期: M15
策略核心逻辑:
1. 波动率压缩:检测当前ATR(14)是否低于过去20根K线平均ATR的0.65倍。
2. 突破方向:当价格收盘高于压缩期间最高点→潜在买入;低于压缩期间最低点→潜在卖出。
3. Order Block过滤:确认近期摆动结构支持突破方向(价格已突破前期关键水平位)。
4. 网格执行:首单设固定止损(ATR×1.2),后续按ATR距离间隔加仓,手数1.5倍递增(最多3层)。
5. 止盈退出:当总浮动盈利达到账户余额的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个月。历史表现不代表未来结果。
```