实时的提基 - 页 22

 
Andrey Khatimlianskii:

看一下日志的时间。这一切都发生在一个毫秒中,而在它旁边(在同一个毫秒中)有一堆的安书。

你可以通过计数器来计算所有的事件,但即使在视觉上你也可以看到有更多的OnBooks。

安德鲁,那里的数字是固定的微秒数,当OnFunctions被触发时,所有的数字都被打印在一起,然后从数组中。也许总共有更多的OnBooks--我将计算它们,但不清楚为什么它们在队列中比OnTicks跳得早。或者不是每个OnTick都对应着一个OnBook?
 
prostotrader:


你不是写了你使用异步订单吗?
我想知道,你用什么算法来控制交易的执行?

 
Aleksey Mavrin:
安德鲁,那里的数字是触发OnFunctions时的固定微秒数,然后从数组中把所有东西都打印出来。OnBooks的总数可能更多--我会计算,但不清楚为什么它们会在队列中跳到OnTicks之前,或者是什么。或者不是每个OnTick都对应着一个OnBook?

欢迎来到网络世界 ))))

最简单的做法是在管理员下运行Netstat - a -b

你会看到端口和软件,我不想打扰,但我认为MT5服务器会异步传递带有不同信息的数据包,终端会将其放入需要的 "货架"。

SZZY: 关于Print(),如果你一次打印很多,就跳过打印,你知道吗?- 只要把你的信息写在文件里就可以了--这样你就能按顺序保存所有的信息,但在关闭文件之前不要忘记关闭文件。理论上说和Print()文件中的日志应该是完整的,但没有检查过,一般来说我不相信如果有大量的数据输出。在这里讨论https://www.mql5.com/ru/forum/329730 ,经常讨论 "缺失的印刷品"))- 搜索

 
Aleksey Mavrin:
安德鲁,当OnFunctions被触发时,这些数字是固定的微秒数,然后从数组中全部打印出来。也许总共有更多的OnBooks--我将计算它们,但不清楚为什么它们在队列中比OnTicks跳得早。或者不是每个OnTick都对应着一个OnBook?

明白了。

嗯,反正周围有很多OnBooks。对于这样的日志,很难得出任何结论。

 
Roman:

我以为你写的是你在使用异步订单?
我想知道,你用什么算法来控制交易执行?

OnTradeTransaction()+检查功能中,如果长时间没有服务器响应。

一般来说是靠魔术。

在设置EA时,我为每个符号保留65535个魔法符号。

而在发送订单时,我给它分配了一个独特的神奇数字,它不会以任何方式与其他符号相交。

这与其他文书没有任何重叠之处。

我是这样为一个符号设置初始魔法数字的

//+------------------------------------------------------------------+
//|                                                    AutoMagic.mqh |
//|                                 Copyright 2017-2018 prostotrader |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
//version   "1.01
ulong symb_magic;
//-------------------------------------------------------------------+
// Split string function                                             |
//+------------------------------------------------------------------+
string SplitString(const string a_str,ulong &a_month,ulong &a_year)
  {
   int str_size=StringLen(a_str);
   int str_tire=StringFind(a_str, "-");
   int str_tochka=StringFind(a_str, ".", str_tire);
   if((str_tire>0) && (str_tochka>0) &&(str_size > 0))
     {
      a_month= ulong(StringToInteger(StringSubstr(a_str,str_tire+1,str_tochka-str_tire-1)));
      a_year = ulong(StringToInteger(StringSubstr(a_str,str_tochka+1,str_size-str_tochka-1)));
      if((a_month > 0) && (a_year > 0)) return(StringSubstr(a_str, 0, str_tire));
     }
   return("");
  }
//-------------------------------------------------------------------+
// Get Magic function                                                |
//+------------------------------------------------------------------+
ulong GetMagic(const string a_symbol)
{
  symb_magic = 0;
  if(SymbolSelect(Symbol(), true) == false)
  {
    Print(__FUNCTION__, ": Нет такого символа!");
    return(0);
  }
  ulong month = 0;
  ulong year = 0;
  string new_str = SplitString(a_symbol,month,year);
  if(StringLen(new_str)>0)
  {
    uchar char_array[];
    int result=StringToCharArray(new_str,char_array,0,WHOLE_ARRAY,CP_ACP);
    if(result>0)
   {
     ulong value;
     for(int i = 0; i < result - 1; i++)
     {
       value=ulong(char_array[i]);
       value<<=(56 -(i*8));
       symb_magic += value;
     }
     month<<=24;
     symb_magic += month;
     year<<=16;
     symb_magic += year;
     return(symb_magic);
   }
 }
  return(0); 
}
//-------------------------------------------------------------------+
// Is my magic function                                              |
//+------------------------------------------------------------------+
bool IsMyMagic(const ulong m_magic)
{
  if(m_magic > 0)
  {
    ulong stored_magic=symb_magic;
    stored_magic>>=16;
    ulong in_magic = m_magic;
    in_magic>>=16;
    if(in_magic == stored_magic) return(true);
  }  
  return(false);
}
//-------------------------------------------------------------------+
// Get stored magic function                                         |
//+------------------------------------------------------------------+
ulong GetStoredMagic()
{
  if(symb_magic > 0) return(symb_magic);
  return(0);  
}
//+------------------------------------------------------------------+

魔术 - ulong(8字节),例如:

GAZR-3.12

字节[7](高字节)为 "G"

字节[6]是 "A"

字节[5]为 "Z"。

字节[4]是 "R

字节[3]是 "3

字节[2]是 "12"

Byte[1]和Byte[0]是Magiks储备(65535)。

在发送订单时,我就是这样通过魔法的。

  mem_magic = magic_storage + 1;
  if(magic_storage >= (magic_number + 65530)) mem_magic = magic_number;

但这只适用于FORTS,因为符号名称是标准化的!

添加

如果订单被成功发送,那么

记忆中的时间

  if(OrderSendAsync(request, result) == true)
  {
    if((result.retcode == TRADE_RETCODE_PLACED) || (result.retcode == TRADE_RETCODE_DONE)) 
    {
      req_id = result.request_id;
      magic_storage = mem_magic;
      state = ORD_DO_SET;
      mem_time = GetMicrosecondCount();
      mem_start_time = TimeCurrent();
      SetTransCount();
    }
    else
    {
      mem_magic = 0;
      mem_time = 0;
      mem_start_time = 0;
      CheckError(result.retcode, "Place: Ордер не установлен! Причина: ", order_status, ticket);
    }
  }
mem_time = GetMicrosecondCount(); - для проверки времени задержки OnTradeTransaction
mem_start_time = TimeCurrent();   - для сужения рамок поиска в истории

然后(如果在OnTradeTransaction中没有回应的话)

ticket = FindOrderBuyMagic(mem_magic, start_time);

然后是FindOrderBuyMagic 函数本身

#define  TIME_DELAY    180
//+------------------------------------------------------------------+
// Expert Find order Buy Magic function                              |
//+------------------------------------------------------------------+
ulong FindOrderBuyMagic(const ulong a_magic, const datetime set_time)
{
  if(a_magic > 0)
  {
    if(IsMyMagic(a_magic) == true)
    {
      ulong cur_ticket = 0;
      for(int i = OrdersTotal() - 1; i >= 0; i--)
      {
        cur_ticket = OrderGetTicket(i);
        if(OrderSelect(cur_ticket))
        {
          if( ulong(OrderGetInteger(ORDER_MAGIC)) == a_magic) return(cur_ticket);
        }  
     }
      cur_ticket = 0;
      datetime start_time = datetime(ulong(set_time) - TIME_DELAY);
      datetime end_time = datetime(ulong(TimeCurrent()) + TIME_DELAY);    
      if(HistorySelect(start_time, end_time))
      {
        for(int i = HistoryOrdersTotal() - 1; i >= 0; i--)
        {
          cur_ticket = HistoryOrderGetTicket(i);
          if(ulong(HistoryOrderGetInteger(cur_ticket, ORDER_MAGIC)) == a_magic) return(cur_ticket);
        }
      }
    }
  }
  return(0);
}

由以下人员添加

将EA标识符(0-255)添加到automagic的第1个字节的 "好主意"。

但我还不需要它,所以我还没有做 :)

Документация по MQL5: Основы языка / Функции / Функции обработки событий
Документация по MQL5: Основы языка / Функции / Функции обработки событий
  • www.mql5.com
В языке MQL5 предусмотрена обработка некоторых предопределенных событий. Функции для обработки этих событий должны быть определены в программе MQL5: имя функции, тип возвращаемого значения, состав параметров (если они есть) и их типы должны строго соответствовать описанию функции-обработчика события. Именно по типу возвращаемого значения и по...
 
prostotrader:

OnTradeTransaction()+检查功能中,如果长时间没有服务器响应。

谢谢你的提示。

 
prostotrader:

1.经纪人的第二个及以后的终端是现收现付,我没有只交易股票(股票组合)的策略。

2.如果你要输出累积的GetMicrosecondCount(),那么

在OnDeinit()中不使用定时器,当EA退出时,一切都会打印出来。

请把经纪人的链接发给我,在LC中是可以的。

这是一个有趣的分支...:-)

 
Igor Makanu:

欢迎来到网络世界 ))))

最简单的做法是在管理员下运行Netstat - a -b

你会看到端口和软件,我不想打扰,但我认为MT5服务器会异步传递带有不同信息的数据包,终端会将其放入需要的 "货架"。

HH:你知道Print()和跳过打印的问题吗,如果你一次输出很多的话?- 只要把你的信息写在文件里就可以了--这样你就能按顺序保存所有的信息,但在关闭文件之前不要忘记关闭文件。理论上说和Print()文件中的日志应该是完整的,但没有检查过,一般来说我不相信如果有大量的数据输出。在这里讨论https://www.mql5.com/ru/forum/329730 ,经常讨论 "缺失的印刷品"))- 搜索

伊戈尔,那些没有打开过日志文件的人讨论过打印件丢失的问题,一百次了,里纳特-法特库林自己写道,日志文件中没有任何丢失。但你的帖子没有白发:)我在一个单独的文件中增加了输出,此外我还做了第二个文件,在那里我的输出方式有点不同(收集CArrayObj中的所有事件),以绕过我的设计中可能存在的错误,这两个数组的顺序,即我把两个数组中的所有东西放在CArrayObj中,然后按微秒排序,输出时标记什么事件Tick或Book。

是的,这与港口有什么关系,这与它有什么关系?我只是在测试EA的事件队列。如果有嘀嗒声,应该形成两个事件--OnTick,和相应的OnBook,OnBook总是放在队列中,如果队列中已经有OnTick,OnTick就会消失(如手册中),即。当一个接一个的OnTick没有OnTick的时候,只有当1.OnTicks "不排队 "2.OnBook有系统延迟 的时候,这是我想检查的,这可以解释之前同事们发现的几秒钟的滞后。总的来说,OnBooks在一天内是2倍以上,但为什么会滞后呢? 如果这种延迟是由于异步数据包和解析造成的,也许是,但到目前为止,我只检查它们到达专家顾问的事实。如何在测试时考虑到其余的细微差别,还没有考虑到这个问题。

这里是新的代码,打开后我将测试工作的正确性并运行一天。

s.w.原因也可能是:如果Tick以同样的价格通过,而不改变杯子--OnBook没有形成? 我不是股票交易的专家,谁能告诉我。我以为OnTick总是导致OnBook

//+------------------------------------------------------------------+
//|                                                   TestOnBook.mq5 |
//|                                           Copyright 2019, Allex@ |
//|                                                 alex-all@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, Allex@"
#property link      "alex-all@mail.ru"
#property version   "1.00"
#include <Allex\Logger.mqh>
#include <Arrays\ArrayObj.mqh>
//---
bool is_book;
enum ENUM_BOOK_OR_TICK
{
        USE_BOOK,       // Use OnBookEvent
        USE_TICK        // Use OnTick
};
class CMcsOn: public CObject
{
public:
ulong mcs;
ENUM_BOOK_OR_TICK Ontype;
CMcsOn(ulong m, ENUM_BOOK_OR_TICK t):mcs(m),Ontype(t){};
int       Compare(const CObject*Object,const int mode=0) const
     {
      const CMcsOn* obj1=dynamic_cast<const CMcsOn*>(Object);
      CMcsOn* obj=(CMcsOn*)(obj1);
      if(!obj)return 0;
      return (mcs-obj.mcs);
      }
};
input ENUM_BOOK_OR_TICK Mode = USE_BOOK;
input int   SecForPrint =  3600;
//---
ulong TimeArrayBook[65536];
ulong TimeArrayTick[65536];
ushort curBook,curTick;
ulong  DelaySum=0,DelayCount=0,CountOnBook=0,CountOnTick=0;
int delay,delayMax=0;
CLogger* Logger,*Logger2;
CArrayObj ArrayObj;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   curBook=0;
   curTick=0; 
   DelaySum=0;DelayCount=0;CountOnBook=0;CountOnTick=0;delayMax=0;
   ArrayInitialize(TimeArrayBook,INT_MAX);
   ArrayInitialize(TimeArrayTick,INT_MAX);
   Logger=CLogger::GetLogger();
   Logger2= new CLogger();
   Logger.SetSetting(__FILE__+"\\",Symbol()+"_"+EnumToString(Period())+"_"+TimeToString(TimeCurrent(),TIME_DATE));  
   Logger2.SetSetting(__FILE__+"\\","Alt_"+Symbol()+"_"+EnumToString(Period())+"_"+TimeToString(TimeCurrent(),TIME_DATE));  
  if(Mode == USE_BOOK) is_book = MarketBookAdd(Symbol());
  ArrayObj.Shutdown();
  if (EventSetTimer(SecForPrint) &&  Logger.Init() && Logger2.Init()) 
  return(INIT_SUCCEEDED);
  else return (INIT_FAILED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
  if(Mode == USE_BOOK)
  {
    if(is_book == true) MarketBookRelease(Symbol());
  }  
   delete Logger;
   delete Logger2;
}
//+------------------------------------------------------------------+
//| BookEvent function                                               |
//+------------------------------------------------------------------+
void OnBookEvent(const string &symbol)
{  
  TimeArrayBook[curBook++]=GetMicrosecondCount();
  CountOnBook++;
  //Print(__FUNCTION__, " ",curBook);
}
void OnTick()
{
  TimeArrayTick[curTick++]=GetMicrosecondCount();
  CountOnTick++;
  //Print(__FUNCTION__, " ",curTick);

}
//+------------------------------------------------------------------+
void OnTimer()
  {
   string out=NULL;
   int total=MathMax(curBook,curTick);
   int i=0,k=0;
   while(i<total)
     {
      while(i<total && TimeArrayBook[i]<TimeArrayTick[k] )
        {
          MyPrint("Book "+TimeArrayBook[i++]);
        }    
      if(k<curTick-1)
        {
        if(i<total)
          {
           delay=TimeArrayBook[i]-TimeArrayTick[k];
           if (delay>delayMax) 
            delayMax=delay;
           if (delay>0)
              {
                 DelaySum+=delay;
                 DelayCount++;
              }
          }
         MyPrint("Tick "+TimeArrayTick[k++]+ " delay mcs "+delay);
        }       
        i++;
     }
     if (curTick>0)
     {
     MyPrint("Tick "+TimeArrayTick[curTick-1]+ " last");
     string out="Count Event Book after Tick "+DelayCount+". Delay Average "+DoubleToString(DelaySum/DelayCount,2)+". Max "+delayMax+" OnBooks "+CountOnBook+" OnTicks "+CountOnTick;
     MyPrint (out);
     Comment(out);
     }
     Logger.Logger();
     Alt();
     curBook=0;
     curTick=0;
  }
//---
void MyPrint(string out)  
{
   Print(out);
   Logger.Log(__FUNCTION__,out,2,false);
}
//---
void Alt()
{
int last=ArrayObj.Total();
for(int i=0;i<curBook;i++)
  {
   if (!ArrayObj.Add(new CMcsOn(TimeArrayBook[i],USE_BOOK)))
      Logger2.Log(__FUNCTION__,"Error Book Add",0);   
  }
for(int i=0;i<curTick;i++)
  {
   if (!ArrayObj.Add(new CMcsOn(TimeArrayTick[i],USE_TICK)))
      Logger2.Log(__FUNCTION__,"Error Tick Add",0);   
  }
  ArrayObj.Sort();
  int total=ArrayObj.Total();
  total-=last;
  CMcsOn*Obj;
  for(int i=0;i<total;i++)
    {    
     Obj=ArrayObj.At(i);
     if(CheckPointer(Obj)==POINTER_INVALID )
      { Logger2.Log(__FUNCTION__,"Error At Array",0); continue;}
      string out = Obj.USE_BOOK ? "Book ": "Tick ";
      out+= Obj.mcs  ;
      Logger2.Log(__FUNCTION__,out,2);
    }
   Logger2.Log("ArrayObj_","Last "+last+" total "+ArrayObj.Total(),1);  
   Logger2.Logger();
   //ArrayObj.Shutdown(); 
}
 
prostotrader:
但我不知道负责人是否对他的问题的答案感到满意。

我已经收到了所有的答案,并得出了自己的结论。
我需要分析一段固定时间内的交易条数--交易的价格、实现的数量等。
而且我还需要在策略测试器中 模拟算法的运行。
OnTick事件完美地应对了这一点,真实交易的结果和测试器中建模的结果一致,只有一个小的误差,这让我很满意。
如果你需要更快的带材分析,你可以使用OnTimer。

而且,不一定每一个进入终端的tick都要放在OnBook中--这是市场订单执行的具体内容。

 
Vladimir Mikhailov:


而进入终端的每一个tick不一定要进入OnBook--这是市场订单执行的具体内容。

相反,每个 进入OnTick处理程序的tick(事件)都必须与OnBook同步。
在OnTick处理程序中有三个事件,最佳买入价格的变化,最佳卖出价格的变化,以及交易(最后)。
如果在没有交易的情况下买入或卖出价格发生变化,这将是一个事件,OnTick将接收这些事件。
而OnBook也必须捕捉这些事件,但它自己的事件,它的处理程序,否则处理程序之间会出现买入和卖出价格的不匹配。

而如果OnTick收到最后一个事件,就意味着一个交易已经过去。
交易在OnTick中产生事件,因为在交易之后,价格或出价和要价的数量在市场上发生变化。
这是一个恶性循环。

在OnTick和OnBook中,有一个Best Bid和Best Ask事件。
这些事件在两个处理程序中应该始终是同步的。
而事件本身是最后的,它在交易后会在OnBook中产生一个事件。
因此,任何进入OnTick处理程序的事件必须同步反映在OnBook中。