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




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

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

交易逻辑说明
  • <strong>趋势过滤</strong>:使用H1周期的EMA(200)判断长期方向。仅当价格 > EMA200时做多,价格 < EMA200时做空。

  • <strong>入场信号</strong>:使用快速SMA交叉(SMA5和SMA20)并经额外过滤确认。需交叉持续1根K线。

  • <strong>风控机制</strong>:

  • - 止损 = ATR(14) ATR倍数(默认2.0)
    - 止盈 = 止损
    风报比(默认1.5)
    - 手数 = 风险百分比 账户余额 / (止损点数 每手点值)
  • <strong>时间过滤</strong>:仅在经纪商时间08:00-20:00交易,避开低流动性时段。

  • <strong>最大点差控制</strong>:点差超过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高波动特性。
    ``