程序库: MT4Orders - 页 12

 
举例说明在网络账户上使用专家顾问库时,其交易部分是多么简洁可靠。

在您的账户上自动执行 MetaTrader 5 的交易信号

LCHI2017

MetaTrader 5
免费

Expert Advisor 针对股票工具进行交易。

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

sinput double exLots = 1;

int OrderScan( const int Type0, const int Type1 = -1, const int Type2 = -1, const int Type3 = -1 )
{
  int Res = -1;

  int Types[4];
    
  Types[0] = Type0;
  Types[1] = Type1;
  Types[2] = Type2;
  Types[3] = Type3;
  
  for (int i = 0; (i < 4) && (Types[i] != -1) && (Res == -1); i++)
    for (int j = OrdersTotal() - 1; j >= 0; j--)
      if (OrderSelect(j, SELECT_BY_POS) && (OrderType() == Types[i]) && (OrderSymbol() == _Symbol))
      {
        Res = Types[i];
        
        break;
      }
      
  return(Res);    
}

bool MyOrderModify( const double Price )
{
  return((CP(Price) != OrderOpenPrice()) && OrderModify(OrderTicket(), Price, 0, 0, 0));
}

bool MyOrderSend( const int Type, const double Price )
{
  const double Lots = exLots + OrderLots();      
  
  return((OrderScan(Type) == -1) ? OrderSend(_Symbol, Type, Lots, Price, 0, 0, 0) : MyOrderModify(Price));
}

MqlTick Ticks[];

void OnTick( void )
{  
  static const MqlTick NullTick = {0};
  
  const MqlTick Level = GetLevel(Ticks);
  
  if (_R(Level) != NullTick)
  {
    const int Type = OrderScan(OP_BUY, OP_SELL, OP_BUYLIMIT, OP_SELLLIMIT);
    
    if (Type == OP_BUY)
      MyOrderSend(OP_SELLLIMIT, Level.bid);
    else if (Type == OP_SELL)
      MyOrderSend(OP_BUYLIMIT, Level.ask);
    else if (Type != -1)
      MyOrderModify((OrderScan(OP_BUYLIMIT, OP_SELLLIMIT) == OP_BUYLIMIT) ? Level.ask : Level.bid);
    else
      OrderSend(_Symbol, OP_BUYLIMIT, exLots, Level.ask, 0, 0, 0);
  }
  
  return;
}
 
非常有用,谢谢!
 
这里 随时提供最新版本。
 

脚本显示SELECT_BY_POS+MODE_TRADES 模式下订单选择功能 的一个特殊之处

#include <MT4Orders.mqh>
#include <MQL4_To_MQL5.mqh>

void OnStart()
{
  OrderSend(_Symbol, OP_BUYLIMIT, 1, Ask - 100 * _Point, 0, 0, 0);  // 设置买入上限
  OrderSend(_Symbol, OP_SELLLIMIT, 1, Bid + 100 * _Point, 0, 0, 0); // 设置卖出限额
  OrderSend(_Symbol, OP_BUY, 1, Ask, 100, 0, 0);                    // 建仓买入
  
  bool FirstRun = true;
  
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS))
    {
      OrderPrint();
      
      if (FirstRun)
      {
        OrderSend(_Symbol, OP_SELL, 1, Bid, 100, 0, 0); // 打开卖出仓位
        
        FirstRun = false;
      }
    }    
}

MT4

#196155484 2017.05.04 15:38:07 buy 1.00 EURUSD 1.09229 0.00000 0.00000 1.09221 0.00 0.00 -8.00  0
#196155480 2017.05.04 15:38:06 sell limit 1.00 EURUSD 1.09321 0.00000 0.00000 1.09221 0.00 0.00 0.00  0
#196155479 2017.05.04 15:38:06 buy limit 1.00 EURUSD 1.09129 0.00000 0.00000 1.09229 0.00 0.00 0.00  0

MT5

#147352190 2017.05.04 15:38:06 sell limit 1.00 EURUSD 1.09322 0.00000 0.00000 1.09222 0.00 0.00 0.00 0
#147352193 2017.05.04 15:38:06 sell 1.00 EURUSD 1.09222 0.00000 0.00000 1.09231 0.00 0.00 -9.00 0
#147352191 2017.05.04 15:38:06 buy 1.00 EURUSD 1.09231 0.00000 0.00000 1.09222 0.00 0.00 -9.00 0

尽管该脚本在两个平台上的交易结果完全相同,但订单选择的工作方式却不同。因此会出现不同的日志。

该脚本是专门吸出的,我不推荐这种编写交易逻辑的方式,因为它在每个平台上都充满了难以察觉的逻辑错误。而且这种代码在执行过程中不再是 100% 一致的。

这就是为什么修正程序库,使 MT4 中罕见的曲线能在 MT5 中绝对完美地执行,就像正常代码一样,似乎并不合适。

如果我对此类 MT4 交易结构的曲率和罕见性的理解有误,请予以澄清。

 
不知何故,它甚至会因为速度变慢而变得有趣。
 
Vitaly Muzichenko:
慢下来的感觉很有趣。

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

MT4 测试仪 VS MT5 测试仪

fxsaber, 2017.05.08 01:11 pm.

如果怀疑 MT5 速度变慢是由于使用第三方库造成的,有心人可以根据自己的喜好在 MQL5 中重写此 EA 的简单 MT4 逻辑,并测试这一假设。
 
fxsaber:

一个脚本,显示在 SELECT_BY_POS+MODE_TRADES 模式下,OrderSelect 执行的一个特点

该脚本是特别吸出的,我不推荐这种编写交易逻辑的方式

在另一种极不推荐的交易逻辑编写方式中,您可能会遇到OrderSelect 的另一个功能,但已经是在SELECT_BY_TICKET+MODE_HISTORY 模式下了。

#include <MT4Orders.mqh>

#define Ask (::SymbolInfoDouble(_Symbol, SYMBOL_ASK))

void OnTick()
{
  static bool FirstRun = true;
  
  if (FirstRun && OrderSelect(OrderSend(_Symbol, OP_BUY, 1, Ask, 0, 0, 0), SELECT_BY_TICKET) &&
      OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0))  
  {
    Print(OrderTicket()); // 2 - OPEN 位置与该票一致
    
    Print(OrderSelect(OrderTicket(), SELECT_BY_TICKET, MODE_HISTORY)); //false, потому что тикет ЗАКРЫТОЙ позиции равен тикету закрывающей сделки.
    Print(OrderSelect(OrderTicket() + 1, SELECT_BY_TICKET, MODE_HISTORY)); // true,原因如上。
      
    FirstRun = false;
  }
}

这是一个测试人员的智能交易系统。注释中说明了这种行为的原因。它是正确的,因为

  • 未结头寸的单子(通常)等于开仓订单的单子(非交易)。(MT5 术语)。
  • 如果头寸被部分关闭,为避免歧义,关闭的相应头寸的单子不得等于未结头寸的单子(MT5 术语)。

  • 也就是说,MT5 本身就是如此 "歪打正着",以至于很难想到 MT4Orders 的其他行为。当然,如果先按历史记录进行 SELECT_BY_POS,记录下所有单子,那么 SELECT_BY_TICKET 就能顺利运行。

    一般来说,如果 MT4 交易逻辑写得 "糟糕",MT5+MT4Orders 的结果和 MT4 的结果之间可能会有差异,这对于 MT4 理解来说是不正常的。如果按照 "正确的 "MT4 写法,就不会在库中发现任何问题。

     
    fxsaber:

    如果使用另一种极不推荐的方式编写交易逻辑,则可能会遇到订单选择的另一种功能,但已处于 SELECT_BY_TICKET+MODE_HISTORY 模式。

    一般来说,如果 MT4 交易逻辑写得 "糟糕",那么 MT5+MT4Orders 和 MT4 结果之间可能会出现 MT4 无法理解的差异。如果坚持 "正确 "的 MT4 写法,就不会在程序库中发现任何问题。


    库非常棒,非常感谢 :)添加历史同步功能后,它就不可或缺了。即使是 hft 策略也能快速运行

    我想把它添加到 MT5 的标准配置中。

     

    更新

    // 更改列表:
    // 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。

    INT_MIN 模式允许您完全清除测试仪日志中的堵塞信息 - 这在优化过程中尤为重要,因为由于错误的交易逻辑,大量的信息会使优化性能降低很多倍,从而不仅增加时间成本,还增加了资金成本(云计算)。

    在平仓 的 TP/SL。

    也许有一天,这一功能会成为 MT5 的标准功能。


    使用异步 MQL4 函数的示例

    #property script_show_inputs
    
    sinput int Amount = 5; // 测试次数 OrderSend(Async)
    
    #include <MT4Orders2.mqh>
    
    #define Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)
    #define  PRINT(A) Print(#A + " = " + (string)(A));
    
    void OnStart()
    {  
    // OrderSendAsync  
      const ulong StartTime1 = GetMicrosecondCount();
      
      for (int i = 0; i < Amount; i++)
        PRINT(OrderSendAsync(NULL, OP_BUY, 0.1, Ask, 100, 0, 0))
        
      PRINT(GetMicrosecondCount() - StartTime1)
    
    // OrderSend
      const ulong StartTime2 = GetMicrosecondCount();
      
      for (int i = 0; i < Amount; i++)
      {
        PRINT(OrderSend(NULL, OP_BUY, 0.1, Ask, 100, 0, 0))
        Print(MT4ORDERS::LastTradeResult.comment);
      }
        
      PRINT(GetMicrosecondCount() - StartTime2)
      
      PRINT(TerminalInfoInteger(TERMINAL_PING_LAST))
    }


    结果

    OrderSendAsync(NULL,OP_BUY,0.1,Ask,100,0,0) = 117
    OrderSendAsync(NULL,OP_BUY,0.1,Ask,100,0,0) = 118
    OrderSendAsync(NULL,OP_BUY,0.1,Ask,100,0,0) = 119
    OrderSendAsync(NULL,OP_BUY,0.1,Ask,100,0,0) = 120
    OrderSendAsync(NULL,OP_BUY,0.1,Ask,100,0,0) = 121
    GetMicrosecondCount()-StartTime1 = 403
    
    OrderSend(NULL,OP_BUY,0.1,Ask,100,0,0) = 153496331
    Request executed 221.820 + 0.013 ms
    OrderSend(NULL,OP_BUY,0.1,Ask,100,0,0) = 153496331
    Request executed 252.067 + 0.008 ms
    OrderSend(NULL,OP_BUY,0.1,Ask,100,0,0) = 153496331
    Request executed 220.909 + 0.005 ms
    OrderSend(NULL,OP_BUY,0.1,Ask,100,0,0) = 153496331
    Request executed 189.578 + 0.005 ms
    OrderSend(NULL,OP_BUY,0.1,Ask,100,0,0) = 153496331
    Request executed 180.182 + 0.010 ms
    GetMicrosecondCount()-StartTime2 = 1064775
    
    TerminalInfoInteger(TERMINAL_PING_LAST) = 97942