贸易交易时 - 页 8

 
Igor Zakharov:

在 "正常 "机器人上,也就是我所描述的情况,我完全没有注意到;但在一个案例中,我被要求做一个安全系统:条件是头寸总是被锁定(要么是真实头寸,要么是挂单),也就是说,买入手数等于卖出手数。就是这个案例让我认识到了五角大楼中订单/位置/交易计数的细微差别。

我对自己的解释是:区别在于,四号机在得到经纪人的答复时,首先将其 "表 "与未结订单和历史记录同步,然后通知用户经纪人的答复。 五号机立即将这个答复广播给我们,同时纠正其 "表"(所有mql程序从这些 "表 "中读取数据)。这就是我们在毫秒计时器上捕捉到的时刻。但是,为什么我们不在测试器中抓住它呢?

总的来说,我已经使我的心态平和了...

不,事情更糟糕。

订单在从挂单(或市场)转变为历史订单(执行或取消)的时刻,会从终端完全消失一段时间。它既没有出现在待定(或 "开始 "的市场)中,也没有出现在历史上的市场中。

所以这不是一个执行的问题,而是这两个表的同步问题。服务器的回答是("订单已执行,产生了某某交易"),它被从一个表中删除,但它没有被输入到另一个表中。

 
Andrey Khatimlianskii:

不,事情更糟糕。

当一个订单从挂单(或市场)变为历史订单(已执行或已取消)时,它将从终端完全消失一段时间。它既没有出现在待定(或 "开始 "的市场)中,也没有出现在历史上的市场中。

所以这不是一个执行的问题,而是这两个表的同步问题。答案来自服务器("订单已执行,触发了某某交易"),它被从一个表中删除,但没有进入另一个表中。

检查一下很有意思。伊戈尔-马卡努 的任务让我很感兴趣,https://www.mql5.com/ru/forum/6343/page1097#comment_12518742

我在膝盖上做了第一个近似值。然后我将对OnOrder和OnOrderTransaction的操作和交易环境状态 进行一些统计, 如果我不太懒的话,我可能会把它放在模拟测试中,看看不同账户/经纪商的情况如何。

那么就有可能进行分析。到目前为止的假设:1.没有检查部分执行,也没有检查账户的特殊性;我发送了一个市场订单,打开的头寸被记住了,我等待这个头寸的平仓出现在日志中,并在相反的方向再次打开。2.理想情况下,某个交易应该在OnOrderTransaction中被捕获,但到目前为止,我是这样做的--在这两个事件中,我以同样的方式检查一切。

当然,该代码不是最佳的。我已经可以看到,如果一切都像上面的帖子中描述的那样糟糕,那么订单位置将会丢失。

//+------------------------------------------------------------------+
//|                                                 Test_Makalu2.mq5 |
//|                                           Copyright 2019, Allex@ |
//|                                                 alex-all@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, Allex@"
#property link      "alex-all@mail.ru"
#property version   "1.00"
#include <Expert\Expert.mqh>
//--- input parameters
input int      TP=200;
input int      SL=200;
input double   Lot=0.01;
input string   File;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CExpertTest : public CExpert
  {
public:
   int               type;
   ulong             order;
   ulong             deal;
   ulong             position;
   bool              send;
   bool              placed;
   bool              opened;
   bool              history;
   datetime          last_history;

                     CExpertTest() {order=0;};
                    ~CExpertTest() {};
   bool              Buy(double volume,double price,double sl,double tp,const string comment="") {return m_trade.Buy(volume, price, sl, tp,  comment);};
   bool              Sell(double volume,double price,double sl,double tp,const string comment="") {return m_trade.Sell(volume, price, sl, tp,  comment);};
   bool              CheckOrder(ulong order)
     {
      ulong state;
      if(OrderSelect(order))
        {
         if(OrderGetInteger(ORDER_STATE)==ORDER_STATE_FILLED)
            position=OrderGetInteger(ORDER_POSITION_ID);
        }
      else
         if(HistoryOrderSelect(order))
           {
            if(HistoryOrderGetInteger(order,ORDER_STATE,state)&& state==ORDER_STATE_FILLED)
               position=HistoryOrderGetInteger(order,ORDER_POSITION_ID);
           }
         else
           {
            return false;
           }
      return true;

     }
   virtual bool      Processing(void)
     {
      double price;
      if(order==0)
        {
         last_history=TimeCurrent();
         price=m_symbol.Ask();
         if(Buy(Lot,price,m_symbol.NormalizePrice(price-SL*m_symbol.Point()),m_symbol.NormalizePrice(price+TP*m_symbol.Point())))
            if(m_trade.ResultRetcode()==TRADE_RETCODE_DONE)
              {
               //ulong deal2;
               deal=m_trade.ResultDeal();
               order=m_trade.ResultOrder();
               if(order!=0 && CheckOrder(order))
                  return true;
              }
        }
      return false;
     }
   void              OnTrade()
     {
      if(order==0 || !CheckOrder(order))
         return;
      HistorySelect(last_history,TimeCurrent());
      for(int i=HistoryDealsTotal()-1; i>=0; i--)
        {
         ulong ticket=HistoryDealGetTicket(i);
         ulong ordticket=HistoryDealGetInteger(ticket,DEAL_ORDER);
         ulong pos=HistoryDealGetInteger(ticket,DEAL_POSITION_ID);
         if(pos==position || ordticket==order || ticket==deal)
           {
            int entry=HistoryDealGetInteger(ticket,DEAL_ENTRY);
            ulong type=HistoryDealGetInteger(ticket,DEAL_TYPE);
            if(pos==position && entry==DEAL_ENTRY_OUT)
              {
               Refresh();
               double price;
               double sl;
               double tp;
               bool result=false;
               datetime dt=TimeCurrent();
               if(type==DEAL_TYPE_SELL)
                 {
                  price=m_symbol.Bid();
                  sl=m_symbol.NormalizePrice(price+SL*m_symbol.Point());
                  tp=m_symbol.NormalizePrice(price-TP*m_symbol.Point());
                  result=Sell(Lot,price,sl,tp);
                 }
               if(type==DEAL_TYPE_BUY)
                 {
                  price=m_symbol.Ask();
                  sl=m_symbol.NormalizePrice(price-SL*m_symbol.Point());
                  tp=m_symbol.NormalizePrice(price+TP*m_symbol.Point());
                  result=Buy(Lot,price,sl,tp);
                 }
               if(result && m_trade.ResultRetcode()==TRADE_RETCODE_DONE)
                 {
                  deal=m_trade.ResultDeal();
                  order=m_trade.ResultOrder();
                  if(order!=0 && CheckOrder(order))
                     last_history=dt;
                 }
              }
           }
        }
     }
  };
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
CExpertTest Expert;
//---
int OnInit()
  {
   if(!Expert.Init(Symbol(),Period(),Point()))
      return INIT_FAILED;
   Expert.OnTradeProcess(true);
   return(INIT_SUCCEEDED);
  }
//---
void OnTick()
  {
   Expert.OnTick();
  }
//+------------------------------------------------------------------+
void OnTrade()
  {
   Expert.OnTrade();
  }
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
  {
   Expert.OnTrade();
  }
Вопросы от начинающих MQL5 MT5 MetaTrader 5
Вопросы от начинающих MQL5 MT5 MetaTrader 5
  • 2019.07.21
  • www.mql5.com
Подскажите пожалуйста, такой показатель тестера в жизни реален? И хороший это или плохой результат за год с депо 3000...
 
Aleksey Mavrin:

这是有趣的检查。伊戈尔-马卡努 让我感兴趣的任务是https://www.mql5.com/ru/forum/6343/page1097#comment_12518742

在讨论中,有一个解决方案https://www.mql5.com/ru/forum/6343/page1098#comment_12519819 ,但部分讨论内容已被删除((()
 
在MT4Orders主题中,有一个解决方案。但你必须亲自感受每一个耙子;)
 
Aleksey Mavrin:

在膝盖上做了一个初步的近似。

这个演示是比较好看的。ForexTimeFXTM-Demo01

 
Igor Zakharov:

我完全没有注意到我在 "正常 "交易机器人上描述的情况。

任何交易库都可以而且应该使用各种模拟账户的压力测试来检查其可靠性。它应该能顺利通过一切。

那么,为了实现这一目标,作者必须亲自熟悉MT5-笑话。在我的实践中,事实证明,即使这样也是不够的。

有一些非常具体的东西,没有被可怕的向交易服务器发送的订单检测出来。由于反馈,我们有可能发现相当奇怪的行为,甚至连开发人员自己似乎都没有意识到。

 
Igor Makanu:
在讨论中,有一个解决方案https://www.mql5.com/ru/forum/6343/page1098#comment_12519819 ,部分讨论已被删除(()
安德烈-哈蒂姆连斯基
在MT4Orders的分支里有一个解决方案。但你必须亲自感受每一个耙子;)

没错,耙子总是很有趣,然后看看专业人士是怎么做的。fxsaber 的解决方案简洁明了,但我发现该解决方案有一个缺陷--手册中说仓单完全是所开订单的仓单,但不是所有的。

在我的解决方案中,我是以此为出发点的。

fxsaber
fxsaber
  • www.mql5.com
Опубликовал пост "Out-Of-Sample" - где расположить, справа или слева? Когда-то в паблике столкнулся с мнением, что OOS должен располагаться только справа. Т.е. расположение его слева от интервала Оптимизации - ошибка. Я с этим был категорически не согласен, т.к. не видел разницы. Теперь вижу. Ошибался, был не прав... Опубликовал пост...
 
fxsaber:

任何交易库都可以而且应该通过各种模拟账户的压力测试来检查其可靠性。它应该能顺利通过一切。

我在测试中使用了200毫秒,当我把它送回去时,那人把它设置为5毫秒。 在5毫秒时,它几乎每次都能在任何账户上工作。

我不知道这是否重要,但他们使用了winapi的timeBeginPeriod(1),也就是说,低于标准的20ms,一切都发生了。

 
Aleksey Mavrin:

仓单总体上是开仓单,但并非总是如此。

我记得不是很清楚,但似乎总是这样。

 
fxsaber:

我记得不是很清楚,但我认为它一直都在那里。

是的,你是对的,因为在这种情况下,它是一个位置标识符,在整个生命过程中是不变的。我把它与仓位代码混淆了,它在翻转和净值期间会发生变化。

但我不明白,当一个头寸被部分平仓时,票据不会变成影响该头寸的最后一笔订单的票据?

我将审查我的代码,谢谢。我参观了这个论坛,并非一无所获)

关于不在当前或历史订单列表中的 "丢失的订单":在我看来,这不是一个错误,我只是需要仔细研究一下以下功能

我认为这不是一个错误,只是需要仔细研究终端服务器MT-市场的特殊性(在即时执行的情况下,市场不工作)。我想是的,看--终端发送一个市场订单,在同步功能的情况下--它等待并从服务器得到一个回复。

如果没有错误,回复可能只是TRADE_RETCODE_DONE(在即时执行的情况下,它是重新报价,但到目前为止是市场类型),这基本上意味着服务器已经将订单发送到市场,它

它实际上意味着服务器已经发送了订单并等待其回复。如果我没有弄错的话,此刻订单的状态是ORDER_STATE_STARTED,而且它的票据是已知的。如果订单被执行,服务器向终端发送OnTradeTransaction,订单状态变为ORDER_STATE_FILLED,交易被知晓。

和位置变得已知。只有在这个时候,终端才会将该订单记录到历史记录中。它不会事先这样做,因为我们不确定它发生了什么,而且它已经给出了来自服务器的最初答复。

这是直到订单在ECN网络或其他地方执行的时间,他们不在两个列表中的任何一个。也就是说,在市场订单的情况下,它只出现在历史上(我不确定即时执行期间的重新报价情况)。

它将永远不会出现在开放的列表中。当挂单触发时,它被从未结订单列表中删除,因为它已经成为一个市场订单,我们等待市场服务器的回应,然后它被发送到历史。

我说的对吗?