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




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

推荐加载周期: H4
策略核心逻辑:
1. 网格设置:在当前价格上下距离 = ATR(14) × 网格距离倍数 处放置初始买入和卖出订单。
2. 网格扩展:当价格触发某方向订单后,在同方向相同距离处放置新的限价订单(无马丁格尔)。
3. 风险控制:限制最大网格层数、每日亏损限额和总回撤保护。
4. 止盈逻辑:当所有网格订单的总浮动盈利达到网格盈利目标时,平仓全部网格并重置。

```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个月。历史表现不代表未来结果。
```