程序库: MT4Orders - 页 43

 
traveller00:
在证券交易所的真实账户和真实交易中,经纪人 Otkrytie 即使等待 10 秒钟也无济于事,仍然会弹出历史记录不同步的提示。而且弹出的频率很高。这在我看来是很奇怪的,在其他特殊的滞后中是看不到的,ping 4 毫秒,订单执行 通常小于 15 毫秒。我甚至开始怀疑这里的一切是否正确,也许这与网络有关?虽然我不使用 INOUT,但所有 IN 和 OUT 都是分开的。是否有计划绕过这种情况?例如,自己背票。解决这个问题的优先级有多高?

请公布这两份日志。

 

你好 fxsaber、

祝您 2020 年好运!

MT4OrderClose 功能的交易请求中不包含魔数是一种设计选择吗?

目前,MT4OrderCloseDEAL_ENTRY_OUT 将有 magic ==0。

这并没有太大区别,因为通过仓位 ID,您可以跟踪 DEAL_ENTRY_IN 中的魔数,但出于历史分析目的,DEAL_ENTRY_IN / DEAL_ENTRY_OUT 的匹配可能会提供更大的灵活性。


Hi fxsaber,

祝 2020 年一切顺利!

MT4OrderClose 功能的交易请求中不包含神奇数字是一种设计选择吗?

目前,MT4OrderClose 的 DEAL_ENTRY_OUT 将有 magic ==0。

这并不是什么大问题,因为使用头寸 ID 可以从 DEAL_ENTRY_IN 反向追踪魔数,但是对于历史分析而言,匹配 DEAL_ENTRY_IN/DEAL_ENTRY_OUT 可能会提供更大的灵活性。

 
Enrique Dangeroux:

MT4OrderClose 功能的交易请求中不包含神奇数字是一种设计选择吗?

目前,MT4OrderCloseDEAL_ENTRY_OUT 将包含 magic ==0。

这并无太大区别,因为通过仓位 ID,您可以跟踪 DEAL_ENTRY_IN 中的魔数,但出于历史分析目的,DEAL_ENTRY_IN / DEAL_ENTRY_OUT 的匹配可能会提供更大的灵活性。

如果愿意,您可以在 OrderClose 中设置 MagicNumber。

在 MT5 中,当部分平仓时,您可以更改未结头寸的 MagicNumber,这样您就有了选择。

例如,如果您有一个 MagicNumber = 5 的未结头寸,并且手动平仓,那么 DEAL_ENTRY_OUT_MAGIC = 0。程序库仍会返回 OrderMagicNumber() = 5。

 
// 更改列表:
// 12.01.2020
// 修复:余额交易的 OrderTicketID() 现在会返回正确的值。
// 修复:更正了通过 OrderTicketID() 进行的 SELECT_BY_TICKET 选择(MT5-PositionID)。
// 修复:更改了库内部方法的名称,以便更好地与宏兼容。
 
我不知道这是一个错误还是一项功能,但对于期货来说,利润和开仓价的计算并不完全符合预期。假设在 12.00开仓,在 18.40 清仓并自动重新开仓,然后在 20.00 平仓。第 4 笔交易(平仓)的 GetHistoryPositionData 票据选择的利润为 MT4ORDERS::Order.Profit = ::HistoryDealGetDouble(Ticket, DEAL_PROFIT);这将返回第 3-4 笔交易(清仓和平仓)之间的差额。但它会返回开盘价,即 MT4ORDERS::Order.OpenPrice = ::HistoryDealGetDouble(OpenTicket, DEAL_PRICE);。也就是说,它将返回第一笔交易的开盘价。在我看来,应该使其统一,要么从第一笔交易中获取所有信息(包括开仓价和利润),要么从最后一笔开仓交易中获取所有信息(从第三笔交易到清算)。还是说这是一种功能,应该是这样的,而我遗漏了什么?
 
traveller00:
我不知道这是一个错误还是一个功能,但对于期货来说,利润和开仓价的计算并不完全符合预期。假设在 12.00开仓,在 18.40 清仓并自动重新开仓,然后在 20.00 平仓。第 4 笔交易(平仓)的 GetHistoryPositionData 票据选择的利润为 MT4ORDERS::Order.Profit = ::HistoryDealGetDouble(Ticket, DEAL_PROFIT);这将返回第 3-4 笔交易(清仓和平仓)之间的差额。但它会返回开盘价,即 MT4ORDERS::Order.OpenPrice = ::HistoryDealGetDouble(OpenTicket, DEAL_PRICE);。也就是说,它将返回第一笔交易的开盘价。在我看来,让它统一是有意义的,要么从第一笔交易中获取所有信息(包括开仓价和利润),要么从最后一笔开仓交易中获取所有信息(从第三笔交易到清算)。还是说这是一种功能,应该是这样的,而我遗漏了什么?

所以,您是在通过库分析净额结算的历史记录。这正是最初提出的情况,而库尚未完成。能否完成是个大问题。因为要做很多手脚,而在实践中却没有这种需要。

我在 Netting 上仍然使用同一个库,但我绕过了历史工作。

 

https://www.mql5.com/ru/blogs/post/733393


从博文中测量情况的速度。

#include <MT4Orders.mqh>

#define  BENCH(A)                                                               \
{                                                                              \
  const ulong _StartTime = GetMicrosecondCount();                              \
  A;                                                                           \
  Print("Time[" + #A + "] = " + (string)(GetMicrosecondCount() - _StartTime)); \
}

void OnStart()
{
  BENCH(HistorySelectByPosition(270107))
  BENCH(HistorySelectByPosition(270107))

  BENCH(HistorySelect(0, INT_MAX))
  BENCH(HistorySelect(0, INT_MAX))

  BENCH(OrdersHistoryTotal())
  BENCH(OrdersHistoryTotal())

  BENCH(OrderSelect(270107, SELECT_BY_TICKET, MODE_HISTORY))
  BENCH(OrderPrint());

  BENCH(OrderSelect(1000, SELECT_BY_POS, MODE_HISTORY))
  BENCH(OrderPrint());
}


结果。

Time[HistorySelectByPosition(270107)] = 9232 // 冷启动。
Time[HistorySelectByPosition(270107)] = 8571 // Hot Launch.

Time[HistorySelect(0,INT_MAX)] = 152856 // 冷启动。
Time[HistorySelect(0,INT_MAX)] = 94924  // Hot Launch.

Time[OrdersHistoryTotal()] = 155735 // 冷启动。
Time[OrdersHistoryTotal()] = 6774   // Hot Launch.

Time[OrderSelect(270107,1,1)] = 23 // 免费。
#85469 2020.02.05 22:32:12 buy 0.01 USDCNH 6.97767 0.00000 6.98533 2020.02.05 22:32:13 6.97533 0.00 0.00 -0.34 OrderSendTest_Position 0
Time[OrderPrint()] = 20 // 免费。

Time[OrderSelect(1000,0,1)] = 11 // 免费。
#10613 2020.02.06 02:34:32 buy 0.01 EURUSD 1.10049 0.00000 1.11046 2020.02.06 02:34:32 1.10046 0.00 0.00 -0.03 OrderSendTest_Position 0
Time[OrderPrint()] = 13 // 免费。


您可以清楚地看到 HistorySelect 函数花费了多少时间。

OrdersHistoryTotal 对热点的影响虽然较小,但仍很明显,因此建议在每个 On-event 事件中尽量不要调用超过一次。

按历史记录选择订单原来是免费的。

Особенности исполнения торговых приказов MT5
Особенности исполнения торговых приказов MT5
  • www.mql5.com
Анализировал с владельцем MT5-сервера тормоза торговых приказов. Запускался OrderSend-Test2.mq5 в том же месте, где MT5-сервер стоит. Т.е. нулевой пинг. Демо, все внутри. Изучались логи MT5-сервера (2170) и MT5-клиента (2280). Логи сервера не буду приводить, просто словами опишу. Думаю, результаты буду интерсны всем, т.к. это поможет раскрыть...
 

您可以收集市场订单(包括 TP/SL)执行时间的统计数据。

// 统计执行市场订单(包括 TP/SL)所花费的时间。
#property script_show_inputs

input datetime inFrom = 0;
input datetime inTo = INT_MAX;

struct ORDER
{
  ulong Ticket;
  
  ulong FillingTime;
  
  string ToString( void ) const
  {
    return((string)Ticket + ": " + ::TimeToString(this.FillingTime / 1000, TIME_SECONDS) +
                            "." + ::IntegerToString(this.FillingTime % 1000, 3, '0'));
  }
};

// 收集执行市场订单所用时间的数据
int GetOrders( ORDER &Orders[], const datetime From = 0, const datetime To = INT_MAX )
{
  int Amount = 0;
  
  if (HistorySelect(From, To)) // 如果历史记录中有记录
    for (int i = ArrayResize(Orders, HistoryOrdersTotal()) - 1; i >= 0; i--) // 选择订单
    {
      const ulong TicketOrder = HistoryOrderGetTicket(i); // 我们选择了一个授权令
      
      if ((HistoryOrderGetInteger(TicketOrder, ORDER_TYPE) <= ORDER_TYPE_SELL) &&   // 如果市场订单
          (HistoryOrderGetInteger(TicketOrder, ORDER_STATE) == ORDER_STATE_FILLED)) // 如果订单已执行
      {
        Orders[Amount].Ticket = TicketOrder;
        
        // 记住执行所需的时间。
        Orders[Amount++].FillingTime = HistoryOrderGetInteger(TicketOrder, ORDER_TIME_DONE_MSC) -
                                       HistoryOrderGetInteger(TicketOrder, ORDER_TIME_SETUP_MSC);
      }
      }
  
  return(ArrayResize(Orders, Amount));
}

// #include <MT4Orders.mqh> //https://www.mql5.com/zh/code/16006

#define  PRINT(A) Print(#A + " = " + (string)(A))

void OnStart()
{
  ORDER Orders[];
  
  if (GetOrders(Orders, inFrom, inTo))
  {
    ArraySortStruct(Orders, FillingTime); //https://www.mql5.com/ru/forum/170952/page166#comment_15151387
    
    // 打印出执行时间最长的市场订单。
    for (int i = ArraySize(Orders) - 1, k = 0; (i >= 0) && (k < 10); i--, k++)
    {
      Print((string)k + " - " + Orders[i].ToString());

    #ifdef __MT4ORDERS__
      if (OrderSelect(Orders[i].Ticket, SELECT_BY_TICKET))
      {
        OrderPrint();
        
        PRINT(OrderTicketID());
        PRINT(OrderTicketOpen());
  
        Print("-------------------");      
      }
    #endif // __mt4orders__ 
    }
  }
}


结果。

0 - 348806: 00:01:57.311
1 - 348530: 00:01:39.027
2 - 348494: 00:01:15.259
3 - 348406: 00:01:07.671
4 - 348950: 00:01:04.869
5 - 348960: 00:01:02.888
6 - 348814: 00:01:00.654
7 - 348392: 00:01:00.642
8 - 348508: 00:00:54.515
9 - 348550: 00:00:54.467


一个运行账户的执行时间最长可达两分钟。在此分享您的统计数据。该脚本不使用任何库,适用于 Netting/Hedge。

 

在 MT4/5 中,使用交易历史记录进行调试非常不方便。您必须使用各种拐杖解决方案。


在 MT5 中,您可以立即查看通过 MT4Orders 选择的订单的所有字段。为此,您需要将MT4ORDERS::Order 添加到MT4ORDERS::Order 观察中。


这样,您就可以看到所选订单的所有属性。

 
fxsaber:

在此分享您的统计数据。该脚本不使用任何库,适用于 Netting/Hedge。

真实情况就是这样:

2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      0 - 34487054: 00:00:06.768
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      1 - 34487223: 00:00:06.166
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      2 - 49869622: 00:00:03.656
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      3 - 34486559: 00:00:02.833
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      4 - 34486482: 00:00:02.051
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      5 - 34486480: 00:00:02.023
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      6 - 34486467: 00:00:01.983
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      7 - 42624984: 00:00:01.589
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      8 - 33738445: 00:00:01.088
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      9 - 42625044: 00:00:00.932