Summary: 比特币安全网格EA是一款专为比特币设计的MQL4网格交易专家顾问。使用基于ATR的自适应网格间距、无马丁格尔的固定手数、权益回撤保护。适合H4周期。




比特币安全网格EA实现了一种保守的网格交易策略,专门针对比特币的高波动性进行调整。与高风险的马丁格尔系统不同,本EA使用固定手数,并包含防止网格过度扩展的安全模块。网格间距使用ATR动态计算,以适应市场当前波动率。EA包含最大网格层数限制、基于权益的回撤保护,以及平仓整个网格的盈利目标。无金字塔加仓或指数级手数增长。

推荐加载周期: H4
策略核心逻辑:
  • 网格设置:在当前价格上下距离 = ATR(14) × 网格距离倍数 处放置初始买入和卖出订单。

  • 网格扩展:当价格触发某方向订单后,在同方向相同距离处放置新的限价订单(无马丁格尔)。

  • 风险控制:限制最大网格层数、每日亏损限额和总回撤保护。

  • 止盈逻辑:当所有网格订单的总浮动盈利达到网格盈利目标时,平仓全部网格并重置。


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

    //--- 输入参数及注释
    input double BaseLotSize = 0.01; // 每笔网格订单固定手数(0.01 BTC)
    input int GridDistanceATR = 14; // 动态网格间距的ATR周期
    input double GridDistanceMultiplier = 1.5; // 网格间距倍数(间距 = ATR × 倍数)
    input int MaxGridLevels = 5; // 每个方向最大网格层数
    input double GridProfitTarget = 50.0; // 网格平仓盈利目标(账户货币单位:美元)
    input double MaxDrawdownPercent = 12.0; // 最大允许回撤百分比(硬止损)
    input double DailyLossLimit = 6.0; // 每日亏损限额(账户余额百分比)
    input int MagicNumber = 202417; // EA魔术号
    input int MaxSpread = 100; // 最大允许点差(比特币点差较宽)
    input bool UseFridayClose = true; // 周五20:00 GMT前平仓
    input int Slippage = 50; // 最大滑点(单位:点)

    //--- 全局变量
    double dailyStartBalance = 0;
    datetime lastBarTime = 0;
    bool fridayCloseExecuted = false;
    bool drawdownStop = false;
    double currentGridDistance = 0;
    double lastATR = 0;

    //+------------------------------------------------------------------+
    //| EA初始化函数 |
    //+------------------------------------------------------------------+
    int OnInit()
    {
    dailyStartBalance = AccountBalance();
    lastBarTime = 0;
    fridayCloseExecuted = false;
    drawdownStop = false;
    lastATR = iATR(Symbol(), PERIOD_H4, GridDistanceATR, 1);
    if(lastATR <= 0) lastATR = 500 Point;
    currentGridDistance = lastATR
    GridDistanceMultiplier;
    return(INIT_SUCCEEDED);
    }

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

    //+------------------------------------------------------------------+
    //| 获取当前基于ATR的网格间距 |
    //+------------------------------------------------------------------+
    double GetGridDistance()
    {
    double atr = iATR(Symbol(), PERIOD_H4, GridDistanceATR, 1);
    if(atr <= 0) atr = lastATR;
    lastATR = atr;
    return atr GridDistanceMultiplier;
    }

    //+------------------------------------------------------------------+
    //| 统计网格订单数量(分别统计买卖) |
    //+------------------------------------------------------------------+
    void CountGridOrders(int &buyCount, int &sellCount)
    {
    buyCount = 0;
    sellCount = 0;
    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) buyCount++;
    if(OrderType() == OP_SELL) sellCount++;
    }
    }
    }
    }

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

    //+------------------------------------------------------------------+
    //| 检查并扩展网格 |
    //+------------------------------------------------------------------+
    void ManageGridExpansion()
    {
    int buyCount, sellCount;
    CountGridOrders(buyCount, sellCount);

    double currentPrice = Bid;
    double ask = Ask;
    double gridDist = GetGridDistance();

    // 查找最高买入订单价格和最低卖出订单价格
    double highestBuy = 0;
    double lowestSell = 9999999;

    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 && OrderOpenPrice() > highestBuy)
    highestBuy = OrderOpenPrice();
    if(OrderType() == OP_SELL && OrderOpenPrice() < lowestSell)
    lowestSell = OrderOpenPrice();
    }
    }
    }

    // 扩展买入网格:价格上涨超过最高买入价+间距且未达最大层数
    if(buyCount < MaxGridLevels)
    {
    double nextBuyPrice = (highestBuy > 0) ? highestBuy + gridDist : currentPrice + gridDist;
    if(currentPrice >= nextBuyPrice - (gridDist
    0.3))
    {
    double sl = nextBuyPrice - (gridDist 2);
    double tp = nextBuyPrice + (gridDist
    3);
    int ticket = OrderSend(Symbol(), OP_BUY, BaseLotSize, ask, Slippage, sl, tp, "Grid Buy", MagicNumber, 0, clrNONE);
    if(ticket > 0)
    Print("买入网格第 ", buyCount+1, " 层,价格 ", nextBuyPrice);
    }
    }

    // 扩展卖出网格:价格下跌超过最低卖出价-间距且未达最大层数
    if(sellCount < MaxGridLevels)
    {
    double nextSellPrice = (lowestSell < 9999999) ? lowestSell - gridDist : currentPrice - gridDist;
    if(currentPrice <= nextSellPrice + (gridDist 0.3))
    {
    double sl = nextSellPrice + (gridDist
    2);
    double tp = nextSellPrice - (gridDist 3);
    int ticket = OrderSend(Symbol(), OP_SELL, BaseLotSize, Bid, Slippage, sl, tp, "Grid Sell", MagicNumber, 0, clrNONE);
    if(ticket > 0)
    Print("卖出网格第 ", sellCount+1, " 层,价格 ", nextSellPrice);
    }
    }
    }

    //+------------------------------------------------------------------+
    //| 平仓所有网格订单 |
    //+------------------------------------------------------------------+
    void CloseAllGridOrders()
    {
    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, Slippage, clrNONE);
    else if(OrderType() == OP_SELL)
    OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, clrNONE);
    }
    }
    }
    }

    //+------------------------------------------------------------------+
    //| 初始化网格(无订单时创建初始双边订单) |
    //+------------------------------------------------------------------+
    void InitializeGrid()
    {
    int buyCount, sellCount;
    CountGridOrders(buyCount, sellCount);

    if(buyCount == 0 && sellCount == 0)
    {
    double gridDist = GetGridDistance();
    double currentPrice = (Ask + Bid) / 2;

    // 在当前价格下方放置首个买入限价订单
    double firstBuy = currentPrice - gridDist;
    double buySL = firstBuy - (gridDist
    2);
    double buyTP = firstBuy + (gridDist 3);

    // 在当前价格上方放置首个卖出限价订单
    double firstSell = currentPrice + gridDist;
    double sellSL = firstSell + (gridDist
    2);
    double sellTP = firstSell - (gridDist 3);

    int buyTicket = OrderSend(Symbol(), OP_BUY, BaseLotSize, firstBuy, Slippage, buySL, buyTP, "Grid Buy", MagicNumber, 0, clrNONE);
    int sellTicket = OrderSend(Symbol(), OP_SELL, BaseLotSize, firstSell, Slippage, sellSL, sellTP, "Grid Sell", MagicNumber, 0, clrNONE);

    if(buyTicket > 0 && sellTicket > 0)
    Print("初始网格已设置。买入价 ", firstBuy, " 卖出价 ", firstSell);
    }
    }

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

    // 最大回撤保护(硬止损)
    double drawdownPercent = (dailyStartBalance - currentEquity) / dailyStartBalance * 100;
    if(drawdownPercent >= MaxDrawdownPercent && !drawdownStop)
    {
    CloseAllGridOrders();
    drawdownStop = true;
    Comment("已达最大回撤,网格已停止");
    return;
    }

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

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

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

    // 检查网格是否存在,不存在则初始化
    int buyCount, sellCount;
    CountGridOrders(buyCount, sellCount);
    if(buyCount == 0 && sellCount == 0 && !drawdownStop)
    {
    InitializeGrid();
    return;
    }

    // 根据价格运动管理网格扩展
    ManageGridExpansion();

    // 止盈:总盈利达到目标时平仓全部网格
    double totalProfit = GetGridFloatingProfit();
    if(totalProfit >= GridProfitTarget)
    {
    CloseAllGridOrders();
    Print("网格盈利目标已达成:", totalProfit, "。网格重置。");
    drawdownStop = false;
    dailyStartBalance = AccountBalance();
    }

    // 每日重置起始余额
    if(TimeDayOfYear(TimeCurrent()) != TimeDayOfYear(TimeCurrent() - PeriodSeconds(PERIOD_D1)))
    {
    dailyStartBalance = AccountBalance();
    }
    }

    //+------------------------------------------------------------------+
    //+------------------------------------------------------------------+
    `
    参考来源: 原创MQL4代码,仅供学习参考。
    免责声明: 比特币网格交易具有重大风险,包括可能损失全部本金。本EA使用固定手数(无马丁格尔),但网格策略在强趋势行情中仍可能亏损。本EA按“原样”提供,不保证盈利。实盘交易前请至少在模拟账户测试2个月。历史表现不代表未来结果。
    ``