程序库: MT4Orders - 页 85

 
mt4 代码的无缝转换真是令人惊叹。辛苦了,感谢您的分享,我真的很感激。
 

关于交易、自动交易系统和测试交易策略的论坛

库:MT4Orders

fxsaber, 2023.07.07 13:12

性能。

b3815 和 b2958 的性能表(以毫秒为单位的执行时间)。

MT5 版本 LastCloseTimeMQL4 LastCloseTimeMQL5 LastCloseTimeMQL4_2 LastCloseTimeMQL4+VIRTUAL::Snapshot LastCloseTimeMQL4+VirtualTester
b3815 2875 113 708 732 45
b2958 2718 107 675 715 50

MT4Orders 从20.07.2022 开始使用。

使用相同的方法,比较两个 MT5 版本:b4040 和b4057

MT5 版本 LastCloseTimeMQL4 LastCloseTimeMQL5 LastCloseTimeMQL4_2 LastCloseTimeMQL4+VIRTUAL::Snapshot LastCloseTimeMQL4+VirtualTester
b4040 3663 117 881 928 27
b4057 246 122 171 213 27

在 b4057+ 上,MT4Orders 在处理历史记录时的性能并不比本地 MQL5 差。


因此,之前给出的建议不再适用(对于 MT5 b4057+)

交易、自动交易系统和交易策略测试论坛。

库:MT4Orders

fxsaber, 2023.07.07 13:12

  • 有必要减少历史订单的 OrderSelect 调用。这可以通过表格右侧三列所示的方式实现。
 

关于交易、自动交易系统和测试交易策略的论坛

图书馆:MT4Orders

fxsaber, 2017.06.14 11:30 AM.

// 更改列表:
// 14.06.2017:
// 添加:已启用平仓(通过 OrderClose 关闭)的 SL/TP 检测功能。
// 添加:MagicNumber 现在的类型是 long - 8 字节(以前是 int - 4 字节)。
// 补充:如果在 OrderSend、OrderClose 或 OrderModify 中,颜色输入参数(最新参数)被设置为等于 INT_MAX,则将生成该参数。
// 相应的 MT5 交易请求 (MT4ORDERS::LastTradeRequest),但不会发送。取而代之的是 MT5 检查、
// 其结果将在MT4ORDERS::LastTradeCheckResult 中提供.
// 如果订单修改和订单关闭成功,它们将返回 true,否则将返回 false。
// OrderSend 如果成功将返回 0,否则返回-1。
//
// 如果相应颜色输入参数的设置早于INT_MIN, то ТОЛЬКО в случае успешной MT5-проверки сформированного
// 交易请求(如 INT_MAX)将被发送。
// 添加:已添加 MQL4 交易函数的异步类似函数:OrderSendAsync, OrderModifyAsync, OrderCloseAsync, OrderDeleteAsync.
// 如果成功,则返回相应的 Result.request_id,否则返回 0。

如果您需要了解,终端对交易订单或服务器做出了拒绝。

// 如果被拒绝,请查看拒绝原因。  
if (!OrderDelete(OrderTicket(), INT_MIN)) //https://www.mql5.com/ru/forum/93352/page12#comment_5290455
  Print(ToString(MT4ORDERS::LastTradeRequest) + //https://www.mql5.com/en/forum/203931#comment_5287237
        ToString(MT4ORDERS::LastTradeResult) +
        ToString(MT4ORDERS::LastTradeCheckResult));
 

真实。我使用 MT4Orders,通过 Virtual 虚拟环境,实现虚拟与真实同步。为此,在每个刻度线中,我都会多次查看在真实订单中打开的订单。为此,在第一遍时,我形成一个感兴趣的订单列表,在其他各遍时,我使用该列表。

我曾经有过这样一个代码:

long OrderTickets[];
for(int i=OrdersTotal()-1;i>=0;--i)
{
  if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
    continue;
  AddToArray(OrderTickets,OrderTicket());
}
...
for(int i=ArraySize(OrderTickets)-1;i>=0;--i)
{
  if(!OrderSelect(OrderTickets[i],SELECT_BY_TICKET,MODE_TRADES))
    continue;
  do_something();
}

实践证明,这不是一个好方法。一个部分成交的限制器会产生两张相同的订单,而在第二次交易时,这将是一个不幸。

现在我改用以下代码

int Orders[];
for(int i=OrdersTotal()-1;i>=0;--i)
{
  if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
    continue;
  AddToArray(Orders,i);
}
...
for(int i=0;i!=ArraySize(Orders);++i)
{
  if(!OrderSelect(Orders[i],SELECT_BY_POS,MODE_TRADES))
    continue;
  do_something();
}

此外,在工作前会进行快照。这样做是否正确,还是会出现其他问题?

 
traveller00 每个刻度线中,我都会多次查看在真实订单中打开的订单。为此,在第一遍时,我会列出一个感兴趣的订单列表,然后在其他遍数中使用该列表。

以前的代码是这样的

实践证明,这样做并不好。部分成交的限制器会产生两张相同的订单,而在第二次交易时,这将是一个不幸。

如果这样做,就不会有悲伤。

AddToArray(OrderTickets, (OrderType() <= OP_SELL) ? OrderTicket() : - OrderTicket());

这是 MT4Orders 的一项功能。但是,在 MT4/5 和虚拟化中,SELECT_BY_TICKET 并不是一种快速机制。其中一个原因是,如果它在实时交易中找不到,就会转到历史记录(MODE_TRADES-flag 只是优先指示先找哪里)。


现在我改用了以下代码

此外,在工作前会做一个快照。这样做是否正确,还是会出现其他问题?

这里我们已经谈到了 Virtual.mqh 的附加功能。当然,如果有很多角色/魔法在交易,快照会加快工作速度。

快照可将与智能交易系统外部环境(交易 API)的工作减至最少。也就是说,最慢的函数只需调用一次进行初始读取,然后所有与交易环境有关的工作都会在 EA 内部进行,程序员不会察觉,因为这与 MT4 风格相同。


使用这些快照变体之一是有意义的。

#define  VIRTUAL_SNAPSHOT_REFRESHTIME 1000 // 用于更新的快照寿命。在 MT5 中需要连接 MT4Orders.mqh
#define  VIRTUAL_SNAPSHOT_WITHOUT_HISTORY // 丢弃历史快照以提高性能
#include <fxsaber\Virtual\Virtual.mqh>

VIRTUAL::Snapshot(); // 1: один (_Symbol) символ, все мэджики.
VIRTUAL::Snapshot(VIRTUAL_SNAPSHOT_REFRESHTIME, MyMagic); // 2: один (_Symbol), один мэджик.
VIRTUAL::Snapshot(VIRTUAL_SNAPSHOT_REFRESHTIME, -1, false, ""); // 3: все символы и мэджики.


  1. 我使用的就是这种方式。我可以在单通道 EA 中拥有多个子OTC(每个子OTC 都有自己的主程序)。即使一个符号上有多个智能交易系统,我仍然认为使用该选项是合理的。也就是说,只需进行一次快照,然后所有子运行控制器都会根据结果运行。
  2. 如果单币种智能交易系统只使用一种货币,这是最快的选择
  3. 多货币智能交易系统,您可以设置一个majic 或所有majic。


您可以连续千次调用 VIRTUAL::Snapshot(),但它与外部交易 API 的交互频率不会超过 VIRTUAL_SNAPSHOT_REFRESHTIME 中的设置(在示例中为一毫秒,对我来说足够了)。因此不需要记忆任何东西,代码大致如下。

VIRTUAL::Snapshot();

for (uint i = OrdersTotal(); (bool)i--;)
{
  VIRTUAL::Snapshot();
  
  do_something();
}


下面是我的同步代码(为每个子 TS 调用)和虚拟环境。

  // 根据当前(选定)和 VirtualPointerOut(关闭位置)同步 VirtualPointerTo-environment。
  static bool SyncChannel( const string &Symb, const MAGIC_TYPE Magic, const double Lots,
                           const VIRTUAL_POINTER &VirtualPointerTo, const VIRTUAL_POINTER &VirtualPointerOut, const int FlagChange = false )
  {      
    // 需要 IsNull 机制。
    if (!VirtualPointerTo.GetHandle() || !VIRTUAL::GetHandle())
      _B2(VIRTUAL::Snapshot());    
    
    const bool IsNull = !OrdersTotal() && !_VP(VirtualPointerTo, OrdersTotal());
    bool Res = IsNull || !FlagChange || _B(SYNCCHANNEL::IsNotChange(true), 500);
  
    if (!IsNull)
    {
      Res &= SYNCCHANNEL::IsCloseBy(/*Symb*/.) && MACRO_ISCHANGE(SYNCCHANNEL::SyncCloseBy(Symb, Magic, VirtualPointerTo/*, (inMinLotCorrection <= 0)*/));
      
      Res &= MACRO_ISCHANGE(SYNCCHANNEL::SyncExistOrders(Symb, Magic, VirtualPointerTo, VirtualPointerOut));

      if (Lots && (inMinLotCorrection > Lots))
        ::Alert("inMinLotCorrection(" + (string)inMinLotCorrection + ") > Lots(" + (string)Lots + ")");
      
      Res &= MACRO_ISCHANGE(SYNCCHANNEL::SetNewLimit(Symb, Magic, Lots, OP_BUYLIMIT, VirtualPointerTo, inMinLotCorrection));
      Res &= MACRO_ISCHANGE(SYNCCHANNEL::SetNewLimit(Symb, Magic, Lots, OP_SELLLIMIT, VirtualPointerTo, inMinLotCorrection));
    }    

    return(Res);    
  }

从突出显示的部分可以看到快照的创建。它应在制动功能之后调用。例如,OrderSend。如果多调用一次,也没什么大不了的,如上面的代码所示。

不过,给出源代码还有另一个原因。我将所有可能较慢的函数放入一个宏中,如果在同步过程中出现新的刻度线(SymbolInfoTick 或 CopyTicks),该宏会完全停止同步,因为新的刻度线必须首先通过所有虚函数抛出,然后才与实函数同步。一切都与交易复制器和外部加密货币交易所的工作方式完全相同。

 
Caught OrderBug22 什么问题?RP 0 19:00:01.733 Pip Funnels 1.0 (AUDJPY,H2) Line = 1537 NF 0 19:00:01.733 Pip Funnels 1.0 (AUDJPY,H2) Before MT4ORDERS::HistoryDealSelect(Result): DP 0 19:00:01.733 Pip Funnels 1.0 (AUDJPY,H2) MT4ORDERS::OrderSendBug = 22 CL 0 19:00:01.733 Pip Funnels 1.0 (AUDJPY,H2) Result.deal = 0
 
Sviatoslav Tyshchyk :HistoryDealSelect(Result):DP 0 19:00:01.733 Pip Funnels 1.0 (AUDJPY,H2) MT4ORDERS::OrderSendBug = 22 CL 0 19:00:01.733 Pip Funnels 1.0 (AUDJPY,H2) Result.deal = 0

没问题。

 
这项技术可以从交易历史中删除挂单。
int HistoryOrdersTotalTmp( void ) { return(-1); }

#define HistoryOrdersTotal HistoryOrdersTotalTmp
  #include <MT4Orders.mqh> //https://www.mql5.com/zh/code/16006
#undef HistoryOrdersTotal
 
Line = 1773
Before ::HistoryOrderSelect(Result.order):
MT4ORDERS::OrderSendBug = 96
Result.deal = 0
Line = 1796
Before MT4ORDERS::HistoryDealSelect(Result):
MT4ORDERS::OrderSendBug = 96
Result.deal = 0
Alert: OrderSend(1505369998) - BUG!
Alert: Please send the logs to the coauthor - https://www.mql5.com/en/users/fxsaber
Alert: C:\Program Files\MetaTrader 5 5\MQL5\Logs\20240402.log

一些错误

 
leonerd #:

一些错误

这很正常。