советник - разные вопросы - страница 24

 

Это уже есть в примере.

При закрытии ордера вы используете булево возвращаемое значение функции OrderClose(), и если функция была успешной, вы можете удалить объекты, связанные с ордером.

                           bool close=OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),3,clrBlue);
                             {
                              if(close==0)
                                {
                                 Alert(" Order Close Error! # "+IntegerToString(OrderTicket()));
                                }
                              if(close==1)
                                {
                                 Alert(" Order: "+IntegerToString(OrderTicket())+" Closed due to TP Profit = "+DoubleToString(OrderProfit(),2));
                                 ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-TP");
                                 ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-SL");
                                }
                             }
 
Marco vd Heijden:

Это уже есть в примере.
Когда вы закрываете ордер, вы используете булево возвращаемое значение функции OrderClose(), и если функция была успешной, вы можете удалить объекты, связанные с ордером.

Я уже знаю это, я уже пробовал. Возможно, я сделал что-то не так. Я попробую еще раз, но прежде хочу спросить, я бы не хотел использовать OrderClose(). (иногда я закрываю ордера вручную).
Вопрос: Итак, могу ли я удалить объекты ордеров после закрытия ордера без OrderClose()?

Заранее спасибо.

 

Возвращаемое значение функции Order Close() решает, было ли действие успешным или нет, поэтому если вы закрываете ордер вручную, вам придется разработать и использовать немного другой механизм.

Вы можете сделать теневую копию списка заказов и сравнить ее с реальным списком, и всякий раз, когда что-то изменится из-за того, что вы закрыли заказ вручную, искать, что изменилось, а затем удалять эти объекты.

Но более простым способом может быть проверка того, что OrderTicket() все еще существует в активном пуле заказов, так что когда он исчезнет, потому что вы закрыли заказ вручную, объекты будут автоматически удалены.

Так что все зависит от того, как вы хотите это настроить.

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


Поскольку создание объектов уже полностью автоматизировано, я предлагаю вам сделать то же самое для удаления объектов, чтобы вам не пришлось беспокоиться об этом в будущем.

Для этого вы можете просто использовать

OrdersHistoryTotal()

И пул истории

MODE_HISTORY

Все просто, сканируется пул истории заказов, и в каждом цикле код будет смотреть, существуют ли объекты, связанные с номером OrderTicket(), и если есть совпадение, объекты автоматически удаляются.

Для этого достаточно добавить еще один цикл, но на этот раз над пулом истории.

См. пример.

//+------------------------------------------------------------------+
//|                                                ObjectsRemove.mq4 |
//|      Copyright 2017, Marco vd Heijden, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, Marco vd Heijden, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

static input int takeprofit=500;// Take Profit
static input int stoploss=500;  // Stop Loss
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create timer
   EventSetTimer(1);

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
   for(int order=OrdersTotal(); order>=0; order--)
     {
      bool selected=OrderSelect(order,SELECT_BY_POS);
        {
         if(selected==1)
           {
            if(Symbol()==OrderSymbol()) // only for current chart symbol
              {
               switch(OrderType())
                 {
                  case OP_BUY: // for buy order
                    {
                     // if objects not found - create them
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,OrderOpenPrice()+takeprofit*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-TP",7,3);
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJ_HLINE,0,0,OrderOpenPrice()-stoploss*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-SL",7,3);
                       }
                     // if objects exist
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
                       {
                        if(Bid>ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")>=0)
                       {
                        if(Ask<ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                    }
                  break;

                  case OP_SELL: // for sell order
                    {
                     // if objects not found - create them
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,OrderOpenPrice()-takeprofit*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-TP",7,3);
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJ_HLINE,0,0,OrderOpenPrice()+stoploss*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-SL",7,3);
                       }
                     // if objects exist
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
                       {
                        if(Ask<ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")>=0)
                       {
                        if(Bid>ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                    }
                  break;
                 }
              }
           }
        }
     }
//+------------------------------------------------------------------+
//--- delete objects when order is closed
   for(int order=OrdersHistoryTotal()-1; order>=0; order--)
     {
      bool selected=OrderSelect(order,SELECT_BY_POS,MODE_HISTORY);
        {
         if(selected==1)
           {
            // if objects are still found - Delete them
            if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
              {
               ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-TP");
              }
            if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")>=0)
              {
               ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-SL");
              }
           }
        }
     }
//+------------------------------------------------------------------+    
  } // end OnTimer() function
//+------------------------------------------------------------------+

Итак, теперь у вас есть полностью автоматизированное добавление виртуальных линий тейк-профита и стоплосса, а также полностью автоматизированное удаление этих линий.

Конечно, этот пример постоянно сканирует пул истории...

Дополнительно вы можете добавить целое число, которое хранит количество ордеров, которое затем сравнивается с OrdersTotal(), и всякий раз, когда что-то меняется, вы запускаете код удаления объекта.

Или вы можете добавить простой счетчик (60), тогда часть кода будет проверять только раз в минуту, нужно ли что-то удалить.

 

Эй, мужик! Это отлично работает! Спасибо большое!

Я только немного изменил. Пока что все работает без проблем.

//--- delete objects when order is closed
   for(int order=OrdersHistoryTotal()-1; order>=0; order--)
     {
      bool selected=OrderSelect(order,SELECT_BY_POS,MODE_HISTORY);
        {
         if(selected==1)
           {
            // if objects are still found - Delete them
            ObjectsDeleteAll( 0, "#" + IntegerToString( OrderTicket() ) ); // for arrows
            ObjectsDeleteAll( 0, _prefix + " #" + IntegerToString( OrderTicket() ) ); // order, sl, tp, price objects
           }
        }
     }

Если что-то не так, пожалуйста, дайте мне знать об этом.
Еще раз большое спасибо!

 

Возможно, никто не понял мой вопрос. Но мне все равно нужен хороший комментарий. Поэтому сейчас я пытаюсь прояснить свой вопрос с помощью изображения.
Вопрос: Также Stop Loss, Take Profit Lines перед объектами торговой панели. Я знаю, что это вызвано последним созданием объекта. Но если вы понимаете меня, пожалуйста, дайте мне знать, как я могу сделать так, чтобы объект торговой панели был перед всеми другими объектами без линий стоп-лосса и тейк-профита.

Смешанные объекты

Я знаю, что могу использовать OBJPROP_BACK, но я не хочу его использовать. Мне просто нужно видеть линию и цену, как у них обоих. Надеюсь, я получу хорошие комментарии по этому поводу.


Open, Stop Loss, Take Profit, ценовые линии "Create и Delete", чтобы все они были в одной функции. Так что сейчас я пытаюсь разделить ее, потому что мне нужно поместить эту функцию в OnChartEvent(). Но прежде мне нужно спросить.
Вопрос: Если я помещу эту функцию в OnChartEvent() - эта функция не сможет воздействовать на мои ручные ордера?

Сейчас я работаю над этим.

Пожалуйста, помогите мне, спасибо заранее.

 

Нет Onchartevent() будет выполнять код только при наличии события графика, это не похоже на функцию OnTImer().

Поэтому вы должны точно знать, что вы делаете.

Например, если вы используете код сканирования :

if(Bid>ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJPROP_PRICE,0))

Чтобы проверить, пересекла ли цена вашу линию, это не будет работать в OnChartEvent().

Также если вы хотите использовать автоматизированный пример

if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
   {
     ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,OrderOpenPrice()-takeprofit*Point());
     ObjectSet("#"+IntegerToString(OrderTicket())+"-TP",7,3);
   }

Это не сработает и не создаст объекты.

Вам придется заново написать код.

Также, вы можете установить для объектов H_LINE значение OBJPROP_BACK, это не проблема, вы все равно увидите их и они будут под вашей панелью.

 

Действительно хороший и полезный комментарий, теперь я точно знаю, что должен попробовать хотя бы один раз, чтобы знать, что я могу сделать дополнительно.

Спасибо за быстрый ответ и полезный комментарий.

 
Marco vd Heijden:

Вам придется заново написать код.

( Я уже внимательно прочитал ваш комментарий, но я просто хотел попробовать один раз - в конце концов, как вы сказали, это не работает как OnTimer(). )

Омг! Должен ли я изменить все в этом коде блока?
Теперь у меня есть четыре функции. Я просто пытаюсь вставить их в OnChartEvent(). Я уже пробовал, я просто вижу одно обновление это просто Print() для цен стоп лосс, тейк профит.
OrderModify() в ней не работает.

Я начну пробовать что-то снова для этого вопроса через 8 - 10 часов.
Мне просто очень нужны хорошие комментарии, надеюсь, я их получу.

Заранее большое спасибо.

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
  {
   if(id==CHARTEVENT_OBJECT_DRAG) // I already tried with take profit object - there was not any effects
     {
      SL_TPcreateobjects();
      SL_TPdrags();
      SL_TPmodify();
      deleteobjs();
     }
  }
// if objects not found - create them
SL_TPcreateobjects()
  {
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) continue;
      if(Symbol()!=OrderSymbol()) continue;

      if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
        {
         ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,takeprofit);
        }
     }
  }
// if objects exist
SL_TPdrags()
  {
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) continue;
      if(Symbol()!=OrderSymbol()) continue;

      if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
        {
         if(TP_Price!=ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
           {
            TP_drag=1;
            TP_Price=ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0);
           }
         if(TP_drag==1)
           {
            if(TP_Price==ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
              {
               Print("Take Profit Price:",DoubleToString(TP_Price,Digits));
               TP_drag=0;
              }
           }
        }
     }
  }
// order closed - delete junks
deleteobjs()
{
  for(int i=OrdersHistoryTotal()-1; i>=0; i--)
    {
     bool Selected=OrderSelect(i,SELECT_BY_POS,MODE_HISTORY);
     if(Selected==1)
       {
        ObjectsDeleteAll(0,"#"+IntegerToString(OrderTicket())+"-TP");
       }
    }
}
// ordermodify()
SL_TPmodify()
{
  Order_Modify=OrderModify(OrderTicket(),OrderOpenPrice(),SL_Price,TP_Price,0,CLR_NONE);
}
//+------------------------------------------------------------------+
 

Эти функции будут выполняться только при возникновении события chartevent.

По крайней мере, это то, что вы показываете здесь.

Чартевент - это просто триггер для процедуры прерывания, когда кто-то нажимает кнопку или что-то еще на графике.

Теперь вы взяли полностью автоматизированный пример и поместили его под кнопку, ничего не произойдет, если никто не нажмет на нее.

 
Marco vd Heijden:

Эти функции будут выполняться только тогда, когда произойдет какое-либо событие.
По крайней мере, это то, что вы здесь показываете.
Chartevent - это просто триггер для процедуры прерывания, когда кто-то нажимает кнопку или что-то еще на графике.
Теперь вы взяли полностью автоматизированный пример и поместили его под кнопку, ничего не произойдет, если никто не нажмет на нее.

Возможно, ваш последний комментарий выглядит так просто, но на самом деле этот комментарий показал мне правильный путь.
Так что теперь я решил свой вопрос, какой из них я пытаюсь использовать.

И теперь я начинаю исследовать некоторые другие графические объекты, перемещающиеся с этим объектом HLine.

Спасибо большое!
Всего вам наилучшего!


honest_knave:

Также подумайте о том, как часто вы перемещаете линию. Раз в секунду? Скорее всего, нет.
Поместите свой код в OnChartEvent():

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
  {
   if(id==CHARTEVENT_OBJECT_DRAG && sparam=="line") // the chart event of dragging the line
Большое спасибо! Ваш комментарий очень помог мне!