Можно ли вытащить значение переменной из условия? - страница 2

 
papaklass:

 Попробуйте нижеприведенный код:

   Здорово. Это примерно именно то к чему я стремился на данном этапе..
   Единственное, что докупаться позиция начинает почему то не через каждые 50 пунктов(+- проскальзывание допустим) а опять(как и в предыдущих версиях кода) через непонятный(пока что) мне алгоритм.? )

  

   P.S. Если на будущее, необходимо будет докупаться по 2,3,4 и т.д. кругу - это надо будет для каждого, отдельно взятого круга создавать свой "If" ?
   (Или это уже совсем другая история и там надо будет, что то более хитроумное изобретать?)
   Что мне сейчас первое в голову приходит так это не умножать лот(0.01) на 2 а умножать его на какой то коэффициент, который должен будет менятся в зависимости от того, cколько уже на данный момент было сделано доливок.
   (или сколько лотов куплено уже к настоящему моменту.)
   + условие для наращивания позиции необходимо будет как то модифицировать(если это возможно.), что бы оно было одно на все случаи жизни и постоянно могло доливаться с разными коэффициентами лотов.
   (я в правильном направлении двигаюсь?)
 
Mike_Kharkov:

   ...   (Пытался просматривать код в одном из советников по мартину, но тот код мне непонятен + написан он однозначно неправильно с точки зрения оформления, как мне кажется.
...

О да! Точно. Зеленый свисток надо заменить синим бурлюкатором.
 
papaklass:

 Код подправил. Разберитесь хорошо с исправленным кодом.

   Вроде бы разобрался с кодом.
   Но есть моменты: )
  

   Позиция по прежнему отказывается докупаться по тем параметрам, которые прописаны в коде. )
   То есть по идее(в данном случае) доливаться должна сделка через каждые 100 пунктов(против себя) + удвоенным лотом.
   Проверка на истории показывает, что позиция не удваивается а утраивается.
   (начиная с момента наращивания объема.)
   + докупка осуществляется не через каждые 100 пунктов а через 50-90 пунктов +-(в зависимости от случая.)
  
   P.S. Ещё хотел выяснить такой момент для себя:

   У вас есть такой кусок кода:

 if (PositionSelect(Symbol()))
         {
            double priceOpen = PositionGetDouble(POSITION_PRICE_OPEN);
            double posTP     = PositionGetDouble(POSITION_TP);
            Print(" Количество открытых позиций: ", PositionsTotal());
            Print(" Цена в сделке, подтверждённая брокером : ", DoubleToString(priceOpen, 5));
            Print(" Тэйк-Профит позиции : ", DoubleToString(posTP, 5));
            Print("                        ");
         }

Мне не совсем понятно, зачем здесь осуществляется проверка "If" ?
Какую цель она преследует?
Почему допустим нельзя прописать тоже самое без проверки? )

И точно так же не до конца ясно, что возвращает вот этот код:
if (!OrderCalcMargin(request.type, request.symbol, request.volume, request.price, margin))
      return(false);
Он возвращает ложь тогда, когда не хватает средств на маржу? (Или в чем состоит суть "ЛЖИ" в данной операции?)
 
papaklass:

По функции OrderCalcMargin() откройте справку и прочтите ее.

Не бойтесь пользоваться справкой, это только убыстрит процесс обучения программированию. 

   Да уже по 10 раз перечитал до этого по поводу этой(и не только этой) функции.
   Написано:
   "Возвращает true в случае успеха, иначе false."
   Вот и все.
   А что такое успех или не успех в данном случае мне не ясно.
   (по этому и задал вопрос что означает "ложь" в данном случае.)
  
   P.S. На счет всего остального постараюсь разобраться.
   (Спасибо за подсказки и написанный код.)
   Просто после последней версии вашего кода я подумал, что позиция должна докупаться по нормальному объему и цене т.к. вы написали что "Подправили код."
   Если бы сказали сразу что он не будет работать идеально - я бы не задавал лишних вопросов в последнем сообщении и попытался бы в первую очередь понять почему это происходит. )
 
papaklass:

После разбора справки, думаю что нижеприведенный код Вам понятен до последнего символа:

   Спасибо за разъяснения. На счет данного примера теперь всё ясно.
   Я только сейчас понял, что в справке помечены [in] или [out] - параметры которые я должен прописать и параметры которые функция должна вернуть.
   Правда вот такое обозначение [in,out] мне не ясно до сих пор.. )
   (возможно, что структура может и принимать и возвращать значения в тех или иных ситуациях..)
 
 
papaklass:

 Вы не разобрались с кодом.

1. Насчет наращивания позиции подсказка: сколько будет 1 + 2 ? Или так 1 + 1*2 ?

2. Отличается ли цена открытия существующей позиции после доливки? Если отличается то почему?

3. Какая цена является отправной для увеличения объема позиции? Где эти данные в коде?

   В общем за сегодня просидел над этим кодом уже часов 7-8 наверное в сумме. )
   Все что пришло на ум(пока что) оказалось не эффективным.
   Не смог понять причины изменения цены докупки(начиная с 3-го круга) и точно также не понял причину изменения объема лота.
   С объемом можно в принципе разобраться при помощи изменения коэффициента. (Изменив число 2 на 1)
   Цену 2-ой докупки можно нормализовать путём высчитывания операций не по биду(как было в коде) а по аску.
   Но, как я уже сказал ранее, после 3-го круга проблема все равно имеет место.
   В итоге у меня получился вот такой код:
   

//+------------------------------------------------------------------+
//|                                                  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 = 100;  //количество пунктов прохода цены для уведичения позиции

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{

  
  /*
  Print(" Тикет сделки:" , result.deal);
  Print(" Ордер: ", result.order);
  Print(" Обьём: " , result.volume);
  Print(" Цена в сделке, подтверждённая брокером: " , result.price);
  Print(" Текущая рыночная цена предложения (цены реквоты): " , result.bid);
  Print(" Текущая рыночная цена спроса (цены реквоты): " , result.ask);
  Print(" Комментарий брокера к операции (по умолчанию заполняется расшифровкой: " , result.comment);
  Print(" Идентификатор запроса, проставляемый терминалом при отсылке на торговый сервер: " , result.request_id);
  */

//---
   
//---
   return(INIT_SUCCEEDED);
}//---------------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}//---------------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{ 
   int positions_total = PositionsTotal();
  
//---блок первоначального окрытия позиции по текущей цене
   if(PositionsTotal() < 1)
   {
      double prc = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
      double lot = 0.01;
      
      // вызов функции формирования торгового запроса
      bool isOpen = SendOrder(prc, lot);
       
      if (isOpen)
      {
         Print("         Первоначальное открытие               ");
   
         if (PositionSelect(Symbol()))
         {
            double priceOpen = PositionGetDouble(POSITION_PRICE_OPEN);
            double posTP     = PositionGetDouble(POSITION_TP);
            Print(" Количество открытых позиций: ", PositionsTotal());
            Print(" Цена в сделке, подтверждённая брокером : ", DoubleToString(priceOpen, 5));
            Print(" Тэйк-Профит позиции : ", DoubleToString(posTP, 5));
            Print("                        ");
         }
      }
      return;
   }
      
//---блок наращивания существующей позиции
   double posPriceOpen  = 0;
   double ask           = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double posVolume     = 0.01;
   
   // узнаем цену открытия и совокупный объем позиции
   if (PositionSelect(Symbol()))
   {
      posPriceOpen = PositionGetDouble(POSITION_PRICE_OPEN);
      posVolume    = PositionGetDouble(POSITION_VOLUME);
   }
   
   // условие для наращивания позиции
   if( ask <= posPriceOpen - DELTA * _Point && PositionsTotal() == 1)
   {
      double prc = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
      //увеличим размер позиции на коэффициент
      double lot = posVolume * COEF;
      
      // вызов функции формирования торгового запроса
      bool isOpen = SendOrder(prc, lot);
       
      if (isOpen)
      {
         Print("          Увеличение объема позиции              ");
         
         if (PositionSelect(Symbol()))
         {
            posPriceOpen = PositionGetDouble(POSITION_PRICE_OPEN);
            posVolume    = PositionGetDouble(POSITION_VOLUME);
            double posTP = PositionGetDouble(POSITION_TP);
            Print(" Количество открытых позиций_2: ", PositionsTotal());
            Print(" Оъем открытой позиции : ", DoubleToString(posVolume, 2));
            Print(" Цена в сделке, подтверждённая брокером : ", DoubleToString(posPriceOpen, 5));
            Print(" Тэйк-Профит позиции : ", DoubleToString(posTP, 5));
            Print("                        ");
         }
      }
      return;
   }
//---
   
}//---------------------------------------------------------------------------+

//функция формирующая торговый запрос на открытие позиции
//и проверки результата открытия
bool SendOrder(double price, double volume)
{
   MqlTradeRequest request = {0};
   MqlTradeResult  result  = {0};
  
//---заполняем поля торгового запроса
   request.action       = TRADE_ACTION_DEAL;    // Тип выполняемого действия
   request.symbol       = _Symbol;              // Имя торгового инструмента
   request.volume       = volume;               // Запрашиваемый объем сделки в лотах
   request.price        = price;                // Цена  
   request.type         = ORDER_TYPE_BUY;       // Тип ордера
   request.tp           = price + 100*_Point;    // Цена, по которой сработает Take Profit ордер при движении цены в благоприятном направлении
   request.sl           = 0;                    // Цена, по которой сработает Stop Loss ордер при движении цены в неблагоприятном направлении
   request.type_filling = ORDER_FILLING_FOK;    // Тип ордера по исполнению
   request.type_time    = ORDER_TIME_GTC;
   
//---проверим хватает ли средств для открытия позиции
   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))
      return(true);
   else
      Print(__FUNCTION__,"   При выставлении ордера произошла ошибка. Error = ",GetLastError());
                                    
   return(false);
}//---------------------------------------------------------------------------+


И вот такие результаты(в плане цен и объемов) на истории:



     То есть мне не понятно(и пока идеи даже нет) почему цена именно после 3-го круга
     (а не после 2-го допустим, когда начинается блок наращивания существующей позиции)
     становится с дельтой в 2 раза меньшей, чем у предыдущих 2-х цен.
     Задать какой то параметр(или функцию) высчитывания цены докупки именно из текущей цены(при помощи PositionGetDouble(POSITION_PRICE_CURRENT) к примеру)
     тоже оказалось невозможным.(хотя это и логично конечно.)
     P.S. Вот такие вот дела пока что. )
     Возможно завтра ещё что то(какая то идея) на ум придёт - но пока, в любом случае, мои варианты исчерпаны..
  
 
Mike_Kharkov:

 
      То есть мне не понятно(и пока идеи даже нет) почему цена именно после 3-го круга

     (а не после 2-го допустим, когда начинается блок наращивания существующей позиции)
     становится с дельтой в 2 раза меньшей, чем у предыдущих 2-х цен.
Вы используете PositionPriceOpen. Это усредненная цена всех сделок (т.е. имеющейся позиции), а не цена последней сделки. Читайте про неттинг, ордера, позиции, сделки. То же самое с объемами.
 
Wahoo:
Вы используете PositionPriceOpen. Это усредненная цена всех сделок (т.е. имеющейся позиции), а не цена последней сделки.
    Это я понимаю - но почему следующие сделки докупаются не по цене, которая ниже 100 пунктов от предыдущей усреднённой, а по цене, которая ниже на 50 пунктов?
    P.S. Мне например и надо, что бы позиция докупалась через каждые 100 пунктов(в данном случае) именно по усреднённой цене.
    (а не по цене последней сделки.)
    Или вы хотите сказать, что в данном случае всё именно так и проиcходит?

    P.S. Щас ещё раз внимательно посчитал и понял что действительно это все дело докупается именно по средней цене.
    (просто в графе именно средняя цена нигде не указывается и нужно считать самому..)
 
Wahoo:
Это усредненная цена всех сделок (т.е. имеющейся позиции), а не цена последней сделки. Читайте про неттинг, ордера, позиции, сделки. То же самое с объемами.
   Насчет последней сделки.
   Вчера и сегодня пытался использовать ссылку которая есть в вышеизложенном сообщении.
   И попробовал сделать вот такой вариант:
  
//---блок наращивания существующей позиции
   double posPriceOpen  = 0;
   double ask           = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double posVolume     = 0.01;
   
   // узнаем цену открытия и совокупный объем позиции
   if (PositionSelect(Symbol()))
   {
      posPriceOpen = SymbolInfoDouble(_Symbol, SYMBOL_LAST);
      posVolume    = PositionGetDouble(POSITION_VOLUME);
   }
   
   // условие для наращивания позиции
   if( ask <= posPriceOpen - DELTA * _Point && PositionsTotal() == 1)
   {
      double prc = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
      //увеличим размер позиции на коэффициент
      double lot = posVolume * COEF;
      
      // вызов функции формирования торгового запроса
      bool isOpen = SendOrder(prc, lot);
       
      if (isOpen)
      {
         Print("          Увеличение объема позиции              ");
         
         if (PositionSelect(Symbol()))
         {
            posPriceOpen = SymbolInfoDouble(_Symbol, SYMBOL_LAST);
            posVolume    = PositionGetDouble(POSITION_VOLUME);
            double posTP = PositionGetDouble(POSITION_TP);
            Print(" Количество открытых позиций_2: ", PositionsTotal());
            Print(" Оъем открытой позиции : ", DoubleToString(posVolume, 2));
            Print(" Цена в сделке, подтверждённая брокером : ", DoubleToString(posPriceOpen, 5));
            Print(" Тэйк-Профит позиции : ", DoubleToString(posTP, 5));
            Print("                        ");
         }
      }
      return;
   }
//---
То есть этим кодом я хотел докупаться отталкиваясь от цены последней докупки.
Но позиция в этом варианте вообще перестала докупаться.

Хотя в принте

Print(" Цена в сделке, подтверждённая брокером : ", DoubleToString(posPriceOpen, 5));
в журнале такая цена существует.
Почему же тогда условие на неё не ориентируется и позиция не докупается соответственно?

P.S. На счет журнала - я в принципе постоянно так и делаю.
Пользуюсь принтами и смотрю как это выводится потом..
 
Mike_Kharkov:

   То есть этим кодом я хотел докупаться отталкиваясь от цены последней сделки.

https://www.mql5.com/ru/docs/trading/historydealselect
Документация по MQL5: Торговые функции / HistoryDealSelect
Документация по MQL5: Торговые функции / HistoryDealSelect
  • www.mql5.com
Торговые функции / HistoryDealSelect - справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
Причина обращения: