应对交易环境时的典型错误和如何处理这些错误

Artyom Trishkin  
在这个主题中,我们将讨论在一些算法中使用终端的交易环境时所犯的常见错误,以及在未来消除和避免这些错误的方法。
Andrei Fandeev  
好的。
只是作为一个介绍。
专家顾问分析了最后一个平仓订单的方向(或利润,...)。最后一个订单是在2天前结束的。
交易员将历史深度设置为1天。
OrdersHistoryTotal()并没有看到该订单。
解决办法是什么?
Artyom Trishkin  
Andrei Fandeev:
好的。
只是作为一个介绍。
专家顾问分析了最后一个平仓订单的方向(或利润,...)。最后一个订单是在2天前结束的。
而交易员将历史深度设置为1天。
OrdersHistoryTotal()并没有看到该订单。
解决办法?

对于MT4--在我看来,毫不含糊地,在启动EA时给用户一个警告,让其使用所需的历史深度。

MT5允许加载历史记录到所需的深度。

Andrei Fandeev  
Artyom Trishkin:

对于MT4--在我看来,毫不含糊地,在启动EA时给用户一个警告,让其使用所需的历史深度。

依靠用户是一个坏主意。需要有一个检查。
Artem,在MT4中,我没有找到获取设置历史深度值的方法。
真的无法通过编程获得吗?

Artyom Trishkin  
Andrei Fandeev:

依靠用户是一个坏主意。你需要一张支票。
Artem,在MT4中,我找不到Get来获取设定的历史深度值。
真的无法通过编程获得吗?

的确如此。

fxsaber  

有两种范式来处理交易环境和编写EA。

  1. 事件输入(OnTick、OnTimer等)相互依赖。在事件之间有必须有的信息(不是为了速度,如缓存,而是为了可用性)。例如,我们需要保存OrderSendAsync的结果并在OnTradeTransaction 中使用它。缓存不是强制性的信息,只用于加快速度。这就是为什么我们不马上考虑他们。
  2. 事件输入(OnTick、OnTimer等)不是相互依赖的。每个输入都是从零开始。大致上就像一个你自己在每个事件上运行的脚本。
在MT4中,你可能可以通过第二个选项来解决一切问题。MT5并不那么明确。


第二种方案比第一种方案的优势

  • 你可以在任何地方终止该算法(正常和非正常)。
  • 你可以在任何地方开始/继续执行该算法。
  • 高度的可靠性。


劣势

  • In Tester在性能方面将不如第一个变体。
  • 这种 "从头开始 "的逻辑使你写的代码有些 "不合逻辑",这在第一阶段需要一些适应。

fxsaber  

我如何比较交易环境的API?引入各种不同的TS。让我们想象一下我们理想的虚拟API,它将允许以最小的努力在可靠的代码中体现出TS。

如果有可能将这种非常理想的虚拟API作为真正的API的包装物来创建,那么原来的API就非常好。尽管甚至需要花费多少精力和时间来创建一个包装器。


按照这个标准,MT4和MT5是优秀的API。只有源API是困难的,但它们允许(没有架构/技术限制)写一个伟大的包装,因此是好的。

因此,当他们说MT5比MT4更复杂--他们的意思是,他们还没有遇到一个MT5包装器(也许还没有写出来),能像他们使用的MT4包装器一样可用的。


一般来说,这两个平台都允许你从低级别的API中创建一个高级别的API(包装器)。因此,他们的交易环境API的复杂性是相等的!

fxsaber  

MT4有一个相当高级的API,所以很少有人试图写一个普遍的更方便用户的包装器。但MT5不是这样的--原来的底层API只是要求编写某种包装器。因此,在这个问题上讨论每个包装器的特点没有什么意义。相反,重要的是要表明仍然需要一个包装器。在编写高层API时,确实需要考虑低层API的哪些特征。

В общем, обе платформы позволяют из низкоуровневых API создать единый высокоуровневый API (обертка). Так что сложности API торговых окружений у них равны!

基于这种说法,我们需要学习如何编写MT5代码,在实用性方面不逊于MT4代码。API包装可能不同(语法通常),但从架构上看,MT5不应该比MT4差,否则就失去了强调的意义。因此,更繁琐的MT5代码不应视为批评的理由,而应视为将其缝合到不亚于MT4的用户友好包装中的帮助。

fxsaber  
让我们来看看一个简单的MT4模板TS

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

组织一个订单循环

fxsaber, 2018.02.15 23:19

// Шаблон большинства ТС

#property strict // обязательно

// Сигнал на покупку
bool BuySignal( const string Symb ) { return(true); }

// Сигнал на продажу
bool SellSignal( const string Symb ) { return(false); }

// Находит ордер соответствующего типа
bool OrdersScan( const string Symb, const int Type )
{
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS) && (OrderType() == Type) && (OrderSymbol() == Symb))
      return(true);    
    
  return(false);  
}

// Торговое действие на сигнал
bool Action( const string Symb, const int Type, const double Lots = 1 )
{
  bool Res = true;    
  
  // Закрыли противоположные сигналу позиции
  while ((OrdersScan(Symb, 1 - Type)) && (Res = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 100)));

  // Открыли позицию по сигналу
  return(Res && !OrdersScan(Symb, Type) && OrderSend(Symb, Type, Lots, SymbolInfoDouble(Symb, Type ? SYMBOL_BID : SYMBOL_ASK), 100, 0, 0));
}

// Шаблон торговой стратегии
void Strategy( const string Symb )
{
  if (BuySignal(Symb))
    Action(Symb, OP_BUY);
  else if (SellSignal(Symb))
    Action(Symb, OP_SELL);
}

void OnTick()
{
  Strategy(_Symbol);
}

这丝毫没有显示出MT4的便利性,它只是作为一个比较的基准点。这是一个MT5封装器应该能够保持的较低的可用性标准。模板是根据第二个范 式编写的。


看来我们在MT5上写的东西是一样的

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

组织一个订单溢出周期

fxsaber, 2018.02.15 22:30

// Шаблон большинства ТС

#include <Trade/Trade.mqh>

// Сигнал на покупку
bool BuySignal( const string Symb ) { return(true); }

// Сигнал на продажу
bool SellSignal( const string Symb ) { return(false); }

// Находит позицию соответствующего типа
bool PositionsScan( const string Symb, const ENUM_POSITION_TYPE Type )
{
  for (int i = PositionsTotal() - 1; i >= 0; i--)
    if ((PositionGetSymbol(i) == Symb) && (PositionGetInteger(POSITION_TYPE) == Type))
      return(true);    
    
  return(false);  
}

// Торговое действие на сигнал
bool Action( const string Symb, const ENUM_POSITION_TYPE Type, const double Lots = 1 )
{
  static CTrade Trade;    
  bool Res = true;    
  
  // Закрыли противоположные сигналу позиции
  while ((PositionsScan(Symb, (ENUM_POSITION_TYPE)(1 - Type))) && (Res = Trade.PositionClose(PositionGetInteger(POSITION_TICKET))));

  // Открыли позицию по сигналу
  return(Res && !PositionsScan(Symb, Type) && (Type ? Trade.Sell(Lots, Symb) : Trade.Buy(Lots, Symb)));
}

// Шаблон торговой стратегии
void Strategy( const string Symb )
{
  if (BuySignal(Symb))
    Action(Symb, POSITION_TYPE_BUY);
  else if (SellSignal(Symb))
    Action(Symb, POSITION_TYPE_SELL);
}

void OnTick()
{
  Strategy(_Symbol);
}

由于某些原因,有些人为了同样的TS写了更多的代码。但事实上,这段代码做得同样好。大多数TC只需要写BuySignal和SellSignal。不需要其他任何东西。

该模板的例子是专门用SB写的。因此,向MT5专家提问,该代码是否正确?


显示需要包装器的函数被标为红色。这里 描述了它的问题。有人会想起,这就是古代用睡眠法解决的仓位重开问题,在OrderSend后等待仓位打开。但事实上,这个问题与OrderSend没有关系。你需要知道如何正确阅读交易环境。

fxsaber  
fxsaber:

你需要能够正确阅读交易环境。

用一个简单的例子来正确地认识它

// Возвращает количество позиций по символу
int GetAmountPositions( const string Symb )
{
  int Res = 0;
  
  for (int i = PositionsTotal() - 1; i >= 0; i--)
    if (PositionGetSymbol(i) == Symb)
      Res++;
      
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderGetTicket(i) && (OrderGetInteger(ORDER_TYPE) <= ORDER_TYPE_SELL) &&
        !OrderGetInteger(ORDER_POSITION_ID) && (OrderGetString(ORDER_SYMBOL) == Symb))
      Res++;  

/*
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) && (OrderSymbol() == Symb))
      Res++;
*/      
  return(Res);
}

简而言之,重点是:如果有市场订单,也要考虑它是一个 "头寸"。用引号,因为它是一个包裹的位置。突出显示的代码通常不会出现在任何地方。但它避免了重新开 仓。这里最有趣的事情是用红色强调的。这个芯片的必要性并不立即显现。

事情是这样的,有所谓的收盘市场订单。同样的SL/TP。显然,我们不希望将这种市场订单视为 "头寸"。我们也不希望看到我们已经下的那些订单也被关闭。因此,突出显示的条件是适当的过滤器。


ZZZ在这里 粘贴这个代码,并在演示服务器上 检查结果。

Artyom Trishkin  
fxsaber:

使用一个简单的例子的正确选择

简而言之,重点是:如果有市场订单,也要考虑它是一个 "头寸"。用引号,因为它是一个包裹的位置。突出显示的代码通常不会出现在任何地方。但它避免了重新开 仓。这里最有趣的事情是用红色强调的。对这一芯片的需求并没有立即显现出来。

事情是这样的,有所谓的收盘市场订单。同样的SL/TP。显然,我们不希望将这种市场订单视为 "头寸"。我们也不希望看到我们已经下的那些订单也被关闭。因此,突出显示的条件是适当的过滤器。


这里 粘贴这个代码,并在演示服务器上 检查结果。

问题:如果在发送交易订单后,直到下一个tick,市场订单没有被服务器放置,会发生什么?

原因: