Summary: 黄金稳定EA是一个专为XAUUSD设计的MQL4机器人。采用EMA趋势过滤、ATR动态止损和波动率自适应手数,降低风险,适合黄金品种特性,稳定运行。




黄金稳定EA专门针对高波动性黄金市场(XAUUSD)设计。它采用趋势跟踪逻辑,包含慢速EMA过滤器、基于ATR的止损和止盈,并设有时段限制以避免重大跳空风险。手数根据当前波动率自适应调整,以确保每笔交易风险一致。

加载周期建议:H1(1小时)。该策略针对H1周期优化,在信号可靠性和交易频率之间取得平衡。

交易逻辑说明
1. 趋势过滤:使用H1周期的EMA(200)判断长期方向。仅当价格 > EMA200时做多,价格 < EMA200时做空。
2. 入场信号:使用快速SMA交叉(SMA5和SMA20)并经额外过滤确认。需交叉持续1根K线。
3. 风控机制
- 止损 = ATR(14) * ATR倍数(默认2.0)
- 止盈 = 止损 * 风报比(默认1.5)
- 手数 = 风险百分比 * 账户余额 / (止损点数 * 每手点值)
4. 时间过滤:仅在经纪商时间08:00-20:00交易,避开低流动性时段。
5. 最大点差控制:点差超过MaxSpread则放弃交易。

免责声明:外汇和黄金交易具有高风险。过去表现不保证未来结果。本EA仅供学习参考。实盘前请在模拟账户充分测试。作者不对任何资金损失负责。

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

//+------------------------------------------------------------------+
//| 输入参数 |
//+------------------------------------------------------------------+
input double LotSizeFixed = 0.01; // 固定手数(当UseRiskPercent=false时使用)
input bool UseRiskPercent = true; // 使用动态风险百分比(true=使用RiskPercentPerTrade)
input double RiskPercentPerTrade = 1.0; // 每笔风险百分比(账户余额的1%动态计算手数)
input double ATR_Multiplier = 2.0; // ATR倍数用于止损(越大止损越宽)
input double RiskRewardRatio = 1.5; // 盈亏比(止盈 = 止损 * 该值)
input int FastMAPeriod = 5; // 快速SMA周期(入场信号)
input int SlowMAPeriod = 20; // 慢速SMA周期(入场信号)
input int TrendEMAPeriod = 200; // 趋势EMA周期(方向过滤)
input int ATRPeriod = 14; // ATR周期(波动率测量)
input int StartHour = 8; // 允许交易开始时间(经纪商时间)
input int EndHour = 20; // 允许交易结束时间(经纪商时间)
input double MaxSpread = 35.0; // 最大允许点差(单位:点)
input int Slippage = 30; // 滑点(单位:点)
input bool UseCloseSignals = true; // 启用反向交叉离场
input long MagicNumber = 20241115; // EA唯一标识号

//+------------------------------------------------------------------+
//| 全局变量 |
//+------------------------------------------------------------------+
double lastBarTime = 0;
bool tradeAllowed = true;

//+------------------------------------------------------------------+
//| 初始化函数 |
//+------------------------------------------------------------------+
int OnInit()
{
if(UseRiskPercent && RiskPercentPerTrade <= 0)
{
Print("错误:当UseRiskPercent=true时RiskPercentPerTrade必须大于0");
return(INIT_PARAMETERS_INCORRECT);
}
if(ATR_Multiplier <= 0 || RiskRewardRatio <= 0)
{
Print("错误:倍数参数必须为正数");
return(INIT_PARAMETERS_INCORRECT);
}
lastBarTime = Time[0];
return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| 反初始化函数 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}

//+------------------------------------------------------------------+
//| 主循环函数 |
//+------------------------------------------------------------------+
void OnTick()
{
// 检测新K线
if(lastBarTime == Time[0]) return;
lastBarTime = Time[0];

// 刷新数据
RefreshRates();

// 检查时间与点差条件
if(!IsTradeTime()) return;
if(MarketInfo(Symbol(), MODE_SPREAD) > MaxSpread) return;

// 管理现有订单(为保持低风险,不做移动止损)
ManageOrders();

// 生成新信号
int signal = GetSignal();
if(signal != 0)
ExecuteTrade(signal);
}

//+------------------------------------------------------------------+
//| 检查当前时间是否在允许交易时段内 |
//+------------------------------------------------------------------+
bool IsTradeTime()
{
datetime now = TimeCurrent();
int hour = TimeHour(now);
return (hour >= StartHour && hour < EndHour);
}

//+------------------------------------------------------------------+
//| 获取交易信号:1=买入,-1=卖出,0=无信号 |
//+------------------------------------------------------------------+
int GetSignal()
{
double emaTrend = iMA(Symbol(), PERIOD_H1, TrendEMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
double fastMA = iMA(Symbol(), 0, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);
double slowMA = iMA(Symbol(), 0, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);
double prevFast = iMA(Symbol(), 0, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 2);
double prevSlow = iMA(Symbol(), 0, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 2);

if(emaTrend == 0 || fastMA == 0 || slowMA == 0) return 0;

bool trendUp = Close[1] > emaTrend;
bool trendDown = Close[1] < emaTrend;

// 金叉确认且趋势向上
if(prevFast <= prevSlow && fastMA > slowMA && trendUp)
return 1;
// 死叉确认且趋势向下
if(prevFast >= prevSlow && fastMA < slowMA && trendDown)
return -1;

return 0;
}

//+------------------------------------------------------------------+
//| 执行买入或卖出订单 |
//+------------------------------------------------------------------+
void ExecuteTrade(int signal)
{
// 先平反向订单
CloseOrders(-signal);

// 如果已有同向订单,不再开仓
if(CountOrders(signal) > 0) return;

double atr = iATR(Symbol(), 0, ATRPeriod, 1);
if(atr <= 0) return;
double slDistance = atr * ATR_Multiplier;
double tpDistance = slDistance * RiskRewardRatio;
double entryPrice, slPrice, tpPrice;
int cmd;
double point = Point;
if(Digits == 3 || Digits == 5) point = Point * 10;

if(signal == 1) // 买入
{
entryPrice = Ask;
slPrice = entryPrice - slDistance;
tpPrice = entryPrice + tpDistance;
cmd = OP_BUY;
}
else // 卖出
{
entryPrice = Bid;
slPrice = entryPrice + slDistance;
tpPrice = entryPrice - tpDistance;
cmd = OP_SELL;
}

// 价格标准化
slPrice = NormalizeDouble(slPrice, Digits);
tpPrice = NormalizeDouble(tpPrice, Digits);
entryPrice = NormalizeDouble(entryPrice, Digits);

double lot = CalculateLotSize(slDistance, signal);
if(lot <= 0) return;

int ticket = OrderSend(Symbol(), cmd, lot, entryPrice, Slippage, slPrice, tpPrice, "Gold Stabilizer", MagicNumber, 0, clrNONE);
if(ticket < 0)
Print("订单发送失败: ", GetLastError());
}

//+------------------------------------------------------------------+
//| 根据风险百分比或固定手数计算开仓手数 |
//+------------------------------------------------------------------+
double CalculateLotSize(double slDistanceInPoints, int signal)
{
if(!UseRiskPercent)
return LotSizeFixed;

double balance = AccountBalance();
double riskAmount = balance * RiskPercentPerTrade / 100.0;
double tickValue = MarketInfo(Symbol(), MODE_TICKVALUE);
if(tickValue <= 0) return 0;

// slDistanceInPoints 是价格单位,转换成点数
double point = Point;
if(Digits == 3 || Digits == 5) point = Point * 10;
double slPoints = slDistanceInPoints / point;
if(slPoints <= 0) return 0;

double lot = riskAmount / (slPoints * tickValue);
double minLot = MarketInfo(Symbol(), MODE_MINLOT);
double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);
double stepLot = MarketInfo(Symbol(), MODE_LOTSTEP);

lot = MathFloor(lot / stepLot) * stepLot;
lot = MathMax(minLot, MathMin(maxLot, lot));
return lot;
}

//+------------------------------------------------------------------+
//| 统计指定信号方向的订单数量 |
//+------------------------------------------------------------------+
int CountOrders(int signal)
{
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((signal == 1 && OrderType() == OP_BUY) || (signal == -1 && OrderType() == OP_SELL))
count++;
}
}
}
return count;
}

//+------------------------------------------------------------------+
//| 平掉与给定信号相反的订单 |
//+------------------------------------------------------------------+
void CloseOrders(int oppositeSignal)
{
for(int i=OrdersTotal()-1; i>=0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
bool opposite = (oppositeSignal == 1 && OrderType() == OP_SELL) ||
(oppositeSignal == -1 && OrderType() == OP_BUY);
if(opposite)
{
if(OrderType() == OP_BUY)
OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, clrNONE);
else if(OrderType() == OP_SELL)
OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, clrNONE);
}
}
}
}
}

//+------------------------------------------------------------------+
//| 管理现有订单:可选的反向交叉离场 |
//+------------------------------------------------------------------+
void ManageOrders()
{
if(!UseCloseSignals) return;

double fastMA = iMA(Symbol(), 0, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);
double slowMA = iMA(Symbol(), 0, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);
double prevFast = iMA(Symbol(), 0, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 2);
double prevSlow = iMA(Symbol(), 0, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 2);

bool bearCross = (prevFast > prevSlow && fastMA <= slowMA);
bool bullCross = (prevFast < prevSlow && fastMA >= slowMA);

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 && bearCross)
OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, clrNONE);
else if(OrderType() == OP_SELL && bullCross)
OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, clrNONE);
}
}
}
}
//+------------------------------------------------------------------+
```

参考来源:基于黄金低风险趋势跟踪常见策略原则编写,适配MQL4稳定性及XAUUSD高波动特性。
```