我的首单和加仓单都是错误的,我的首单是0.01首,加仓0.02,0.03,但是实际的是0.02,0.03,0.03这样的加仓,有人可以指导一下吗

 
//+------------------------------------------------------------------+
//| 趋势加微马丁策略.mq5                                            |
//| Copyright 2026,廖先生                                           |
//| https://www.mql5.com                                             |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026,廖先生"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property description "趋势策略"
#property description "极少数人能在交易中长期获利,请全面了解此策略再小资金尝试"
#property description "EA只是工具,使用EA获得的盈利和造成的损失均由您自行负责,与EA开发者无关"

#include <Trade/Trade.Mqh>
#include <Trade/PositionInfo.Mqh>
#include <Trade/OrderInfo.Mqh>

//+------------------------------------------------------------------+
//| 输入参数(用户可修改)                                           |
//+------------------------------------------------------------------+

input string AllowedSymbols = "XAUUSD";            // 允许交易的品种(多个用逗号分隔)

input string Section1 = "=====基础设置=====";
input double InitialLotSize = 0.01;                // 初始手数
input string GridLotsStr = "0.02,0.03";            // 加仓手数序列(第一加仓,第二加仓)
input int  MagicNumber = 20260415;                 // EA魔术号(身份证)
input int  Slippage = 3;                           // 滑点(点)
input int  MaxSpread = 50;                         // 最大允许点差(点)

input string Section2 = "=====指标参数=====";
input int  BBPPeriod = 20;                         // 布林带周期
input double BBDeviation = 2.0;                    // 布林带宽度
input int  RSIPeriod = 14;                         // RSI周期
input int  MAPeriod = 5;                           // MA周期
input int  EMAPeriod = 5;                          // EMA周期

input string Section3 = "=====仓位管理=====";
input int  GridInterval = 200;                     // 加仓间隔(点)
input int  TakeProfitPoints = 350;                 // 固定止盈点数
input int  SecondGridStopLoss = 200;               // 第二加仓单固定止损(点)
input int  TrailingStopPoints = 200;               // 移动止损点数
input int  TrailingActivation = 350;               // 移动止损激活点数

input string Section4 = "=====风控设置=====";
input double MaxFloatingLoss1 = 15.0;              // 第一级风控:浮动亏损达余额百分比(%),全平暂停5分钟
input double MaxFloatingLoss2 = 30.0;              // 第二级风控:浮动亏损达余额百分比(%),永久暂停
input int    PauseSeconds = 300;                   // 暂停时间(秒)

input string Section5 = "=====时间设置=====";
input int  TimeStopSeconds = 3600;                 // 第二加仓单超时平仓时间(秒)

//+------------------------------------------------------------------+
//| 全局变量(代码内部使用)                                         |
//+------------------------------------------------------------------+

// 交易对象
CTrade trade;

// 指标句柄
int EMA5Handle;      // EMA5
int EMA10Handle;     // EMA10  
int EMA20Handle;     // EMA20
int BBHandle;
int ADXHandle;
int RSIHandle;

// 指标数组
double EMA5[];
double EMA10[];
double EMA20[];
double BB_middle[];
double BB_upper[];
double BB_lower[];
double ADX[];
double RSI[];
double MA5[];

// 加仓手数数组(从输入字符串解析)
double gridLots[];

// 状态变量
datetime lastBarTime;           // 上一根K线时间(用于避免同一K线重复开单)
int lastOrderTickets[3];        // 0-首单,1-第一加仓单,2-第二加仓单
datetime secondOrderOpenTime;   // 第二加仓单开仓时间
datetime pauseUntil;            // 暂停截止时间
bool isPaused = false;          // 是否暂停状态
bool isPermanentlyStopped = false;  // 是否永久停止(30%风控触发)

// 方向记录(避免反方向同时持仓)
int currentDirection = 0;       // 0=无持仓, 1=做多, -1=做空

// 移动止损追踪
double secondGridHighestProfit = 0;  // 第二加仓单最高盈利点数

// 辅助标志
bool isFirstTick = true;         // 是否是第一个tick
datetime lastTradeTime = 0;      // 上次开仓时间(避免同一信号重复开单)

//+------------------------------------------------------------------+
//| 状态机枚举                                                       |
//+------------------------------------------------------------------+
enum EA_STATE
{
   STATE_STOPPED,          // 停止(30%风控触发)
   STATE_RUNNING,          // 运行中
   STATE_PAUSED            // 临时暂停(15%风控触发或时间风控)
};
EA_STATE g_eaState = STATE_RUNNING;

//+------------------------------------------------------------------+
//| 解析加仓手数字符串                                               |
//+------------------------------------------------------------------+
void ParseGridLots()
{
   string temp = GridLotsStr;
   string lots[];
   int count = StringSplit(temp, ',', lots);
   
   ArrayResize(gridLots, count);
   for(int i = 0; i < count; i++)
   {
      gridLots[i] = StringToDouble(lots[i]);
   }
}
//+------------------------------------------------------------------+
//| 初始化函数                                                       |
//+------------------------------------------------------------------+
int OnInit()
{
   // 解析加仓手数
   ParseGridLots();
   
   // 创建指标句柄
   EMA5Handle = iMA(_Symbol, PERIOD_M5, 5, 0, MODE_EMA, PRICE_CLOSE);
   EMA10Handle = iMA(_Symbol, PERIOD_M5, 10, 0, MODE_EMA, PRICE_CLOSE);
   EMA20Handle = iMA(_Symbol, PERIOD_M5, 20, 0, MODE_EMA, PRICE_CLOSE);
   BBHandle = iBands(_Symbol, PERIOD_M5, BBPPeriod, 0, BBDeviation, PRICE_CLOSE);
   RSIHandle = iRSI(_Symbol, PERIOD_M5, RSIPeriod, PRICE_CLOSE);
   
   // 检查句柄是否创建成功
   if(EMA5Handle == INVALID_HANDLE || EMA10Handle == INVALID_HANDLE || EMA20Handle == INVALID_HANDLE ||
      BBHandle == INVALID_HANDLE  ||
      RSIHandle == INVALID_HANDLE)
   {
      Print("指标句柄创建失败");
      return INIT_FAILED;
   }
   
   // 设置交易
   trade.SetExpertMagicNumber(MagicNumber);
   trade.SetDeviationInPoints(Slippage);
   trade.SetTypeFilling(ORDER_FILLING_FOK);
   trade.SetAsyncMode(false);
   
   // 初始化订单数组
   ArrayFill(lastOrderTickets, 0, 3, 0);
   
   // 获取上一根K线时间
   lastBarTime = iTime(_Symbol, PERIOD_M5, 1);
   
   Print("EA初始化成功,品种:", _Symbol, " 魔术号:", MagicNumber);
   Print("加仓手数序列: ", GridLotsStr);
   
   return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| 反初始化函数                                                     |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // 释放指标句柄
   if(EMA5Handle != INVALID_HANDLE) IndicatorRelease(EMA5Handle);
   if(EMA10Handle != INVALID_HANDLE) IndicatorRelease(EMA10Handle);
   if(EMA20Handle != INVALID_HANDLE) IndicatorRelease(EMA20Handle);
   if(BBHandle != INVALID_HANDLE) IndicatorRelease(BBHandle);
   if(RSIHandle != INVALID_HANDLE) IndicatorRelease(RSIHandle);
   
   Print("EA已卸载,原因代码:", reason);
}
//+------------------------------------------------------------------+
//| 检查当前品种是否允许交易                                         |
//+------------------------------------------------------------------+
bool IsSymbolAllowed()
{
   if(StringLen(AllowedSymbols) == 0)
      return true;
   
   string currentSymbol = _Symbol;
   string symbolsList = AllowedSymbols;
   StringToUpper(symbolsList);
   StringToUpper(currentSymbol);
   
   if(StringFind(symbolsList, currentSymbol) >= 0)
      return true;
   
   static bool warningPrinted = false;
   if(!warningPrinted)
   {
      Print("品种 ", _Symbol, " 不在允许列表中");
      warningPrinted = true;
   }
   return false;
}

//+------------------------------------------------------------------+
//| 异常处理                                                         |
//+------------------------------------------------------------------+
bool HandleExceptions()
{
   // 服务器时间检查
   if(TimeCurrent() <= 0)
   {
      static datetime lastWarn = 0;
      if(TimeCurrent() - lastWarn > 300)
      {
         Print("[异常] 服务器时间异常");
         lastWarn = TimeCurrent();
      }
      return false;
   }
   
   // 周末检查
   MqlDateTime dt;
   TimeToStruct(TimeCurrent(), dt);
   if(dt.day_of_week == 0 || dt.day_of_week == 6)
   {
      static datetime lastWarn = 0;
      if(TimeCurrent() - lastWarn > 3600)
      {
         Print("[异常] 周末休市");
         lastWarn = TimeCurrent();
      }
      return false;
   }
   
   // 连接检查
   if(!TerminalInfoInteger(TERMINAL_CONNECTED))
   {
      static datetime lastWarn = 0;
      if(TimeCurrent() - lastWarn > 60)
      {
         Print("[异常] 服务器断开连接");
         lastWarn = TimeCurrent();
      }
      return false;
   }
   
   return true;
}

//+------------------------------------------------------------------+
//| 检查点差                                                         |
//+------------------------------------------------------------------+
bool IsSpreadAcceptable()
{
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
   
   if(ask <= 0 || bid <= 0 || point <= 0)
      return false;
   
   // 点差单位转换(5位报价平台)
   double pipSize = point;
   if(digits == 5 || digits == 3)
      pipSize = point * 10;
   
   double currentSpread = (ask - bid) / pipSize;
   
   if(currentSpread > MaxSpread)
   {
      static datetime lastWarning = 0;
      if(TimeCurrent() - lastWarning >= 5)
      {
         PrintFormat("点差过大: %.1f > %d", currentSpread, MaxSpread);
         lastWarning = TimeCurrent();
      }
      return false;
   }
   
   return true;
}

//+------------------------------------------------------------------+
//| 检查做多条件                                                     |
//+------------------------------------------------------------------+
bool CheckBuyCondition()
{
   // 获取指标数据
   double ema5[1], ema10[1], ema20[1];
   double rsi[1];
   double bbMiddle[1];
   
   CopyBuffer(EMA5Handle, 0, 1, 1, ema5);
   CopyBuffer(EMA10Handle, 0, 1, 1, ema10);
   CopyBuffer(EMA20Handle, 0, 1, 1, ema20);
   CopyBuffer(RSIHandle, 0, 1, 1, rsi);
   CopyBuffer(BBHandle, 0, 1, 1, bbMiddle);
   
   double close = iClose(_Symbol, PERIOD_M5, 1);
   double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   
   // EMA多头排列
   bool emaCondition = (ema5[0] > ema10[0] && ema10[0] > ema20[0]);
   
   // 收盘价条件
   bool closeCondition = (close > ema5[0] - 50 * point);
   
   // MACD条件   
   // RSI条件
   bool rsiCondition = (rsi[0] < 70);
   
   // 布林带条件(收盘价 > 中轨)
   bool bbCondition = (close > bbMiddle[0]);
   
   return (emaCondition && closeCondition && rsiCondition && bbCondition);
}

//+------------------------------------------------------------------+
//| 检查做空条件                                                     |
//+------------------------------------------------------------------+
bool CheckSellCondition()
{
   // 获取指标数据
   double ema5[1], ema10[1], ema20[1];
   double rsi[1];
   double bbMiddle[1];
   
   CopyBuffer(EMA5Handle, 0, 1, 1, ema5);
   CopyBuffer(EMA10Handle, 0, 1, 1, ema10);
   CopyBuffer(EMA20Handle, 0, 1, 1, ema20);
   CopyBuffer(RSIHandle, 0, 1, 1, rsi);
   CopyBuffer(BBHandle, 0, 1, 1, bbMiddle);
   
   double close = iClose(_Symbol, PERIOD_M5, 1);
   double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   
   // EMA空头排列
   bool emaCondition = (ema5[0] < ema10[0] && ema10[0] < ema20[0]);
   
   // 收盘价条件
   bool closeCondition = (close < ema5[0] + 50 * point);  
   
   // RSI条件
   bool rsiCondition = (rsi[0] > 30);
   
   // 布林带条件(收盘价 < 中轨)
   bool bbCondition = (close < bbMiddle[0]);
   
   return (emaCondition && closeCondition && rsiCondition && bbCondition);
}

//+------------------------------------------------------------------+
//| 执行做多                                                         |
//+------------------------------------------------------------------+
void ExecutionBuy()
{
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double lot = NormalizeLot(InitialLotSize);
   
   if(trade.Buy(lot, _Symbol, ask, 0, 0, "Trend Buy"))
   {
      lastOrderTickets[0] = (int)trade.ResultOrder();
      currentDirection = 1;
      Print("开首单成功 方向:BUY 手数:", lot, " Ticket:", lastOrderTickets[0]);
   }
   else
   {
      Print("开首单失败 错误:", GetLastError());
   }
}

//+------------------------------------------------------------------+
//| 执行做空                                                         |
//+------------------------------------------------------------------+
void ExecutionSell()
{
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double lot = NormalizeLot(InitialLotSize);
   
   if(trade.Sell(lot, _Symbol, bid, 0, 0, "Trend Sell"))
   {
      lastOrderTickets[0] = (int)trade.ResultOrder();
      currentDirection = -1;
      Print("开首单成功 方向:SELL 手数:", lot, " Ticket:", lastOrderTickets[0]);
   }
   else
   {
      Print("开首单失败 错误:", GetLastError());
   }
}

//+------------------------------------------------------------------+
//| 检查并执行加仓                                                   |
//+------------------------------------------------------------------+
void CheckAndAddGrid()
{
   int count=CountOpenedOrders();
   if(count==0 || count>=3) return;
   if(currentDirection==0) return;
   double lastPrice=GetLastOrderPrice();
   if(lastPrice<=0) return;
   double currentPrice=(currentDirection==1)?SymbolInfoDouble(_Symbol,SYMBOL_BID):SymbolInfoDouble(_Symbol,SYMBOL_ASK);
   double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
   if(point<=0) return;
   double diff=MathAbs(currentPrice-lastPrice)/point;
   if(diff>=GridInterval)
   {
      int gridIndex=count-1;
      if(gridIndex<0 || gridIndex>=ArraySize(gridLots))
      {
         Print("错误: gridIndex=",gridIndex," 超出范围");
         return;
      }
      double lot=NormalizeLot(gridLots[gridIndex]);
      if(currentDirection==1)
      {
         double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
         if(ask<=0) return;
         if(trade.Buy(lot,_Symbol,ask,0,0,"Grid Add"))
         {
            int newTicket=(int)trade.ResultOrder();
            for(int i=0;i<3;i++)
            {
               if(lastOrderTickets[i]==0)
               {
                  lastOrderTickets[i]=newTicket;
                  break;
               }
            }
            if(count==2)
            {
               secondOrderOpenTime=TimeCurrent();
               SetSecondGridStopLoss();
            }
         }
      }
      else
      {
         double bid=SymbolInfoDouble(_Symbol,SYMBOL_BID);
         if(bid<=0) return;
         if(trade.Sell(lot,_Symbol,bid,0,0,"Grid Add"))
         {
            int newTicket=(int)trade.ResultOrder();
            for(int i=0;i<3;i++)
            {
               if(lastOrderTickets[i]==0)
               {
                  lastOrderTickets[i]=newTicket;
                  break;
               }
            }
            if(count==2)
            {
               secondOrderOpenTime=TimeCurrent();
               SetSecondGridStopLoss();
            }
         }
      }
   }
}
//+------------------------------------------------------------------+
//| 检查止盈条件                                                     |
//+------------------------------------------------------------------+
bool CheckTakeProfit()
{
   double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   
   // 首单止盈
   if(lastOrderTickets[0] != 0 && GetOrderProfitInPoints(lastOrderTickets[0]) >= TakeProfitPoints)
   {
      CloseOrder(lastOrderTickets[0]);
      lastOrderTickets[0] = 0;
      Print("首单止盈平仓");
      return true;
   }
   
   // 第一加仓单止盈(平首单+第一加仓单)
   if(lastOrderTickets[1] != 0 && GetOrderProfitInPoints(lastOrderTickets[1]) >= TakeProfitPoints)
   {
      if(lastOrderTickets[0] != 0)
         CloseOrder(lastOrderTickets[0]);
      CloseOrder(lastOrderTickets[1]);
      lastOrderTickets[0] = 0;
      lastOrderTickets[1] = 0;
      Print("第一加仓单止盈,平首单+第一加仓单");
      return true;
   }
   
   return false;
}

//+------------------------------------------------------------------+
//| 检查第二加仓单移动止损                                           |
//+------------------------------------------------------------------+
void CheckTrailingStop()
{
   if(lastOrderTickets[2] == 0) return;
   
   double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   double profit = GetOrderProfitInPoints(lastOrderTickets[2]);
   
   // 更新最高盈利
   if(profit > secondGridHighestProfit)
      secondGridHighestProfit = profit;
   
   // 浮盈达到激活点数后启动移动止损
   if(secondGridHighestProfit >= TrailingActivation)
   {
      if(profit <= secondGridHighestProfit - TrailingStopPoints)
      {
         CloseOrder(lastOrderTickets[2]);
         lastOrderTickets[2] = 0;
         secondGridHighestProfit = 0;
         Print("第二加仓单移动止损平仓");
      }
   }
}

//+------------------------------------------------------------------+
//| 设置第二加仓单固定止损                                           |
//+------------------------------------------------------------------+
void SetSecondGridStopLoss()
{
   if(lastOrderTickets[2] == 0) return;
   
   double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   double sl = 0;
   
   if(currentDirection == 1)  // 做多
   {
      double openPrice = GetOrderOpenPrice(lastOrderTickets[2]);
      sl = openPrice - SecondGridStopLoss * point;
   }
   else  // 做空
   {
      double openPrice = GetOrderOpenPrice(lastOrderTickets[2]);
      sl = openPrice + SecondGridStopLoss * point;
   }
   
   trade.PositionModify(lastOrderTickets[2], sl, 0);
   Print("设置第二加仓单固定止损 ", SecondGridStopLoss, " 点");
}
//+------------------------------------------------------------------+
//| 时间风控:第二加仓单超时平仓                                     |
//+------------------------------------------------------------------+
bool CheckTimeStop()
{
   if(lastOrderTickets[2] == 0) return false;
   
   if(TimeCurrent() - secondOrderOpenTime >= TimeStopSeconds)
   {
      CloseAllOrders();
      ArrayFill(lastOrderTickets, 0, 3, 0);
      currentDirection = 0;
      secondGridHighestProfit = 0;
      g_eaState = STATE_PAUSED;
      pauseUntil = TimeCurrent() + PauseSeconds;
      Print("时间风控触发:第二加仓单超时,平全部持仓,暂停", PauseSeconds, "秒");
      return true;
   }
   
   return false;
}

//+------------------------------------------------------------------+
//| 资金管理:15%全平重启,30%永久暂停                                |
//+------------------------------------------------------------------+
bool CheckMoneyManagement()
{
   double balance = AccountInfoDouble(ACCOUNT_BALANCE);
   double equity = AccountInfoDouble(ACCOUNT_EQUITY);
   
   if(balance <= 0) return false;
   
   double floatingLossPercent = (balance - equity) / balance * 100;
   
   // 30%永久暂停
   if(floatingLossPercent >= MaxFloatingLoss2)
   {
      if(g_eaState != STATE_STOPPED)
      {
         CloseAllOrders();
         g_eaState = STATE_STOPPED;
         Print("资金管理:亏损达", MaxFloatingLoss2, "%,EA永久暂停");
      }
      return true;
   }
   
   // 15%全平并暂停
   if(floatingLossPercent >= MaxFloatingLoss1)
   {
      if(g_eaState != STATE_PAUSED)
      {
         CloseAllOrders();
         ArrayFill(lastOrderTickets, 0, 3, 0);
         currentDirection = 0;
         secondGridHighestProfit = 0;
         g_eaState = STATE_PAUSED;
         pauseUntil = TimeCurrent() + PauseSeconds;
         Print("资金管理:亏损达", MaxFloatingLoss1, "%,全平平仓,暂停", PauseSeconds, "秒");
      }
      return true;
   }
   
   return false;
}
//+------------------------------------------------------------------+
//| 标准化手数                                                       |
//+------------------------------------------------------------------+
double NormalizeLot(double lot)
{
   double step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
   double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   
   double normalizedLot = NormalizeDouble(lot / step, 0) * step;
   if(normalizedLot < minLot) normalizedLot = minLot;
   if(normalizedLot > maxLot) normalizedLot = maxLot;
   
   return normalizedLot;
}

//+------------------------------------------------------------------+
//| 更新订单状态                                                     |
//+------------------------------------------------------------------+
void UpdateOrderStatus()
{
   for(int i=0;i<3;i++)
   {
      if(lastOrderTickets[i]!=0 && !PositionSelectByTicket(lastOrderTickets[i]))
         lastOrderTickets[i]=0;
   }
   int actualCount=0;
   for(int i=PositionsTotal()-1;i>=0;i--)
   {
      ulong ticket=PositionGetTicket(i);
      if(PositionSelectByTicket(ticket) && PositionGetInteger(POSITION_MAGIC)==MagicNumber)
      {
         actualCount++;
         bool found=false;
         for(int j=0;j<3;j++)
         {
            if(lastOrderTickets[j]==(int)ticket)
            {
               found=true;
               break;
            }
         }
         if(!found)
         {
            for(int j=0;j<3;j++)
            {
               if(lastOrderTickets[j]==0)
               {
                  lastOrderTickets[j]=(int)ticket;
                  break;
               }
            }
         }
      }
   }
   if(actualCount==0)
   {
      ArrayFill(lastOrderTickets,0,3,0);
      currentDirection=0;
      secondGridHighestProfit=0;
   }
   else
   {
      for(int i=0;i<3;i++)
      {
         if(lastOrderTickets[i]!=0 && PositionSelectByTicket(lastOrderTickets[i]))
         {
            currentDirection=(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)?1:-1;
            break;
         }
      }
   }
}
//+------------------------------------------------------------------+
//| 计算已开订单数量                                                 |
//+------------------------------------------------------------------+
int CountOpenedOrders()
{
   int count = 0;
   for(int i = 0; i < 3; i++)
   {
      if(lastOrderTickets[i] != 0)
         count++;
   }
   return count;
}

//+------------------------------------------------------------------+
//| 获取最后一个订单的开仓价                                         |
//+------------------------------------------------------------------+
double GetLastOrderPrice()
{
   for(int i = 2; i >= 0; i--)
   {
      if(lastOrderTickets[i] != 0)
      {
         return GetOrderOpenPrice(lastOrderTickets[i]);
      }
   }
   return 0;
}

//+------------------------------------------------------------------+
//| 获取订单开仓价                                                   |
//+------------------------------------------------------------------+
double GetOrderOpenPrice(int ticket)
{
   if(!PositionSelectByTicket(ticket)) return 0;
   return PositionGetDouble(POSITION_PRICE_OPEN);
}

//+------------------------------------------------------------------+
//| 获取订单浮动盈亏(点数)                                         |
//+------------------------------------------------------------------+
double GetOrderProfitInPoints(int ticket)
{
   if(!PositionSelectByTicket(ticket)) return 0;
   
   double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
   double currentPrice = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) ? 
                         SymbolInfoDouble(_Symbol, SYMBOL_BID) : 
                         SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   
   if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
      return (currentPrice - openPrice) / point;
   else
      return (openPrice - currentPrice) / point;
}

//+------------------------------------------------------------------+
//| 平仓单个订单                                                     |
//+------------------------------------------------------------------+
void CloseOrder(int ticket)
{
   if(ticket == 0) return;
   if(!PositionSelectByTicket(ticket)) return;
   
   trade.PositionClose(ticket);
   Print("平仓订单:", ticket);
}

//+------------------------------------------------------------------+
//| 平仓所有订单                                                     |
//+------------------------------------------------------------------+
void CloseAllOrders()
{
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(PositionSelectByTicket(ticket))
      {
         if(PositionGetInteger(POSITION_MAGIC) == MagicNumber)
         {
            trade.PositionClose(ticket);
            Print("平仓订单:", ticket);
         }
      }
   }
}


//+------------------------------------------------------------------+
//| Tick函数                                                         |
//+------------------------------------------------------------------+
void OnTick()
   // ========== 1. 基础检查 ==========
   if(!IsSymbolAllowed()) return;
   if(!HandleExceptions()) return;
   //if(!IsSpreadAcceptable()) return;
   
   // ========== 2. 状态检查 ==========
   if(g_eaState == STATE_STOPPED)
   {
      // 30%风控触发,永久停止
      return;
   }
   
   if(g_eaState == STATE_PAUSED)
   {
      if(TimeCurrent() < pauseUntil)
         return;
      else
      {
         // 暂停结束,重置状态
         g_eaState = STATE_RUNNING;
         isPaused = false;
         ArrayFill(lastOrderTickets, 0, 3, 0);
         currentDirection = 0;
         secondGridHighestProfit = 0;
         Print("暂停结束,恢复运行");
      }
   }
   
   // ========== 3. 资金管理检查(优先级最高) ==========
   if(CheckMoneyManagement()) return;
   
   // ========== 4. 更新订单状态 ==========
   UpdateOrderStatus();
   
   // ========== 5. 检查第二加仓单移动止损 ==========
   CheckTrailingStop();
   
   // ========== 6. 检查止盈 ==========
   if(CheckTakeProfit()) return;
   
   // ========== 7. 时间风控(第二加仓单超时) ==========
   if(CheckTimeStop()) return;
   
   // ========== 8. 加仓逻辑 ==========
   CheckAndAddGrid();
   
   // ========== 9. 开新仓(首单) ==========
   // 避免同一K线重复开单
   datetime currentBarTime = iTime(_Symbol, PERIOD_M5, 0);
   if(currentBarTime == lastBarTime)
      return;
   lastBarTime = currentBarTime;
   
   // 无持仓时才能开首单
   if(CountOpenedOrders() == 0 && currentDirection == 0)
   {
      // 避免同一信号重复开单(5秒内不重复)
      if(TimeCurrent() - lastTradeTime < 5)
         return;
      
      if(CheckBuyCondition())
      {
         ExecutionBuy();
         lastTradeTime = TimeCurrent();
      }
      else if(CheckSellCondition())
      {
         ExecutionSell();
         lastTradeTime = TimeCurrent();
      }
   }
}
 
马丁 你这是
 

您好


【新手必看】如何防止机器人误判:讨论代码时请使用代码表述功能

https://www.mql5.com/zh/forum/448896

【新手必看】如何防止机器人误判:讨论代码时请使用代码表述功能
【新手必看】如何防止机器人误判:讨论代码时请使用代码表述功能
  • 2023.06.13
  • www.mql5.com
大家好,我是官网版主。 官网内部有机器人辅助管理,目的是自动下架一些有误导性的内容。 内容过长,或同一个IP多次注册,容易导致机器人误判,而被无辜删帖。 如果您被无故删帖,我们对这种体验感到万分抱歉。 为了防止机器人误判,请在讨论代码的时候使用代码表述功能...