专家顾问 - 杂项问题 - 页 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
           }
        }
     }

如果有什么问题,请让我知道。
再次感谢你,伙计!

 

也许没有人理解我的问题。但我仍然需要好的评论。所以现在我想用图片来澄清我的问题。
问题: 在交易面板对象的前面还有止损、止盈线。我知道这是由上次创建的对象 引起的。但如果你能理解我,请让我知道我怎样才能使交易面板对象在所有其他对象前面没有 "止损和止盈 "线。

混合的物体

我知道我可以使用OBJPROP_BACK,但我不想使用它。 我只需要看到像他们两个一样的线和价格。我希望我可以得到好的评论。


开仓、止损、止盈、价格线 "创建和删除",所有这些都在一个函数中。所以现在我正试图分割它,因为我需要把这个函数放在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时才会被执行。

至少这是你在这里所展示的。

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
谢谢你,伙计!所以你的这个评论真的对我帮助很大!