初学者的问题 MQL5 MT5 MetaTrader 5 - 页 1207

 

mql5 (保 值)

如何实现两种条件下的 平仓 算法?

1箱。如果有2个头寸未平,那么就关闭利润大于......2的那个案例。如果有2个或更多的未结头寸,那么就通过平均化的方式关闭...

现在我有两种方法来关闭这些头寸。

对于1种情况,按利润比较仓位,关闭利润较多的仓位;对于2种情况,按公平原则关闭所有仓位,取其平均值。

这些方法单独使用效果很好,但不能一起使用,因为两个事件中有一个属于两种方法的分布范围。

我无法设法将它们分开。因此,这两个案例主要是在公平的基础上关闭了所有头寸。这导致了这样一个事实:在第一种情况下,所需的位置被删除并重新打开。

结果是。双重传播,双重佣金。这是令人沮丧的))))。

设置订单和仓位的方案看起来像这样用于卖出(进一步说只用于卖出)。

限价单。卖出限价

位置。卖出(总是在订单之间)。

停止命令。卖出_STOP

我在此附上图表。

关闭职位。

1. 如果触发了止损单,即同时出现两个或更多的头寸,你应该关闭一个利润高于...(20)

2. 如果触发了限价 订单,即同时开了两个或更多的头寸,它们的平均值(按净值计算)应被关闭..... (15)

问题。如何将这两个方法分开,使它们只处理自己的事件?

也许有一些其他的方法来处理这两种情况?

我使用的方法的例子。

//+---------------------------------------------------------------------+
//|  -- ЗАКРЫВАЕМ ОДНУ ИЗ ДВУХ ПОЗИЦИЙ С НИЗУ, ГДЕ ПРОФИТ БОЛЬШЕ ЧЕМ ---|
//+---------------------------------------------------------------------+ 
ulong ticket_n=ULONG_MAX;  double profit=DBL_MIN;

     if(invert_close == true) //Проверка на наличие 2х и более поз.
     {
     int positions=PositionsTotal();
     for(int i=PositionsTotal()-1; i>=0; i--)
     {
     ulong tmp_ticket=PositionGetTicket(i);
     if(ticket_n!=0)
     {
     double tmp_profit=PositionGetDouble(POSITION_PROFIT);
     if(tmp_profit>profit+Prof_eqw_niz)// допустим 20
     {
     ticket_n=tmp_ticket;
     profit=tmp_profit;
     }
     }
     }
//-----------
     if(ticket_n!=ULONG_MAX)
     m_trade.PositionClose(ticket_n);
     invert_close = false;
     Print("------  ЗАКРЫЛИ ТОЛСТУЮ ---------");
     }       

//+---------------------------------------------------------------------+
//|                     Э К В И Т И   ДЛЯ SELL_LIMIT                    |
//+---------------------------------------------------------------------+
   npos_ALL=0; NPos_ALL(npos_ALL);
   if (npos_ALL>=Metod_Eqw && m_account.Equity()>= m_account.Balance()+Prof_eqw)//Допустим 15
   {
   CloseAllPositions();
   Print("------  ЗАКРЫЛИ ВСЕ ---------");
   }
Совершение сделок - Торговые операции - Справка по MetaTrader 5
Совершение сделок - Торговые операции - Справка по MetaTrader 5
  • www.metatrader5.com
Торговая деятельность в платформе связана с формированием и отсылкой рыночных и отложенных ордеров для исполнения брокером, а также с управлением текущими позициями путем их модификации или закрытия. Платформа позволяет удобно просматривать торговую историю на счете, настраивать оповещения о событиях на рынке и многое другое. Открытие позиций...
附加的文件:
 
Vladpedro:


是否按EA工作的符号开仓?是否使用了魔术师的号码?
 
Vladimir Karputov:
是否按EA工作的符号开仓?使用神奇的数字

是的,通过当前的符号。 是的,使用了magik。

 
Vladpedro:

是的,由当前的角色来做。 是的,使用魔法。

解释一下第二个条件,它是什么意思?(如果有2个或更多的头寸未结,那么就通过平均数值来关闭... )

 
Vladimir Karputov:

解释一下第二个条件,它是什么意思?(如果有2个或更多的头寸未平仓,通过对数值的平均化来关闭...)

这意味着:如果有两个或更多的头寸未平,并且权益 余额多出任何数值(比如15),那么所有的头寸都将被关闭。

例如,开了三个仓位,第一个当前亏损为-10,第二个盈利为-5,第三个盈利为+30,合计+15,所有仓位都可以平仓。

如果没有达到+15的平均利润,头寸将被其自己预设的SL或TP关闭。(这算是平仓的 第三个条件,但没有问题,所以我省略了)。

 
Vladpedro:

这意味着:如果有两个或更多的头寸未平,而权益大于 余额的任何数值(例如15),那么所有的头寸将被关闭。

例如,有三个仓位未平,第一个仓位当前亏损为-10,第二个仓位盈利为-5,第三个仓位+30+总计为+15,所有仓位都可以平仓。

如果没有达到+15的平均利润,头寸将被其自己预设的SL或TP关闭。(这算是平仓的 第三个条件,但没有问题,所以我把它省略了)。

下面是两个条件的完整代码。

//+------------------------------------------------------------------+
//|                                       Closing Two conditions.mq5 |
//|                              Copyright © 2020, Vladimir Karputov |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2020, Vladimir Karputov"
#property version   "1.00"
/*
   barabashkakvn Trading engine 3.116
*/
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
//---
CPositionInfo  m_position;                   // object of CPositionInfo class
CTrade         m_trade;                      // object of CTrade class
CSymbolInfo    m_symbol;                     // object of CSymbolInfo class
//--- input parameters
input double   InpProfitTarget      = 15;       // Profit target, in deposit money (if Positions > 2)
input ulong    InpDeviation         = 10;       // Deviation, in points (1.00045-1.00055=10 points)
input ulong    InpMagic             = 200;      // Magic number
//---
bool     m_need_close_all           = false;    // close all positions
ulong    m_need_close_ticket        = ULONG_MAX;// close one position
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   if(!m_symbol.Name(Symbol())) // sets symbol name
     {
      Print(__FILE__," ",__FUNCTION__,", ERROR: CSymbolInfo.Name");
      return(INIT_FAILED);
     }
//---
   m_trade.SetExpertMagicNumber(InpMagic);
   m_trade.SetMarginMode();
   m_trade.SetTypeFillingBySymbol(m_symbol.Name());
   m_trade.SetDeviationInPoints(InpDeviation);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(m_need_close_all)
     {
      if(IsPositionExists())
        {
         CloseAllPositions();
         return;
        }
      else
         m_need_close_all=false;
     }
//---
   if(m_need_close_ticket!=ULONG_MAX)
     {
      //--- close one position
      if(m_position.SelectByTicket(m_need_close_ticket))
        {
         m_trade.PositionClose(m_need_close_ticket); // close a position
         return;
        }
      else
         m_need_close_ticket=ULONG_MAX;
     }
//--- calculate all positions
   int total=0;
   for(int i=PositionsTotal()-1; i>=0; i--)
      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==InpMagic)
            total++;

   if(total==2)
     {
      //--- conditon 1
      ulong tmp_ticket=ULONG_MAX;
      double tmp_profit=DBL_MIN;
      for(int i=PositionsTotal()-1; i>=0; i--)
         if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
            if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==InpMagic)
              {
               double profit=m_position.Commission()+m_position.Swap()+m_position.Profit();
               if(profit>tmp_profit)
                 {
                  tmp_profit=profit;
                  tmp_ticket=m_position.Ticket();
                 }
              }
      //---
      if(tmp_ticket!=ULONG_MAX)
         m_need_close_ticket=tmp_ticket;
     }
   else
     {
      if(total>2)
        {
         //--- conditon 2
         double profit=0;
         for(int i=PositionsTotal()-1; i>=0; i--)
            if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
               if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==InpMagic)
                  profit+=m_position.Commission()+m_position.Swap()+m_position.Profit();
         //---
         if(profit>=InpProfitTarget)
            m_need_close_all=true;
        }
     }
  }
//+------------------------------------------------------------------+
//| Is position exists                                               |
//+------------------------------------------------------------------+
bool IsPositionExists(void)
  {
   for(int i=PositionsTotal()-1; i>=0; i--)
      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==InpMagic)
            return(true);
//---
   return(false);
  }
//+------------------------------------------------------------------+
//| Close all positions                                              |
//+------------------------------------------------------------------+
void CloseAllPositions(void)
  {
   for(int i=PositionsTotal()-1; i>=0; i--) // returns the number of current positions
      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==InpMagic)
            m_trade.PositionClose(m_position.Ticket()); // close a position by the specified m_symbol
  }
//+------------------------------------------------------------------+
附加的文件:
 
Vladimir Karputov:

下面是这两个条件的完整代码。

谢谢你,弗拉基米尔,我会设法解决这个问题。

我试图用自己的方式来解决这个问题,我明白你怎么能把这两个条件分开。

比如说。

我们来声明三个逻辑变量。

Pos_1;

Pos_2_Clos_1;

Pos_2_Clos_All。

1.检查空缺职位 的数量。

如果我们只有1个未结头寸,则卖出设置为

Pos_1=true; Pos_2_Clos_1=false; Pos_2_Clos_All=false

如果有2个仓位被打开,并且权益金额是正数(这可能只在SELL_STOP订单触发时发生,为该事件分配一个逻辑值

Pos_1=false ; Pos_2_Clos_1=true; Pos_2_Clos_All=false。

如果建立了2个头寸,并且权益金额为负数(这可能只发生在SELL_LIMIT订单触发时),那么

Pos_1=false ; Pos_2_Clos_1=false; Pos_2_Clos_All=true

这似乎就是全部...你可以检查逻辑变量,并将它们分配给你自己的关闭方法,但由于某些原因,它对我不起作用...

我是一个糟糕的程序员,也许我在某处犯了一个错误......。

谢谢你的帮助)

Совершение сделок - Торговые операции - Справка по MetaTrader 5
Совершение сделок - Торговые операции - Справка по MetaTrader 5
  • www.metatrader5.com
Торговая деятельность в платформе связана с формированием и отсылкой рыночных и отложенных ордеров для исполнения брокером, а также с управлением текущими позициями путем их модификации или закрытия. Платформа позволяет удобно просматривать торговую историю на счете, настраивать оповещения о событиях на рынке и многое другое. Открытие позиций...
 

弗拉基米尔-卡尔普托夫

Vladimir,我遇到了麻烦。 当SELL_STOP订单触发时,一切正常。 只有一个有较大利润的头寸被关闭。

但当SELL_LIMIT被触发时,所有的东西都被错误地关闭了,不是按所有未结头寸的总和,但看起来是利润较高的头寸被关闭。

我以前也有过类似的错误,现在我开始想,也许是我的错,也许我没有正确计算和开仓。

请检查我准备好的测试代码,看看你是否有错误,但也许你的代码中也有一些不一致的地方,或者我没有正确解释......我的平均利润是多少?

我现在开始分析这个算法,发现它的后果比我之前告诉你的还要复杂一些。

按SL关闭一个头寸 时,第三个条件可能会导致前两个条件的算法出现错误。

我将再次描述仅针对SELL_LIMIT情况的 完整平仓算法,因为SEL_STOP情况是正常执行的。暂时不谈这个问题。

1.我们最初有一个未结头寸SELL,它有指定的SL,但它高于SELL_LIMIT,这意味着SL在SELL_LIMIT之前不会被激活。

2.SELL_LIMIT已经触发,并且有第二个 SELL 头寸,它有自己的SL,在下一个SELL_LIMIT之前也不能平仓。

如果SELL_LIMIT订单已经触发,则新的SELL_LIMIT订单已经被放置。(总是)

4.开放的SELL_LIMIT头寸的数量可能是1-3个 或更多,这完全取决于他们站在SL的多远。如果最多有三个人,请考虑这种情况。(我可以把这限制在SL上)

现在是平仓的情景。

如果有空缺职位。2、关闭一个或所有头寸只有两种情况 可能发生

1.通过Equity,如果它比余额多出15(所有头寸都被关闭),(m_account.Equity()>= m_account.Balance()+15) 我的意思是通过平均数关闭几个头寸。

2.通过自己的SL(一个位置被关闭)。

3.剩下的一个位置, 如果之前设置了关闭条件,现在必须清除,因为我们不知道该对其适用什么条件。

它可以重复SELL_LIMIT的情况,也可以降到SEL_STOP,进入另一个平仓条件。

4.如果有三个仓位, 我们也要关闭它们(m_account.Equity()>= m_account.Balance()+15),否则其中一个会触发SL,而剩下两个仓位。

应用这一规则,直到剩下一个职位,并且没有定义关闭条件......。

Совершение сделок - Торговые операции - Справка по MetaTrader 5
Совершение сделок - Торговые операции - Справка по MetaTrader 5
  • www.metatrader5.com
Торговая деятельность в платформе связана с формированием и отсылкой рыночных и отложенных ордеров для исполнения брокером, а также с управлением текущими позициями путем их модификации или закрытия. Платформа позволяет удобно просматривать торговую историю на счете, настраивать оповещения о событиях на рынке и многое другое. Открытие позиций...
附加的文件:
 
Vladpedro:

弗拉基米尔-卡尔普托夫

Vladimir,我遇到了麻烦。 当我的SELL_STOP订单触发时,一切正常。 只有一个利润较大的头寸被关闭。

但当SELL_LIMIT被触发时,订单的平仓方式不正确,不是按所有未平仓头寸的总和平仓,而似乎是以最高的利润平仓。

我以前也有过类似的错误,现在我开始想,也许是我的错,也许我没有正确计算和开仓。

请查看我准备好的测试代码,看看你是否有错误,但也许你的代码不符合条件。 或者我没有正确解释...我的平均利润是多少。

一般来说,哪个挂单 触发并不重要--事实上,我们最终会有一个头寸,然后计算该头寸的利润。

 
Vladimir Karputov:

哪个挂单 触发没有任何区别--毕竟,我们得到一个头寸,然后计算头寸的利润。

这没有任何区别。我怀疑有区别,因为在设置订单和头寸时,我为头寸分配了自己的 "评论",为订单分配了自己的评论。因此,当一个订单移动到一个位置时,它继承了订单的评论。

然后当我们通过评论检查位置时,出现了混乱......评论是不同的。 我修复了这个。

我在你的代码中没有发现,或者说不明白在Equity触发的SELL_LIMIT条件下是如何平仓的。

if(total==2)
   {
//-------------------------------------------------------- conditon 1
      ulong tmp_ticket=ULONG_MAX;
      double tmp_profit=DBL_MIN;
      for(int i=PositionsTotal()-1; i>=0; i--)
      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
      if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==InpMagic)
      {
      double profit=m_position.Commission()+m_position.Swap()+m_position.Profit();
      if(profit>tmp_profit)
      {
      tmp_profit=profit;
      tmp_ticket=m_position.Ticket();
      }
      }
      //---
      if(tmp_ticket!=ULONG_MAX)
      m_need_close_ticket=tmp_ticket;
      }
      else
      {
      if(total==2)
        {
//--------------------------------------------------------- conditon 2
        double profit=0;
        for(int i=PositionsTotal()-1; i>=0; i--)
        if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
        if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==InpMagic)
        profit+=m_position.Commission()+m_position.Swap()+m_position.Profit();
//--------
       if(profit>=InpProfitTarget)
        m_need_close_all=true;
        }
        }

似乎我们已经检查了所有的头寸是否可以被关闭,并且为它设置了标志。

但在CloseAllPositions()

if(m_need_close_all)
   {
   if(IsPositionExists())
   {
   CloseAllPositions();
   return;
   }
   else
   m_need_close_all=false;
   }

缺少一些东西。

 if(m_account.Equity()>= m_account.Balance()+15)

没有检查关闭所有头寸的情况 - SELL_LIMIT已经触发了

也许这个同样的m_account.Equity()>= m_account.Balance()+15是以其他方式实现的?

也可能是因为我误解了 "平均 "的含义。