Вопросы от начинающих MQL5 MT5 MetaTrader 5 - страница 1504

 

Здравствуйте, я еще совсем новичок впрограммировании наMQL5 и застрял на написании кода для советника по сетке. В принципе, я хочу, чтобы советник делал следующее:

Шаг 1. Если нет открытых позиций и отложенных ордеров, советник должен вызвать функцию OpenNewTrade()

Шаг 2. Если есть открытые позиции или отложенные ордера, советник должен закрыть все остальные позиции на продажу и удалить все лимитные ордера на покупку, когда позиция на продажу достигнет тейк-профита. Также он должен закрывать все остальные позиции на покупку и удалять все лимитные ордера на продажу, когда позиция на покупку достигает тейк-профита.

Шаг 3. Если шаг 2 выполнен правильно, то открытых позиций и отложенных ордеров больше не будет, поэтому шаг 1 вызывается снова в цикле.


ПРОБЛЕМА

==========

Все функции работают нормально, за исключением того, что функция закрытия позиций, как в шаге 2 выше, не работает должным образом, поэтому я не знаю, есть ли ошибка в логике кода. Например, всякий раз, когда позиция на продажу достигает тейк-профита, лимитные ордера на покупку удаляются корректно, но другая позиция (позиции) на продажу удаляется вместе с позицией (позициями) на покупку. Так не должно быть, поскольку я хочу, чтобы советник работал строго в соответствии с шагом 2. Ниже приведен код советника:

#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\AccountInfo.mqh>
#include <Trade\DealInfo.mqh>
#include <Trade\OrderInfo.mqh>
#include <Expert\Money\MoneyFixedMargin.mqh>
//-------
CPositionInfo  m_position;
CTrade         trade;
CSymbolInfo    m_symbol;
CAccountInfo   m_account;
CDealInfo      m_deal;
COrderInfo     m_order;
CMoneyFixedMargin *m_money;
//--------
bool     m_need_close_all_buy             = false;
bool     m_need_close_all_sell            = false; 
bool     m_need_delete_all_buy            = false;
bool     m_need_delete_all_sell           = false;
//--------
input double FirstLot = 0.01;           
input int TakeProfitPoints = 20;
input int GridLevelBuy = 3;
input int GridLevelSell = 3;   
input int GridDistancePoints = 20;   
input int InpMagic = 123456;
//-------
void OnInit()
{
   trade.SetExpertMagicNumber(InpMagic);
}
//-------
void OnDeinit(const int reason)
{
   
}
//-------
void OnTick()
   {
           if(m_need_close_all_buy)
           {
            CloseAllBuyPositions();
           }
         //----
         if(m_need_close_all_sell)
           {
             CloseAllSellPositions();
           }
         //---
         if(m_need_delete_all_buy)
           {
              DeleteAllPendingBuyOrders();
           }
         //---
         if(m_need_delete_all_sell)
           {
              DeleteAllPendingSellOrders();
           }
         //---
         if(PositionsTotal() == 0 && OrdersTotal() == 0)
            {
               OpenNewTrades();
            } 
   }
//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//--- get transaction type as enumeration value
   ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
//--- if transaction is result of addition of the transaction in history
   if(type==TRADE_TRANSACTION_DEAL_ADD)
     {
          if(HistoryDealSelect(trans.deal))
          {
              m_deal.Ticket(trans.deal);
              
              if(m_deal.DealType() == DEAL_TYPE_SELL && 
                 (m_deal.Entry() == DEAL_ENTRY_OUT || m_deal.Entry() == DEAL_ENTRY_INOUT))
              {
                  long deal_reason = -1;
                  if(m_deal.InfoInteger(DEAL_REASON, deal_reason))
                  {
                      if((ENUM_DEAL_REASON)deal_reason == DEAL_REASON_TP)
                      {
                          // Close all sell positions
                          m_need_close_all_sell=true;//---------------------------------------------This is the line of code that wont execute properly
                          // Delete all pending buy orders
                          m_need_delete_all_buy=true;
                      }
                  }
              }
              if(m_deal.DealType() == DEAL_TYPE_BUY && 
                 (m_deal.Entry() == DEAL_ENTRY_OUT || m_deal.Entry() == DEAL_ENTRY_INOUT))
              {
                  long deal_reason = -1;
                  if(m_deal.InfoInteger(DEAL_REASON, deal_reason))
                  {
                      if((ENUM_DEAL_REASON)deal_reason == DEAL_REASON_TP)
                      {
                          // Close all buy positions
                          m_need_close_all_buy=true;//---------------------------------------------This is the line of code that wont execute properly
                          // Delete all pending sell orders
                          m_need_delete_all_sell=true;
                      }
                  }
              }            
          }
     }
  }
//+------------------------------------------------------------------+
//| Close all positions                                              |
//+------------------------------------------------------------------+
void CloseAllBuyPositions(void)
  {
   int totalPositions = PositionsTotal();
       for(int i = PositionsTotal()-1; i >= 0; i--)
            {
               ulong ticket = PositionGetTicket(i);
               string symbol = PositionGetString(POSITION_SYMBOL);
               if(PositionGetInteger(POSITION_MAGIC) == InpMagic && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && symbol == _Symbol)
               {
                  trade.PositionClose(ticket);
               }
            }
  }
void CloseAllSellPositions(void)
  {
   int totalPositions = PositionsTotal();
       for(int i = PositionsTotal()-1; i >= 0; i--)
            {
               ulong ticket = PositionGetTicket(i);
               string symbol = PositionGetString(POSITION_SYMBOL);
               if(PositionGetInteger(POSITION_MAGIC) == InpMagic && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && symbol == _Symbol)
               {
                  trade.PositionClose(ticket);
               }
            }
  }
//+------------------------------------------------------------------+
//| Delete all pending orders                                        |
//+------------------------------------------------------------------+
void DeleteAllPendingBuyOrders(void)
  {
       int totalOrders = OrdersTotal();
       for(int i = OrdersTotal()-1; i >= 0; i--)
            {
               ulong ticket = OrderGetTicket(i);
               string symbol = OrderGetString(ORDER_SYMBOL);
               if(OrderGetInteger(ORDER_MAGIC) == InpMagic && OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT && symbol == _Symbol)
               {
                  trade.OrderDelete(ticket);
               }
            }
  }
void DeleteAllPendingSellOrders(void)
  {
       int totalOrders = OrdersTotal();
       for(int i = OrdersTotal()-1; i >= 0; i--)
            {
               ulong ticket = OrderGetTicket(i);
               string symbol = OrderGetString(ORDER_SYMBOL);
               if(OrderGetInteger(ORDER_MAGIC) == InpMagic && OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT && symbol == _Symbol)
               {
                  trade.OrderDelete(ticket);
               }
            }
  }
//+------------------------------------------------------------------+
void OpenNewTrades()
   {
    double bid = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits);
    double ask = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits);
    double tpBuy, tpSell, buyLimitPrice, sellLimitPrice;

    // Calculate take profit for initial buy and sell positions
    tpBuy = ask + TakeProfitPoints * _Point;
    tpSell = bid - TakeProfitPoints * _Point;

    // Place initial buy position with take profit
    trade.Buy(FirstLot, _Symbol, ask, 0, tpBuy);
    
    // Place initial sell position with take profit
    trade.Sell(FirstLot, _Symbol, bid, 0, tpSell);

    // Place buy limit orders
    for(int i = 0; i < GridLevelBuy; i++)
    {
        buyLimitPrice = ask - (GridDistancePoints * (i + 1)) * _Point;
        tpBuy = buyLimitPrice + TakeProfitPoints * _Point;
        trade.BuyLimit(FirstLot * MathPow(2, i), buyLimitPrice, _Symbol, 0, tpBuy);
    }

    // Place sell limit orders
    for(int i = 0; i < GridLevelSell; i++)
    {
        sellLimitPrice = bid + (GridDistancePoints * (i + 1)) * _Point;
        tpSell = sellLimitPrice - TakeProfitPoints * _Point;
        trade.SellLimit(FirstLot * MathPow(2, i), sellLimitPrice, _Symbol, 0, tpSell);
    }
   }
Также я не знаю, как сделать так, чтобы советник задавал свое имя в качестве торговых комментариев. Было бы здорово, если бы вы помогли мне с этим, так как я хочу, чтобы сделки этого советника отличались от сделок других советников. Спасибо.
How to Order a Trading Robot in MQL5 and MQL4
How to Order a Trading Robot in MQL5 and MQL4
  • www.mql5.com
"Freelance" is the largest freelance service for ordering MQL4/MQL5 trading robots and technical indicators. Hundreds of professional developers are ready to develop a custom trading application for the MetaTrader 4/5 terminal.
 

Подскажите начинающему. Не могу додуматься как можно преобразовать строку.

Как заменить символы в "var_1" подстроки от заданного индекса, на символы "var_2'' ?

   string var_1  = "100000000";
   string var_2  = " млн."
   Print(); // 100 млн   
 

Позиция на продажу, закрывается сделкой на покупку.

Этот код у вас проверяет закрытие позиции Sell.

m_deal.DealType() == DEAL_TYPE_BUY

Попробуйте так.

//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//--- get transaction type as enumeration value
   ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
//--- if transaction is result of addition of the transaction in history
   if(type==TRADE_TRANSACTION_DEAL_ADD)
     {
          if(HistoryDealSelect(trans.deal))
          {
              m_deal.Ticket(trans.deal);
              
              if(m_deal.DealType() == DEAL_TYPE_BUY && 
                 (m_deal.Entry() == DEAL_ENTRY_OUT || m_deal.Entry() == DEAL_ENTRY_INOUT))
              {
                  long deal_reason = -1;
                  if(m_deal.InfoInteger(DEAL_REASON, deal_reason))
                  {
                      if((ENUM_DEAL_REASON)deal_reason == DEAL_REASON_TP)
                      {
                          // Close all sell positions
                          m_need_close_all_sell=true;//---------------------------------------------This is the line of code that wont execute properly
                          // Delete all pending buy orders
                          m_need_delete_all_buy=true;
                      }
                  }
              }
              if(m_deal.DealType() == DEAL_TYPE_SELL&& 
                 (m_deal.Entry() == DEAL_ENTRY_OUT || m_deal.Entry() == DEAL_ENTRY_INOUT))
              {
                  long deal_reason = -1;
                  if(m_deal.InfoInteger(DEAL_REASON, deal_reason))
                  {
                      if((ENUM_DEAL_REASON)deal_reason == DEAL_REASON_TP)
                      {
                          // Close all buy positions
                          m_need_close_all_buy=true;//---------------------------------------------This is the line of code that wont execute properly
                          // Delete all pending sell orders
                          m_need_delete_all_sell=true;
                      }
                  }
              }            
          }
     }
  }

К тому же у вас флаг удаления позиций и ордеров, после первого удаления всегда true, так как нигде в коде вы его после удаления позиций и ордеров не делаете false.

Вроде по логике, должно быть так.

void OnTick()
  {
   if(m_need_close_all_buy)
     {
      CloseAllBuyPositions();
      m_need_close_all_buy = false;
     }
//----
   if(m_need_close_all_sell)
     {
      CloseAllSellPositions();
      m_need_close_all_sell = false;
     }
//---
   if(m_need_delete_all_buy)
     {
      DeleteAllPendingBuyOrders();
      m_need_delete_all_buy = false;
     }
//---
   if(m_need_delete_all_sell)
     {
      DeleteAllPendingSellOrders();
      m_need_delete_all_sell = false;
     }
//---
   if(PositionsTotal() == 0 && OrdersTotal() == 0)
     {
      OpenNewTrades();
     }
  }
 
Aleksandr Slavskii #:

К тому же у вас флаг удаления позиций и ордеров, после первого удаления всегда true, так как нигде в коде вы его после удаления позиций и ордеров не делаете false.

Вроде по логике, должно быть так.

Александр, а то, что эти флаги инициализированы false на глобальном уровне, разве это в счёт не идёт?

С уважением, Владимир.

 
MrBrooklin #:

Александр, а то, что эти флаги инициализированы false на глобальном уровне, разве это в счёт не идёт?

С уважением, Владимир.

Один раз false. А потом они всегда true и на каждом тике будут удалять отложенные ордера и позиции.

 
Aleksandr Slavskii #:

Один раз false. А потом они всегда true и на каждом тике будут удалять отложенные ордера и позиции.

Ну, да, логично. Спасибо за разъяснение.

С уважением, Владимир.

 
При запуске советника в MT5 Strategy Tester я постоянно получаю ошибку "failed market sell 0.01 EURUSD [Unsupported filling mode]". Код результата (retcode) возвращается 10030.
Вот структура моего запроса. Пожалуйста, помогите.
   MqlTradeRequest request = {} ;
   MqlTradeResult  result = {} ;
   double bid = SymbolInfoDouble(Symbol(),SYMBOL_BID)
   request.action = TRADE_ACTION_DEAL ;
   request.magic = Magic ;
   request.symbol = Symbol() ;
   request.volume = 0.01 ;
   request.price = bid ;
   request.deviation = 5 ;
   request.sl = bid + 100 * _Points ;
   request.tp = bid - 200 * _Points ;
   request.type = ORDER_TYPE_SELL ;
   request.type_filling = SymbolInfoInteger(_Symbol,SYMBOL_FILLING_MODE);

   order_success = OrderSend(request, result) ;


 
Albert Mathenge #:
При запуске советника в MT5 Strategy Tester я постоянно получаю ошибку "failed market sell 0.01 EURUSD [Unsupported filling mode]". Код результата (retcode) возвращается 10030.
Вот структура моего запроса. Пожалуйста, помогите.

Попробуйте поменять строку

request.type_filling = SymbolInfoInteger(_Symbol,SYMBOL_FILLING_MODE);

на строку

request.type_filling = ORDER_FILLING_FOK;

И странно, что компилятор выдает только одну ошибку. Хотя, если _Points и order_success были проинициализированы на глобальном уровне, то тогда, пардон!

С уважением, Владимир.

 
MrBrooklin #:

Попробуйте изменить строку

на строку

И странно, что компилятор выдает только одну ошибку. Хотя, если _Points и order_success были инициализированы на глобальном уровне, то, пардон!

С уважением, Владимир.

Да, я просто заменил имена переменных для этого форума, чтобы вы не осуждали мои странные имена переменных. lol.
Спасибо за предложение, но у меня раньше было ORDER_FILLING_FOK и я получал ту же ошибку. Я прочитал, что не все символы поддерживают все режимы заполнения, поэтому я изменил его на тот, что указан в исходном сообщении, чтобы убедиться, что в запросе указаны только разрешенные режимы заполнения.
 
Albert Mathenge #:
Да, я просто заменил имена переменных для этого форума, чтобы вы не осуждали мои странные имена переменных. lol.
Спасибо за предложение, но у меня раньше было ORDER_FILLING_FOK и я получал ту же ошибку. Я прочитал, что не все символы поддерживают все режимы заполнения, поэтому я изменил его на тот, что указан в исходном сообщении, чтобы убедиться, что в запросе указаны только разрешенные режимы заполнения.

SymbolInfoInteger(_Symbol,SYMBOL_FILLING_MODE) возвращает все разрешённые режимы заполнения, а указать в запросе надо один конкретный из разрешённых.