Summary: 黄金雷霆暴利EA是一款专为XAUUSD设计的高收益MQL4智能交易系统。使用布林带突破检测、亏损后动态加仓(马丁格尔)、波动率调仓。适合M15周期。




黄金雷霆暴利EA专为黄金(XAUUSD)设计,在追求高收益的同时融入可控的风险机制。EA使用布林带和ATR波动率识别关键支撑/阻力突破。当发生亏损交易时,采用计算型马丁格尔恢复策略(可配置倍数),但限制最大恢复循环次数。波动率调仓在高波动新闻时段自动调整手数。策略目标为快速1:1至1:2盈亏比交易,配合激进追踪止盈锁定利润。

推荐加载周期: M15
策略核心逻辑:
  • 突破检测:价格在盘整后(ATR定义的窄幅区间)收盘于布林带(20,2)之外。

  • 入场:突破确认后立即市价入场,并挂待补单(本版本为即时入场)。

  • 恢复模式:亏损后,下一单手数 = 上一手数 × 恢复倍数(上限为最大恢复步数)。

  • 波动率调仓:高ATR降低手数,低ATR提高手数(在限制范围内)。

  • 风险控制:每日最大亏损10%,最大点差40点,周五收盘前1小时停止开仓。


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

    //--- 输入参数及注释
    input double BaseLotSize = 0.01; // 基础手数(首单)
    input double RecoveryMultiplier = 1.8; // 亏损后手数倍数(马丁格尔)
    input int MaxRecoverySteps = 3; // 最大马丁格尔恢复次数
    input int BollingerPeriod = 20; // 布林带周期
    input double BollingerDeviation = 2.0; // 布林带标准差倍数
    input int ATRPeriod = 14; // ATR周期(波动率过滤)
    input double MinATRPercentile = 0.4; // 最小ATR相对值(低于20周期均值的40%不开仓)
    input double MaxATRPercentile = 1.6; // 最大ATR相对值(高于160%不开仓)
    input int RiskRewardRatio = 150; // 盈亏比(止盈 = 止损 × 比率/100)
    input int StopLossPoints = 150; // 固定止损点数(黄金150点)
    input int TrailingStopTrigger = 80; // 触发追踪止损的盈利点数
    input int TrailingStep = 25; // 追踪步长(点数)
    input int MagicNumber = 202414; // EA魔术号
    input int MaxSpread = 40; // 最大允许点差
    input double DailyLossLimit = 10.0; // 每日亏损限额(百分比)
    input bool UseFridayLock = true; // 周五收盘前1小时禁止开仓
    input int Slippage = 3; // 允许滑点

    //--- 全局变量
    double dailyStartBalance = 0;
    datetime lastBarTime = 0;
    int consecutiveLosses = 0;
    double lastLotUsed = 0;
    double currentATR20Avg = 0;
    bool fridayLockActive = false;

    //+------------------------------------------------------------------+
    //| EA初始化函数 |
    //+------------------------------------------------------------------+
    int OnInit()
    {
    dailyStartBalance = AccountBalance();
    lastBarTime = 0;
    consecutiveLosses = 0;
    lastLotUsed = BaseLotSize;
    fridayLockActive = false;
    currentATR20Avg = iATR(Symbol(), PERIOD_M15, ATRPeriod, 1);
    if(currentATR20Avg <= 0) currentATR20Avg = 50;
    return(INIT_SUCCEEDED);
    }

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

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

    // 跨日重置余额基准
    if(TimeDayOfYear(TimeCurrent()) != TimeDayOfYear(TimeCurrent()-PeriodSeconds(PERIOD_D1)))
    dailyStartBalance = AccountBalance();

    // 周五锁定:收盘前1小时(周五21点经纪商时间)不开新仓
    if(UseFridayLock)
    {
    datetime currentTime = TimeCurrent();
    int dayOfWeek = TimeDayOfWeek(currentTime);
    int hour = TimeHour(currentTime);
    if(dayOfWeek == 5 && hour >= 20)
    fridayLockActive = true;
    else
    fridayLockActive = false;

    if(fridayLockActive)
    {
    Comment("周五锁定中,不开新仓");
    return;
    }
    }

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

    // 新K线检测(M15)
    if(Time[0] == lastBarTime)
    return;
    lastBarTime = Time[0];

    // 检查现有持仓
    if(CountPositions() > 0)
    {
    ManageTrailingStop();
    return;
    }

    // 波动率调仓
    double atr = iATR(Symbol(), PERIOD_M15, ATRPeriod, 1);
    double atr20Avg = 0;
    for(int i=1; i<=20; i++)
    atr20Avg += iATR(Symbol(), PERIOD_M15, ATRPeriod, i);
    atr20Avg /= 20;
    currentATR20Avg = atr20Avg;

    double atrRatio = atr / atr20Avg;
    if(atrRatio < MinATRPercentile || atrRatio > MaxATRPercentile)
    {
    Comment("ATR比例超出范围: ", atrRatio);
    return;
    }

    double dynamicLot = BaseLotSize;
    if(consecutiveLosses > 0 && consecutiveLosses <= MaxRecoverySteps)
    dynamicLot = lastLotUsed
    RecoveryMultiplier;
    else if(consecutiveLosses > MaxRecoverySteps)
    dynamicLot = BaseLotSize;
    else
    dynamicLot = BaseLotSize;

    // 波动率调整因子
    double volatilityFactor = MathMax(0.5, MathMin(1.5, atr20Avg / atr));
    dynamicLot = dynamicLot volatilityFactor;
    if(dynamicLot < 0.01) dynamicLot = 0.01;
    if(dynamicLot > 1.0) dynamicLot = 1.0;

    // 布林带突破检测
    double bollUpper = iBands(Symbol(), PERIOD_M15, BollingerPeriod, BollingerDeviation, 0, PRICE_CLOSE, MODE_UPPER, 1);
    double bollLower = iBands(Symbol(), PERIOD_M15, BollingerPeriod, BollingerDeviation, 0, PRICE_CLOSE, MODE_LOWER, 1);
    double close1 = iClose(Symbol(), PERIOD_M15, 1);
    double close0 = iClose(Symbol(), PERIOD_M15, 0);
    double high1 = iHigh(Symbol(), PERIOD_M15, 1);
    double low1 = iLow(Symbol(), PERIOD_M15, 1);

    // 盘整检测:前一根K线范围较小
    double range1 = high1 - low1;
    double avgRange = iATR(Symbol(), PERIOD_M15, 20, 1);
    bool consolidated = (range1 < avgRange
    0.6);

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

    // 多头突破:收盘于上轨之上且前一根也收盘于上轨之上
    if(consolidated && close1 > bollUpper && close0 > bollUpper)
    {
    cmd = OP_BUY;
    entryPrice = Ask;
    sl = entryPrice - StopLossPoints Point;
    tp = entryPrice + (StopLossPoints
    RiskRewardRatio / 100) Point;
    }
    // 空头突破:收盘于下轨之下且前一根也收盘于下轨之下
    else if(consolidated && close1 < bollLower && close0 < bollLower)
    {
    cmd = OP_SELL;
    entryPrice = Bid;
    sl = entryPrice + StopLossPoints
    Point;
    tp = entryPrice - (StopLossPoints RiskRewardRatio / 100) Point;
    }

    if(cmd != -1)
    {
    int ticket = OrderSend(Symbol(), cmd, dynamicLot, entryPrice, Slippage, sl, tp, "Gold Thunder EA", MagicNumber, 0, clrNONE);
    if(ticket > 0)
    {
    lastLotUsed = dynamicLot;
    Print("开仓成功: ", ticket, " 手数: ", dynamicLot, " 连亏次数: ", consecutiveLosses);
    }
    else
    {
    Print("开仓失败,错误码: ", GetLastError());
    }
    }
    }

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

    if(OrderType() == OP_BUY)
    {
    profitPoints = (Bid - OrderOpenPrice()) / Point;
    if(profitPoints >= TrailingStopTrigger)
    {
    newSL = Bid - TrailingStep Point;
    if(newSL > OrderStopLoss())
    {
    if(OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE))
    Print("买入追踪止损更新 #", OrderTicket());
    }
    }
    }
    else if(OrderType() == OP_SELL)
    {
    profitPoints = (OrderOpenPrice() - Ask) / Point;
    if(profitPoints >= TrailingStopTrigger)
    {
    newSL = Ask + TrailingStep
    Point;
    if(newSL < OrderStopLoss() || OrderStopLoss() == 0)
    {
    if(OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE))
    Print("卖出追踪止损更新 #", OrderTicket());
    }
    }
    }
    break;
    }
    }
    }
    }

    //+------------------------------------------------------------------+
    //| 统计持仓数量 |
    //+------------------------------------------------------------------+
    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;
    }

    //+------------------------------------------------------------------+
    //| 更新连亏次数(实际使用时在平仓逻辑中调用) |
    //+------------------------------------------------------------------+
    void UpdateConsecutiveLosses(bool wasLoss)
    {
    if(wasLoss)
    consecutiveLosses++;
    else
    consecutiveLosses = 0;
    }
    //+------------------------------------------------------------------+
    `
    参考来源: 原创MQL4代码,仅供学习参考。
    免责声明: 高收益策略伴随高风险,包括本金全部亏损。黄金交易波动剧烈。本EA使用马丁格尔恢复机制可能放大亏损。请在模拟账户充分测试。历史表现不代表未来结果。并非适合所有投资者。
    ``