tailing1985 发表于 2025-3-14 14:09:41

寻求一个简单的挂单ea的编写

版本        MT4               
参数设置
手数       
平仓方式可选        1:每单单独止盈止损       
                        2:任意一单止盈则全部平仓       
止盈点数                50
止损点数                50
挂单间隔点数        250

开仓说明       
多单        即时价格之上间隔X点挂多单,成交后以成交价格为基础继续间隔X点之上挂多单        举例:即时价格为2900,在2900之上间隔250点也就是2902.5挂多单,如果成交就继续在2905挂多单
空单        即时价格之下间隔X点挂空单,成交后以成交价格为基础继续间隔X点之下挂空单       

平仓说明        1:每单单独止盈止损        如选择该种平仓方式,则任一成交单止盈后,删除全部挂单,重新开始挂多空双向的单子,保留的单子设好止盈后保留即可,等待成交不用管它了        这里可能有两种情况,一种是,某个方向的单子成交后直接走向止盈,另一种是没有触达止盈而是向着相反的方向走去,从而使得反向单成交,反向单成交后,两个单子最终会有一个止盈,止盈后就删掉挂单重新开始新的挂单,保留的那个单子按照止盈止损设置好不用管了就,一直等到他止盈或者止损
2:任意一单止盈则全部平仓        如果选择这种平仓方式,则任一单止盈后,平掉所有持仓单及挂单,然后重新开始挂单

fakebird 发表于 2025-3-16 14:14:08

咋联系

fakebird 发表于 2025-3-19 09:16:09

这样也行吧,需要的下载

124349433 发表于 2025-3-27 14:18:44

/*
EA名称:PendingOrderEA.mq4
版本:MT4

参数说明:
Lots                - 交易手数
CloseMode         - 平仓方式:1为“每单单独止盈止损”,2为“任一单止盈则全部平仓”
TakeProfitPoints    - 止盈点数(例如50点)
StopLossPoints      - 止损点数(例如50点)
PendingDistancePoints - 挂单间隔点数(例如250点)

开仓说明:
多单:以当前 g_longBase 为基准,在其上加上 PendingDistancePoints 换算后的价格间隔挂 Buy Stop 单,
      成交后以成交价格更新 g_longBase,再继续挂出下一单。
空单:以当前 g_shortBase 为基准,在其下减去价格间隔挂 Sell Stop 单,
      成交后以成交价格更新 g_shortBase,再继续挂出下一单。

平仓说明:
若 CloseMode = 1(每单单独止盈止损):任一挂单成交且止盈(检测历史订单近5秒内盈利)时,仅取消所有挂单,
      重新挂出多空挂单(已成交订单保留,后续由各自的 TP/SL 自动平仓)。
若 CloseMode = 2(任一单止盈则全部平仓):任一挂单止盈后,关闭所有持仓及挂单,然后重新挂单。

注意:代码中采用 PendingDistancePoints、TakeProfitPoints、StopLossPoints 与价格之间的换算因子 PointFactor,
      此处默认1点 = 0.01价格单位,请根据品种实际小数位调整。
*/

#property strict

extern double Lots = 0.1;
extern int    CloseMode = 1;            // 1:每单单独止盈止损,2:任一单止盈则全部平仓
extern int    TakeProfitPoints = 50;      // 止盈点数
extern int    StopLossPoints = 50;      // 止损点数
extern int    PendingDistancePoints = 250;// 挂单间隔点数

int MagicNumber = 123456;   // 魔术数字

// 用于计算挂单价格的换算因子(根据品种小数位调整)
double PointFactor = 0.01;

// 多单和空单的基准价
double g_longBase = 0;
double g_shortBase = 0;

// 取消所有挂单(Buy Stop 和 Sell Stop)
void CancelPendingOrders()
{
   for (int i = OrdersTotal()-1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderMagicNumber() == MagicNumber &&
            (OrderType() == OP_BUYSTOP || OrderType() == OP_SELLSTOP))
         {
            if(!OrderDelete(OrderTicket()))
               Print("删除挂单失败, Error:", GetLastError());
         }
      }
   }
}

// 挂出挂单:多单挂 Buy Stop,空单挂 Sell Stop
void PlacePendingOrders()
{
   double offset = PendingDistancePoints * PointFactor;
   
   // 挂多单:价格 = g_longBase + offset
   double buyPrice = NormalizeDouble(g_longBase + offset, Digits);
   double tpLong = NormalizeDouble(buyPrice + TakeProfitPoints * PointFactor, Digits);
   double slLong = NormalizeDouble(buyPrice - StopLossPoints * PointFactor, Digits);
   int ticket = OrderSend(Symbol(), OP_BUYSTOP, Lots, buyPrice, 3, slLong, tpLong, "Buy Pending", MagicNumber, 0, Blue);
   if(ticket < 0)
      Print("挂Buy Stop失败, Error:", GetLastError());
   
   // 挂空单:价格 = g_shortBase - offset
   double sellPrice = NormalizeDouble(g_shortBase - offset, Digits);
   double tpShort = NormalizeDouble(sellPrice - TakeProfitPoints * PointFactor, Digits);
   double slShort = NormalizeDouble(sellPrice + StopLossPoints * PointFactor, Digits);
   ticket = OrderSend(Symbol(), OP_SELLSTOP, Lots, sellPrice, 3, slShort, tpShort, "Sell Pending", MagicNumber, 0, Red);
   if(ticket < 0)
      Print("挂Sell Stop失败, Error:", GetLastError());
}

// 重置挂单:取消挂单、更新基准价(当无持仓时更新为当前市场价)并重新挂单
void ResetPendingOrders()
{
   CancelPendingOrders();
   bool hasPosition = false;
   for(int i = 0; i < OrdersTotal(); i++)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderMagicNumber() == MagicNumber && (OrderType() == OP_BUY || OrderType() == OP_SELL))
         {
            hasPosition = true;
            break;
         }
      }
   }
   if(!hasPosition)
   {
      g_longBase = Ask;
      g_shortBase = Bid;
   }
   PlacePendingOrders();
}

// 检查是否有止盈成交:检测历史订单中近5秒内盈利的订单
bool CheckTPHit()
{
   bool tpHit = false;
   int totalHist = OrdersHistoryTotal();
   for (int i = totalHist - 1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
      {
         if(OrderMagicNumber() == MagicNumber)
         {
            datetime closeTime = OrderCloseTime();
            if(closeTime > TimeCurrent() - 5 && OrderProfit() > 0)
            {
               tpHit = true;
               break;
            }
         }
      }
   }
   return tpHit;
}

// 检查是否有新成交挂单,若有则更新相应方向的基准价,并重挂挂单
void UpdatePendingAfterExecution()
{
   bool updateLong = false;
   bool updateShort = false;
   for(int i = 0; i < OrdersTotal(); i++)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderMagicNumber() == MagicNumber)
         {
            if(OrderType() == OP_BUY)
            {
               if(OrderOpenPrice() > g_longBase)
               {
                  g_longBase = OrderOpenPrice();
                  updateLong = true;
               }
            }
            else if(OrderType() == OP_SELL)
            {
               if(OrderOpenPrice() < g_shortBase)
               {
                  g_shortBase = OrderOpenPrice();
                  updateShort = true;
               }
            }
         }
      }
   }
   if(updateLong || updateShort)
   {
      CancelPendingOrders();
      PlacePendingOrders();
   }
}

// 关闭所有持仓(用于平仓方式2)
void CloseAllOrders()
{
   for(int i = OrdersTotal()-1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderMagicNumber() == MagicNumber && (OrderType() == OP_BUY || OrderType() == OP_SELL))
         {
            double price = (OrderType() == OP_BUY) ? Bid : Ask;
            if(!OrderClose(OrderTicket(), OrderLots(), price, 3, clrYellow))
               Print("平仓失败, Error:", GetLastError());
         }
      }
   }
}

// 主程序入口
int start()
{
   // 初次启动时初始化基准价并挂出挂单
   if(g_longBase == 0 || g_shortBase == 0)
   {
      g_longBase = Ask;
      g_shortBase = Bid;
      PlacePendingOrders();
   }
   
   // 检查挂单数量,若没有挂单则重新挂出
   int pendingCount = 0;
   for(int i = 0; i < OrdersTotal(); i++)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderMagicNumber() == MagicNumber &&
            (OrderType() == OP_BUYSTOP || OrderType() == OP_SELLSTOP))
            pendingCount++;
      }
   }
   if(pendingCount == 0)
      PlacePendingOrders();
      
   // 检查是否有新成交挂单,更新基准价并重挂挂单
   UpdatePendingAfterExecution();
   
   // 检查是否有止盈成交触发
   if(CheckTPHit())
   {
      if(CloseMode == 1)
      {
         // 模式1:取消所有挂单,重新挂单(持仓保留,由各自TP/SL自动平仓)
         ResetPendingOrders();
      }
      else if(CloseMode == 2)
      {
         // 模式2:平掉所有持仓和挂单,再重新挂单
         CloseAllOrders();
         CancelPendingOrders();
         g_longBase = Ask;
         g_shortBase = Bid;
         PlacePendingOrders();
      }
   }
   
   return(0);
}
页: [1]
查看完整版本: 寻求一个简单的挂单ea的编写