Скачать MetaTrader 5

Проблемы с выходом из сделки.

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Узнай принцип работы Торговых Сигналов для MetaTrader
Mike Kharkov
846
Mike Kharkov 2014.09.30 15:01 
Всем привет.
Есть такой код:
//+------------------------------------------------------------------+
//|                                                  My_Practics.mq5 |
//+------------------------------------------------------------------+
#property copyright "Mike_Kharkov"
#property link      "https://www.fl.ru/users/Yamaradg/"
#property version   "1.00"
double COEF  = 1.0;                                              // коэффициент кратности увеличения лота
int    DELTA = 200;                                               // количество пунктов прохода цены для уведичения позиции
ulong  magic_number = 87654321;                                  // магический ордер
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Expert Get history price function                                |
//+------------------------------------------------------------------+
double GetHistoryPrice( const string aSymbol )
{
  double price_in = 0;
  double volume_in = 0;
  
  if ( PositionSelect( aSymbol ) )
  {
    long pos_id = long( PositionGetInteger( POSITION_IDENTIFIER ) );
    
    if ( pos_id > 0 )
    {
      if ( HistorySelectByPosition( ulong( pos_id ) ) )
      {
        int deals = HistoryDealsTotal();
      
        for( int i = 0; i < deals; i++ )
        {
          ulong deal_ticket = HistoryDealGetTicket( i );
          ulong order_ticket = ulong( HistoryDealGetInteger( deal_ticket, DEAL_ORDER ) );
        
          if ( order_ticket > 0 )
          {
            long deal_entry = long( HistoryDealGetInteger( deal_ticket, DEAL_ENTRY ) );
              
            if ( deal_entry == DEAL_ENTRY_IN )
            {
              double price = HistoryDealGetDouble( deal_ticket, DEAL_PRICE );
              double volume = HistoryDealGetDouble( deal_ticket, DEAL_VOLUME );
                                
              price_in = price_in + price * volume;
              volume_in = volume_in + volume;  
            }
          }
        }
        if ( volume_in > 0 ) return( NormalizeDouble( price_in / volume_in, _Digits ) );
      }
      else
      {
        Print( "Не возможно получить историю позиции по символу ", aSymbol );
      }
    }
    else
    {
      Print( "Не возможно определить идентификатор позиции по символу ", aSymbol );
    }
  }
  return( 0 );
}
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+


int OnInit()
{  
//---
   
//---
   return(INIT_SUCCEEDED);
}//---------------------------------------------------------------------------+



//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+


void OnDeinit(const int reason)
{
//---
}//---------------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+


void OnTick()
{ 
      datetime    tm=TimeCurrent();
      MqlDateTime stm;
      TimeToStruct(tm,stm); 
  
      // вызываем функцию вычисления последнего ордера и преобразовываем результат в 5-ти значное число.
      double hist_price = GetHistoryPrice(_Symbol);
      
      double prc = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      
      double price_bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
      
      double posVolume = PositionGetDouble(POSITION_VOLUME);
      
      // Если меньше этого значения - позиция доливается, если больше - закрывается.
      double posProfClose = 500;
    
      // Подсчитываем профит текущей позиции
      double pos_prof_gl = NormalizeDouble(PositionGetDouble(POSITION_PROFIT), 2);
      
      if(!PositionSelect(_Symbol))
      {
        pos_prof_gl = 0;
      };
      
      Print("ТЕКУЩИЙ ПРОФИТ: ", pos_prof_gl);
      Print("ТЕКУЩИЙ BID: ", price_bid);
      
    
    
    
    if(!PositionSelect(_Symbol) && stm.hour >= 0 && stm.hour <= 23)
    {

      // вызываем функцию, подсчитывающую кол-во лотов для стартовой сделки
      double trade_lot = function_trade_lot(AccountInfoDouble(ACCOUNT_BALANCE));
      
      
      if(SendOrder(prc, trade_lot, pos_prof_gl, price_bid))
       {
         // первоначальная позиция открыта..
         Print("Первоначальное открытие");
         Print("Час: "        +(string)stm.hour);
         Print("Минута: "     +(string)stm.min);
         Print("Секунда: "    +(string)stm.sec);
       }
     
      }
      
      
      
      else if(PositionSelect(_Symbol))
      {
        // доливка существующей позиции.  
      
      //увеличим размер позиции на коэффициент
      double lot = posVolume * COEF;
      
      double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      
      if(ask <= hist_price - DELTA * _Point)
      {
      
      // -------+ вызов функции формирования торгового запроса +--------- 
      if(SendOrder(prc, lot, pos_prof_gl, price_bid))
        {
         Print("Позиция добавлена");
         Print("Час: "        +(string)stm.hour);
         Print("Минута: "     +(string)stm.min);
         Print("Секунда: "    +(string)stm.sec);
        }
       
       }
      }
      
      
      
      
      else if(pos_prof_gl > posProfClose)
      {
      Print("НАДО МОДИФИЦИРОВАТЬ ОРДЕР. Профит равен: ", pos_prof_gl, "-ти" );
      
        // модификация существующей позиции.  
      
      // -------+ вызов функции формирования торгового запроса +--------- 
      if(ModifyOrder(prc, price_bid, posVolume))
        {
         Print("ПОЗИЦИИ МОДИФИКАЦИРОВАНА. Тейк профит равен:", price_bid);
         Print("Час: "        +(string)stm.hour);
         Print("Минута: "     +(string)stm.min);
         Print("Секунда: "    +(string)stm.sec);
        }
       
      else
      {
        Print("Ошибка Модификации!!!");
      }
       
       
       
      }
      
};

//функция формирующая торговый запрос на открытие позиции и проверку результата открытия  -------------------+

bool SendOrder(double price, double volume, double pos_prof, double prc_bid)
{  
   
   if(volume >= 50){
   Print("ОШИБКА! Обьем Ордера привысил размер 50 лотов и сейчас ровняется", volume,"-м");
   return(false);
   };

   MqlTradeRequest request = {0};
   MqlTradeResult  result  = {0};
   //---заполняем поля торгового запроса
   request.action       = TRADE_ACTION_DEAL;        // Тип выполняемого действия
   request.symbol       = _Symbol;                 // Имя торгового инструмента
   request.magic        = magic_number;            // Магический Ордер
   request.volume       = volume;                  // Запрашиваемый объем сделки в лотах
   request.price        = price;                   // Цена  
   request.type         = ORDER_TYPE_BUY;           // Тип ордера
   request.tp           = 0;                        // Цена, по которой сработает Take Profit ордер при движении цены в благоприятном направлении
   request.sl           = 0;                       // Цена, по которой сработает Stop Loss ордер при движении цены в неблагоприятном направлении
   request.deviation    = 0;                       // Максимально приемлемое отклонение от запрашиваемой цены, задаваемое в пунктах
   request.type_filling = ORDER_FILLING_IOC;       // Тип ордера по исполнению
   request.type_time    = ORDER_TIME_DAY;          // Тип  длительности действия ордера               
                  
                  
   //---проверим хватает ли средств для открытия позиции
        double margin = 0.0;
                     
   if (!OrderCalcMargin(request.type, request.symbol, request.volume, request.price, margin))
                        return(false);
                     
   if (margin > AccountInfoDouble(ACCOUNT_FREEMARGIN))
                        return(false);
                  
                     
   //---отправка запроса на сервер и проверка результата отправки
   if (OrderSend(request,result))
       {
         if ( result.retcode == TRADE_RETCODE_DONE)
              {
                 return (true);
              };
            };

                                                  
                     return(false);
   };// функция торгового запроса-------------------------------------------------------------------------------------------------+
      
   
   
   
   
   
 //функция формирующая модификацию торгового запроса и проверки результата -------------------+

bool ModifyOrder(double price, double prc_bid, double posVolume)
{  

   MqlTradeRequest request = {0};
   MqlTradeResult  result  = {0};
   //---заполняем поля торгового запроса
   request.action       = TRADE_ACTION_DEAL;       // Тип выполняемого действия
   request.symbol       = _Symbol;                 // Имя торгового инструмента
   request.magic        = magic_number;            // Магический Ордер
   request.volume       = posVolume;               // Запрашиваемый объем сделки в лотах
   request.price        = prc_bid;                 // Цена  
   request.type         = ORDER_TYPE_SELL;         // Тип ордера
   request.tp           = 0;                       // Цена, по которой сработает Take Profit ордер при движении цены в благоприятном направлении
   request.sl           = 0;                       // Цена, по которой сработает Stop Loss ордер при движении цены в неблагоприятном направлении
   request.deviation    = 0;                       // Максимально приемлемое отклонение от запрашиваемой цены, задаваемое в пунктах
   request.type_filling = ORDER_FILLING_IOC;       // Тип ордера по исполнению
   request.type_time    = ORDER_TIME_DAY;          // Тип  длительности действия ордера 
                  
                  
                     
   //---отправка запроса на сервер и проверка результата отправки
   if (OrderSend(request,result))
       {
        Print ("Запрос отправлен, результат:",result.retcode);

         if ( result.retcode == TRADE_RETCODE_DONE)
              {
                 Print("TRADE_RETCODE_DONE");
                 return (true);
              };
       }
    else
       {
        Print("Ошибка при отправке запроса #", GetLastError());
       };

                                                  
   
   return(false);
   
   };// функция модификации торгового запроса-------------------------------------------------------------------------------------------------+
   
   
   
   
   
   
   

// возвращает цену открытия последнего ордера, где nMode - ORDER_TYPE_BUY/ORDER_TYPE_SELL ----------+
// для позиции с идентификатором PositionID
double FindLastPrice(int nMode)
  {
    int  CntPos;               // количество ордеров в истории
    ulong nTicket;             // тикет выбранного ордера из истории
    ulong OldTicket = 0;       // тикет ордера найденного ранее
    long PosID, PosiID;        // идентификатор позиции, к которой относится выбранный ордер
    //long Magic;              // магический номер
    long Type;                 // тип найденного ордера (Buy или Sell)
    double OrderPrice = 0;     // найденная цена
    // идентификатор позиции
    if((PosiID = PositionGetInteger(POSITION_IDENTIFIER))==0) return(0.0);
    
    // создадим список ордеров и сделок, находящихся в истории
    HistorySelect(0, TimeCurrent());
    
    CntPos = HistoryOrdersTotal(); // количество ордеров в истории
    
    // переберем все ордеры истории и отберем те, что относятся к нашей открытой позиции
    for (int i = 0; i < CntPos; i++)
      {
        nTicket = HistoryOrderGetTicket(i);  // получим тикет очередного ордера
        PosID  = HistoryOrderGetInteger(nTicket, ORDER_POSITION_ID);  // позиция ордера
        Type   = HistoryOrderGetInteger(nTicket, ORDER_TYPE);         // тип ордера
        
        if ((PosID == PosiID) && (Type == nMode)) 
          {
            if (nTicket > OldTicket)  // этот ордер был открыт позже найденного ранее
              {
                OrderPrice = HistoryOrderGetDouble(nTicket, ORDER_PRICE_OPEN); // цена открытия ордера
                OldTicket = nTicket; // запомним тикет
              };
          };
      };
      
    return(OrderPrice);
  };//---------------------------------------------------------------------------+

  
// ---- функция подсчета значения стартового лота. ------------------------------+

       double function_trade_lot(double account_balance ){
       
          double lot = 0.01;
          
          //lot = NormalizeDouble(0.01+MathMax(MathFloor((account_balance-100000)/50000),0)*0.01,2);
          
          //lot = MathMin(lot, SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX));
          
          
    return(lot);
  
  };//---------------------------------------------------------------------------+
В данной версии кода не работает выход из позиции.
(это должно происходить в случае, когда профит равен больше 500-ста.
Желтым цветом отметил части кода которые за это отвечают.)
Вопрос:
Почему это проиcходит(условие не срабатывает) и как это пофиксить?
Vasiliy Smirnov
12313
Vasiliy Smirnov 2014.09.30 21:11  

Пропишите тест.

Print();
Mike Kharkov
846
Mike Kharkov 2014.10.01 08:32  
zfs:

Пропишите тест.

  
А как это делается на примере можите показать?

Например я прописал такие принты:

Print("ТЕКУЩИЙ ПРОФИТ: ", pos_prof_gl);

Print("ТЕКУЩИЙ BID: ", price_bid);

Дальше тестирую в тестере с визуализацией и вижу, что условие уже должно сработать(прибыль больше 500-ста)

но оно не срабатывает.

https://yadi.sk/i/qLhK-DdnbknWf

Какой я должен делать из этого вывод?

Или какой ещё принт можно прописать, что бы что то проверить для себя в данном контексте?

P.S. Интересно что в таком варианте кода:
      else if(pos_prof_gl < posProfClose)
      {
        // доливка существующей позиции.  
      
      //увеличим размер позиции на коэффициент
      double lot = posVolume * COEF;
      
      double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      
      if(ask <= hist_price - DELTA * _Point)
      {
      
      // -------+ вызов функции формирования торгового запроса +--------- 
      if(SendOrder(prc, lot, pos_prof_gl, price_bid))
        {
         Print("Позиция добавлена");
         Print("Час: "        +(string)stm.hour);
         Print("Минута: "     +(string)stm.min);
         Print("Секунда: "    +(string)stm.sec);
        }
       
       }
      }
      
      
      
      
      else if(pos_prof_gl >= posProfClose)
      {
      Print("НАДО МОДИФИЦИРОВАТЬ ОРДЕР. Профит равен: ", pos_prof_gl, "-ти" );
      
        // модификация существующей позиции.  
      
      // -------+ вызов функции формирования торгового запроса +--------- 
      if(ModifyOrder(prc, price_bid, posVolume))
        {
         Print("ПОЗИЦИИ МОДИФИКАЦИРОВАНА. Тейк профит равен:", price_bid);
         Print("Час: "        +(string)stm.hour);
         Print("Минута: "     +(string)stm.min);
         Print("Секунда: "    +(string)stm.sec);
        }
       
      else
      {
        Print("Ошибка Модификации!!!");
      }
       
       
       
      }
все срабатывает нормально. Разница в том что первое условие уже зависит от прибыли а не от времени суток.
Stanislav Korotky
17884
Stanislav Korotky 2014.10.01 14:05  
Слишком много букаф, да и цветовая схема не очень дружественная, но после беглого просмотра вопрос - разве не стоит вызывать PositionSelect сперва, а уже после него всякие PositionGetXXX включая тот, что для профита?
Mike Kharkov
846
Mike Kharkov 2014.10.01 16:55  
marketeer:
Слишком много букаф, да и цветовая схема не очень дружественная, но после беглого просмотра вопрос - разве не стоит вызывать PositionSelect сперва, а уже после него всякие PositionGetXXX включая тот, что для профита?
   та я не профи в этом деле. Написал как то в общем криво косо + с помощью форумов это дело.
   что бы оно хотя бы жило +- )
Vasiliy Smirnov
12313
Vasiliy Smirnov 2014.10.01 19:36  
Mike_Kharkov:
   та я не профи в этом деле. Написал как то в общем криво косо + с помощью форумов это дело.
   что бы оно хотя бы жило +- )
Так надо пройтись еще раз, потестить в тестере. Там и посмотреть, что принты выдают и почему нет закрытия. Т.е. тут всё открыто, все ошибки того плана надо находить учится самому. Лругое дело нюансы и методы реализации, это будут обсуждать, а так всё бессмысленно портянки выкладывать.
Mike Kharkov
846
Mike Kharkov 2014.10.02 08:26  
zfs:
Так надо пройтись еще раз, потестить в тестере. Там и посмотреть, что принты выдают и почему нет закрытия. Т.е. тут всё открыто, все ошибки того плана надо находить учится самому. Лругое дело нюансы и методы реализации, это будут обсуждать, а так всё бессмысленно портянки выкладывать.
   Та я уже ставил эти принты куда угодно.
   Показывает что прибыль есть та которая необходима для срабатывания условия.
   Показатель
posProfClose
  тоже по принтам отображается нормально.
  Как ещё я могу что либо проверить что бы понять что делать дальше в плане поиска ошибок?
Vasiliy Smirnov
12313
Vasiliy Smirnov 2014.10.02 22:03  
Mike_Kharkov:
   Та я уже ставил эти принты куда угодно.
   Показывает что прибыль есть та которая необходима для срабатывания условия.
   Показатель
  тоже по принтам отображается нормально.
  Как ещё я могу что либо проверить что бы понять что делать дальше в плане поиска ошибок?
Проверяйте выполнение всех условий и шагов. А также результаты выполнения операций с получением номера ошибки.
Kirill Burziev
904
Kirill Burziev 2014.10.03 09:51  
Тред не читал, код читать лень, извиняйте уж меня. Опишите русским языком, какова идея робота. Самое первое, что приходит на ум - закрытие позиции, если разница между аккаунт_профитом и балансом больше 500
Mike Kharkov
846
Mike Kharkov 2014.10.03 12:08  
burz:
Тред не читал, код читать лень, извиняйте уж меня. Опишите русским языком, какова идея робота. Самое первое, что приходит на ум - закрытие позиции, если разница между аккаунт_профитом и балансом больше 500
   идея такова:
   Стратегия по мартину.
   Пока, что покупает он только(продает только во время выхода из позы)
   Через каждые delta(переменная) пунктов он докупается.
   закрытие позиции, если прибыль больше, чем 500(значение переменной posProfClose в данном случае)
   В перспективе хочу что бы все это дело на индикаторы ориентировалось.
   (пока не знаю как это в коде оформить правильно.)
  Не пойму почему условие не срабатывает - по принтам вижу что прибыль необходимая есть.
  Чувствую(нутром) что дело все в конструкции else if и её неправильном построении по всей видимости.
  Потому , что при других вариантах условий позиция закрывается так как надо.
Mike Kharkov
846
Mike Kharkov 2014.10.03 13:07  
Mike_Kharkov:
   идея такова:
   Стратегия по мартину.
   Пока, что покупает он только(продает только во время выхода из позы)
   Через каждые delta(переменная) пунктов он докупается.
   закрытие позиции, если прибыль больше, чем 500(значение переменной posProfClose в данном случае)
   В перспективе хочу что бы все это дело на индикаторы ориентировалось.
   (пока не знаю как это в коде оформить правильно.)
  Не пойму почему условие не срабатывает - по принтам вижу что прибыль необходимая есть.
  Чувствую(нутром) что дело все в конструкции else if и её неправильном построении по всей видимости.
  Потому , что при других вариантах условий позиция закрывается так как надо.
   Так - вроде разобрался уже.
  
12
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий